1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
4 #include <linux/semaphore.h>
5 #include <linux/slab.h>
6 #include <linux/uaccess.h>
12 #define DOWNLOAD_IMAGE 1
13 #define VALIDATE_IMAGE 2
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
;
33 struct update_props_workarea
{
40 struct update_nodes_workarea
{
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
53 static int rcall(int token
, char *buf
, s32 scope
)
57 spin_lock(&rtas_data_buf_lock
);
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
);
63 spin_unlock(&rtas_data_buf_lock
);
67 static int update_property(struct device_node
*dn
, const char *name
,
70 struct property
*new_prop
;
74 new_prop
= kzalloc(sizeof(*new_prop
), GFP_KERNEL
);
78 new_prop
->name
= kstrdup(name
, GFP_KERNEL
);
79 if (!new_prop
->name
) {
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
);
91 memcpy(new_prop
->value
, value
, vd
);
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
));
99 kfree(new_prop
->name
);
100 kfree(new_prop
->value
);
106 static int update_node(__be32 phandle
, s32 scope
)
108 struct update_props_workarea
*upwa
;
109 struct device_node
*dn
;
117 token
= rtas_token("ibm,update-properties");
118 if (token
== RTAS_UNKNOWN_SERVICE
)
121 buf
= kzalloc(RTAS_DATA_BUF_SIZE
, GFP_KERNEL
);
125 dn
= of_find_node_by_phandle(be32_to_cpu(phandle
));
131 upwa
= (struct update_props_workarea
*)&buf
[0];
132 upwa
->phandle
= phandle
;
134 rc
= rcall(token
, buf
, scope
);
138 prop_data
= buf
+ sizeof(*upwa
);
139 nprops
= be32_to_cpu(upwa
->nprops
);
141 if (*prop_data
== 0) {
143 vd
= be32_to_cpu(*(__be32
*)prop_data
);
144 prop_data
+= vd
+ sizeof(vd
);
148 for (i
= 0; i
< nprops
; i
++) {
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
);
156 if ((vd
!= 0x00000000) && (vd
!= 0x80000000)) {
157 ret
= update_property(dn
, prop_name
, vd
,
160 pr_err("cxl: Could not update property %s - %i\n",
173 static int update_devicetree(struct cxl
*adapter
, s32 scope
)
175 struct update_nodes_workarea
*unwa
;
176 u32 action
, node_count
;
178 __be32
*data
, drc_index
, phandle
;
181 token
= rtas_token("ibm,update-nodes");
182 if (token
== RTAS_UNKNOWN_SERVICE
)
185 buf
= kzalloc(RTAS_DATA_BUF_SIZE
, GFP_KERNEL
);
189 unwa
= (struct update_nodes_workarea
*)&buf
[0];
190 unwa
->unit_address
= cpu_to_be64(adapter
->guest
->handle
);
192 rc
= rcall(token
, buf
, scope
);
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",
204 for (i
= 0; i
< node_count
; i
++) {
212 update_node(phandle
, scope
);
215 /* nothing to do, just move pointer */
227 static int handle_image(struct cxl
*adapter
, int operation
,
228 long (*fct
)(u64
, u64
, u64
, u64
*),
229 struct cxl_adapter_image
*ai
)
231 size_t mod
, s_copy
, len_chunk
= 0;
232 struct ai_header
*header
= NULL
;
233 unsigned int entries
= 0, i
;
235 int rc
= 0, need_header
;
237 /* base adapter image header */
238 need_header
= (ai
->flags
& CXL_AI_NEED_HEADER
);
240 header
= kzalloc(sizeof(struct ai_header
), GFP_KERNEL
);
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
);
252 /* number of entries in the list */
253 len_chunk
= ai
->len_data
;
255 len_chunk
+= CXL_AI_HEADER_SIZE
;
257 entries
= len_chunk
/ CXL_AI_BUFFER_SIZE
;
258 mod
= len_chunk
% CXL_AI_BUFFER_SIZE
;
262 if (entries
> CXL_AI_MAX_ENTRIES
) {
267 /* < -- MAX_CHUNK_SIZE = 4096 * 256 = 1048576 bytes -->
268 * chunk 0 ----------------------------------------------------
270 * ----------------------------------------------------
271 * chunk 1 ----------------------------------------------------
273 * ----------------------------------------------------
275 * chunk n ----------------------------------------------------
277 * ----------------------------------------------------
279 from
= (void *) ai
->data
;
280 for (i
= 0; i
< entries
; i
++) {
282 s_copy
= CXL_AI_BUFFER_SIZE
;
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 */
290 if ((i
== (entries
- 1)) && mod
)
294 if (copy_from_user(dest
, from
, s_copy
))
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
);
304 pr_devel("%s (op: %i, need header: %i, entries: %i, token: %#llx)\n",
305 __func__
, operation
, need_header
, entries
, continue_token
);
308 * download/validate the adapter image to the coherent
311 rc
= fct(adapter
->guest
->handle
, virt_to_phys(le
), entries
,
313 if (rc
== 0) /* success of download/validation operation */
322 static int transfer_image(struct cxl
*adapter
, int operation
,
323 struct cxl_adapter_image
*ai
)
330 rc
= handle_image(adapter
, operation
,
331 &cxl_h_download_adapter_image
, ai
);
333 pr_devel("resetting adapter\n");
334 cxl_h_reset_adapter(adapter
->guest
->handle
);
339 rc
= handle_image(adapter
, operation
,
340 &cxl_h_validate_adapter_image
, ai
);
342 pr_devel("resetting adapter\n");
343 cxl_h_reset_adapter(adapter
->guest
->handle
);
347 pr_devel("remove current afu\n");
348 for (afu
= 0; afu
< adapter
->slices
; afu
++)
349 cxl_guest_remove_afu(adapter
->afu
[afu
]);
351 pr_devel("resetting adapter\n");
352 cxl_h_reset_adapter(adapter
->guest
->handle
);
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
362 rc
= update_devicetree(adapter
, DEVICE_SCOPE
);
371 static long ioctl_transfer_image(struct cxl
*adapter
, int operation
,
372 struct cxl_adapter_image __user
*uai
)
374 struct cxl_adapter_image ai
;
376 pr_devel("%s\n", __func__
);
378 if (copy_from_user(&ai
, uai
, sizeof(struct cxl_adapter_image
)))
382 * Make sure reserved fields and bits are set to 0
384 if (ai
.reserved1
|| ai
.reserved2
|| ai
.reserved3
|| ai
.reserved4
||
385 (ai
.flags
& ~CXL_AI_ALL
))
388 return transfer_image(adapter
, operation
, &ai
);
391 static int device_open(struct inode
*inode
, struct file
*file
)
393 int adapter_num
= CXL_DEVT_ADAPTER(inode
->i_rdev
);
397 pr_devel("in %s\n", __func__
);
399 BUG_ON(sizeof(struct ai_header
) != CXL_AI_HEADER_SIZE
);
401 /* Allows one process to open the device by using a semaphore */
402 if (down_interruptible(&sem
) != 0)
405 if (!(adapter
= get_cxl_adapter(adapter_num
))) {
410 file
->private_data
= adapter
;
414 for (i
= 0; i
< CXL_AI_MAX_ENTRIES
; i
++)
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
424 * Logical real address of buffer N - Buffer N length in bytes
426 le
= (struct sg_list
*)get_zeroed_page(GFP_KERNEL
);
432 for (i
= 0; i
< CXL_AI_MAX_ENTRIES
; i
++) {
433 buffer
[i
] = (unsigned long *)get_zeroed_page(GFP_KERNEL
);
443 for (i
= 0; i
< CXL_AI_MAX_ENTRIES
; i
++) {
445 free_page((unsigned long) buffer
[i
]);
449 free_page((unsigned long) le
);
451 put_device(&adapter
->dev
);
458 static long device_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
460 struct cxl
*adapter
= file
->private_data
;
462 pr_devel("in %s\n", __func__
);
464 if (cmd
== CXL_IOCTL_DOWNLOAD_IMAGE
)
465 return ioctl_transfer_image(adapter
,
467 (struct cxl_adapter_image __user
*)arg
);
468 else if (cmd
== CXL_IOCTL_VALIDATE_IMAGE
)
469 return ioctl_transfer_image(adapter
,
471 (struct cxl_adapter_image __user
*)arg
);
476 static long device_compat_ioctl(struct file
*file
, unsigned int cmd
,
479 return device_ioctl(file
, cmd
, arg
);
482 static int device_close(struct inode
*inode
, struct file
*file
)
484 struct cxl
*adapter
= file
->private_data
;
487 pr_devel("in %s\n", __func__
);
489 for (i
= 0; i
< CXL_AI_MAX_ENTRIES
; i
++) {
491 free_page((unsigned long) buffer
[i
]);
495 free_page((unsigned long) le
);
498 put_device(&adapter
->dev
);
501 /* reload the module */
503 cxl_guest_reload_module(adapter
);
505 pr_devel("resetting adapter\n");
506 cxl_h_reset_adapter(adapter
->guest
->handle
);
513 static const struct file_operations fops
= {
514 .owner
= THIS_MODULE
,
516 .unlocked_ioctl
= device_ioctl
,
517 .compat_ioctl
= device_compat_ioctl
,
518 .release
= device_close
,
521 void cxl_guest_remove_chardev(struct cxl
*adapter
)
523 cdev_del(&adapter
->guest
->cdev
);
526 int cxl_guest_add_chardev(struct cxl
*adapter
)
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
);
539 adapter
->dev
.devt
= devt
;