diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 14:08:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 14:08:17 -0400 |
commit | 5047887caf1806f31652210df27fb62a7c43f27d (patch) | |
tree | 4098ead40c1aa7b904167f67cff87a247cfa0b6c /arch/powerpc/kernel/lparcfg.c | |
parent | 996abf053eec4d67136be8b911bbaaf989cfb99c (diff) | |
parent | 973b7d83ebeb1e34b8bee69208916e5f0e2353c3 (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (34 commits)
powerpc: Wireup new syscalls
Move update_mmu_cache() declaration from tlbflush.h to pgtable.h
powerpc/pseries: Remove kmalloc call in handling writes to lparcfg
powerpc/pseries: Update arch vector to indicate support for CMO
ibmvfc: Add support for collaborative memory overcommit
ibmvscsi: driver enablement for CMO
ibmveth: enable driver for CMO
ibmveth: Automatically enable larger rx buffer pools for larger mtu
powerpc/pseries: Verify CMO memory entitlement updates with virtual I/O
powerpc/pseries: vio bus support for CMO
powerpc/pseries: iommu enablement for CMO
powerpc/pseries: Add CMO paging statistics
powerpc/pseries: Add collaborative memory manager
powerpc/pseries: Utilities to set firmware page state
powerpc/pseries: Enable CMO feature during platform setup
powerpc/pseries: Split retrieval of processor entitlement data into a helper routine
powerpc/pseries: Add memory entitlement capabilities to /proc/ppc64/lparcfg
powerpc/pseries: Split processor entitlement retrieval and gathering to helper routines
powerpc/pseries: Remove extraneous error reporting for hcall failures in lparcfg
powerpc: Fix compile error with binutils 2.15
...
Fixed up conflict in arch/powerpc/platforms/52xx/Kconfig manually.
Diffstat (limited to 'arch/powerpc/kernel/lparcfg.c')
-rw-r--r-- | arch/powerpc/kernel/lparcfg.c | 386 |
1 files changed, 260 insertions, 126 deletions
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 827a5726a035..9f856a0c3e38 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -34,8 +34,9 @@ | |||
34 | #include <asm/time.h> | 34 | #include <asm/time.h> |
35 | #include <asm/prom.h> | 35 | #include <asm/prom.h> |
36 | #include <asm/vdso_datapage.h> | 36 | #include <asm/vdso_datapage.h> |
37 | #include <asm/vio.h> | ||
37 | 38 | ||
38 | #define MODULE_VERS "1.7" | 39 | #define MODULE_VERS "1.8" |
39 | #define MODULE_NAME "lparcfg" | 40 | #define MODULE_NAME "lparcfg" |
40 | 41 | ||
41 | /* #define LPARCFG_DEBUG */ | 42 | /* #define LPARCFG_DEBUG */ |
@@ -129,32 +130,46 @@ static int iseries_lparcfg_data(struct seq_file *m, void *v) | |||
129 | /* | 130 | /* |
130 | * Methods used to fetch LPAR data when running on a pSeries platform. | 131 | * Methods used to fetch LPAR data when running on a pSeries platform. |
131 | */ | 132 | */ |
132 | static void log_plpar_hcall_return(unsigned long rc, char *tag) | 133 | /** |
134 | * h_get_mpp | ||
135 | * H_GET_MPP hcall returns info in 7 parms | ||
136 | */ | ||
137 | int h_get_mpp(struct hvcall_mpp_data *mpp_data) | ||
133 | { | 138 | { |
134 | switch(rc) { | 139 | int rc; |
135 | case 0: | 140 | unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; |
136 | return; | 141 | |
137 | case H_HARDWARE: | 142 | rc = plpar_hcall9(H_GET_MPP, retbuf); |
138 | printk(KERN_INFO "plpar-hcall (%s) " | 143 | |
139 | "Hardware fault\n", tag); | 144 | mpp_data->entitled_mem = retbuf[0]; |
140 | return; | 145 | mpp_data->mapped_mem = retbuf[1]; |
141 | case H_FUNCTION: | 146 | |
142 | printk(KERN_INFO "plpar-hcall (%s) " | 147 | mpp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff; |
143 | "Function not allowed\n", tag); | 148 | mpp_data->pool_num = retbuf[2] & 0xffff; |
144 | return; | 149 | |
145 | case H_AUTHORITY: | 150 | mpp_data->mem_weight = (retbuf[3] >> 7 * 8) & 0xff; |
146 | printk(KERN_INFO "plpar-hcall (%s) " | 151 | mpp_data->unallocated_mem_weight = (retbuf[3] >> 6 * 8) & 0xff; |
147 | "Not authorized to this function\n", tag); | 152 | mpp_data->unallocated_entitlement = retbuf[3] & 0xffffffffffff; |
148 | return; | 153 | |
149 | case H_PARAMETER: | 154 | mpp_data->pool_size = retbuf[4]; |
150 | printk(KERN_INFO "plpar-hcall (%s) " | 155 | mpp_data->loan_request = retbuf[5]; |
151 | "Bad parameter(s)\n",tag); | 156 | mpp_data->backing_mem = retbuf[6]; |
152 | return; | 157 | |
153 | default: | 158 | return rc; |
154 | printk(KERN_INFO "plpar-hcall (%s) " | ||
155 | "Unexpected rc(0x%lx)\n", tag, rc); | ||
156 | } | ||
157 | } | 159 | } |
160 | EXPORT_SYMBOL(h_get_mpp); | ||
161 | |||
162 | struct hvcall_ppp_data { | ||
163 | u64 entitlement; | ||
164 | u64 unallocated_entitlement; | ||
165 | u16 group_num; | ||
166 | u16 pool_num; | ||
167 | u8 capped; | ||
168 | u8 weight; | ||
169 | u8 unallocated_weight; | ||
170 | u16 active_procs_in_pool; | ||
171 | u16 active_system_procs; | ||
172 | }; | ||
158 | 173 | ||
159 | /* | 174 | /* |
160 | * H_GET_PPP hcall returns info in 4 parms. | 175 | * H_GET_PPP hcall returns info in 4 parms. |
@@ -176,27 +191,30 @@ static void log_plpar_hcall_return(unsigned long rc, char *tag) | |||
176 | * XXXX - Active processors in Physical Processor Pool. | 191 | * XXXX - Active processors in Physical Processor Pool. |
177 | * XXXX - Processors active on platform. | 192 | * XXXX - Processors active on platform. |
178 | */ | 193 | */ |
179 | static unsigned int h_get_ppp(unsigned long *entitled, | 194 | static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data) |
180 | unsigned long *unallocated, | ||
181 | unsigned long *aggregation, | ||
182 | unsigned long *resource) | ||
183 | { | 195 | { |
184 | unsigned long rc; | 196 | unsigned long rc; |
185 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | 197 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
186 | 198 | ||
187 | rc = plpar_hcall(H_GET_PPP, retbuf); | 199 | rc = plpar_hcall(H_GET_PPP, retbuf); |
188 | 200 | ||
189 | *entitled = retbuf[0]; | 201 | ppp_data->entitlement = retbuf[0]; |
190 | *unallocated = retbuf[1]; | 202 | ppp_data->unallocated_entitlement = retbuf[1]; |
191 | *aggregation = retbuf[2]; | 203 | |
192 | *resource = retbuf[3]; | 204 | ppp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff; |
205 | ppp_data->pool_num = retbuf[2] & 0xffff; | ||
193 | 206 | ||
194 | log_plpar_hcall_return(rc, "H_GET_PPP"); | 207 | ppp_data->capped = (retbuf[3] >> 6 * 8) & 0x01; |
208 | ppp_data->weight = (retbuf[3] >> 5 * 8) & 0xff; | ||
209 | ppp_data->unallocated_weight = (retbuf[3] >> 4 * 8) & 0xff; | ||
210 | ppp_data->active_procs_in_pool = (retbuf[3] >> 2 * 8) & 0xffff; | ||
211 | ppp_data->active_system_procs = retbuf[3] & 0xffff; | ||
195 | 212 | ||
196 | return rc; | 213 | return rc; |
197 | } | 214 | } |
198 | 215 | ||
199 | static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs) | 216 | static unsigned h_pic(unsigned long *pool_idle_time, |
217 | unsigned long *num_procs) | ||
200 | { | 218 | { |
201 | unsigned long rc; | 219 | unsigned long rc; |
202 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | 220 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
@@ -206,8 +224,87 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs) | |||
206 | *pool_idle_time = retbuf[0]; | 224 | *pool_idle_time = retbuf[0]; |
207 | *num_procs = retbuf[1]; | 225 | *num_procs = retbuf[1]; |
208 | 226 | ||
209 | if (rc != H_AUTHORITY) | 227 | return rc; |
210 | log_plpar_hcall_return(rc, "H_PIC"); | 228 | } |
229 | |||
230 | /* | ||
231 | * parse_ppp_data | ||
232 | * Parse out the data returned from h_get_ppp and h_pic | ||
233 | */ | ||
234 | static void parse_ppp_data(struct seq_file *m) | ||
235 | { | ||
236 | struct hvcall_ppp_data ppp_data; | ||
237 | int rc; | ||
238 | |||
239 | rc = h_get_ppp(&ppp_data); | ||
240 | if (rc) | ||
241 | return; | ||
242 | |||
243 | seq_printf(m, "partition_entitled_capacity=%ld\n", | ||
244 | ppp_data.entitlement); | ||
245 | seq_printf(m, "group=%d\n", ppp_data.group_num); | ||
246 | seq_printf(m, "system_active_processors=%d\n", | ||
247 | ppp_data.active_system_procs); | ||
248 | |||
249 | /* pool related entries are apropriate for shared configs */ | ||
250 | if (lppaca[0].shared_proc) { | ||
251 | unsigned long pool_idle_time, pool_procs; | ||
252 | |||
253 | seq_printf(m, "pool=%d\n", ppp_data.pool_num); | ||
254 | |||
255 | /* report pool_capacity in percentage */ | ||
256 | seq_printf(m, "pool_capacity=%d\n", | ||
257 | ppp_data.active_procs_in_pool * 100); | ||
258 | |||
259 | h_pic(&pool_idle_time, &pool_procs); | ||
260 | seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time); | ||
261 | seq_printf(m, "pool_num_procs=%ld\n", pool_procs); | ||
262 | } | ||
263 | |||
264 | seq_printf(m, "unallocated_capacity_weight=%d\n", | ||
265 | ppp_data.unallocated_weight); | ||
266 | seq_printf(m, "capacity_weight=%d\n", ppp_data.weight); | ||
267 | seq_printf(m, "capped=%d\n", ppp_data.capped); | ||
268 | seq_printf(m, "unallocated_capacity=%ld\n", | ||
269 | ppp_data.unallocated_entitlement); | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * parse_mpp_data | ||
274 | * Parse out data returned from h_get_mpp | ||
275 | */ | ||
276 | static void parse_mpp_data(struct seq_file *m) | ||
277 | { | ||
278 | struct hvcall_mpp_data mpp_data; | ||
279 | int rc; | ||
280 | |||
281 | rc = h_get_mpp(&mpp_data); | ||
282 | if (rc) | ||
283 | return; | ||
284 | |||
285 | seq_printf(m, "entitled_memory=%ld\n", mpp_data.entitled_mem); | ||
286 | |||
287 | if (mpp_data.mapped_mem != -1) | ||
288 | seq_printf(m, "mapped_entitled_memory=%ld\n", | ||
289 | mpp_data.mapped_mem); | ||
290 | |||
291 | seq_printf(m, "entitled_memory_group_number=%d\n", mpp_data.group_num); | ||
292 | seq_printf(m, "entitled_memory_pool_number=%d\n", mpp_data.pool_num); | ||
293 | |||
294 | seq_printf(m, "entitled_memory_weight=%d\n", mpp_data.mem_weight); | ||
295 | seq_printf(m, "unallocated_entitled_memory_weight=%d\n", | ||
296 | mpp_data.unallocated_mem_weight); | ||
297 | seq_printf(m, "unallocated_io_mapping_entitlement=%ld\n", | ||
298 | mpp_data.unallocated_entitlement); | ||
299 | |||
300 | if (mpp_data.pool_size != -1) | ||
301 | seq_printf(m, "entitled_memory_pool_size=%ld bytes\n", | ||
302 | mpp_data.pool_size); | ||
303 | |||
304 | seq_printf(m, "entitled_memory_loan_request=%ld\n", | ||
305 | mpp_data.loan_request); | ||
306 | |||
307 | seq_printf(m, "backing_memory=%ld bytes\n", mpp_data.backing_mem); | ||
211 | } | 308 | } |
212 | 309 | ||
213 | #define SPLPAR_CHARACTERISTICS_TOKEN 20 | 310 | #define SPLPAR_CHARACTERISTICS_TOKEN 20 |
@@ -313,6 +410,25 @@ static int lparcfg_count_active_processors(void) | |||
313 | return count; | 410 | return count; |
314 | } | 411 | } |
315 | 412 | ||
413 | static void pseries_cmo_data(struct seq_file *m) | ||
414 | { | ||
415 | int cpu; | ||
416 | unsigned long cmo_faults = 0; | ||
417 | unsigned long cmo_fault_time = 0; | ||
418 | |||
419 | if (!firmware_has_feature(FW_FEATURE_CMO)) | ||
420 | return; | ||
421 | |||
422 | for_each_possible_cpu(cpu) { | ||
423 | cmo_faults += lppaca[cpu].cmo_faults; | ||
424 | cmo_fault_time += lppaca[cpu].cmo_fault_time; | ||
425 | } | ||
426 | |||
427 | seq_printf(m, "cmo_faults=%lu\n", cmo_faults); | ||
428 | seq_printf(m, "cmo_fault_time_usec=%lu\n", | ||
429 | cmo_fault_time / tb_ticks_per_usec); | ||
430 | } | ||
431 | |||
316 | static int pseries_lparcfg_data(struct seq_file *m, void *v) | 432 | static int pseries_lparcfg_data(struct seq_file *m, void *v) |
317 | { | 433 | { |
318 | int partition_potential_processors; | 434 | int partition_potential_processors; |
@@ -334,60 +450,13 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
334 | partition_active_processors = lparcfg_count_active_processors(); | 450 | partition_active_processors = lparcfg_count_active_processors(); |
335 | 451 | ||
336 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | 452 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { |
337 | unsigned long h_entitled, h_unallocated; | ||
338 | unsigned long h_aggregation, h_resource; | ||
339 | unsigned long pool_idle_time, pool_procs; | ||
340 | unsigned long purr; | ||
341 | |||
342 | h_get_ppp(&h_entitled, &h_unallocated, &h_aggregation, | ||
343 | &h_resource); | ||
344 | |||
345 | seq_printf(m, "R4=0x%lx\n", h_entitled); | ||
346 | seq_printf(m, "R5=0x%lx\n", h_unallocated); | ||
347 | seq_printf(m, "R6=0x%lx\n", h_aggregation); | ||
348 | seq_printf(m, "R7=0x%lx\n", h_resource); | ||
349 | |||
350 | purr = get_purr(); | ||
351 | |||
352 | /* this call handles the ibm,get-system-parameter contents */ | 453 | /* this call handles the ibm,get-system-parameter contents */ |
353 | parse_system_parameter_string(m); | 454 | parse_system_parameter_string(m); |
455 | parse_ppp_data(m); | ||
456 | parse_mpp_data(m); | ||
457 | pseries_cmo_data(m); | ||
354 | 458 | ||
355 | seq_printf(m, "partition_entitled_capacity=%ld\n", h_entitled); | 459 | seq_printf(m, "purr=%ld\n", get_purr()); |
356 | |||
357 | seq_printf(m, "group=%ld\n", (h_aggregation >> 2 * 8) & 0xffff); | ||
358 | |||
359 | seq_printf(m, "system_active_processors=%ld\n", | ||
360 | (h_resource >> 0 * 8) & 0xffff); | ||
361 | |||
362 | /* pool related entries are apropriate for shared configs */ | ||
363 | if (lppaca[0].shared_proc) { | ||
364 | |||
365 | h_pic(&pool_idle_time, &pool_procs); | ||
366 | |||
367 | seq_printf(m, "pool=%ld\n", | ||
368 | (h_aggregation >> 0 * 8) & 0xffff); | ||
369 | |||
370 | /* report pool_capacity in percentage */ | ||
371 | seq_printf(m, "pool_capacity=%ld\n", | ||
372 | ((h_resource >> 2 * 8) & 0xffff) * 100); | ||
373 | |||
374 | seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time); | ||
375 | |||
376 | seq_printf(m, "pool_num_procs=%ld\n", pool_procs); | ||
377 | } | ||
378 | |||
379 | seq_printf(m, "unallocated_capacity_weight=%ld\n", | ||
380 | (h_resource >> 4 * 8) & 0xFF); | ||
381 | |||
382 | seq_printf(m, "capacity_weight=%ld\n", | ||
383 | (h_resource >> 5 * 8) & 0xFF); | ||
384 | |||
385 | seq_printf(m, "capped=%ld\n", (h_resource >> 6 * 8) & 0x01); | ||
386 | |||
387 | seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated); | ||
388 | |||
389 | seq_printf(m, "purr=%ld\n", purr); | ||
390 | |||
391 | } else { /* non SPLPAR case */ | 460 | } else { /* non SPLPAR case */ |
392 | 461 | ||
393 | seq_printf(m, "system_active_processors=%d\n", | 462 | seq_printf(m, "system_active_processors=%d\n", |
@@ -414,6 +483,83 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
414 | return 0; | 483 | return 0; |
415 | } | 484 | } |
416 | 485 | ||
486 | static ssize_t update_ppp(u64 *entitlement, u8 *weight) | ||
487 | { | ||
488 | struct hvcall_ppp_data ppp_data; | ||
489 | u8 new_weight; | ||
490 | u64 new_entitled; | ||
491 | ssize_t retval; | ||
492 | |||
493 | /* Get our current parameters */ | ||
494 | retval = h_get_ppp(&ppp_data); | ||
495 | if (retval) | ||
496 | return retval; | ||
497 | |||
498 | if (entitlement) { | ||
499 | new_weight = ppp_data.weight; | ||
500 | new_entitled = *entitlement; | ||
501 | } else if (weight) { | ||
502 | new_weight = *weight; | ||
503 | new_entitled = ppp_data.entitlement; | ||
504 | } else | ||
505 | return -EINVAL; | ||
506 | |||
507 | pr_debug("%s: current_entitled = %lu, current_weight = %u\n", | ||
508 | __FUNCTION__, ppp_data.entitlement, ppp_data.weight); | ||
509 | |||
510 | pr_debug("%s: new_entitled = %lu, new_weight = %u\n", | ||
511 | __FUNCTION__, new_entitled, new_weight); | ||
512 | |||
513 | retval = plpar_hcall_norets(H_SET_PPP, new_entitled, new_weight); | ||
514 | return retval; | ||
515 | } | ||
516 | |||
517 | /** | ||
518 | * update_mpp | ||
519 | * | ||
520 | * Update the memory entitlement and weight for the partition. Caller must | ||
521 | * specify either a new entitlement or weight, not both, to be updated | ||
522 | * since the h_set_mpp call takes both entitlement and weight as parameters. | ||
523 | */ | ||
524 | static ssize_t update_mpp(u64 *entitlement, u8 *weight) | ||
525 | { | ||
526 | struct hvcall_mpp_data mpp_data; | ||
527 | u64 new_entitled; | ||
528 | u8 new_weight; | ||
529 | ssize_t rc; | ||
530 | |||
531 | if (entitlement) { | ||
532 | /* Check with vio to ensure the new memory entitlement | ||
533 | * can be handled. | ||
534 | */ | ||
535 | rc = vio_cmo_entitlement_update(*entitlement); | ||
536 | if (rc) | ||
537 | return rc; | ||
538 | } | ||
539 | |||
540 | rc = h_get_mpp(&mpp_data); | ||
541 | if (rc) | ||
542 | return rc; | ||
543 | |||
544 | if (entitlement) { | ||
545 | new_weight = mpp_data.mem_weight; | ||
546 | new_entitled = *entitlement; | ||
547 | } else if (weight) { | ||
548 | new_weight = *weight; | ||
549 | new_entitled = mpp_data.entitled_mem; | ||
550 | } else | ||
551 | return -EINVAL; | ||
552 | |||
553 | pr_debug("%s: current_entitled = %lu, current_weight = %u\n", | ||
554 | __FUNCTION__, mpp_data.entitled_mem, mpp_data.mem_weight); | ||
555 | |||
556 | pr_debug("%s: new_entitled = %lu, new_weight = %u\n", | ||
557 | __FUNCTION__, new_entitled, new_weight); | ||
558 | |||
559 | rc = plpar_hcall_norets(H_SET_MPP, new_entitled, new_weight); | ||
560 | return rc; | ||
561 | } | ||
562 | |||
417 | /* | 563 | /* |
418 | * Interface for changing system parameters (variable capacity weight | 564 | * Interface for changing system parameters (variable capacity weight |
419 | * and entitled capacity). Format of input is "param_name=value"; | 565 | * and entitled capacity). Format of input is "param_name=value"; |
@@ -427,35 +573,27 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
427 | static ssize_t lparcfg_write(struct file *file, const char __user * buf, | 573 | static ssize_t lparcfg_write(struct file *file, const char __user * buf, |
428 | size_t count, loff_t * off) | 574 | size_t count, loff_t * off) |
429 | { | 575 | { |
430 | char *kbuf; | 576 | int kbuf_sz = 64; |
577 | char kbuf[kbuf_sz]; | ||
431 | char *tmp; | 578 | char *tmp; |
432 | u64 new_entitled, *new_entitled_ptr = &new_entitled; | 579 | u64 new_entitled, *new_entitled_ptr = &new_entitled; |
433 | u8 new_weight, *new_weight_ptr = &new_weight; | 580 | u8 new_weight, *new_weight_ptr = &new_weight; |
434 | 581 | ssize_t retval; | |
435 | unsigned long current_entitled; /* parameters for h_get_ppp */ | ||
436 | unsigned long dummy; | ||
437 | unsigned long resource; | ||
438 | u8 current_weight; | ||
439 | |||
440 | ssize_t retval = -ENOMEM; | ||
441 | 582 | ||
442 | if (!firmware_has_feature(FW_FEATURE_SPLPAR) || | 583 | if (!firmware_has_feature(FW_FEATURE_SPLPAR) || |
443 | firmware_has_feature(FW_FEATURE_ISERIES)) | 584 | firmware_has_feature(FW_FEATURE_ISERIES)) |
444 | return -EINVAL; | 585 | return -EINVAL; |
445 | 586 | ||
446 | kbuf = kmalloc(count, GFP_KERNEL); | 587 | if (count > kbuf_sz) |
447 | if (!kbuf) | 588 | return -EINVAL; |
448 | goto out; | ||
449 | 589 | ||
450 | retval = -EFAULT; | ||
451 | if (copy_from_user(kbuf, buf, count)) | 590 | if (copy_from_user(kbuf, buf, count)) |
452 | goto out; | 591 | return -EFAULT; |
453 | 592 | ||
454 | retval = -EINVAL; | ||
455 | kbuf[count - 1] = '\0'; | 593 | kbuf[count - 1] = '\0'; |
456 | tmp = strchr(kbuf, '='); | 594 | tmp = strchr(kbuf, '='); |
457 | if (!tmp) | 595 | if (!tmp) |
458 | goto out; | 596 | return -EINVAL; |
459 | 597 | ||
460 | *tmp++ = '\0'; | 598 | *tmp++ = '\0'; |
461 | 599 | ||
@@ -463,34 +601,32 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, | |||
463 | char *endp; | 601 | char *endp; |
464 | *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10); | 602 | *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10); |
465 | if (endp == tmp) | 603 | if (endp == tmp) |
466 | goto out; | 604 | return -EINVAL; |
467 | new_weight_ptr = ¤t_weight; | 605 | |
606 | retval = update_ppp(new_entitled_ptr, NULL); | ||
468 | } else if (!strcmp(kbuf, "capacity_weight")) { | 607 | } else if (!strcmp(kbuf, "capacity_weight")) { |
469 | char *endp; | 608 | char *endp; |
470 | *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10); | 609 | *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10); |
471 | if (endp == tmp) | 610 | if (endp == tmp) |
472 | goto out; | 611 | return -EINVAL; |
473 | new_entitled_ptr = ¤t_entitled; | ||
474 | } else | ||
475 | goto out; | ||
476 | |||
477 | /* Get our current parameters */ | ||
478 | retval = h_get_ppp(¤t_entitled, &dummy, &dummy, &resource); | ||
479 | if (retval) { | ||
480 | retval = -EIO; | ||
481 | goto out; | ||
482 | } | ||
483 | |||
484 | current_weight = (resource >> 5 * 8) & 0xFF; | ||
485 | 612 | ||
486 | pr_debug("%s: current_entitled = %lu, current_weight = %u\n", | 613 | retval = update_ppp(NULL, new_weight_ptr); |
487 | __func__, current_entitled, current_weight); | 614 | } else if (!strcmp(kbuf, "entitled_memory")) { |
615 | char *endp; | ||
616 | *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10); | ||
617 | if (endp == tmp) | ||
618 | return -EINVAL; | ||
488 | 619 | ||
489 | pr_debug("%s: new_entitled = %lu, new_weight = %u\n", | 620 | retval = update_mpp(new_entitled_ptr, NULL); |
490 | __func__, *new_entitled_ptr, *new_weight_ptr); | 621 | } else if (!strcmp(kbuf, "entitled_memory_weight")) { |
622 | char *endp; | ||
623 | *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10); | ||
624 | if (endp == tmp) | ||
625 | return -EINVAL; | ||
491 | 626 | ||
492 | retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr, | 627 | retval = update_mpp(NULL, new_weight_ptr); |
493 | *new_weight_ptr); | 628 | } else |
629 | return -EINVAL; | ||
494 | 630 | ||
495 | if (retval == H_SUCCESS || retval == H_CONSTRAINED) { | 631 | if (retval == H_SUCCESS || retval == H_CONSTRAINED) { |
496 | retval = count; | 632 | retval = count; |
@@ -506,8 +642,6 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, | |||
506 | retval = -EIO; | 642 | retval = -EIO; |
507 | } | 643 | } |
508 | 644 | ||
509 | out: | ||
510 | kfree(kbuf); | ||
511 | return retval; | 645 | return retval; |
512 | } | 646 | } |
513 | 647 | ||