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 psl_timebase_synced_show(struct device *device, 61 struct device_attribute *attr, 62 char *buf) 63 { 64 struct cxl *adapter = to_cxl_adapter(device); 65 u64 psl_tb, delta; 66 67 /* Recompute the status only in native mode */ 68 if (cpu_has_feature(CPU_FTR_HVMODE)) { 69 psl_tb = adapter->native->sl_ops->timebase_read(adapter); 70 delta = abs(mftb() - psl_tb); 71 72 /* CORE TB and PSL TB difference <= 16usecs ? */ 73 adapter->psl_timebase_synced = (tb_to_ns(delta) < 16000) ? true : false; 74 pr_devel("PSL timebase %s - delta: 0x%016llx\n", 75 (tb_to_ns(delta) < 16000) ? "synchronized" : 76 "not synchronized", tb_to_ns(delta)); 77 } 78 return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_timebase_synced); 79 } 80 81 static ssize_t tunneled_ops_supported_show(struct device *device, 82 struct device_attribute *attr, 83 char *buf) 84 { 85 struct cxl *adapter = to_cxl_adapter(device); 86 87 return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->tunneled_ops_supported); 88 } 89 90 static ssize_t reset_adapter_store(struct device *device, 91 struct device_attribute *attr, 92 const char *buf, size_t count) 93 { 94 struct cxl *adapter = to_cxl_adapter(device); 95 int rc; 96 int val; 97 98 rc = sscanf(buf, "%i", &val); 99 if ((rc != 1) || (val != 1 && val != -1)) 100 return -EINVAL; 101 102 /* 103 * See if we can lock the context mapping that's only allowed 104 * when there are no contexts attached to the adapter. Once 105 * taken this will also prevent any context from getting activated. 106 */ 107 if (val == 1) { 108 rc = cxl_adapter_context_lock(adapter); 109 if (rc) 110 goto out; 111 112 rc = cxl_ops->adapter_reset(adapter); 113 /* In case reset failed release context lock */ 114 if (rc) 115 cxl_adapter_context_unlock(adapter); 116 117 } else if (val == -1) { 118 /* Perform a forced adapter reset */ 119 rc = cxl_ops->adapter_reset(adapter); 120 } 121 122 out: 123 return rc ? rc : count; 124 } 125 126 static ssize_t load_image_on_perst_show(struct device *device, 127 struct device_attribute *attr, 128 char *buf) 129 { 130 struct cxl *adapter = to_cxl_adapter(device); 131 132 if (!adapter->perst_loads_image) 133 return scnprintf(buf, PAGE_SIZE, "none\n"); 134 135 if (adapter->perst_select_user) 136 return scnprintf(buf, PAGE_SIZE, "user\n"); 137 return scnprintf(buf, PAGE_SIZE, "factory\n"); 138 } 139 140 static ssize_t load_image_on_perst_store(struct device *device, 141 struct device_attribute *attr, 142 const char *buf, size_t count) 143 { 144 struct cxl *adapter = to_cxl_adapter(device); 145 int rc; 146 147 if (!strncmp(buf, "none", 4)) 148 adapter->perst_loads_image = false; 149 else if (!strncmp(buf, "user", 4)) { 150 adapter->perst_select_user = true; 151 adapter->perst_loads_image = true; 152 } else if (!strncmp(buf, "factory", 7)) { 153 adapter->perst_select_user = false; 154 adapter->perst_loads_image = true; 155 } else 156 return -EINVAL; 157 158 if ((rc = cxl_update_image_control(adapter))) 159 return rc; 160 161 return count; 162 } 163 164 static ssize_t perst_reloads_same_image_show(struct device *device, 165 struct device_attribute *attr, 166 char *buf) 167 { 168 struct cxl *adapter = to_cxl_adapter(device); 169 170 return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->perst_same_image); 171 } 172 173 static ssize_t perst_reloads_same_image_store(struct device *device, 174 struct device_attribute *attr, 175 const char *buf, size_t count) 176 { 177 struct cxl *adapter = to_cxl_adapter(device); 178 int rc; 179 int val; 180 181 rc = sscanf(buf, "%i", &val); 182 if ((rc != 1) || !(val == 1 || val == 0)) 183 return -EINVAL; 184 185 adapter->perst_same_image = (val == 1 ? true : false); 186 return count; 187 } 188 189 static struct device_attribute adapter_attrs[] = { 190 __ATTR_RO(caia_version), 191 __ATTR_RO(psl_revision), 192 __ATTR_RO(base_image), 193 __ATTR_RO(image_loaded), 194 __ATTR_RO(psl_timebase_synced), 195 __ATTR_RO(tunneled_ops_supported), 196 __ATTR_RW(load_image_on_perst), 197 __ATTR_RW(perst_reloads_same_image), 198 __ATTR(reset, S_IWUSR, NULL, reset_adapter_store), 199 }; 200 201 202 /********* AFU master specific attributes **********************************/ 203 204 static ssize_t mmio_size_show_master(struct device *device, 205 struct device_attribute *attr, 206 char *buf) 207 { 208 struct cxl_afu *afu = to_afu_chardev_m(device); 209 210 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->adapter->ps_size); 211 } 212 213 static ssize_t pp_mmio_off_show(struct device *device, 214 struct device_attribute *attr, 215 char *buf) 216 { 217 struct cxl_afu *afu = to_afu_chardev_m(device); 218 219 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->native->pp_offset); 220 } 221 222 static ssize_t pp_mmio_len_show(struct device *device, 223 struct device_attribute *attr, 224 char *buf) 225 { 226 struct cxl_afu *afu = to_afu_chardev_m(device); 227 228 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->pp_size); 229 } 230 231 static struct device_attribute afu_master_attrs[] = { 232 __ATTR(mmio_size, S_IRUGO, mmio_size_show_master, NULL), 233 __ATTR_RO(pp_mmio_off), 234 __ATTR_RO(pp_mmio_len), 235 }; 236 237 238 /********* AFU attributes **************************************************/ 239 240 static ssize_t mmio_size_show(struct device *device, 241 struct device_attribute *attr, 242 char *buf) 243 { 244 struct cxl_afu *afu = to_cxl_afu(device); 245 246 if (afu->pp_size) 247 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->pp_size); 248 return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->adapter->ps_size); 249 } 250 251 static ssize_t reset_store_afu(struct device *device, 252 struct device_attribute *attr, 253 const char *buf, size_t count) 254 { 255 struct cxl_afu *afu = to_cxl_afu(device); 256 int rc; 257 258 /* Not safe to reset if it is currently in use */ 259 mutex_lock(&afu->contexts_lock); 260 if (!idr_is_empty(&afu->contexts_idr)) { 261 rc = -EBUSY; 262 goto err; 263 } 264 265 if ((rc = cxl_ops->afu_reset(afu))) 266 goto err; 267 268 rc = count; 269 err: 270 mutex_unlock(&afu->contexts_lock); 271 return rc; 272 } 273 274 static ssize_t irqs_min_show(struct device *device, 275 struct device_attribute *attr, 276 char *buf) 277 { 278 struct cxl_afu *afu = to_cxl_afu(device); 279 280 return scnprintf(buf, PAGE_SIZE, "%i\n", afu->pp_irqs); 281 } 282 283 static ssize_t irqs_max_show(struct device *device, 284 struct device_attribute *attr, 285 char *buf) 286 { 287 struct cxl_afu *afu = to_cxl_afu(device); 288 289 return scnprintf(buf, PAGE_SIZE, "%i\n", afu->irqs_max); 290 } 291 292 static ssize_t irqs_max_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 ssize_t ret; 298 int irqs_max; 299 300 ret = sscanf(buf, "%i", &irqs_max); 301 if (ret != 1) 302 return -EINVAL; 303 304 if (irqs_max < afu->pp_irqs) 305 return -EINVAL; 306 307 if (cpu_has_feature(CPU_FTR_HVMODE)) { 308 if (irqs_max > afu->adapter->user_irqs) 309 return -EINVAL; 310 } else { 311 /* pHyp sets a per-AFU limit */ 312 if (irqs_max > afu->guest->max_ints) 313 return -EINVAL; 314 } 315 316 afu->irqs_max = irqs_max; 317 return count; 318 } 319 320 static ssize_t modes_supported_show(struct device *device, 321 struct device_attribute *attr, char *buf) 322 { 323 struct cxl_afu *afu = to_cxl_afu(device); 324 char *p = buf, *end = buf + PAGE_SIZE; 325 326 if (afu->modes_supported & CXL_MODE_DEDICATED) 327 p += scnprintf(p, end - p, "dedicated_process\n"); 328 if (afu->modes_supported & CXL_MODE_DIRECTED) 329 p += scnprintf(p, end - p, "afu_directed\n"); 330 return (p - buf); 331 } 332 333 static ssize_t prefault_mode_show(struct device *device, 334 struct device_attribute *attr, 335 char *buf) 336 { 337 struct cxl_afu *afu = to_cxl_afu(device); 338 339 switch (afu->prefault_mode) { 340 case CXL_PREFAULT_WED: 341 return scnprintf(buf, PAGE_SIZE, "work_element_descriptor\n"); 342 case CXL_PREFAULT_ALL: 343 return scnprintf(buf, PAGE_SIZE, "all\n"); 344 default: 345 return scnprintf(buf, PAGE_SIZE, "none\n"); 346 } 347 } 348 349 static ssize_t prefault_mode_store(struct device *device, 350 struct device_attribute *attr, 351 const char *buf, size_t count) 352 { 353 struct cxl_afu *afu = to_cxl_afu(device); 354 enum prefault_modes mode = -1; 355 356 if (!strncmp(buf, "work_element_descriptor", 23)) 357 mode = CXL_PREFAULT_WED; 358 if (!strncmp(buf, "all", 3)) 359 mode = CXL_PREFAULT_ALL; 360 if (!strncmp(buf, "none", 4)) 361 mode = CXL_PREFAULT_NONE; 362 363 if (mode == -1) 364 return -EINVAL; 365 366 afu->prefault_mode = mode; 367 return count; 368 } 369 370 static ssize_t mode_show(struct device *device, 371 struct device_attribute *attr, 372 char *buf) 373 { 374 struct cxl_afu *afu = to_cxl_afu(device); 375 376 if (afu->current_mode == CXL_MODE_DEDICATED) 377 return scnprintf(buf, PAGE_SIZE, "dedicated_process\n"); 378 if (afu->current_mode == CXL_MODE_DIRECTED) 379 return scnprintf(buf, PAGE_SIZE, "afu_directed\n"); 380 return scnprintf(buf, PAGE_SIZE, "none\n"); 381 } 382 383 static ssize_t mode_store(struct device *device, struct device_attribute *attr, 384 const char *buf, size_t count) 385 { 386 struct cxl_afu *afu = to_cxl_afu(device); 387 int old_mode, mode = -1; 388 int rc = -EBUSY; 389 390 /* can't change this if we have a user */ 391 mutex_lock(&afu->contexts_lock); 392 if (!idr_is_empty(&afu->contexts_idr)) 393 goto err; 394 395 if (!strncmp(buf, "dedicated_process", 17)) 396 mode = CXL_MODE_DEDICATED; 397 if (!strncmp(buf, "afu_directed", 12)) 398 mode = CXL_MODE_DIRECTED; 399 if (!strncmp(buf, "none", 4)) 400 mode = 0; 401 402 if (mode == -1) { 403 rc = -EINVAL; 404 goto err; 405 } 406 407 /* 408 * afu_deactivate_mode needs to be done outside the lock, prevent 409 * other contexts coming in before we are ready: 410 */ 411 old_mode = afu->current_mode; 412 afu->current_mode = 0; 413 afu->num_procs = 0; 414 415 mutex_unlock(&afu->contexts_lock); 416 417 if ((rc = cxl_ops->afu_deactivate_mode(afu, old_mode))) 418 return rc; 419 if ((rc = cxl_ops->afu_activate_mode(afu, mode))) 420 return rc; 421 422 return count; 423 err: 424 mutex_unlock(&afu->contexts_lock); 425 return rc; 426 } 427 428 static ssize_t api_version_show(struct device *device, 429 struct device_attribute *attr, 430 char *buf) 431 { 432 return scnprintf(buf, PAGE_SIZE, "%i\n", CXL_API_VERSION); 433 } 434 435 static ssize_t api_version_compatible_show(struct device *device, 436 struct device_attribute *attr, 437 char *buf) 438 { 439 return scnprintf(buf, PAGE_SIZE, "%i\n", CXL_API_VERSION_COMPATIBLE); 440 } 441 442 static ssize_t afu_eb_read(struct file *filp, struct kobject *kobj, 443 struct bin_attribute *bin_attr, char *buf, 444 loff_t off, size_t count) 445 { 446 struct cxl_afu *afu = to_cxl_afu(kobj_to_dev(kobj)); 447 448 return cxl_ops->afu_read_err_buffer(afu, buf, off, count); 449 } 450 451 static struct device_attribute afu_attrs[] = { 452 __ATTR_RO(mmio_size), 453 __ATTR_RO(irqs_min), 454 __ATTR_RW(irqs_max), 455 __ATTR_RO(modes_supported), 456 __ATTR_RW(mode), 457 __ATTR_RW(prefault_mode), 458 __ATTR_RO(api_version), 459 __ATTR_RO(api_version_compatible), 460 __ATTR(reset, S_IWUSR, NULL, reset_store_afu), 461 }; 462 463 int cxl_sysfs_adapter_add(struct cxl *adapter) 464 { 465 struct device_attribute *dev_attr; 466 int i, rc; 467 468 for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) { 469 dev_attr = &adapter_attrs[i]; 470 if (cxl_ops->support_attributes(dev_attr->attr.name, 471 CXL_ADAPTER_ATTRS)) { 472 if ((rc = device_create_file(&adapter->dev, dev_attr))) 473 goto err; 474 } 475 } 476 return 0; 477 err: 478 for (i--; i >= 0; i--) { 479 dev_attr = &adapter_attrs[i]; 480 if (cxl_ops->support_attributes(dev_attr->attr.name, 481 CXL_ADAPTER_ATTRS)) 482 device_remove_file(&adapter->dev, dev_attr); 483 } 484 return rc; 485 } 486 487 void cxl_sysfs_adapter_remove(struct cxl *adapter) 488 { 489 struct device_attribute *dev_attr; 490 int i; 491 492 for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) { 493 dev_attr = &adapter_attrs[i]; 494 if (cxl_ops->support_attributes(dev_attr->attr.name, 495 CXL_ADAPTER_ATTRS)) 496 device_remove_file(&adapter->dev, dev_attr); 497 } 498 } 499 500 struct afu_config_record { 501 struct kobject kobj; 502 struct bin_attribute config_attr; 503 struct list_head list; 504 int cr; 505 u16 device; 506 u16 vendor; 507 u32 class; 508 }; 509 510 #define to_cr(obj) container_of(obj, struct afu_config_record, kobj) 511 512 static ssize_t vendor_show(struct kobject *kobj, 513 struct kobj_attribute *attr, char *buf) 514 { 515 struct afu_config_record *cr = to_cr(kobj); 516 517 return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->vendor); 518 } 519 520 static ssize_t device_show(struct kobject *kobj, 521 struct kobj_attribute *attr, char *buf) 522 { 523 struct afu_config_record *cr = to_cr(kobj); 524 525 return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->device); 526 } 527 528 static ssize_t class_show(struct kobject *kobj, 529 struct kobj_attribute *attr, char *buf) 530 { 531 struct afu_config_record *cr = to_cr(kobj); 532 533 return scnprintf(buf, PAGE_SIZE, "0x%.6x\n", cr->class); 534 } 535 536 static ssize_t afu_read_config(struct file *filp, struct kobject *kobj, 537 struct bin_attribute *bin_attr, char *buf, 538 loff_t off, size_t count) 539 { 540 struct afu_config_record *cr = to_cr(kobj); 541 struct cxl_afu *afu = to_cxl_afu(kobj_to_dev(kobj->parent)); 542 543 u64 i, j, val, rc; 544 545 for (i = 0; i < count;) { 546 rc = cxl_ops->afu_cr_read64(afu, cr->cr, off & ~0x7, &val); 547 if (rc) 548 val = ~0ULL; 549 for (j = off & 0x7; j < 8 && i < count; i++, j++, off++) 550 buf[i] = (val >> (j * 8)) & 0xff; 551 } 552 553 return count; 554 } 555 556 static struct kobj_attribute vendor_attribute = 557 __ATTR_RO(vendor); 558 static struct kobj_attribute device_attribute = 559 __ATTR_RO(device); 560 static struct kobj_attribute class_attribute = 561 __ATTR_RO(class); 562 563 static struct attribute *afu_cr_attrs[] = { 564 &vendor_attribute.attr, 565 &device_attribute.attr, 566 &class_attribute.attr, 567 NULL, 568 }; 569 570 static void release_afu_config_record(struct kobject *kobj) 571 { 572 struct afu_config_record *cr = to_cr(kobj); 573 574 kfree(cr); 575 } 576 577 static struct kobj_type afu_config_record_type = { 578 .sysfs_ops = &kobj_sysfs_ops, 579 .release = release_afu_config_record, 580 .default_attrs = afu_cr_attrs, 581 }; 582 583 static struct afu_config_record *cxl_sysfs_afu_new_cr(struct cxl_afu *afu, int cr_idx) 584 { 585 struct afu_config_record *cr; 586 int rc; 587 588 cr = kzalloc(sizeof(struct afu_config_record), GFP_KERNEL); 589 if (!cr) 590 return ERR_PTR(-ENOMEM); 591 592 cr->cr = cr_idx; 593 594 rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID, &cr->device); 595 if (rc) 596 goto err; 597 rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID, &cr->vendor); 598 if (rc) 599 goto err; 600 rc = cxl_ops->afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION, &cr->class); 601 if (rc) 602 goto err; 603 cr->class >>= 8; 604 605 /* 606 * Export raw AFU PCIe like config record. For now this is read only by 607 * root - we can expand that later to be readable by non-root and maybe 608 * even writable provided we have a good use-case. Once we support 609 * exposing AFUs through a virtual PHB they will get that for free from 610 * Linux' PCI infrastructure, but until then it's not clear that we 611 * need it for anything since the main use case is just identifying 612 * AFUs, which can be done via the vendor, device and class attributes. 613 */ 614 sysfs_bin_attr_init(&cr->config_attr); 615 cr->config_attr.attr.name = "config"; 616 cr->config_attr.attr.mode = S_IRUSR; 617 cr->config_attr.size = afu->crs_len; 618 cr->config_attr.read = afu_read_config; 619 620 rc = kobject_init_and_add(&cr->kobj, &afu_config_record_type, 621 &afu->dev.kobj, "cr%i", cr->cr); 622 if (rc) 623 goto err; 624 625 rc = sysfs_create_bin_file(&cr->kobj, &cr->config_attr); 626 if (rc) 627 goto err1; 628 629 rc = kobject_uevent(&cr->kobj, KOBJ_ADD); 630 if (rc) 631 goto err2; 632 633 return cr; 634 err2: 635 sysfs_remove_bin_file(&cr->kobj, &cr->config_attr); 636 err1: 637 kobject_put(&cr->kobj); 638 return ERR_PTR(rc); 639 err: 640 kfree(cr); 641 return ERR_PTR(rc); 642 } 643 644 void cxl_sysfs_afu_remove(struct cxl_afu *afu) 645 { 646 struct device_attribute *dev_attr; 647 struct afu_config_record *cr, *tmp; 648 int i; 649 650 /* remove the err buffer bin attribute */ 651 if (afu->eb_len) 652 device_remove_bin_file(&afu->dev, &afu->attr_eb); 653 654 for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) { 655 dev_attr = &afu_attrs[i]; 656 if (cxl_ops->support_attributes(dev_attr->attr.name, 657 CXL_AFU_ATTRS)) 658 device_remove_file(&afu->dev, &afu_attrs[i]); 659 } 660 661 list_for_each_entry_safe(cr, tmp, &afu->crs, list) { 662 sysfs_remove_bin_file(&cr->kobj, &cr->config_attr); 663 kobject_put(&cr->kobj); 664 } 665 } 666 667 int cxl_sysfs_afu_add(struct cxl_afu *afu) 668 { 669 struct device_attribute *dev_attr; 670 struct afu_config_record *cr; 671 int i, rc; 672 673 INIT_LIST_HEAD(&afu->crs); 674 675 for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) { 676 dev_attr = &afu_attrs[i]; 677 if (cxl_ops->support_attributes(dev_attr->attr.name, 678 CXL_AFU_ATTRS)) { 679 if ((rc = device_create_file(&afu->dev, &afu_attrs[i]))) 680 goto err; 681 } 682 } 683 684 /* conditionally create the add the binary file for error info buffer */ 685 if (afu->eb_len) { 686 sysfs_attr_init(&afu->attr_eb.attr); 687 688 afu->attr_eb.attr.name = "afu_err_buff"; 689 afu->attr_eb.attr.mode = S_IRUGO; 690 afu->attr_eb.size = afu->eb_len; 691 afu->attr_eb.read = afu_eb_read; 692 693 rc = device_create_bin_file(&afu->dev, &afu->attr_eb); 694 if (rc) { 695 dev_err(&afu->dev, 696 "Unable to create eb attr for the afu. Err(%d)\n", 697 rc); 698 goto err; 699 } 700 } 701 702 for (i = 0; i < afu->crs_num; i++) { 703 cr = cxl_sysfs_afu_new_cr(afu, i); 704 if (IS_ERR(cr)) { 705 rc = PTR_ERR(cr); 706 goto err1; 707 } 708 list_add(&cr->list, &afu->crs); 709 } 710 711 return 0; 712 713 err1: 714 cxl_sysfs_afu_remove(afu); 715 return rc; 716 err: 717 /* reset the eb_len as we havent created the bin attr */ 718 afu->eb_len = 0; 719 720 for (i--; i >= 0; i--) { 721 dev_attr = &afu_attrs[i]; 722 if (cxl_ops->support_attributes(dev_attr->attr.name, 723 CXL_AFU_ATTRS)) 724 device_remove_file(&afu->dev, &afu_attrs[i]); 725 } 726 return rc; 727 } 728 729 int cxl_sysfs_afu_m_add(struct cxl_afu *afu) 730 { 731 struct device_attribute *dev_attr; 732 int i, rc; 733 734 for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) { 735 dev_attr = &afu_master_attrs[i]; 736 if (cxl_ops->support_attributes(dev_attr->attr.name, 737 CXL_AFU_MASTER_ATTRS)) { 738 if ((rc = device_create_file(afu->chardev_m, &afu_master_attrs[i]))) 739 goto err; 740 } 741 } 742 743 return 0; 744 745 err: 746 for (i--; i >= 0; i--) { 747 dev_attr = &afu_master_attrs[i]; 748 if (cxl_ops->support_attributes(dev_attr->attr.name, 749 CXL_AFU_MASTER_ATTRS)) 750 device_remove_file(afu->chardev_m, &afu_master_attrs[i]); 751 } 752 return rc; 753 } 754 755 void cxl_sysfs_afu_m_remove(struct cxl_afu *afu) 756 { 757 struct device_attribute *dev_attr; 758 int i; 759 760 for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) { 761 dev_attr = &afu_master_attrs[i]; 762 if (cxl_ops->support_attributes(dev_attr->attr.name, 763 CXL_AFU_MASTER_ATTRS)) 764 device_remove_file(afu->chardev_m, &afu_master_attrs[i]); 765 } 766 } 767