flash.c (12560B)
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 16struct 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 28static struct semaphore sem; 29static unsigned long *buffer[CXL_AI_MAX_ENTRIES]; 30static struct sg_list *le; 31static u64 continue_token; 32static unsigned int transfer; 33 34struct update_props_workarea { 35 __be32 phandle; 36 __be32 state; 37 __be64 reserved; 38 __be32 nprops; 39} __packed; 40 41struct 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 54static 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 68static 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 107static 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 174static 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 228static 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 317err: 318 kfree(header); 319 320 return rc; 321} 322 323static 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 372static 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 392static 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 443err1: 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); 451err: 452 put_device(&adapter->dev); 453err_unlock: 454 up(&sem); 455 456 return rc; 457} 458 459static 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 477static 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 508static 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 516void cxl_guest_remove_chardev(struct cxl *adapter) 517{ 518 cdev_del(&adapter->guest->cdev); 519} 520 521int 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); 536err: 537 return rc; 538}