GNU Linux-libre 4.4.284-gnu1
[releases.git] / arch / powerpc / platforms / pseries / dlpar.c
1 /*
2  * Support for dynamic reconfiguration for PCI, Memory, and CPU
3  * Hotplug and Dynamic Logical Partitioning on RPA platforms.
4  *
5  * Copyright (C) 2009 Nathan Fontenot
6  * Copyright (C) 2009 IBM Corporation
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version
10  * 2 as published by the Free Software Foundation.
11  */
12
13 #define pr_fmt(fmt)     "dlpar: " fmt
14
15 #include <linux/kernel.h>
16 #include <linux/notifier.h>
17 #include <linux/spinlock.h>
18 #include <linux/cpu.h>
19 #include <linux/slab.h>
20 #include <linux/of.h>
21
22 #include "of_helpers.h"
23 #include "offline_states.h"
24 #include "pseries.h"
25
26 #include <asm/prom.h>
27 #include <asm/machdep.h>
28 #include <asm/uaccess.h>
29 #include <asm/rtas.h>
30
31 struct cc_workarea {
32         __be32  drc_index;
33         __be32  zero;
34         __be32  name_offset;
35         __be32  prop_length;
36         __be32  prop_offset;
37 };
38
39 void dlpar_free_cc_property(struct property *prop)
40 {
41         kfree(prop->name);
42         kfree(prop->value);
43         kfree(prop);
44 }
45
46 static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa)
47 {
48         struct property *prop;
49         char *name;
50         char *value;
51
52         prop = kzalloc(sizeof(*prop), GFP_KERNEL);
53         if (!prop)
54                 return NULL;
55
56         name = (char *)ccwa + be32_to_cpu(ccwa->name_offset);
57         prop->name = kstrdup(name, GFP_KERNEL);
58         if (!prop->name) {
59                 dlpar_free_cc_property(prop);
60                 return NULL;
61         }
62
63         prop->length = be32_to_cpu(ccwa->prop_length);
64         value = (char *)ccwa + be32_to_cpu(ccwa->prop_offset);
65         prop->value = kmemdup(value, prop->length, GFP_KERNEL);
66         if (!prop->value) {
67                 dlpar_free_cc_property(prop);
68                 return NULL;
69         }
70
71         return prop;
72 }
73
74 static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa,
75                                                const char *path)
76 {
77         struct device_node *dn;
78         char *name;
79
80         /* If parent node path is "/" advance path to NULL terminator to
81          * prevent double leading slashs in full_name.
82          */
83         if (!path[1])
84                 path++;
85
86         dn = kzalloc(sizeof(*dn), GFP_KERNEL);
87         if (!dn)
88                 return NULL;
89
90         name = (char *)ccwa + be32_to_cpu(ccwa->name_offset);
91         dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name);
92         if (!dn->full_name) {
93                 kfree(dn);
94                 return NULL;
95         }
96
97         of_node_set_flag(dn, OF_DYNAMIC);
98         of_node_init(dn);
99
100         return dn;
101 }
102
103 static void dlpar_free_one_cc_node(struct device_node *dn)
104 {
105         struct property *prop;
106
107         while (dn->properties) {
108                 prop = dn->properties;
109                 dn->properties = prop->next;
110                 dlpar_free_cc_property(prop);
111         }
112
113         kfree(dn->full_name);
114         kfree(dn);
115 }
116
117 void dlpar_free_cc_nodes(struct device_node *dn)
118 {
119         if (dn->child)
120                 dlpar_free_cc_nodes(dn->child);
121
122         if (dn->sibling)
123                 dlpar_free_cc_nodes(dn->sibling);
124
125         dlpar_free_one_cc_node(dn);
126 }
127
128 #define COMPLETE        0
129 #define NEXT_SIBLING    1
130 #define NEXT_CHILD      2
131 #define NEXT_PROPERTY   3
132 #define PREV_PARENT     4
133 #define MORE_MEMORY     5
134 #define ERR_CFG_USE     -9003
135
136 struct device_node *dlpar_configure_connector(__be32 drc_index,
137                                               struct device_node *parent)
138 {
139         struct device_node *dn;
140         struct device_node *first_dn = NULL;
141         struct device_node *last_dn = NULL;
142         struct property *property;
143         struct property *last_property = NULL;
144         struct cc_workarea *ccwa;
145         char *data_buf;
146         const char *parent_path = parent->full_name;
147         int cc_token;
148         int rc = -1;
149
150         cc_token = rtas_token("ibm,configure-connector");
151         if (cc_token == RTAS_UNKNOWN_SERVICE)
152                 return NULL;
153
154         data_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
155         if (!data_buf)
156                 return NULL;
157
158         ccwa = (struct cc_workarea *)&data_buf[0];
159         ccwa->drc_index = drc_index;
160         ccwa->zero = 0;
161
162         do {
163                 /* Since we release the rtas_data_buf lock between configure
164                  * connector calls we want to re-populate the rtas_data_buffer
165                  * with the contents of the previous call.
166                  */
167                 spin_lock(&rtas_data_buf_lock);
168
169                 memcpy(rtas_data_buf, data_buf, RTAS_DATA_BUF_SIZE);
170                 rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL);
171                 memcpy(data_buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
172
173                 spin_unlock(&rtas_data_buf_lock);
174
175                 if (rtas_busy_delay(rc))
176                         continue;
177
178                 switch (rc) {
179                 case COMPLETE:
180                         break;
181
182                 case NEXT_SIBLING:
183                         dn = dlpar_parse_cc_node(ccwa, parent_path);
184                         if (!dn)
185                                 goto cc_error;
186
187                         dn->parent = last_dn->parent;
188                         last_dn->sibling = dn;
189                         last_dn = dn;
190                         break;
191
192                 case NEXT_CHILD:
193                         if (first_dn)
194                                 parent_path = last_dn->full_name;
195
196                         dn = dlpar_parse_cc_node(ccwa, parent_path);
197                         if (!dn)
198                                 goto cc_error;
199
200                         if (!first_dn) {
201                                 dn->parent = parent;
202                                 first_dn = dn;
203                         } else {
204                                 dn->parent = last_dn;
205                                 if (last_dn)
206                                         last_dn->child = dn;
207                         }
208
209                         last_dn = dn;
210                         break;
211
212                 case NEXT_PROPERTY:
213                         property = dlpar_parse_cc_property(ccwa);
214                         if (!property)
215                                 goto cc_error;
216
217                         if (!last_dn->properties)
218                                 last_dn->properties = property;
219                         else
220                                 last_property->next = property;
221
222                         last_property = property;
223                         break;
224
225                 case PREV_PARENT:
226                         last_dn = last_dn->parent;
227                         parent_path = last_dn->parent->full_name;
228                         break;
229
230                 case MORE_MEMORY:
231                 case ERR_CFG_USE:
232                 default:
233                         printk(KERN_ERR "Unexpected Error (%d) "
234                                "returned from configure-connector\n", rc);
235                         goto cc_error;
236                 }
237         } while (rc);
238
239 cc_error:
240         kfree(data_buf);
241
242         if (rc) {
243                 if (first_dn)
244                         dlpar_free_cc_nodes(first_dn);
245
246                 return NULL;
247         }
248
249         return first_dn;
250 }
251
252 int dlpar_attach_node(struct device_node *dn)
253 {
254         int rc;
255
256         dn->parent = pseries_of_derive_parent(dn->full_name);
257         if (IS_ERR(dn->parent))
258                 return PTR_ERR(dn->parent);
259
260         rc = of_attach_node(dn);
261         if (rc) {
262                 printk(KERN_ERR "Failed to add device node %s\n",
263                        dn->full_name);
264                 return rc;
265         }
266
267         of_node_put(dn->parent);
268         return 0;
269 }
270
271 int dlpar_detach_node(struct device_node *dn)
272 {
273         struct device_node *child;
274         int rc;
275
276         child = of_get_next_child(dn, NULL);
277         while (child) {
278                 dlpar_detach_node(child);
279                 child = of_get_next_child(dn, child);
280         }
281
282         rc = of_detach_node(dn);
283         if (rc)
284                 return rc;
285
286         of_node_put(dn);
287
288         return 0;
289 }
290
291 #define DR_ENTITY_SENSE         9003
292 #define DR_ENTITY_PRESENT       1
293 #define DR_ENTITY_UNUSABLE      2
294 #define ALLOCATION_STATE        9003
295 #define ALLOC_UNUSABLE          0
296 #define ALLOC_USABLE            1
297 #define ISOLATION_STATE         9001
298 #define ISOLATE                 0
299 #define UNISOLATE               1
300
301 int dlpar_acquire_drc(u32 drc_index)
302 {
303         int dr_status, rc;
304
305         rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status,
306                        DR_ENTITY_SENSE, drc_index);
307         if (rc || dr_status != DR_ENTITY_UNUSABLE)
308                 return -1;
309
310         rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_USABLE);
311         if (rc)
312                 return rc;
313
314         rc = rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE);
315         if (rc) {
316                 rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE);
317                 return rc;
318         }
319
320         return 0;
321 }
322
323 int dlpar_release_drc(u32 drc_index)
324 {
325         int dr_status, rc;
326
327         rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status,
328                        DR_ENTITY_SENSE, drc_index);
329         if (rc || dr_status != DR_ENTITY_PRESENT)
330                 return -1;
331
332         rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE);
333         if (rc)
334                 return rc;
335
336         rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE);
337         if (rc) {
338                 rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE);
339                 return rc;
340         }
341
342         return 0;
343 }
344
345 #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
346
347 static int dlpar_online_cpu(struct device_node *dn)
348 {
349         int rc = 0;
350         unsigned int cpu;
351         int len, nthreads, i;
352         const __be32 *intserv;
353         u32 thread;
354
355         intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len);
356         if (!intserv)
357                 return -EINVAL;
358
359         nthreads = len / sizeof(u32);
360
361         cpu_maps_update_begin();
362         for (i = 0; i < nthreads; i++) {
363                 thread = be32_to_cpu(intserv[i]);
364                 for_each_present_cpu(cpu) {
365                         if (get_hard_smp_processor_id(cpu) != thread)
366                                 continue;
367                         BUG_ON(get_cpu_current_state(cpu)
368                                         != CPU_STATE_OFFLINE);
369                         cpu_maps_update_done();
370                         rc = device_online(get_cpu_device(cpu));
371                         if (rc)
372                                 goto out;
373                         cpu_maps_update_begin();
374
375                         break;
376                 }
377                 if (cpu == num_possible_cpus())
378                         printk(KERN_WARNING "Could not find cpu to online "
379                                "with physical id 0x%x\n", thread);
380         }
381         cpu_maps_update_done();
382
383 out:
384         return rc;
385
386 }
387
388 static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
389 {
390         struct device_node *dn, *parent;
391         u32 drc_index;
392         int rc;
393
394         rc = kstrtou32(buf, 0, &drc_index);
395         if (rc)
396                 return -EINVAL;
397
398         rc = dlpar_acquire_drc(drc_index);
399         if (rc)
400                 return -EINVAL;
401
402         parent = of_find_node_by_path("/cpus");
403         if (!parent)
404                 return -ENODEV;
405
406         dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
407         of_node_put(parent);
408         if (!dn) {
409                 dlpar_release_drc(drc_index);
410                 return -EINVAL;
411         }
412
413         rc = dlpar_attach_node(dn);
414         if (rc) {
415                 dlpar_release_drc(drc_index);
416                 dlpar_free_cc_nodes(dn);
417                 return rc;
418         }
419
420         rc = dlpar_online_cpu(dn);
421         if (rc)
422                 return rc;
423
424         return count;
425 }
426
427 static int dlpar_offline_cpu(struct device_node *dn)
428 {
429         int rc = 0;
430         unsigned int cpu;
431         int len, nthreads, i;
432         const __be32 *intserv;
433         u32 thread;
434
435         intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len);
436         if (!intserv)
437                 return -EINVAL;
438
439         nthreads = len / sizeof(u32);
440
441         cpu_maps_update_begin();
442         for (i = 0; i < nthreads; i++) {
443                 thread = be32_to_cpu(intserv[i]);
444                 for_each_present_cpu(cpu) {
445                         if (get_hard_smp_processor_id(cpu) != thread)
446                                 continue;
447
448                         if (get_cpu_current_state(cpu) == CPU_STATE_OFFLINE)
449                                 break;
450
451                         if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) {
452                                 set_preferred_offline_state(cpu, CPU_STATE_OFFLINE);
453                                 cpu_maps_update_done();
454                                 rc = device_offline(get_cpu_device(cpu));
455                                 if (rc)
456                                         goto out;
457                                 cpu_maps_update_begin();
458                                 break;
459
460                         }
461
462                         /*
463                          * The cpu is in CPU_STATE_INACTIVE.
464                          * Upgrade it's state to CPU_STATE_OFFLINE.
465                          */
466                         set_preferred_offline_state(cpu, CPU_STATE_OFFLINE);
467                         BUG_ON(plpar_hcall_norets(H_PROD, thread)
468                                                                 != H_SUCCESS);
469                         __cpu_die(cpu);
470                         break;
471                 }
472                 if (cpu == num_possible_cpus())
473                         printk(KERN_WARNING "Could not find cpu to offline "
474                                "with physical id 0x%x\n", thread);
475         }
476         cpu_maps_update_done();
477
478 out:
479         return rc;
480
481 }
482
483 static ssize_t dlpar_cpu_release(const char *buf, size_t count)
484 {
485         struct device_node *dn;
486         u32 drc_index;
487         int rc;
488
489         dn = of_find_node_by_path(buf);
490         if (!dn)
491                 return -EINVAL;
492
493         rc = of_property_read_u32(dn, "ibm,my-drc-index", &drc_index);
494         if (rc) {
495                 of_node_put(dn);
496                 return -EINVAL;
497         }
498
499         rc = dlpar_offline_cpu(dn);
500         if (rc) {
501                 of_node_put(dn);
502                 return -EINVAL;
503         }
504
505         rc = dlpar_release_drc(drc_index);
506         if (rc) {
507                 of_node_put(dn);
508                 return rc;
509         }
510
511         rc = dlpar_detach_node(dn);
512         if (rc) {
513                 dlpar_acquire_drc(drc_index);
514                 return rc;
515         }
516
517         of_node_put(dn);
518
519         return count;
520 }
521
522 #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
523
524 static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog)
525 {
526         int rc;
527
528         /* pseries error logs are in BE format, convert to cpu type */
529         switch (hp_elog->id_type) {
530         case PSERIES_HP_ELOG_ID_DRC_COUNT:
531                 hp_elog->_drc_u.drc_count =
532                                         be32_to_cpu(hp_elog->_drc_u.drc_count);
533                 break;
534         case PSERIES_HP_ELOG_ID_DRC_INDEX:
535                 hp_elog->_drc_u.drc_index =
536                                         be32_to_cpu(hp_elog->_drc_u.drc_index);
537         }
538
539         switch (hp_elog->resource) {
540         case PSERIES_HP_ELOG_RESOURCE_MEM:
541                 rc = dlpar_memory(hp_elog);
542                 break;
543         default:
544                 pr_warn_ratelimited("Invalid resource (%d) specified\n",
545                                     hp_elog->resource);
546                 rc = -EINVAL;
547         }
548
549         return rc;
550 }
551
552 static ssize_t dlpar_store(struct class *class, struct class_attribute *attr,
553                            const char *buf, size_t count)
554 {
555         struct pseries_hp_errorlog *hp_elog;
556         const char *arg;
557         int rc;
558
559         hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL);
560         if (!hp_elog) {
561                 rc = -ENOMEM;
562                 goto dlpar_store_out;
563         }
564
565         /* Parse out the request from the user, this will be in the form
566          * <resource> <action> <id_type> <id>
567          */
568         arg = buf;
569         if (!strncmp(arg, "memory", 6)) {
570                 hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_MEM;
571                 arg += strlen("memory ");
572         } else {
573                 pr_err("Invalid resource specified: \"%s\"\n", buf);
574                 rc = -EINVAL;
575                 goto dlpar_store_out;
576         }
577
578         if (!strncmp(arg, "add", 3)) {
579                 hp_elog->action = PSERIES_HP_ELOG_ACTION_ADD;
580                 arg += strlen("add ");
581         } else if (!strncmp(arg, "remove", 6)) {
582                 hp_elog->action = PSERIES_HP_ELOG_ACTION_REMOVE;
583                 arg += strlen("remove ");
584         } else {
585                 pr_err("Invalid action specified: \"%s\"\n", buf);
586                 rc = -EINVAL;
587                 goto dlpar_store_out;
588         }
589
590         if (!strncmp(arg, "index", 5)) {
591                 u32 index;
592
593                 hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX;
594                 arg += strlen("index ");
595                 if (kstrtou32(arg, 0, &index)) {
596                         rc = -EINVAL;
597                         pr_err("Invalid drc_index specified: \"%s\"\n", buf);
598                         goto dlpar_store_out;
599                 }
600
601                 hp_elog->_drc_u.drc_index = cpu_to_be32(index);
602         } else if (!strncmp(arg, "count", 5)) {
603                 u32 count;
604
605                 hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_COUNT;
606                 arg += strlen("count ");
607                 if (kstrtou32(arg, 0, &count)) {
608                         rc = -EINVAL;
609                         pr_err("Invalid count specified: \"%s\"\n", buf);
610                         goto dlpar_store_out;
611                 }
612
613                 hp_elog->_drc_u.drc_count = cpu_to_be32(count);
614         } else {
615                 pr_err("Invalid id_type specified: \"%s\"\n", buf);
616                 rc = -EINVAL;
617                 goto dlpar_store_out;
618         }
619
620         rc = handle_dlpar_errorlog(hp_elog);
621
622 dlpar_store_out:
623         kfree(hp_elog);
624         return rc ? rc : count;
625 }
626
627 static CLASS_ATTR(dlpar, S_IWUSR, NULL, dlpar_store);
628
629 static int __init pseries_dlpar_init(void)
630 {
631         int rc;
632
633 #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
634         ppc_md.cpu_probe = dlpar_cpu_probe;
635         ppc_md.cpu_release = dlpar_cpu_release;
636 #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
637
638         rc = sysfs_create_file(kernel_kobj, &class_attr_dlpar.attr);
639
640         return rc;
641 }
642 machine_device_initcall(pseries, pseries_dlpar_init);
643