diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig Thu Feb 12 14:59:00 2004 +++ b/arch/ppc64/Kconfig Thu Feb 12 14:59:00 2004 @@ -160,7 +160,7 @@ depends on PPC_RTAS config LPARCFG - bool "LPAR Configuration Data" + tristate "LPAR Configuration Data" help Provide system capacity information via human readable = pairs through a /proc/ppc64/lparcfg interface. diff -Nru a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c --- a/arch/ppc64/kernel/lparcfg.c Thu Feb 12 14:58:59 2004 +++ b/arch/ppc64/kernel/lparcfg.c Thu Feb 12 14:58:59 2004 @@ -29,9 +29,34 @@ #include #include -#define MODULE_VERSION "1.0" +#define MODULE_VERSION "1.1" #define MODULE_NAME "lparcfg" +/* move splpar_characteristics_token to a header */ +#define SPLPAR_CHARACTERISTICS_TOKEN 20 +#define SPLPAR_MAXLENGTH 1026*(sizeof(char)) + +/* +#define LPARCFG_DEBUG +*/ + +/* find a better place for this function... */ +void log_plpar_hcall_return(unsigned long rc,char * tag) +{ + if (rc==0) /* success, return */ + return; +/* todo/fixme - check for null tag ? */ + if (rc == H_Hardware) + printk("plpar-hcall (%s) failed with hardware fault\n",tag); + else if (rc == H_Function) + printk("plpar-hcall (%s) failed; function not allowed\n",tag); + else if (rc == H_Authority) + printk("plpar-hcall (%s) failed; not authorized to this function\n",tag); + else + printk("plpar-hcall (%s) failed with unexpected rc(0x%lx)\n",tag,rc); +} + + static struct proc_dir_entry *proc_ppc64_lparcfg; #define LPARCFG_BUFF_SIZE 4096 @@ -217,7 +242,7 @@ * XXXX - reserved (0) * XXXX - Group Number * XXXX - Pool Number. - * R7 (PPOONNMMLLKKJJII) + * R7 (IIJJKKLLMMNNOOPP). * XX - reserved. (0) * XX - bit 0-6 reserved (0). bit 7 is Capped indicator. * XX - variable processor Capacity Weight @@ -229,72 +254,131 @@ { unsigned long rc; rc = plpar_hcall_4out(H_GET_PPP,0,0,0,0,entitled,unallocated,aggregation,resource); + + log_plpar_hcall_return(rc,"H_GET_PPP"); + + return 0; +} + +unsigned int h_pic(unsigned long *pool_idle_time,unsigned long *num_procs) +{ + unsigned long rc; + unsigned long dummy; + rc = plpar_hcall(H_PIC,0,0,0,0,pool_idle_time,num_procs,&dummy); + + log_plpar_hcall_return(rc,"H_PIC"); + + return 0; +} + +/* prototyping h_purr functionality. this may need to be moved into decrementer code. */ +unsigned int h_purr(unsigned long *purr) +{ + unsigned long rc; + + unsigned long dummy; + rc = plpar_hcall(H_PURR, 0, 0, 0, 0,purr, &dummy, &dummy); + + log_plpar_hcall_return(rc,"H_PURR"); return 0; } /* - * get_splpar_potential_characteristics(). - * Retrieve the potential_processors and max_entitled_capacity values - * through the get-system-parameter rtas call. + * parse_system_parameter_string() + * Retrieve the get-system-parameter strings through the get-system-parameter rtas call. + * Replace keyword strings as desired to match interfaces, and add the contents to 'buf'. */ -#define SPLPAR_CHARACTERISTICS_TOKEN 20 -#define SPLPAR_MAXLENGTH 1026*(sizeof(char)) -unsigned int get_splpar_potential_characteristics(void) +unsigned long parse_system_parameter_string(unsigned long n, char * buf) { - /* return 0 for now. Underlying rtas functionality is not yet complete. 12/01/2003*/ - return 0; -#if 0 long call_status; unsigned long ret[2]; - char * buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); - - printk("token for ibm,get-system-parameter (0x%x)\n",rtas_token("ibm,get-system-parameter")); + char * local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); - call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1, - NULL, - SPLPAR_CHARACTERISTICS_TOKEN, - &buffer, - SPLPAR_MAXLENGTH, - (void *)&ret); + { + spin_lock(&rtas_data_buf_lock); + memset(rtas_data_buf, 0, SPLPAR_MAXLENGTH); + call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1, + NULL, + SPLPAR_CHARACTERISTICS_TOKEN, + __pa(rtas_data_buf), + SPLPAR_MAXLENGTH, + (void *)&ret); + memcpy(local_buffer,rtas_data_buf, SPLPAR_MAXLENGTH); + spin_unlock(&rtas_data_buf_lock); + } if (call_status!=0) { - printk("Error calling get-system-parameter (0x%lx)\n",call_status); - kfree(buffer); - return -1; + printk("%s %s Error calling get-system-parameter (0x%lx)\n",__FILE__,__FUNCTION__,call_status); } else { - printk("get-system-parameter (%s)\n",buffer); - kfree(buffer); - /* TODO: Add code here to parse out value for system_potential_processors and partition_max_entitled_capacity */ - return 1; - } + int splpar_strlen; + int idx,w_idx; + w_idx=0; + idx=0; +#ifdef LPARCFG_DEBUG + printk("success calling get-system-parameter \n"); #endif + /* first two bytes indicate the total string length, + including the length field itself. */ + splpar_strlen=local_buffer[idx]*0x100 + local_buffer[idx+1]; + idx+=2; + + char * workbuffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); + memset(workbuffer, 0, SPLPAR_MAXLENGTH); + + while ((*local_buffer) && (idx LPARCFG_BUFF_SIZE)) { return -EFAULT; } memset(buf, 0, size); - root = find_path_device("/"); - if (root) { - model = get_property(root, "model", NULL); - system_id = get_property(root, "system-id", NULL); - lp_index_ptr = (unsigned int *)get_property(root, "ibm,partition-no", NULL); - if(lp_index_ptr) lp_index = *lp_index_ptr; + 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; } n = snprintf(buf, LPARCFG_BUFF_SIZE - n, @@ -307,85 +391,110 @@ "partition_id=%d\n", (int)lp_index); rtas_node = find_path_device("/rtas"); - ip = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); - if (ip == NULL) { + lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); + + if (lrdrp == NULL) { system_active_processors = systemcfg->processorCount; } else { - system_active_processors = *(ip + 4); - } + system_active_processors = *(lrdrp + 4); + } + + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + unsigned long h_entitled,h_unallocated,h_aggregation,h_resource; - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { h_get_ppp(&h_entitled,&h_unallocated,&h_aggregation,&h_resource); -#ifdef DEBUG + +#ifdef LPARCFG_DEBUG n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R4=0x%lx\n", h_entitled); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R5=0x%lx\n", h_unallocated); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R6=0x%lx\n", h_aggregation); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R7=0x%lx\n", h_resource); -#endif /* DEBUG */ - } +#endif /* LPARCFG_DEBUG */ + + /* the call to parse_system_parameter_string will handle + * the ibm,get-system-parameter contents. + */ + n = parse_system_parameter_string(n,buf); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_entitled_capacity=%ld\n", + h_entitled); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "pool=%ld\n", + (h_aggregation >> 0*8) & 0xffff); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "group=%ld\n", + (h_aggregation >> 2*8) & 0xffff); - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { - system_potential_processors = get_splpar_potential_characteristics(); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_active_processors=%ld\n", (h_resource >> 2*8) & 0xffff); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "system_potential_processors=%d\n", - system_potential_processors); - } else { - system_potential_processors = system_active_processors; + "pool_capacity=%ld\n", + (h_resource >> 3*8) & 0xffff); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "system_active_processors=%d\n", - system_active_processors); + "capacity_weight=%ld\n", + (h_resource>>5*8) & 0xFF); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "system_potential_processors=%d\n", - system_potential_processors); - } + "capped=%ld\n", + (h_resource >> 6*8) & 0x40); - processors = systemcfg->processorCount; - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "partition_active_processors=%d\n", processors); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "partition_potential_processors=%d\n", - system_active_processors); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "unallocated_variable_weight=%ld\n", + (h_resource>>7*8) & 0xFF); - /* max_entitled_capacity will come out of get_splpar_potential_characteristics() when that function is complete */ - max_entitled_capacity = system_active_processors * 100; - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "partition_entitled_capacity=%ld\n", h_entitled); - } else { + "unallocated_capacity=%ld\n", + h_unallocated); + + unsigned long pool_idle_time,pool_procs; + h_pic(&pool_idle_time,&pool_procs); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "partition_entitled_capacity=%d\n", system_active_processors*100); - } + "pool_idle_time=%ld\n", + pool_idle_time); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "partition_max_entitled_capacity=%d\n", - max_entitled_capacity); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "pool_num_procs=%ld\n", + pool_procs); - shared = 0; - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "shared_processor_mode=%d\n", shared); + unsigned long purr; + h_purr(&purr); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "purr=%ld\n", + purr); - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + } else /* non SPLPAR case */ { n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "pool=%ld\n", (h_aggregation >> 0*8)&0xffff); + "system_active_processors=%d\n", + system_active_processors); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "pool_capacity=%ld\n", (h_resource >> 3*8) &0xffff); + "system_potential_processors=%d\n", + system_active_processors); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "group=%ld\n", (h_aggregation >> 2*8)&0xffff); + "partition_entitled_capacity=%d\n", + system_active_processors*100); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "capped=%ld\n", (h_resource >> 6*8)&0x40); + "partition_max_entitled_capacity=%d\n", + 100*system_active_processors); + /* shared is always zero in non-splpar config */ n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF); + "shared_processor_mode=%d\n", 0); } return 0; } diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c --- a/arch/ppc64/kernel/ppc_ksyms.c Thu Feb 12 14:58:59 2004 +++ b/arch/ppc64/kernel/ppc_ksyms.c Thu Feb 12 14:58:59 2004 @@ -226,3 +226,8 @@ EXPORT_SYMBOL(tb_ticks_per_usec); EXPORT_SYMBOL(paca); EXPORT_SYMBOL(proc_ppc64); +EXPORT_SYMBOL(plpar_hcall_4out); +EXPORT_SYMBOL(plpar_hcall); +EXPORT_SYMBOL(cur_cpu_spec); +EXPORT_SYMBOL(systemcfg); + diff -Nru a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h --- a/include/asm-ppc64/hvcall.h Thu Feb 12 14:58:59 2004 +++ b/include/asm-ppc64/hvcall.h Thu Feb 12 14:58:59 2004 @@ -37,7 +37,6 @@ #define H_PP2 (1UL<<(63-63)) - /* pSeries hypervisor opcodes */ #define H_REMOVE 0x04 #define H_ENTER 0x08 @@ -76,7 +75,7 @@ #define H_PROD 0xE8 #define H_GET_PPP 0xEC #define H_SET_PPP 0xF0 -#define H_SET_PURR 0xF4 +#define H_PURR 0xF4 #define H_PIC 0xF8 #define H_REG_CRQ 0xFC #define H_FREE_CRQ 0x100 @@ -142,5 +141,6 @@ unsigned long *out2, unsigned long *out3, unsigned long *out4); + #endif /* _PPC64_HVCALL_H */