xref: /openbmc/linux/drivers/misc/cxl/flash.c (revision 293d5b43)
1 #include <linux/kernel.h>
2 #include <linux/fs.h>
3 #include <linux/semaphore.h>
4 #include <linux/slab.h>
5 #include <linux/uaccess.h>
6 #include <asm/rtas.h>
7 
8 #include "cxl.h"
9 #include "hcalls.h"
10 
11 #define DOWNLOAD_IMAGE 1
12 #define VALIDATE_IMAGE 2
13 
14 struct ai_header {
15 	u16 version;
16 	u8  reserved0[6];
17 	u16 vendor;
18 	u16 device;
19 	u16 subsystem_vendor;
20 	u16 subsystem;
21 	u64 image_offset;
22 	u64 image_length;
23 	u8  reserved1[96];
24 };
25 
26 static struct semaphore sem;
27 static unsigned long *buffer[CXL_AI_MAX_ENTRIES];
28 static struct sg_list *le;
29 static u64 continue_token;
30 static unsigned int transfer;
31 
32 struct update_props_workarea {
33 	__be32 phandle;
34 	__be32 state;
35 	__be64 reserved;
36 	__be32 nprops;
37 } __packed;
38 
39 struct update_nodes_workarea {
40 	__be32 state;
41 	__be64 unit_address;
42 	__be32 reserved;
43 } __packed;
44 
45 #define DEVICE_SCOPE 3
46 #define NODE_ACTION_MASK	0xff000000
47 #define NODE_COUNT_MASK		0x00ffffff
48 #define OPCODE_DELETE	0x01000000
49 #define OPCODE_UPDATE	0x02000000
50 #define OPCODE_ADD	0x03000000
51 
52 static int rcall(int token, char *buf, s32 scope)
53 {
54 	int rc;
55 
56 	spin_lock(&rtas_data_buf_lock);
57 
58 	memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE);
59 	rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, scope);
60 	memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
61 
62 	spin_unlock(&rtas_data_buf_lock);
63 	return rc;
64 }
65 
66 static int update_property(struct device_node *dn, const char *name,
67 			   u32 vd, char *value)
68 {
69 	struct property *new_prop;
70 	u32 *val;
71 	int rc;
72 
73 	new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
74 	if (!new_prop)
75 		return -ENOMEM;
76 
77 	new_prop->name = kstrdup(name, GFP_KERNEL);
78 	if (!new_prop->name) {
79 		kfree(new_prop);
80 		return -ENOMEM;
81 	}
82 
83 	new_prop->length = vd;
84 	new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
85 	if (!new_prop->value) {
86 		kfree(new_prop->name);
87 		kfree(new_prop);
88 		return -ENOMEM;
89 	}
90 	memcpy(new_prop->value, value, vd);
91 
92 	val = (u32 *)new_prop->value;
93 	rc = cxl_update_properties(dn, new_prop);
94 	pr_devel("%s: update property (%s, length: %i, value: %#x)\n",
95 		  dn->name, name, vd, be32_to_cpu(*val));
96 
97 	if (rc) {
98 		kfree(new_prop->name);
99 		kfree(new_prop->value);
100 		kfree(new_prop);
101 	}
102 	return rc;
103 }
104 
105 static int update_node(__be32 phandle, s32 scope)
106 {
107 	struct update_props_workarea *upwa;
108 	struct device_node *dn;
109 	int i, rc, ret;
110 	char *prop_data;
111 	char *buf;
112 	int token;
113 	u32 nprops;
114 	u32 vd;
115 
116 	token = rtas_token("ibm,update-properties");
117 	if (token == RTAS_UNKNOWN_SERVICE)
118 		return -EINVAL;
119 
120 	buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
121 	if (!buf)
122 		return -ENOMEM;
123 
124 	dn = of_find_node_by_phandle(be32_to_cpu(phandle));
125 	if (!dn) {
126 		kfree(buf);
127 		return -ENOENT;
128 	}
129 
130 	upwa = (struct update_props_workarea *)&buf[0];
131 	upwa->phandle = phandle;
132 	do {
133 		rc = rcall(token, buf, scope);
134 		if (rc < 0)
135 			break;
136 
137 		prop_data = buf + sizeof(*upwa);
138 		nprops = be32_to_cpu(upwa->nprops);
139 
140 		if (*prop_data == 0) {
141 			prop_data++;
142 			vd = be32_to_cpu(*(__be32 *)prop_data);
143 			prop_data += vd + sizeof(vd);
144 			nprops--;
145 		}
146 
147 		for (i = 0; i < nprops; i++) {
148 			char *prop_name;
149 
150 			prop_name = prop_data;
151 			prop_data += strlen(prop_name) + 1;
152 			vd = be32_to_cpu(*(__be32 *)prop_data);
153 			prop_data += sizeof(vd);
154 
155 			if ((vd != 0x00000000) && (vd != 0x80000000)) {
156 				ret = update_property(dn, prop_name, vd,
157 						prop_data);
158 				if (ret)
159 					pr_err("cxl: Could not update property %s - %i\n",
160 					       prop_name, ret);
161 
162 				prop_data += vd;
163 			}
164 		}
165 	} while (rc == 1);
166 
167 	of_node_put(dn);
168 	kfree(buf);
169 	return rc;
170 }
171 
172 static int update_devicetree(struct cxl *adapter, s32 scope)
173 {
174 	struct update_nodes_workarea *unwa;
175 	u32 action, node_count;
176 	int token, rc, i;
177 	__be32 *data, drc_index, phandle;
178 	char *buf;
179 
180 	token = rtas_token("ibm,update-nodes");
181 	if (token == RTAS_UNKNOWN_SERVICE)
182 		return -EINVAL;
183 
184 	buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
185 	if (!buf)
186 		return -ENOMEM;
187 
188 	unwa = (struct update_nodes_workarea *)&buf[0];
189 	unwa->unit_address = cpu_to_be64(adapter->guest->handle);
190 	do {
191 		rc = rcall(token, buf, scope);
192 		if (rc && rc != 1)
193 			break;
194 
195 		data = (__be32 *)buf + 4;
196 		while (be32_to_cpu(*data) & NODE_ACTION_MASK) {
197 			action = be32_to_cpu(*data) & NODE_ACTION_MASK;
198 			node_count = be32_to_cpu(*data) & NODE_COUNT_MASK;
199 			pr_devel("device reconfiguration - action: %#x, nodes: %#x\n",
200 				 action, node_count);
201 			data++;
202 
203 			for (i = 0; i < node_count; i++) {
204 				phandle = *data++;
205 
206 				switch (action) {
207 				case OPCODE_DELETE:
208 					/* nothing to do */
209 					break;
210 				case OPCODE_UPDATE:
211 					update_node(phandle, scope);
212 					break;
213 				case OPCODE_ADD:
214 					/* nothing to do, just move pointer */
215 					drc_index = *data++;
216 					break;
217 				}
218 			}
219 		}
220 	} while (rc == 1);
221 
222 	kfree(buf);
223 	return 0;
224 }
225 
226 static int handle_image(struct cxl *adapter, int operation,
227 			long (*fct)(u64, u64, u64, u64 *),
228 			struct cxl_adapter_image *ai)
229 {
230 	size_t mod, s_copy, len_chunk = 0;
231 	struct ai_header *header = NULL;
232 	unsigned int entries = 0, i;
233 	void *dest, *from;
234 	int rc = 0, need_header;
235 
236 	/* base adapter image header */
237 	need_header = (ai->flags & CXL_AI_NEED_HEADER);
238 	if (need_header) {
239 		header = kzalloc(sizeof(struct ai_header), GFP_KERNEL);
240 		if (!header)
241 			return -ENOMEM;
242 		header->version = cpu_to_be16(1);
243 		header->vendor = cpu_to_be16(adapter->guest->vendor);
244 		header->device = cpu_to_be16(adapter->guest->device);
245 		header->subsystem_vendor = cpu_to_be16(adapter->guest->subsystem_vendor);
246 		header->subsystem = cpu_to_be16(adapter->guest->subsystem);
247 		header->image_offset = cpu_to_be64(CXL_AI_HEADER_SIZE);
248 		header->image_length = cpu_to_be64(ai->len_image);
249 	}
250 
251 	/* number of entries in the list */
252 	len_chunk = ai->len_data;
253 	if (need_header)
254 		len_chunk += CXL_AI_HEADER_SIZE;
255 
256 	entries = len_chunk / CXL_AI_BUFFER_SIZE;
257 	mod = len_chunk % CXL_AI_BUFFER_SIZE;
258 	if (mod)
259 		entries++;
260 
261 	if (entries > CXL_AI_MAX_ENTRIES) {
262 		rc = -EINVAL;
263 		goto err;
264 	}
265 
266 	/*          < -- MAX_CHUNK_SIZE = 4096 * 256 = 1048576 bytes -->
267 	 * chunk 0  ----------------------------------------------------
268 	 *          | header   |  data                                 |
269 	 *          ----------------------------------------------------
270 	 * chunk 1  ----------------------------------------------------
271 	 *          | data                                             |
272 	 *          ----------------------------------------------------
273 	 * ....
274 	 * chunk n  ----------------------------------------------------
275 	 *          | data                                             |
276 	 *          ----------------------------------------------------
277 	 */
278 	from = (void *) ai->data;
279 	for (i = 0; i < entries; i++) {
280 		dest = buffer[i];
281 		s_copy = CXL_AI_BUFFER_SIZE;
282 
283 		if ((need_header) && (i == 0)) {
284 			/* add adapter image header */
285 			memcpy(buffer[i], header, sizeof(struct ai_header));
286 			s_copy = CXL_AI_BUFFER_SIZE - CXL_AI_HEADER_SIZE;
287 			dest += CXL_AI_HEADER_SIZE; /* image offset */
288 		}
289 		if ((i == (entries - 1)) && mod)
290 			s_copy = mod;
291 
292 		/* copy data */
293 		if (copy_from_user(dest, from, s_copy))
294 			goto err;
295 
296 		/* fill in the list */
297 		le[i].phys_addr = cpu_to_be64(virt_to_phys(buffer[i]));
298 		le[i].len = cpu_to_be64(CXL_AI_BUFFER_SIZE);
299 		if ((i == (entries - 1)) && mod)
300 			le[i].len = cpu_to_be64(mod);
301 		from += s_copy;
302 	}
303 	pr_devel("%s (op: %i, need header: %i, entries: %i, token: %#llx)\n",
304 		 __func__, operation, need_header, entries, continue_token);
305 
306 	/*
307 	 * download/validate the adapter image to the coherent
308 	 * platform facility
309 	 */
310 	rc = fct(adapter->guest->handle, virt_to_phys(le), entries,
311 		&continue_token);
312 	if (rc == 0) /* success of download/validation operation */
313 		continue_token = 0;
314 
315 err:
316 	kfree(header);
317 
318 	return rc;
319 }
320 
321 static int transfer_image(struct cxl *adapter, int operation,
322 			struct cxl_adapter_image *ai)
323 {
324 	int rc = 0;
325 	int afu;
326 
327 	switch (operation) {
328 	case DOWNLOAD_IMAGE:
329 		rc = handle_image(adapter, operation,
330 				&cxl_h_download_adapter_image, ai);
331 		if (rc < 0) {
332 			pr_devel("resetting adapter\n");
333 			cxl_h_reset_adapter(adapter->guest->handle);
334 		}
335 		return rc;
336 
337 	case VALIDATE_IMAGE:
338 		rc = handle_image(adapter, operation,
339 				&cxl_h_validate_adapter_image, ai);
340 		if (rc < 0) {
341 			pr_devel("resetting adapter\n");
342 			cxl_h_reset_adapter(adapter->guest->handle);
343 			return rc;
344 		}
345 		if (rc == 0) {
346 			pr_devel("remove curent afu\n");
347 			for (afu = 0; afu < adapter->slices; afu++)
348 				cxl_guest_remove_afu(adapter->afu[afu]);
349 
350 			pr_devel("resetting adapter\n");
351 			cxl_h_reset_adapter(adapter->guest->handle);
352 
353 			/* The entire image has now been
354 			 * downloaded and the validation has
355 			 * been successfully performed.
356 			 * After that, the partition should call
357 			 * ibm,update-nodes and
358 			 * ibm,update-properties to receive the
359 			 * current configuration
360 			 */
361 			rc = update_devicetree(adapter, DEVICE_SCOPE);
362 			transfer = 1;
363 		}
364 		return rc;
365 	}
366 
367 	return -EINVAL;
368 }
369 
370 static long ioctl_transfer_image(struct cxl *adapter, int operation,
371 				struct cxl_adapter_image __user *uai)
372 {
373 	struct cxl_adapter_image ai;
374 
375 	pr_devel("%s\n", __func__);
376 
377 	if (copy_from_user(&ai, uai, sizeof(struct cxl_adapter_image)))
378 		return -EFAULT;
379 
380 	/*
381 	 * Make sure reserved fields and bits are set to 0
382 	 */
383 	if (ai.reserved1 || ai.reserved2 || ai.reserved3 || ai.reserved4 ||
384 		(ai.flags & ~CXL_AI_ALL))
385 		return -EINVAL;
386 
387 	return transfer_image(adapter, operation, &ai);
388 }
389 
390 static int device_open(struct inode *inode, struct file *file)
391 {
392 	int adapter_num = CXL_DEVT_ADAPTER(inode->i_rdev);
393 	struct cxl *adapter;
394 	int rc = 0, i;
395 
396 	pr_devel("in %s\n", __func__);
397 
398 	BUG_ON(sizeof(struct ai_header) != CXL_AI_HEADER_SIZE);
399 
400 	/* Allows one process to open the device by using a semaphore */
401 	if (down_interruptible(&sem) != 0)
402 		return -EPERM;
403 
404 	if (!(adapter = get_cxl_adapter(adapter_num)))
405 		return -ENODEV;
406 
407 	file->private_data = adapter;
408 	continue_token = 0;
409 	transfer = 0;
410 
411 	for (i = 0; i < CXL_AI_MAX_ENTRIES; i++)
412 		buffer[i] = NULL;
413 
414 	/* aligned buffer containing list entries which describes up to
415 	 * 1 megabyte of data (256 entries of 4096 bytes each)
416 	 *  Logical real address of buffer 0  -  Buffer 0 length in bytes
417 	 *  Logical real address of buffer 1  -  Buffer 1 length in bytes
418 	 *  Logical real address of buffer 2  -  Buffer 2 length in bytes
419 	 *  ....
420 	 *  ....
421 	 *  Logical real address of buffer N  -  Buffer N length in bytes
422 	 */
423 	le = (struct sg_list *)get_zeroed_page(GFP_KERNEL);
424 	if (!le) {
425 		rc = -ENOMEM;
426 		goto err;
427 	}
428 
429 	for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
430 		buffer[i] = (unsigned long *)get_zeroed_page(GFP_KERNEL);
431 		if (!buffer[i]) {
432 			rc = -ENOMEM;
433 			goto err1;
434 		}
435 	}
436 
437 	return 0;
438 
439 err1:
440 	for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
441 		if (buffer[i])
442 			free_page((unsigned long) buffer[i]);
443 	}
444 
445 	if (le)
446 		free_page((unsigned long) le);
447 err:
448 	put_device(&adapter->dev);
449 
450 	return rc;
451 }
452 
453 static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
454 {
455 	struct cxl *adapter = file->private_data;
456 
457 	pr_devel("in %s\n", __func__);
458 
459 	if (cmd == CXL_IOCTL_DOWNLOAD_IMAGE)
460 		return ioctl_transfer_image(adapter,
461 					DOWNLOAD_IMAGE,
462 					(struct cxl_adapter_image __user *)arg);
463 	else if (cmd == CXL_IOCTL_VALIDATE_IMAGE)
464 		return ioctl_transfer_image(adapter,
465 					VALIDATE_IMAGE,
466 					(struct cxl_adapter_image __user *)arg);
467 	else
468 		return -EINVAL;
469 }
470 
471 static long device_compat_ioctl(struct file *file, unsigned int cmd,
472 				unsigned long arg)
473 {
474 	return device_ioctl(file, cmd, arg);
475 }
476 
477 static int device_close(struct inode *inode, struct file *file)
478 {
479 	struct cxl *adapter = file->private_data;
480 	int i;
481 
482 	pr_devel("in %s\n", __func__);
483 
484 	for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
485 		if (buffer[i])
486 			free_page((unsigned long) buffer[i]);
487 	}
488 
489 	if (le)
490 		free_page((unsigned long) le);
491 
492 	up(&sem);
493 	put_device(&adapter->dev);
494 	continue_token = 0;
495 
496 	/* reload the module */
497 	if (transfer)
498 		cxl_guest_reload_module(adapter);
499 	else {
500 		pr_devel("resetting adapter\n");
501 		cxl_h_reset_adapter(adapter->guest->handle);
502 	}
503 
504 	transfer = 0;
505 	return 0;
506 }
507 
508 static const struct file_operations fops = {
509 	.owner		= THIS_MODULE,
510 	.open		= device_open,
511 	.unlocked_ioctl	= device_ioctl,
512 	.compat_ioctl	= device_compat_ioctl,
513 	.release	= device_close,
514 };
515 
516 void cxl_guest_remove_chardev(struct cxl *adapter)
517 {
518 	cdev_del(&adapter->guest->cdev);
519 }
520 
521 int cxl_guest_add_chardev(struct cxl *adapter)
522 {
523 	dev_t devt;
524 	int rc;
525 
526 	devt = MKDEV(MAJOR(cxl_get_dev()), CXL_CARD_MINOR(adapter));
527 	cdev_init(&adapter->guest->cdev, &fops);
528 	if ((rc = cdev_add(&adapter->guest->cdev, devt, 1))) {
529 		dev_err(&adapter->dev,
530 			"Unable to add chardev on adapter (card%i): %i\n",
531 			adapter->adapter_num, rc);
532 		goto err;
533 	}
534 	adapter->dev.devt = devt;
535 	sema_init(&sem, 1);
536 err:
537 	return rc;
538 }
539