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