diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/pseries/dlpar.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index c80e8ef0eb58..fe8d4b3c50cd 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
@@ -341,4 +341,92 @@ int dlpar_release_drc(u32 drc_index) | |||
341 | return 0; | 341 | return 0; |
342 | } | 342 | } |
343 | 343 | ||
344 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
344 | 345 | ||
346 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | ||
347 | { | ||
348 | struct device_node *dn; | ||
349 | unsigned long drc_index; | ||
350 | char *cpu_name; | ||
351 | int rc; | ||
352 | |||
353 | rc = strict_strtoul(buf, 0, &drc_index); | ||
354 | if (rc) | ||
355 | return -EINVAL; | ||
356 | |||
357 | dn = dlpar_configure_connector(drc_index); | ||
358 | if (!dn) | ||
359 | return -EINVAL; | ||
360 | |||
361 | /* configure-connector reports cpus as living in the base | ||
362 | * directory of the device tree. CPUs actually live in the | ||
363 | * cpus directory so we need to fixup the full_name. | ||
364 | */ | ||
365 | cpu_name = kzalloc(strlen(dn->full_name) + strlen("/cpus") + 1, | ||
366 | GFP_KERNEL); | ||
367 | if (!cpu_name) { | ||
368 | dlpar_free_cc_nodes(dn); | ||
369 | return -ENOMEM; | ||
370 | } | ||
371 | |||
372 | sprintf(cpu_name, "/cpus%s", dn->full_name); | ||
373 | kfree(dn->full_name); | ||
374 | dn->full_name = cpu_name; | ||
375 | |||
376 | rc = dlpar_acquire_drc(drc_index); | ||
377 | if (rc) { | ||
378 | dlpar_free_cc_nodes(dn); | ||
379 | return -EINVAL; | ||
380 | } | ||
381 | |||
382 | rc = dlpar_attach_node(dn); | ||
383 | if (rc) { | ||
384 | dlpar_release_drc(drc_index); | ||
385 | dlpar_free_cc_nodes(dn); | ||
386 | } | ||
387 | |||
388 | return rc ? rc : count; | ||
389 | } | ||
390 | |||
391 | static ssize_t dlpar_cpu_release(const char *buf, size_t count) | ||
392 | { | ||
393 | struct device_node *dn; | ||
394 | const u32 *drc_index; | ||
395 | int rc; | ||
396 | |||
397 | dn = of_find_node_by_path(buf); | ||
398 | if (!dn) | ||
399 | return -EINVAL; | ||
400 | |||
401 | drc_index = of_get_property(dn, "ibm,my-drc-index", NULL); | ||
402 | if (!drc_index) { | ||
403 | of_node_put(dn); | ||
404 | return -EINVAL; | ||
405 | } | ||
406 | |||
407 | rc = dlpar_release_drc(*drc_index); | ||
408 | if (rc) { | ||
409 | of_node_put(dn); | ||
410 | return -EINVAL; | ||
411 | } | ||
412 | |||
413 | rc = dlpar_detach_node(dn); | ||
414 | if (rc) { | ||
415 | dlpar_acquire_drc(*drc_index); | ||
416 | return rc; | ||
417 | } | ||
418 | |||
419 | of_node_put(dn); | ||
420 | return count; | ||
421 | } | ||
422 | |||
423 | static int __init pseries_dlpar_init(void) | ||
424 | { | ||
425 | ppc_md.cpu_probe = dlpar_cpu_probe; | ||
426 | ppc_md.cpu_release = dlpar_cpu_release; | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | machine_device_initcall(pseries, pseries_dlpar_init); | ||
431 | |||
432 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | ||