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