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