📄 lparcfg.c
字号:
} if (0 == strcmp(workbuffer, "MaxPlatProcs")) { strcpy(workbuffer, "system_potential_processors"); w_idx = strlen(workbuffer); } } } kfree(workbuffer); local_buffer -= 2; /* back up over strlen value */ } kfree(local_buffer);}/* Return the number of processors in the system. * This function reads through the device tree and counts * the virtual processors, this does not include threads. */static int lparcfg_count_active_processors(void){ struct device_node *cpus_dn = NULL; int count = 0; while ((cpus_dn = of_find_node_by_type(cpus_dn, "cpu"))) {#ifdef LPARCFG_DEBUG printk(KERN_ERR "cpus_dn %p \n", cpus_dn);#endif count++; } return count;}static int lparcfg_data(struct seq_file *m, void *v){ int partition_potential_processors; int partition_active_processors; struct device_node *rootdn; const char *model = ""; const char *system_id = ""; unsigned int *lp_index_ptr, lp_index = 0; struct device_node *rtas_node; int *lrdrp; rootdn = find_path_device("/"); if (rootdn) { model = get_property(rootdn, "model", NULL); system_id = get_property(rootdn, "system-id", NULL); lp_index_ptr = (unsigned int *) get_property(rootdn, "ibm,partition-no", NULL); if (lp_index_ptr) lp_index = *lp_index_ptr; } seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); seq_printf(m, "serial_number=%s\n", system_id); seq_printf(m, "system_type=%s\n", model); seq_printf(m, "partition_id=%d\n", (int)lp_index); rtas_node = find_path_device("/rtas"); lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); if (lrdrp == NULL) { partition_potential_processors = vdso_data->processorCount; } else { partition_potential_processors = *(lrdrp + 4); } partition_active_processors = lparcfg_count_active_processors(); if (firmware_has_feature(FW_FEATURE_SPLPAR)) { unsigned long h_entitled, h_unallocated; unsigned long h_aggregation, h_resource; unsigned long pool_idle_time, pool_procs; unsigned long purr; h_get_ppp(&h_entitled, &h_unallocated, &h_aggregation, &h_resource); seq_printf(m, "R4=0x%lx\n", h_entitled); seq_printf(m, "R5=0x%lx\n", h_unallocated); seq_printf(m, "R6=0x%lx\n", h_aggregation); seq_printf(m, "R7=0x%lx\n", h_resource); purr = get_purr(); /* this call handles the ibm,get-system-parameter contents */ parse_system_parameter_string(m); seq_printf(m, "partition_entitled_capacity=%ld\n", h_entitled); seq_printf(m, "group=%ld\n", (h_aggregation >> 2 * 8) & 0xffff); seq_printf(m, "system_active_processors=%ld\n", (h_resource >> 0 * 8) & 0xffff); /* pool related entries are apropriate for shared configs */ if (paca[0].lppaca.shared_proc) { h_pic(&pool_idle_time, &pool_procs); seq_printf(m, "pool=%ld\n", (h_aggregation >> 0 * 8) & 0xffff); /* report pool_capacity in percentage */ seq_printf(m, "pool_capacity=%ld\n", ((h_resource >> 2 * 8) & 0xffff) * 100); seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time); seq_printf(m, "pool_num_procs=%ld\n", pool_procs); } seq_printf(m, "unallocated_capacity_weight=%ld\n", (h_resource >> 4 * 8) & 0xFF); seq_printf(m, "capacity_weight=%ld\n", (h_resource >> 5 * 8) & 0xFF); seq_printf(m, "capped=%ld\n", (h_resource >> 6 * 8) & 0x01); seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated); seq_printf(m, "purr=%ld\n", purr); } else { /* non SPLPAR case */ seq_printf(m, "system_active_processors=%d\n", partition_potential_processors); seq_printf(m, "system_potential_processors=%d\n", partition_potential_processors); seq_printf(m, "partition_max_entitled_capacity=%d\n", partition_potential_processors * 100); seq_printf(m, "partition_entitled_capacity=%d\n", partition_active_processors * 100); } seq_printf(m, "partition_active_processors=%d\n", partition_active_processors); seq_printf(m, "partition_potential_processors=%d\n", partition_potential_processors); seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.shared_proc); return 0;}/* * Interface for changing system parameters (variable capacity weight * and entitled capacity). Format of input is "param_name=value"; * anything after value is ignored. Valid parameters at this time are * "partition_entitled_capacity" and "capacity_weight". We use * H_SET_PPP to alter parameters. * * This function should be invoked only on systems with * FW_FEATURE_SPLPAR. */static ssize_t lparcfg_write(struct file *file, const char __user * buf, size_t count, loff_t * off){ char *kbuf; char *tmp; u64 new_entitled, *new_entitled_ptr = &new_entitled; u8 new_weight, *new_weight_ptr = &new_weight; unsigned long current_entitled; /* parameters for h_get_ppp */ unsigned long dummy; unsigned long resource; u8 current_weight; ssize_t retval = -ENOMEM; kbuf = kmalloc(count, GFP_KERNEL); if (!kbuf) goto out; retval = -EFAULT; if (copy_from_user(kbuf, buf, count)) goto out; retval = -EINVAL; kbuf[count - 1] = '\0'; tmp = strchr(kbuf, '='); if (!tmp) goto out; *tmp++ = '\0'; if (!strcmp(kbuf, "partition_entitled_capacity")) { char *endp; *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10); if (endp == tmp) goto out; new_weight_ptr = ¤t_weight; } else if (!strcmp(kbuf, "capacity_weight")) { char *endp; *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10); if (endp == tmp) goto out; new_entitled_ptr = ¤t_entitled; } else goto out; /* Get our current parameters */ retval = h_get_ppp(¤t_entitled, &dummy, &dummy, &resource); if (retval) { retval = -EIO; goto out; } current_weight = (resource >> 5 * 8) & 0xFF; pr_debug("%s: current_entitled = %lu, current_weight = %lu\n", __FUNCTION__, current_entitled, current_weight); pr_debug("%s: new_entitled = %lu, new_weight = %lu\n", __FUNCTION__, *new_entitled_ptr, *new_weight_ptr); retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr, *new_weight_ptr); if (retval == H_Success || retval == H_Constrained) { retval = count; } else if (retval == H_Busy) { retval = -EBUSY; } else if (retval == H_Hardware) { retval = -EIO; } else if (retval == H_Parameter) { retval = -EINVAL; } else { printk(KERN_WARNING "%s: received unknown hv return code %ld", __FUNCTION__, retval); retval = -EIO; }out: kfree(kbuf); return retval;}#endif /* CONFIG_PPC_PSERIES */static int lparcfg_open(struct inode *inode, struct file *file){ return single_open(file, lparcfg_data, NULL);}struct file_operations lparcfg_fops = { .owner = THIS_MODULE, .read = seq_read, .open = lparcfg_open, .release = single_release,};int __init lparcfg_init(void){ struct proc_dir_entry *ent; mode_t mode = S_IRUSR | S_IRGRP | S_IROTH; /* Allow writing if we have FW_FEATURE_SPLPAR */ if (firmware_has_feature(FW_FEATURE_SPLPAR)) { lparcfg_fops.write = lparcfg_write; mode |= S_IWUSR; } ent = create_proc_entry("ppc64/lparcfg", mode, NULL); if (ent) { ent->proc_fops = &lparcfg_fops; ent->data = kmalloc(LPARCFG_BUFF_SIZE, GFP_KERNEL); if (!ent->data) { printk(KERN_ERR "Failed to allocate buffer for lparcfg\n"); remove_proc_entry("lparcfg", ent->parent); return -ENOMEM; } } else { printk(KERN_ERR "Failed to create ppc64/lparcfg\n"); return -EIO; } proc_ppc64_lparcfg = ent; return 0;}void __exit lparcfg_cleanup(void){ if (proc_ppc64_lparcfg) { kfree(proc_ppc64_lparcfg->data); remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent); }}module_init(lparcfg_init);module_exit(lparcfg_cleanup);MODULE_DESCRIPTION("Interface for LPAR configuration data");MODULE_AUTHOR("Dave Engebretsen");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -