Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/kernel.h>
0003 #include <linux/fs.h>
0004 #include <linux/semaphore.h>
0005 #include <linux/slab.h>
0006 #include <linux/uaccess.h>
0007 #include <linux/of.h>
0008 #include <asm/rtas.h>
0009 
0010 #include "cxl.h"
0011 #include "hcalls.h"
0012 
0013 #define DOWNLOAD_IMAGE 1
0014 #define VALIDATE_IMAGE 2
0015 
0016 struct ai_header {
0017     u16 version;
0018     u8  reserved0[6];
0019     u16 vendor;
0020     u16 device;
0021     u16 subsystem_vendor;
0022     u16 subsystem;
0023     u64 image_offset;
0024     u64 image_length;
0025     u8  reserved1[96];
0026 };
0027 
0028 static struct semaphore sem;
0029 static unsigned long *buffer[CXL_AI_MAX_ENTRIES];
0030 static struct sg_list *le;
0031 static u64 continue_token;
0032 static unsigned int transfer;
0033 
0034 struct update_props_workarea {
0035     __be32 phandle;
0036     __be32 state;
0037     __be64 reserved;
0038     __be32 nprops;
0039 } __packed;
0040 
0041 struct update_nodes_workarea {
0042     __be32 state;
0043     __be64 unit_address;
0044     __be32 reserved;
0045 } __packed;
0046 
0047 #define DEVICE_SCOPE 3
0048 #define NODE_ACTION_MASK    0xff000000
0049 #define NODE_COUNT_MASK     0x00ffffff
0050 #define OPCODE_DELETE   0x01000000
0051 #define OPCODE_UPDATE   0x02000000
0052 #define OPCODE_ADD  0x03000000
0053 
0054 static int rcall(int token, char *buf, s32 scope)
0055 {
0056     int rc;
0057 
0058     spin_lock(&rtas_data_buf_lock);
0059 
0060     memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE);
0061     rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, scope);
0062     memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
0063 
0064     spin_unlock(&rtas_data_buf_lock);
0065     return rc;
0066 }
0067 
0068 static int update_property(struct device_node *dn, const char *name,
0069                u32 vd, char *value)
0070 {
0071     struct property *new_prop;
0072     u32 *val;
0073     int rc;
0074 
0075     new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
0076     if (!new_prop)
0077         return -ENOMEM;
0078 
0079     new_prop->name = kstrdup(name, GFP_KERNEL);
0080     if (!new_prop->name) {
0081         kfree(new_prop);
0082         return -ENOMEM;
0083     }
0084 
0085     new_prop->length = vd;
0086     new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
0087     if (!new_prop->value) {
0088         kfree(new_prop->name);
0089         kfree(new_prop);
0090         return -ENOMEM;
0091     }
0092     memcpy(new_prop->value, value, vd);
0093 
0094     val = (u32 *)new_prop->value;
0095     rc = cxl_update_properties(dn, new_prop);
0096     pr_devel("%pOFn: update property (%s, length: %i, value: %#x)\n",
0097           dn, name, vd, be32_to_cpu(*val));
0098 
0099     if (rc) {
0100         kfree(new_prop->name);
0101         kfree(new_prop->value);
0102         kfree(new_prop);
0103     }
0104     return rc;
0105 }
0106 
0107 static int update_node(__be32 phandle, s32 scope)
0108 {
0109     struct update_props_workarea *upwa;
0110     struct device_node *dn;
0111     int i, rc, ret;
0112     char *prop_data;
0113     char *buf;
0114     int token;
0115     u32 nprops;
0116     u32 vd;
0117 
0118     token = rtas_token("ibm,update-properties");
0119     if (token == RTAS_UNKNOWN_SERVICE)
0120         return -EINVAL;
0121 
0122     buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
0123     if (!buf)
0124         return -ENOMEM;
0125 
0126     dn = of_find_node_by_phandle(be32_to_cpu(phandle));
0127     if (!dn) {
0128         kfree(buf);
0129         return -ENOENT;
0130     }
0131 
0132     upwa = (struct update_props_workarea *)&buf[0];
0133     upwa->phandle = phandle;
0134     do {
0135         rc = rcall(token, buf, scope);
0136         if (rc < 0)
0137             break;
0138 
0139         prop_data = buf + sizeof(*upwa);
0140         nprops = be32_to_cpu(upwa->nprops);
0141 
0142         if (*prop_data == 0) {
0143             prop_data++;
0144             vd = be32_to_cpu(*(__be32 *)prop_data);
0145             prop_data += vd + sizeof(vd);
0146             nprops--;
0147         }
0148 
0149         for (i = 0; i < nprops; i++) {
0150             char *prop_name;
0151 
0152             prop_name = prop_data;
0153             prop_data += strlen(prop_name) + 1;
0154             vd = be32_to_cpu(*(__be32 *)prop_data);
0155             prop_data += sizeof(vd);
0156 
0157             if ((vd != 0x00000000) && (vd != 0x80000000)) {
0158                 ret = update_property(dn, prop_name, vd,
0159                         prop_data);
0160                 if (ret)
0161                     pr_err("cxl: Could not update property %s - %i\n",
0162                            prop_name, ret);
0163 
0164                 prop_data += vd;
0165             }
0166         }
0167     } while (rc == 1);
0168 
0169     of_node_put(dn);
0170     kfree(buf);
0171     return rc;
0172 }
0173 
0174 static int update_devicetree(struct cxl *adapter, s32 scope)
0175 {
0176     struct update_nodes_workarea *unwa;
0177     u32 action, node_count;
0178     int token, rc, i;
0179     __be32 *data, phandle;
0180     char *buf;
0181 
0182     token = rtas_token("ibm,update-nodes");
0183     if (token == RTAS_UNKNOWN_SERVICE)
0184         return -EINVAL;
0185 
0186     buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
0187     if (!buf)
0188         return -ENOMEM;
0189 
0190     unwa = (struct update_nodes_workarea *)&buf[0];
0191     unwa->unit_address = cpu_to_be64(adapter->guest->handle);
0192     do {
0193         rc = rcall(token, buf, scope);
0194         if (rc && rc != 1)
0195             break;
0196 
0197         data = (__be32 *)buf + 4;
0198         while (be32_to_cpu(*data) & NODE_ACTION_MASK) {
0199             action = be32_to_cpu(*data) & NODE_ACTION_MASK;
0200             node_count = be32_to_cpu(*data) & NODE_COUNT_MASK;
0201             pr_devel("device reconfiguration - action: %#x, nodes: %#x\n",
0202                  action, node_count);
0203             data++;
0204 
0205             for (i = 0; i < node_count; i++) {
0206                 phandle = *data++;
0207 
0208                 switch (action) {
0209                 case OPCODE_DELETE:
0210                     /* nothing to do */
0211                     break;
0212                 case OPCODE_UPDATE:
0213                     update_node(phandle, scope);
0214                     break;
0215                 case OPCODE_ADD:
0216                     /* nothing to do, just move pointer */
0217                     data++;
0218                     break;
0219                 }
0220             }
0221         }
0222     } while (rc == 1);
0223 
0224     kfree(buf);
0225     return 0;
0226 }
0227 
0228 static int handle_image(struct cxl *adapter, int operation,
0229             long (*fct)(u64, u64, u64, u64 *),
0230             struct cxl_adapter_image *ai)
0231 {
0232     size_t mod, s_copy, len_chunk = 0;
0233     struct ai_header *header = NULL;
0234     unsigned int entries = 0, i;
0235     void *dest, *from;
0236     int rc = 0, need_header;
0237 
0238     /* base adapter image header */
0239     need_header = (ai->flags & CXL_AI_NEED_HEADER);
0240     if (need_header) {
0241         header = kzalloc(sizeof(struct ai_header), GFP_KERNEL);
0242         if (!header)
0243             return -ENOMEM;
0244         header->version = cpu_to_be16(1);
0245         header->vendor = cpu_to_be16(adapter->guest->vendor);
0246         header->device = cpu_to_be16(adapter->guest->device);
0247         header->subsystem_vendor = cpu_to_be16(adapter->guest->subsystem_vendor);
0248         header->subsystem = cpu_to_be16(adapter->guest->subsystem);
0249         header->image_offset = cpu_to_be64(CXL_AI_HEADER_SIZE);
0250         header->image_length = cpu_to_be64(ai->len_image);
0251     }
0252 
0253     /* number of entries in the list */
0254     len_chunk = ai->len_data;
0255     if (need_header)
0256         len_chunk += CXL_AI_HEADER_SIZE;
0257 
0258     entries = len_chunk / CXL_AI_BUFFER_SIZE;
0259     mod = len_chunk % CXL_AI_BUFFER_SIZE;
0260     if (mod)
0261         entries++;
0262 
0263     if (entries > CXL_AI_MAX_ENTRIES) {
0264         rc = -EINVAL;
0265         goto err;
0266     }
0267 
0268     /*          < -- MAX_CHUNK_SIZE = 4096 * 256 = 1048576 bytes -->
0269      * chunk 0  ----------------------------------------------------
0270      *          | header   |  data                                 |
0271      *          ----------------------------------------------------
0272      * chunk 1  ----------------------------------------------------
0273      *          | data                                             |
0274      *          ----------------------------------------------------
0275      * ....
0276      * chunk n  ----------------------------------------------------
0277      *          | data                                             |
0278      *          ----------------------------------------------------
0279      */
0280     from = (void *) ai->data;
0281     for (i = 0; i < entries; i++) {
0282         dest = buffer[i];
0283         s_copy = CXL_AI_BUFFER_SIZE;
0284 
0285         if ((need_header) && (i == 0)) {
0286             /* add adapter image header */
0287             memcpy(buffer[i], header, sizeof(struct ai_header));
0288             s_copy = CXL_AI_BUFFER_SIZE - CXL_AI_HEADER_SIZE;
0289             dest += CXL_AI_HEADER_SIZE; /* image offset */
0290         }
0291         if ((i == (entries - 1)) && mod)
0292             s_copy = mod;
0293 
0294         /* copy data */
0295         if (copy_from_user(dest, from, s_copy))
0296             goto err;
0297 
0298         /* fill in the list */
0299         le[i].phys_addr = cpu_to_be64(virt_to_phys(buffer[i]));
0300         le[i].len = cpu_to_be64(CXL_AI_BUFFER_SIZE);
0301         if ((i == (entries - 1)) && mod)
0302             le[i].len = cpu_to_be64(mod);
0303         from += s_copy;
0304     }
0305     pr_devel("%s (op: %i, need header: %i, entries: %i, token: %#llx)\n",
0306          __func__, operation, need_header, entries, continue_token);
0307 
0308     /*
0309      * download/validate the adapter image to the coherent
0310      * platform facility
0311      */
0312     rc = fct(adapter->guest->handle, virt_to_phys(le), entries,
0313         &continue_token);
0314     if (rc == 0) /* success of download/validation operation */
0315         continue_token = 0;
0316 
0317 err:
0318     kfree(header);
0319 
0320     return rc;
0321 }
0322 
0323 static int transfer_image(struct cxl *adapter, int operation,
0324             struct cxl_adapter_image *ai)
0325 {
0326     int rc = 0;
0327     int afu;
0328 
0329     switch (operation) {
0330     case DOWNLOAD_IMAGE:
0331         rc = handle_image(adapter, operation,
0332                 &cxl_h_download_adapter_image, ai);
0333         if (rc < 0) {
0334             pr_devel("resetting adapter\n");
0335             cxl_h_reset_adapter(adapter->guest->handle);
0336         }
0337         return rc;
0338 
0339     case VALIDATE_IMAGE:
0340         rc = handle_image(adapter, operation,
0341                 &cxl_h_validate_adapter_image, ai);
0342         if (rc < 0) {
0343             pr_devel("resetting adapter\n");
0344             cxl_h_reset_adapter(adapter->guest->handle);
0345             return rc;
0346         }
0347         if (rc == 0) {
0348             pr_devel("remove current afu\n");
0349             for (afu = 0; afu < adapter->slices; afu++)
0350                 cxl_guest_remove_afu(adapter->afu[afu]);
0351 
0352             pr_devel("resetting adapter\n");
0353             cxl_h_reset_adapter(adapter->guest->handle);
0354 
0355             /* The entire image has now been
0356              * downloaded and the validation has
0357              * been successfully performed.
0358              * After that, the partition should call
0359              * ibm,update-nodes and
0360              * ibm,update-properties to receive the
0361              * current configuration
0362              */
0363             rc = update_devicetree(adapter, DEVICE_SCOPE);
0364             transfer = 1;
0365         }
0366         return rc;
0367     }
0368 
0369     return -EINVAL;
0370 }
0371 
0372 static long ioctl_transfer_image(struct cxl *adapter, int operation,
0373                 struct cxl_adapter_image __user *uai)
0374 {
0375     struct cxl_adapter_image ai;
0376 
0377     pr_devel("%s\n", __func__);
0378 
0379     if (copy_from_user(&ai, uai, sizeof(struct cxl_adapter_image)))
0380         return -EFAULT;
0381 
0382     /*
0383      * Make sure reserved fields and bits are set to 0
0384      */
0385     if (ai.reserved1 || ai.reserved2 || ai.reserved3 || ai.reserved4 ||
0386         (ai.flags & ~CXL_AI_ALL))
0387         return -EINVAL;
0388 
0389     return transfer_image(adapter, operation, &ai);
0390 }
0391 
0392 static int device_open(struct inode *inode, struct file *file)
0393 {
0394     int adapter_num = CXL_DEVT_ADAPTER(inode->i_rdev);
0395     struct cxl *adapter;
0396     int rc = 0, i;
0397 
0398     pr_devel("in %s\n", __func__);
0399 
0400     BUG_ON(sizeof(struct ai_header) != CXL_AI_HEADER_SIZE);
0401 
0402     /* Allows one process to open the device by using a semaphore */
0403     if (down_interruptible(&sem) != 0)
0404         return -EPERM;
0405 
0406     if (!(adapter = get_cxl_adapter(adapter_num))) {
0407         rc = -ENODEV;
0408         goto err_unlock;
0409     }
0410 
0411     file->private_data = adapter;
0412     continue_token = 0;
0413     transfer = 0;
0414 
0415     for (i = 0; i < CXL_AI_MAX_ENTRIES; i++)
0416         buffer[i] = NULL;
0417 
0418     /* aligned buffer containing list entries which describes up to
0419      * 1 megabyte of data (256 entries of 4096 bytes each)
0420      *  Logical real address of buffer 0  -  Buffer 0 length in bytes
0421      *  Logical real address of buffer 1  -  Buffer 1 length in bytes
0422      *  Logical real address of buffer 2  -  Buffer 2 length in bytes
0423      *  ....
0424      *  ....
0425      *  Logical real address of buffer N  -  Buffer N length in bytes
0426      */
0427     le = (struct sg_list *)get_zeroed_page(GFP_KERNEL);
0428     if (!le) {
0429         rc = -ENOMEM;
0430         goto err;
0431     }
0432 
0433     for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
0434         buffer[i] = (unsigned long *)get_zeroed_page(GFP_KERNEL);
0435         if (!buffer[i]) {
0436             rc = -ENOMEM;
0437             goto err1;
0438         }
0439     }
0440 
0441     return 0;
0442 
0443 err1:
0444     for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
0445         if (buffer[i])
0446             free_page((unsigned long) buffer[i]);
0447     }
0448 
0449     if (le)
0450         free_page((unsigned long) le);
0451 err:
0452     put_device(&adapter->dev);
0453 err_unlock:
0454     up(&sem);
0455 
0456     return rc;
0457 }
0458 
0459 static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0460 {
0461     struct cxl *adapter = file->private_data;
0462 
0463     pr_devel("in %s\n", __func__);
0464 
0465     if (cmd == CXL_IOCTL_DOWNLOAD_IMAGE)
0466         return ioctl_transfer_image(adapter,
0467                     DOWNLOAD_IMAGE,
0468                     (struct cxl_adapter_image __user *)arg);
0469     else if (cmd == CXL_IOCTL_VALIDATE_IMAGE)
0470         return ioctl_transfer_image(adapter,
0471                     VALIDATE_IMAGE,
0472                     (struct cxl_adapter_image __user *)arg);
0473     else
0474         return -EINVAL;
0475 }
0476 
0477 static int device_close(struct inode *inode, struct file *file)
0478 {
0479     struct cxl *adapter = file->private_data;
0480     int i;
0481 
0482     pr_devel("in %s\n", __func__);
0483 
0484     for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
0485         if (buffer[i])
0486             free_page((unsigned long) buffer[i]);
0487     }
0488 
0489     if (le)
0490         free_page((unsigned long) le);
0491 
0492     up(&sem);
0493     put_device(&adapter->dev);
0494     continue_token = 0;
0495 
0496     /* reload the module */
0497     if (transfer)
0498         cxl_guest_reload_module(adapter);
0499     else {
0500         pr_devel("resetting adapter\n");
0501         cxl_h_reset_adapter(adapter->guest->handle);
0502     }
0503 
0504     transfer = 0;
0505     return 0;
0506 }
0507 
0508 static const struct file_operations fops = {
0509     .owner      = THIS_MODULE,
0510     .open       = device_open,
0511     .unlocked_ioctl = device_ioctl,
0512     .compat_ioctl   = compat_ptr_ioctl,
0513     .release    = device_close,
0514 };
0515 
0516 void cxl_guest_remove_chardev(struct cxl *adapter)
0517 {
0518     cdev_del(&adapter->guest->cdev);
0519 }
0520 
0521 int cxl_guest_add_chardev(struct cxl *adapter)
0522 {
0523     dev_t devt;
0524     int rc;
0525 
0526     devt = MKDEV(MAJOR(cxl_get_dev()), CXL_CARD_MINOR(adapter));
0527     cdev_init(&adapter->guest->cdev, &fops);
0528     if ((rc = cdev_add(&adapter->guest->cdev, devt, 1))) {
0529         dev_err(&adapter->dev,
0530             "Unable to add chardev on adapter (card%i): %i\n",
0531             adapter->adapter_num, rc);
0532         goto err;
0533     }
0534     adapter->dev.devt = devt;
0535     sema_init(&sem, 1);
0536 err:
0537     return rc;
0538 }