aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/dlpar.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/dlpar.c')
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index fe8d4b3c50cd..642e1b2e5c42 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -16,6 +16,7 @@
16#include <linux/proc_fs.h> 16#include <linux/proc_fs.h>
17#include <linux/spinlock.h> 17#include <linux/spinlock.h>
18#include <linux/cpu.h> 18#include <linux/cpu.h>
19#include "offline_states.h"
19 20
20#include <asm/prom.h> 21#include <asm/prom.h>
21#include <asm/machdep.h> 22#include <asm/machdep.h>
@@ -287,6 +288,98 @@ int dlpar_detach_node(struct device_node *dn)
287 return 0; 288 return 0;
288} 289}
289 290
291int online_node_cpus(struct device_node *dn)
292{
293 int rc = 0;
294 unsigned int cpu;
295 int len, nthreads, i;
296 const u32 *intserv;
297
298 intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len);
299 if (!intserv)
300 return -EINVAL;
301
302 nthreads = len / sizeof(u32);
303
304 cpu_maps_update_begin();
305 for (i = 0; i < nthreads; i++) {
306 for_each_present_cpu(cpu) {
307 if (get_hard_smp_processor_id(cpu) != intserv[i])
308 continue;
309 BUG_ON(get_cpu_current_state(cpu)
310 != CPU_STATE_OFFLINE);
311 cpu_maps_update_done();
312 rc = cpu_up(cpu);
313 if (rc)
314 goto out;
315 cpu_maps_update_begin();
316
317 break;
318 }
319 if (cpu == num_possible_cpus())
320 printk(KERN_WARNING "Could not find cpu to online "
321 "with physical id 0x%x\n", intserv[i]);
322 }
323 cpu_maps_update_done();
324
325out:
326 return rc;
327
328}
329
330int offline_node_cpus(struct device_node *dn)
331{
332 int rc = 0;
333 unsigned int cpu;
334 int len, nthreads, i;
335 const u32 *intserv;
336
337 intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len);
338 if (!intserv)
339 return -EINVAL;
340
341 nthreads = len / sizeof(u32);
342
343 cpu_maps_update_begin();
344 for (i = 0; i < nthreads; i++) {
345 for_each_present_cpu(cpu) {
346 if (get_hard_smp_processor_id(cpu) != intserv[i])
347 continue;
348
349 if (get_cpu_current_state(cpu) == CPU_STATE_OFFLINE)
350 break;
351
352 if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) {
353 cpu_maps_update_done();
354 rc = cpu_down(cpu);
355 if (rc)
356 goto out;
357 cpu_maps_update_begin();
358 break;
359
360 }
361
362 /*
363 * The cpu is in CPU_STATE_INACTIVE.
364 * Upgrade it's state to CPU_STATE_OFFLINE.
365 */
366 set_preferred_offline_state(cpu, CPU_STATE_OFFLINE);
367 BUG_ON(plpar_hcall_norets(H_PROD, intserv[i])
368 != H_SUCCESS);
369 __cpu_die(cpu);
370 break;
371 }
372 if (cpu == num_possible_cpus())
373 printk(KERN_WARNING "Could not find cpu to offline "
374 "with physical id 0x%x\n", intserv[i]);
375 }
376 cpu_maps_update_done();
377
378out:
379 return rc;
380
381}
382
290#define DR_ENTITY_SENSE 9003 383#define DR_ENTITY_SENSE 9003
291#define DR_ENTITY_PRESENT 1 384#define DR_ENTITY_PRESENT 1
292#define DR_ENTITY_UNUSABLE 2 385#define DR_ENTITY_UNUSABLE 2
@@ -385,6 +478,8 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
385 dlpar_free_cc_nodes(dn); 478 dlpar_free_cc_nodes(dn);
386 } 479 }
387 480
481 rc = online_node_cpus(dn);
482
388 return rc ? rc : count; 483 return rc ? rc : count;
389} 484}
390 485
@@ -404,6 +499,12 @@ static ssize_t dlpar_cpu_release(const char *buf, size_t count)
404 return -EINVAL; 499 return -EINVAL;
405 } 500 }
406 501
502 rc = offline_node_cpus(dn);
503 if (rc) {
504 of_node_put(dn);
505 return -EINVAL;
506 }
507
407 rc = dlpar_release_drc(*drc_index); 508 rc = dlpar_release_drc(*drc_index);
408 if (rc) { 509 if (rc) {
409 of_node_put(dn); 510 of_node_put(dn);