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