0001
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
0211 break;
0212 case OPCODE_UPDATE:
0213 update_node(phandle, scope);
0214 break;
0215 case OPCODE_ADD:
0216
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
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
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
0269
0270
0271
0272
0273
0274
0275
0276
0277
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
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;
0290 }
0291 if ((i == (entries - 1)) && mod)
0292 s_copy = mod;
0293
0294
0295 if (copy_from_user(dest, from, s_copy))
0296 goto err;
0297
0298
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
0310
0311
0312 rc = fct(adapter->guest->handle, virt_to_phys(le), entries,
0313 &continue_token);
0314 if (rc == 0)
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
0356
0357
0358
0359
0360
0361
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
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
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
0419
0420
0421
0422
0423
0424
0425
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
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 }