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