]> Git Repo - linux.git/blob - drivers/misc/cxl/flash.c
Merge tag 'audit-pr-20221003' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoor...
[linux.git] / drivers / misc / cxl / flash.c
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 }
This page took 0.061767 seconds and 4 git commands to generate.