📄 lparcfg.c
字号:
}static int pseries_lparcfg_data(struct seq_file *m, void *v){ int partition_potential_processors; int partition_active_processors; struct device_node *rtas_node; const int *lrdrp = NULL; rtas_node = of_find_node_by_path("/rtas"); if (rtas_node) lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL); if (lrdrp == NULL) { partition_potential_processors = vdso_data->processorCount; } else { partition_potential_processors = *(lrdrp + 4); } of_node_put(rtas_node); 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 (lppaca[0].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", lppaca[0].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; if (!firmware_has_feature(FW_FEATURE_SPLPAR) || firmware_has_feature(FW_FEATURE_ISERIES)) return -EINVAL; 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 = %u\n", __FUNCTION__, current_entitled, current_weight); pr_debug("%s: new_entitled = %lu, new_weight = %u\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;}#else /* CONFIG_PPC_PSERIES */static int pseries_lparcfg_data(struct seq_file *m, void *v){ return 0;}static ssize_t lparcfg_write(struct file *file, const char __user * buf, size_t count, loff_t * off){ return -EINVAL;}#endif /* CONFIG_PPC_PSERIES */static int lparcfg_data(struct seq_file *m, void *v){ struct device_node *rootdn; const char *model = ""; const char *system_id = ""; const char *tmp; const unsigned int *lp_index_ptr; unsigned int lp_index = 0; seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); rootdn = of_find_node_by_path("/"); if (rootdn) { tmp = of_get_property(rootdn, "model", NULL); if (tmp) { model = tmp; /* Skip "IBM," - see platforms/iseries/dt.c */ if (firmware_has_feature(FW_FEATURE_ISERIES)) model += 4; } tmp = of_get_property(rootdn, "system-id", NULL); if (tmp) { system_id = tmp; /* Skip "IBM," - see platforms/iseries/dt.c */ if (firmware_has_feature(FW_FEATURE_ISERIES)) system_id += 4; } lp_index_ptr = of_get_property(rootdn, "ibm,partition-no", NULL); if (lp_index_ptr) lp_index = *lp_index_ptr; of_node_put(rootdn); } 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); if (firmware_has_feature(FW_FEATURE_ISERIES)) return iseries_lparcfg_data(m, v); return pseries_lparcfg_data(m, v);}static int lparcfg_open(struct inode *inode, struct file *file){ return single_open(file, lparcfg_data, NULL);}const struct file_operations lparcfg_fops = { .owner = THIS_MODULE, .read = seq_read, .write = lparcfg_write, .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) && !firmware_has_feature(FW_FEATURE_ISERIES)) 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 + -