Linux Audio

Check our new training course

Loading...
v6.8
  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
 16struct 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
 28static struct semaphore sem;
 29static unsigned long *buffer[CXL_AI_MAX_ENTRIES];
 30static struct sg_list *le;
 31static u64 continue_token;
 32static unsigned int transfer;
 33
 34struct update_props_workarea {
 35	__be32 phandle;
 36	__be32 state;
 37	__be64 reserved;
 38	__be32 nprops;
 39} __packed;
 40
 41struct 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
 54static 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
 68static 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
107static 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
174static 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
228static 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
317err:
318	kfree(header);
319
320	return rc;
321}
322
323static 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
372static 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
392static 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
443err1:
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);
451err:
452	put_device(&adapter->dev);
453err_unlock:
454	up(&sem);
455
456	return rc;
457}
458
459static 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
 
 
 
 
 
 
477static 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
508static 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
516void cxl_guest_remove_chardev(struct cxl *adapter)
517{
518	cdev_del(&adapter->guest->cdev);
519}
520
521int 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);
536err:
537	return rc;
538}
v4.17
  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
 15struct 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
 27static struct semaphore sem;
 28static unsigned long *buffer[CXL_AI_MAX_ENTRIES];
 29static struct sg_list *le;
 30static u64 continue_token;
 31static unsigned int transfer;
 32
 33struct update_props_workarea {
 34	__be32 phandle;
 35	__be32 state;
 36	__be64 reserved;
 37	__be32 nprops;
 38} __packed;
 39
 40struct 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
 53static 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
 67static 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("%s: update property (%s, length: %i, value: %#x)\n",
 96		  dn->name, 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
106static 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
173static 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
227static 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
316err:
317	kfree(header);
318
319	return rc;
320}
321
322static 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
371static 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
391static 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
442err1:
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);
450err:
451	put_device(&adapter->dev);
452err_unlock:
453	up(&sem);
454
455	return rc;
456}
457
458static 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
476static long device_compat_ioctl(struct file *file, unsigned int cmd,
477				unsigned long arg)
478{
479	return device_ioctl(file, cmd, arg);
480}
481
482static int device_close(struct inode *inode, struct file *file)
483{
484	struct cxl *adapter = file->private_data;
485	int i;
486
487	pr_devel("in %s\n", __func__);
488
489	for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
490		if (buffer[i])
491			free_page((unsigned long) buffer[i]);
492	}
493
494	if (le)
495		free_page((unsigned long) le);
496
497	up(&sem);
498	put_device(&adapter->dev);
499	continue_token = 0;
500
501	/* reload the module */
502	if (transfer)
503		cxl_guest_reload_module(adapter);
504	else {
505		pr_devel("resetting adapter\n");
506		cxl_h_reset_adapter(adapter->guest->handle);
507	}
508
509	transfer = 0;
510	return 0;
511}
512
513static const struct file_operations fops = {
514	.owner		= THIS_MODULE,
515	.open		= device_open,
516	.unlocked_ioctl	= device_ioctl,
517	.compat_ioctl	= device_compat_ioctl,
518	.release	= device_close,
519};
520
521void cxl_guest_remove_chardev(struct cxl *adapter)
522{
523	cdev_del(&adapter->guest->cdev);
524}
525
526int cxl_guest_add_chardev(struct cxl *adapter)
527{
528	dev_t devt;
529	int rc;
530
531	devt = MKDEV(MAJOR(cxl_get_dev()), CXL_CARD_MINOR(adapter));
532	cdev_init(&adapter->guest->cdev, &fops);
533	if ((rc = cdev_add(&adapter->guest->cdev, devt, 1))) {
534		dev_err(&adapter->dev,
535			"Unable to add chardev on adapter (card%i): %i\n",
536			adapter->adapter_num, rc);
537		goto err;
538	}
539	adapter->dev.devt = devt;
540	sema_init(&sem, 1);
541err:
542	return rc;
543}