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