1 /* 2 * Copyright 2014 IBM Corp. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/device.h> 12 #include <linux/sysfs.h> 13 #include <linux/pci_regs.h> 14 15 #include "cxl.h" 16 17 #define to_afu_chardev_m(d) dev_get_drvdata(d) 18 19 /********* Adapter attributes **********************************************/ 20 21 static ssize_t caia_version_show(struct device *device, 22 struct device_attribute *attr, 23 char *buf) 24 { 25 struct cxl *adapter = to_cxl_adapter(device); 26 27 return scnprintf(buf, PAGE_SIZE, "%i.%i\n", adapter->caia_major, 28 adapter->caia_minor); 29 } 30 31 static ssize_t psl_revision_show(struct device *device, 32 struct device_attribute *attr, 33 char *buf) 34 { 35 struct cxl *adapter = to_cxl_adapter(device); 36 37 return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_rev); 38 } 39 40 static ssize_t base_image_show(struct device *device, 41 struct device_attribute *attr, 42 char *buf) 43 { 44 struct cxl *adapter = to_cxl_adapter(device); 45 46 return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->base_image); 47 } 48 49 static ssize_t image_loaded_show(struct device *device, 50 struct device_attribute *attr, 51 char *buf) 52 { 53 struct cxl *adapter = to_cxl_adapter(device); 54 55 if (adapter->user_image_loaded) 56 return scnprintf(buf, PAGE_SIZE, "user\n"); 57 return scnprintf(buf, PAGE_SIZE, "factory\n"); 58 } 59 60 static ssize_t reset_adapter_store(struct device *device, 61 struct device_attribute *attr, 62 const char *buf, size_t count) 63 { 64 struct cxl *adapter = to_cxl_adapter(device); 65 int rc; 66 int val; 67 68 rc = sscanf(buf, "%i", &val); 69 if ((rc != 1) || (val != 1)) 70 return -EINVAL; 71 72 if ((rc = cxl_reset(adapter))) 73 return rc; 74 return count; 75 } 76 77 static ssize_t load_image_on_perst_show(struct device *device, 78 struct device_attribute *attr, 79 char *buf) 80 { 81 struct cxl *adapter = to_cxl_adapter(device); 82 83 if (!adapter->perst_loads_image) 84 return scnprintf(buf, PAGE_SIZE, "none\n"); 85 86 if (adapter->perst_select_user) 87 return scnprintf(buf, PAGE_SIZE, "user\n"); 88 return scnprintf(buf, PAGE_SIZE, "factory\n"); 89 } 90 91 static ssize_t load_image_on_perst_store(struct device *device, 92 struct device_attribute *attr, 93 const char *buf, size_t count) 94 { 95 struct cxl *adapter = to_cxl_adapter(device); 96 int rc; 97 98 if (!strncmp(buf, "none", 4)) 99 adapter->perst_loads_image = false; 100 else if (!strncmp(buf, "user", 4)) { 101 adapter->perst_select_user = true; 102 adapter->perst_loads_image = true; 103 } else if (!strncmp(buf, "factory", 7)) { 104 adapter->perst_select_user = false; 105 adapter->perst_loads_image = true; 106 } else 107 return -EINVAL; 108 109 if ((rc = cxl_update_image_control(adapter))) 110 return rc; 111 112 return count; 113 } 114 115 static struct device_attribute adapter_attrs[] = { 116 __ATTR_RO(caia_version), 117 __ATTR_RO(psl_revision), 118 __ATTR_RO(base_image), 119 __ATTR_RO(image_loaded), 120 __ATTR_RW(load_image_on_perst), 121 __ATTR(reset, S_IWUSR, NULL, reset_adapter_store), 122 }; 123 124 125 /********* AFU master specific attributes **********************************/ 126 127 static ssize_t mmio_size_show_master(struct device *device, 128 struct device_attribute *attr, 129 char *buf) 130 { 131 struct cxl_afu *afu = to_afu_chardev_m(device); 132 133 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->adapter->ps_size); 134 } 135 136 static ssize_t pp_mmio_off_show(struct device *device, 137 struct device_attribute *attr, 138 char *buf) 139 { 140 struct cxl_afu *afu = to_afu_chardev_m(device); 141 142 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->pp_offset); 143 } 144 145 static ssize_t pp_mmio_len_show(struct device *device, 146 struct device_attribute *attr, 147 char *buf) 148 { 149 struct cxl_afu *afu = to_afu_chardev_m(device); 150 151 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->pp_size); 152 } 153 154 static struct device_attribute afu_master_attrs[] = { 155 __ATTR(mmio_size, S_IRUGO, mmio_size_show_master, NULL), 156 __ATTR_RO(pp_mmio_off), 157 __ATTR_RO(pp_mmio_len), 158 }; 159 160 161 /********* AFU attributes **************************************************/ 162 163 static ssize_t mmio_size_show(struct device *device, 164 struct device_attribute *attr, 165 char *buf) 166 { 167 struct cxl_afu *afu = to_cxl_afu(device); 168 169 if (afu->pp_size) 170 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->pp_size); 171 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->adapter->ps_size); 172 } 173 174 static ssize_t reset_store_afu(struct device *device, 175 struct device_attribute *attr, 176 const char *buf, size_t count) 177 { 178 struct cxl_afu *afu = to_cxl_afu(device); 179 int rc; 180 181 /* Not safe to reset if it is currently in use */ 182 mutex_lock(&afu->contexts_lock); 183 if (!idr_is_empty(&afu->contexts_idr)) { 184 rc = -EBUSY; 185 goto err; 186 } 187 188 if ((rc = __cxl_afu_reset(afu))) 189 goto err; 190 191 rc = count; 192 err: 193 mutex_unlock(&afu->contexts_lock); 194 return rc; 195 } 196 197 static ssize_t irqs_min_show(struct device *device, 198 struct device_attribute *attr, 199 char *buf) 200 { 201 struct cxl_afu *afu = to_cxl_afu(device); 202 203 return scnprintf(buf, PAGE_SIZE, "%i\n", afu->pp_irqs); 204 } 205 206 static ssize_t irqs_max_show(struct device *device, 207 struct device_attribute *attr, 208 char *buf) 209 { 210 struct cxl_afu *afu = to_cxl_afu(device); 211 212 return scnprintf(buf, PAGE_SIZE, "%i\n", afu->irqs_max); 213 } 214 215 static ssize_t irqs_max_store(struct device *device, 216 struct device_attribute *attr, 217 const char *buf, size_t count) 218 { 219 struct cxl_afu *afu = to_cxl_afu(device); 220 ssize_t ret; 221 int irqs_max; 222 223 ret = sscanf(buf, "%i", &irqs_max); 224 if (ret != 1) 225 return -EINVAL; 226 227 if (irqs_max < afu->pp_irqs) 228 return -EINVAL; 229 230 if (irqs_max > afu->adapter->user_irqs) 231 return -EINVAL; 232 233 afu->irqs_max = irqs_max; 234 return count; 235 } 236 237 static ssize_t modes_supported_show(struct device *device, 238 struct device_attribute *attr, char *buf) 239 { 240 struct cxl_afu *afu = to_cxl_afu(device); 241 char *p = buf, *end = buf + PAGE_SIZE; 242 243 if (afu->modes_supported & CXL_MODE_DEDICATED) 244 p += scnprintf(p, end - p, "dedicated_process\n"); 245 if (afu->modes_supported & CXL_MODE_DIRECTED) 246 p += scnprintf(p, end - p, "afu_directed\n"); 247 return (p - buf); 248 } 249 250 static ssize_t prefault_mode_show(struct device *device, 251 struct device_attribute *attr, 252 char *buf) 253 { 254 struct cxl_afu *afu = to_cxl_afu(device); 255 256 switch (afu->prefault_mode) { 257 case CXL_PREFAULT_WED: 258 return scnprintf(buf, PAGE_SIZE, "work_element_descriptor\n"); 259 case CXL_PREFAULT_ALL: 260 return scnprintf(buf, PAGE_SIZE, "all\n"); 261 default: 262 return scnprintf(buf, PAGE_SIZE, "none\n"); 263 } 264 } 265 266 static ssize_t prefault_mode_store(struct device *device, 267 struct device_attribute *attr, 268 const char *buf, size_t count) 269 { 270 struct cxl_afu *afu = to_cxl_afu(device); 271 enum prefault_modes mode = -1; 272 273 if (!strncmp(buf, "work_element_descriptor", 23)) 274 mode = CXL_PREFAULT_WED; 275 if (!strncmp(buf, "all", 3)) 276 mode = CXL_PREFAULT_ALL; 277 if (!strncmp(buf, "none", 4)) 278 mode = CXL_PREFAULT_NONE; 279 280 if (mode == -1) 281 return -EINVAL; 282 283 afu->prefault_mode = mode; 284 return count; 285 } 286 287 static ssize_t mode_show(struct device *device, 288 struct device_attribute *attr, 289 char *buf) 290 { 291 struct cxl_afu *afu = to_cxl_afu(device); 292 293 if (afu->current_mode == CXL_MODE_DEDICATED) 294 return scnprintf(buf, PAGE_SIZE, "dedicated_process\n"); 295 if (afu->current_mode == CXL_MODE_DIRECTED) 296 return scnprintf(buf, PAGE_SIZE, "afu_directed\n"); 297 return scnprintf(buf, PAGE_SIZE, "none\n"); 298 } 299 300 static ssize_t mode_store(struct device *device, struct device_attribute *attr, 301 const char *buf, size_t count) 302 { 303 struct cxl_afu *afu = to_cxl_afu(device); 304 int old_mode, mode = -1; 305 int rc = -EBUSY; 306 307 /* can't change this if we have a user */ 308 mutex_lock(&afu->contexts_lock); 309 if (!idr_is_empty(&afu->contexts_idr)) 310 goto err; 311 312 if (!strncmp(buf, "dedicated_process", 17)) 313 mode = CXL_MODE_DEDICATED; 314 if (!strncmp(buf, "afu_directed", 12)) 315 mode = CXL_MODE_DIRECTED; 316 if (!strncmp(buf, "none", 4)) 317 mode = 0; 318 319 if (mode == -1) { 320 rc = -EINVAL; 321 goto err; 322 } 323 324 /* 325 * cxl_afu_deactivate_mode needs to be done outside the lock, prevent 326 * other contexts coming in before we are ready: 327 */ 328 old_mode = afu->current_mode; 329 afu->current_mode = 0; 330 afu->num_procs = 0; 331 332 mutex_unlock(&afu->contexts_lock); 333 334 if ((rc = _cxl_afu_deactivate_mode(afu, old_mode))) 335 return rc; 336 if ((rc = cxl_afu_activate_mode(afu, mode))) 337 return rc; 338 339 return count; 340 err: 341 mutex_unlock(&afu->contexts_lock); 342 return rc; 343 } 344 345 static ssize_t api_version_show(struct device *device, 346 struct device_attribute *attr, 347 char *buf) 348 { 349 return scnprintf(buf, PAGE_SIZE, "%i\n", CXL_API_VERSION); 350 } 351 352 static ssize_t api_version_compatible_show(struct device *device, 353 struct device_attribute *attr, 354 char *buf) 355 { 356 return scnprintf(buf, PAGE_SIZE, "%i\n", CXL_API_VERSION_COMPATIBLE); 357 } 358 359 static ssize_t afu_eb_read(struct file *filp, struct kobject *kobj, 360 struct bin_attribute *bin_attr, char *buf, 361 loff_t off, size_t count) 362 { 363 struct cxl_afu *afu = to_cxl_afu(container_of(kobj, 364 struct device, kobj)); 365 366 return cxl_afu_read_err_buffer(afu, buf, off, count); 367 } 368 369 static struct device_attribute afu_attrs[] = { 370 __ATTR_RO(mmio_size), 371 __ATTR_RO(irqs_min), 372 __ATTR_RW(irqs_max), 373 __ATTR_RO(modes_supported), 374 __ATTR_RW(mode), 375 __ATTR_RW(prefault_mode), 376 __ATTR_RO(api_version), 377 __ATTR_RO(api_version_compatible), 378 __ATTR(reset, S_IWUSR, NULL, reset_store_afu), 379 }; 380 381 int cxl_sysfs_adapter_add(struct cxl *adapter) 382 { 383 int i, rc; 384 385 for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) { 386 if ((rc = device_create_file(&adapter->dev, &adapter_attrs[i]))) 387 goto err; 388 } 389 return 0; 390 err: 391 for (i--; i >= 0; i--) 392 device_remove_file(&adapter->dev, &adapter_attrs[i]); 393 return rc; 394 } 395 void cxl_sysfs_adapter_remove(struct cxl *adapter) 396 { 397 int i; 398 399 for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) 400 device_remove_file(&adapter->dev, &adapter_attrs[i]); 401 } 402 403 struct afu_config_record { 404 struct kobject kobj; 405 struct bin_attribute config_attr; 406 struct list_head list; 407 int cr; 408 u16 device; 409 u16 vendor; 410 u32 class; 411 }; 412 413 #define to_cr(obj) container_of(obj, struct afu_config_record, kobj) 414 415 static ssize_t vendor_show(struct kobject *kobj, 416 struct kobj_attribute *attr, char *buf) 417 { 418 struct afu_config_record *cr = to_cr(kobj); 419 420 return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->vendor); 421 } 422 423 static ssize_t device_show(struct kobject *kobj, 424 struct kobj_attribute *attr, char *buf) 425 { 426 struct afu_config_record *cr = to_cr(kobj); 427 428 return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->device); 429 } 430 431 static ssize_t class_show(struct kobject *kobj, 432 struct kobj_attribute *attr, char *buf) 433 { 434 struct afu_config_record *cr = to_cr(kobj); 435 436 return scnprintf(buf, PAGE_SIZE, "0x%.6x\n", cr->class); 437 } 438 439 static ssize_t afu_read_config(struct file *filp, struct kobject *kobj, 440 struct bin_attribute *bin_attr, char *buf, 441 loff_t off, size_t count) 442 { 443 struct afu_config_record *cr = to_cr(kobj); 444 struct cxl_afu *afu = to_cxl_afu(container_of(kobj->parent, struct device, kobj)); 445 446 u64 i, j, val, size = afu->crs_len; 447 448 if (off > size) 449 return 0; 450 if (off + count > size) 451 count = size - off; 452 453 for (i = 0; i < count;) { 454 val = cxl_afu_cr_read64(afu, cr->cr, off & ~0x7); 455 for (j = off & 0x7; j < 8 && i < count; i++, j++, off++) 456 buf[i] = (val >> (j * 8)) & 0xff; 457 } 458 459 return count; 460 } 461 462 static struct kobj_attribute vendor_attribute = 463 __ATTR_RO(vendor); 464 static struct kobj_attribute device_attribute = 465 __ATTR_RO(device); 466 static struct kobj_attribute class_attribute = 467 __ATTR_RO(class); 468 469 static struct attribute *afu_cr_attrs[] = { 470 &vendor_attribute.attr, 471 &device_attribute.attr, 472 &class_attribute.attr, 473 NULL, 474 }; 475 476 static void release_afu_config_record(struct kobject *kobj) 477 { 478 struct afu_config_record *cr = to_cr(kobj); 479 480 kfree(cr); 481 } 482 483 static struct kobj_type afu_config_record_type = { 484 .sysfs_ops = &kobj_sysfs_ops, 485 .release = release_afu_config_record, 486 .default_attrs = afu_cr_attrs, 487 }; 488 489 static struct afu_config_record *cxl_sysfs_afu_new_cr(struct cxl_afu *afu, int cr_idx) 490 { 491 struct afu_config_record *cr; 492 int rc; 493 494 cr = kzalloc(sizeof(struct afu_config_record), GFP_KERNEL); 495 if (!cr) 496 return ERR_PTR(-ENOMEM); 497 498 cr->cr = cr_idx; 499 cr->device = cxl_afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID); 500 cr->vendor = cxl_afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID); 501 cr->class = cxl_afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION) >> 8; 502 503 /* 504 * Export raw AFU PCIe like config record. For now this is read only by 505 * root - we can expand that later to be readable by non-root and maybe 506 * even writable provided we have a good use-case. Once we suport 507 * exposing AFUs through a virtual PHB they will get that for free from 508 * Linux' PCI infrastructure, but until then it's not clear that we 509 * need it for anything since the main use case is just identifying 510 * AFUs, which can be done via the vendor, device and class attributes. 511 */ 512 sysfs_bin_attr_init(&cr->config_attr); 513 cr->config_attr.attr.name = "config"; 514 cr->config_attr.attr.mode = S_IRUSR; 515 cr->config_attr.size = afu->crs_len; 516 cr->config_attr.read = afu_read_config; 517 518 rc = kobject_init_and_add(&cr->kobj, &afu_config_record_type, 519 &afu->dev.kobj, "cr%i", cr->cr); 520 if (rc) 521 goto err; 522 523 rc = sysfs_create_bin_file(&cr->kobj, &cr->config_attr); 524 if (rc) 525 goto err1; 526 527 rc = kobject_uevent(&cr->kobj, KOBJ_ADD); 528 if (rc) 529 goto err2; 530 531 return cr; 532 err2: 533 sysfs_remove_bin_file(&cr->kobj, &cr->config_attr); 534 err1: 535 kobject_put(&cr->kobj); 536 return ERR_PTR(rc); 537 err: 538 kfree(cr); 539 return ERR_PTR(rc); 540 } 541 542 void cxl_sysfs_afu_remove(struct cxl_afu *afu) 543 { 544 struct afu_config_record *cr, *tmp; 545 int i; 546 547 /* remove the err buffer bin attribute */ 548 if (afu->eb_len) 549 device_remove_bin_file(&afu->dev, &afu->attr_eb); 550 551 for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) 552 device_remove_file(&afu->dev, &afu_attrs[i]); 553 554 list_for_each_entry_safe(cr, tmp, &afu->crs, list) { 555 sysfs_remove_bin_file(&cr->kobj, &cr->config_attr); 556 kobject_put(&cr->kobj); 557 } 558 } 559 560 int cxl_sysfs_afu_add(struct cxl_afu *afu) 561 { 562 struct afu_config_record *cr; 563 int i, rc; 564 565 INIT_LIST_HEAD(&afu->crs); 566 567 for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) { 568 if ((rc = device_create_file(&afu->dev, &afu_attrs[i]))) 569 goto err; 570 } 571 572 /* conditionally create the add the binary file for error info buffer */ 573 if (afu->eb_len) { 574 afu->attr_eb.attr.name = "afu_err_buff"; 575 afu->attr_eb.attr.mode = S_IRUGO; 576 afu->attr_eb.size = afu->eb_len; 577 afu->attr_eb.read = afu_eb_read; 578 579 rc = device_create_bin_file(&afu->dev, &afu->attr_eb); 580 if (rc) { 581 dev_err(&afu->dev, 582 "Unable to create eb attr for the afu. Err(%d)\n", 583 rc); 584 goto err; 585 } 586 } 587 588 for (i = 0; i < afu->crs_num; i++) { 589 cr = cxl_sysfs_afu_new_cr(afu, i); 590 if (IS_ERR(cr)) { 591 rc = PTR_ERR(cr); 592 goto err1; 593 } 594 list_add(&cr->list, &afu->crs); 595 } 596 597 return 0; 598 599 err1: 600 cxl_sysfs_afu_remove(afu); 601 return rc; 602 err: 603 /* reset the eb_len as we havent created the bin attr */ 604 afu->eb_len = 0; 605 606 for (i--; i >= 0; i--) 607 device_remove_file(&afu->dev, &afu_attrs[i]); 608 return rc; 609 } 610 611 int cxl_sysfs_afu_m_add(struct cxl_afu *afu) 612 { 613 int i, rc; 614 615 for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) { 616 if ((rc = device_create_file(afu->chardev_m, &afu_master_attrs[i]))) 617 goto err; 618 } 619 620 return 0; 621 622 err: 623 for (i--; i >= 0; i--) 624 device_remove_file(afu->chardev_m, &afu_master_attrs[i]); 625 return rc; 626 } 627 628 void cxl_sysfs_afu_m_remove(struct cxl_afu *afu) 629 { 630 int i; 631 632 for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) 633 device_remove_file(afu->chardev_m, &afu_master_attrs[i]); 634 } 635