GNU Linux-libre 4.14.290-gnu1
[releases.git] / arch / powerpc / platforms / pseries / mobility.c
1 /*
2  * Support for Partition Mobility/Migration
3  *
4  * Copyright (C) 2010 Nathan Fontenot
5  * Copyright (C) 2010 IBM Corporation
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version
9  * 2 as published by the Free Software Foundation.
10  */
11
12 #include <linux/cpu.h>
13 #include <linux/kernel.h>
14 #include <linux/kobject.h>
15 #include <linux/sched.h>
16 #include <linux/smp.h>
17 #include <linux/stat.h>
18 #include <linux/completion.h>
19 #include <linux/device.h>
20 #include <linux/delay.h>
21 #include <linux/slab.h>
22
23 #include <asm/machdep.h>
24 #include <asm/rtas.h>
25 #include "pseries.h"
26 #include "../../kernel/cacheinfo.h"
27
28 static struct kobject *mobility_kobj;
29
30 struct update_props_workarea {
31         __be32 phandle;
32         __be32 state;
33         __be64 reserved;
34         __be32 nprops;
35 } __packed;
36
37 #define NODE_ACTION_MASK        0xff000000
38 #define NODE_COUNT_MASK         0x00ffffff
39
40 #define DELETE_DT_NODE  0x01000000
41 #define UPDATE_DT_NODE  0x02000000
42 #define ADD_DT_NODE     0x03000000
43
44 #define MIGRATION_SCOPE (1)
45 #define PRRN_SCOPE -2
46
47 static int mobility_rtas_call(int token, char *buf, s32 scope)
48 {
49         int rc;
50
51         spin_lock(&rtas_data_buf_lock);
52
53         memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE);
54         rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, scope);
55         memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
56
57         spin_unlock(&rtas_data_buf_lock);
58         return rc;
59 }
60
61 static int delete_dt_node(__be32 phandle)
62 {
63         struct device_node *dn;
64
65         dn = of_find_node_by_phandle(be32_to_cpu(phandle));
66         if (!dn)
67                 return -ENOENT;
68
69         dlpar_detach_node(dn);
70         of_node_put(dn);
71         return 0;
72 }
73
74 static int update_dt_property(struct device_node *dn, struct property **prop,
75                               const char *name, u32 vd, char *value)
76 {
77         struct property *new_prop = *prop;
78         int more = 0;
79
80         /* A negative 'vd' value indicates that only part of the new property
81          * value is contained in the buffer and we need to call
82          * ibm,update-properties again to get the rest of the value.
83          *
84          * A negative value is also the two's compliment of the actual value.
85          */
86         if (vd & 0x80000000) {
87                 vd = ~vd + 1;
88                 more = 1;
89         }
90
91         if (new_prop) {
92                 /* partial property fixup */
93                 char *new_data = kzalloc(new_prop->length + vd, GFP_KERNEL);
94                 if (!new_data)
95                         return -ENOMEM;
96
97                 memcpy(new_data, new_prop->value, new_prop->length);
98                 memcpy(new_data + new_prop->length, value, vd);
99
100                 kfree(new_prop->value);
101                 new_prop->value = new_data;
102                 new_prop->length += vd;
103         } else {
104                 new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
105                 if (!new_prop)
106                         return -ENOMEM;
107
108                 new_prop->name = kstrdup(name, GFP_KERNEL);
109                 if (!new_prop->name) {
110                         kfree(new_prop);
111                         return -ENOMEM;
112                 }
113
114                 new_prop->length = vd;
115                 new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
116                 if (!new_prop->value) {
117                         kfree(new_prop->name);
118                         kfree(new_prop);
119                         return -ENOMEM;
120                 }
121
122                 memcpy(new_prop->value, value, vd);
123                 *prop = new_prop;
124         }
125
126         if (!more) {
127                 of_update_property(dn, new_prop);
128                 *prop = NULL;
129         }
130
131         return 0;
132 }
133
134 static int update_dt_node(__be32 phandle, s32 scope)
135 {
136         struct update_props_workarea *upwa;
137         struct device_node *dn;
138         struct property *prop = NULL;
139         int i, rc, rtas_rc;
140         char *prop_data;
141         char *rtas_buf;
142         int update_properties_token;
143         u32 nprops;
144         u32 vd;
145
146         update_properties_token = rtas_token("ibm,update-properties");
147         if (update_properties_token == RTAS_UNKNOWN_SERVICE)
148                 return -EINVAL;
149
150         rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
151         if (!rtas_buf)
152                 return -ENOMEM;
153
154         dn = of_find_node_by_phandle(be32_to_cpu(phandle));
155         if (!dn) {
156                 kfree(rtas_buf);
157                 return -ENOENT;
158         }
159
160         upwa = (struct update_props_workarea *)&rtas_buf[0];
161         upwa->phandle = phandle;
162
163         do {
164                 rtas_rc = mobility_rtas_call(update_properties_token, rtas_buf,
165                                         scope);
166                 if (rtas_rc < 0)
167                         break;
168
169                 prop_data = rtas_buf + sizeof(*upwa);
170                 nprops = be32_to_cpu(upwa->nprops);
171
172                 /* On the first call to ibm,update-properties for a node the
173                  * the first property value descriptor contains an empty
174                  * property name, the property value length encoded as u32,
175                  * and the property value is the node path being updated.
176                  */
177                 if (*prop_data == 0) {
178                         prop_data++;
179                         vd = be32_to_cpu(*(__be32 *)prop_data);
180                         prop_data += vd + sizeof(vd);
181                         nprops--;
182                 }
183
184                 for (i = 0; i < nprops; i++) {
185                         char *prop_name;
186
187                         prop_name = prop_data;
188                         prop_data += strlen(prop_name) + 1;
189                         vd = be32_to_cpu(*(__be32 *)prop_data);
190                         prop_data += sizeof(vd);
191
192                         switch (vd) {
193                         case 0x00000000:
194                                 /* name only property, nothing to do */
195                                 break;
196
197                         case 0x80000000:
198                                 of_remove_property(dn, of_find_property(dn,
199                                                         prop_name, NULL));
200                                 prop = NULL;
201                                 break;
202
203                         default:
204                                 rc = update_dt_property(dn, &prop, prop_name,
205                                                         vd, prop_data);
206                                 if (rc) {
207                                         printk(KERN_ERR "Could not update %s"
208                                                " property\n", prop_name);
209                                 }
210
211                                 prop_data += vd;
212                         }
213
214                         cond_resched();
215                 }
216
217                 cond_resched();
218         } while (rtas_rc == 1);
219
220         of_node_put(dn);
221         kfree(rtas_buf);
222         return 0;
223 }
224
225 static int add_dt_node(__be32 parent_phandle, __be32 drc_index)
226 {
227         struct device_node *dn;
228         struct device_node *parent_dn;
229         int rc;
230
231         parent_dn = of_find_node_by_phandle(be32_to_cpu(parent_phandle));
232         if (!parent_dn)
233                 return -ENOENT;
234
235         dn = dlpar_configure_connector(drc_index, parent_dn);
236         if (!dn) {
237                 of_node_put(parent_dn);
238                 return -ENOENT;
239         }
240
241         rc = dlpar_attach_node(dn, parent_dn);
242         if (rc)
243                 dlpar_free_cc_nodes(dn);
244
245         of_node_put(parent_dn);
246         return rc;
247 }
248
249 static void prrn_update_node(__be32 phandle)
250 {
251         struct pseries_hp_errorlog *hp_elog;
252         struct device_node *dn;
253
254         /*
255          * If a node is found from a the given phandle, the phandle does not
256          * represent the drc index of an LMB and we can ignore.
257          */
258         dn = of_find_node_by_phandle(be32_to_cpu(phandle));
259         if (dn) {
260                 of_node_put(dn);
261                 return;
262         }
263
264         hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL);
265         if(!hp_elog)
266                 return;
267
268         hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_MEM;
269         hp_elog->action = PSERIES_HP_ELOG_ACTION_READD;
270         hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX;
271         hp_elog->_drc_u.drc_index = phandle;
272
273         queue_hotplug_event(hp_elog, NULL, NULL);
274
275         kfree(hp_elog);
276 }
277
278 int pseries_devicetree_update(s32 scope)
279 {
280         char *rtas_buf;
281         __be32 *data;
282         int update_nodes_token;
283         int rc;
284
285         update_nodes_token = rtas_token("ibm,update-nodes");
286         if (update_nodes_token == RTAS_UNKNOWN_SERVICE)
287                 return -EINVAL;
288
289         rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
290         if (!rtas_buf)
291                 return -ENOMEM;
292
293         do {
294                 rc = mobility_rtas_call(update_nodes_token, rtas_buf, scope);
295                 if (rc && rc != 1)
296                         break;
297
298                 data = (__be32 *)rtas_buf + 4;
299                 while (be32_to_cpu(*data) & NODE_ACTION_MASK) {
300                         int i;
301                         u32 action = be32_to_cpu(*data) & NODE_ACTION_MASK;
302                         u32 node_count = be32_to_cpu(*data) & NODE_COUNT_MASK;
303
304                         data++;
305
306                         for (i = 0; i < node_count; i++) {
307                                 __be32 phandle = *data++;
308                                 __be32 drc_index;
309
310                                 switch (action) {
311                                 case DELETE_DT_NODE:
312                                         delete_dt_node(phandle);
313                                         break;
314                                 case UPDATE_DT_NODE:
315                                         update_dt_node(phandle, scope);
316
317                                         if (scope == PRRN_SCOPE)
318                                                 prrn_update_node(phandle);
319
320                                         break;
321                                 case ADD_DT_NODE:
322                                         drc_index = *data++;
323                                         add_dt_node(phandle, drc_index);
324                                         break;
325                                 }
326
327                                 cond_resched();
328                         }
329                 }
330
331                 cond_resched();
332         } while (rc == 1);
333
334         kfree(rtas_buf);
335         return rc;
336 }
337
338 void post_mobility_fixup(void)
339 {
340         int rc;
341         int activate_fw_token;
342
343         activate_fw_token = rtas_token("ibm,activate-firmware");
344         if (activate_fw_token == RTAS_UNKNOWN_SERVICE) {
345                 printk(KERN_ERR "Could not make post-mobility "
346                        "activate-fw call.\n");
347                 return;
348         }
349
350         do {
351                 rc = rtas_call(activate_fw_token, 0, 1, NULL);
352         } while (rtas_busy_delay(rc));
353
354         if (rc)
355                 printk(KERN_ERR "Post-mobility activate-fw failed: %d\n", rc);
356
357         /*
358          * We don't want CPUs to go online/offline while the device
359          * tree is being updated.
360          */
361         cpus_read_lock();
362
363         /*
364          * It's common for the destination firmware to replace cache
365          * nodes.  Release all of the cacheinfo hierarchy's references
366          * before updating the device tree.
367          */
368         cacheinfo_teardown();
369
370         rc = pseries_devicetree_update(MIGRATION_SCOPE);
371         if (rc)
372                 printk(KERN_ERR "Post-mobility device tree update "
373                         "failed: %d\n", rc);
374
375         cacheinfo_rebuild();
376
377         cpus_read_unlock();
378
379         /* Possibly switch to a new RFI flush type */
380         pseries_setup_rfi_flush();
381
382         return;
383 }
384
385 static ssize_t migration_store(struct class *class,
386                                struct class_attribute *attr, const char *buf,
387                                size_t count)
388 {
389         u64 streamid;
390         int rc;
391
392         rc = kstrtou64(buf, 0, &streamid);
393         if (rc)
394                 return rc;
395
396         do {
397                 rc = rtas_ibm_suspend_me(streamid);
398                 if (rc == -EAGAIN)
399                         ssleep(1);
400         } while (rc == -EAGAIN);
401
402         if (rc)
403                 return rc;
404
405         post_mobility_fixup();
406         return count;
407 }
408
409 /*
410  * Used by drmgr to determine the kernel behavior of the migration interface.
411  *
412  * Version 1: Performs all PAPR requirements for migration including
413  *      firmware activation and device tree update.
414  */
415 #define MIGRATION_API_VERSION   1
416
417 static CLASS_ATTR_WO(migration);
418 static CLASS_ATTR_STRING(api_version, S_IRUGO, __stringify(MIGRATION_API_VERSION));
419
420 static int __init mobility_sysfs_init(void)
421 {
422         int rc;
423
424         mobility_kobj = kobject_create_and_add("mobility", kernel_kobj);
425         if (!mobility_kobj)
426                 return -ENOMEM;
427
428         rc = sysfs_create_file(mobility_kobj, &class_attr_migration.attr);
429         if (rc)
430                 pr_err("mobility: unable to create migration sysfs file (%d)\n", rc);
431
432         rc = sysfs_create_file(mobility_kobj, &class_attr_api_version.attr.attr);
433         if (rc)
434                 pr_err("mobility: unable to create api_version sysfs file (%d)\n", rc);
435
436         return 0;
437 }
438 machine_device_initcall(pseries, mobility_sysfs_init);