linux/drivers/misc/cxl/sysfs.c
<<
>>
Prefs
   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 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
  69static 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
 101out:
 102        return rc ? rc : count;
 103}
 104
 105static 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
 119static 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
 143static 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
 152static 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
 168static 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
 182static 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
 191static 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
 200static 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
 209static 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
 218static 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
 229static 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;
 247err:
 248        mutex_unlock(&afu->contexts_lock);
 249        return rc;
 250}
 251
 252static 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
 261static 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
 270static 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
 298static 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
 311static 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
 327static 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
 348static 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
 361static 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;
 401err:
 402        mutex_unlock(&afu->contexts_lock);
 403        return rc;
 404}
 405
 406static 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
 413static 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
 420static 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
 429static 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
 441int 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;
 455err:
 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
 465void 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
 478struct 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
 490static 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
 498static 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
 506static 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
 514static 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
 534static struct kobj_attribute vendor_attribute =
 535        __ATTR_RO(vendor);
 536static struct kobj_attribute device_attribute =
 537        __ATTR_RO(device);
 538static struct kobj_attribute class_attribute =
 539        __ATTR_RO(class);
 540
 541static struct attribute *afu_cr_attrs[] = {
 542        &vendor_attribute.attr,
 543        &device_attribute.attr,
 544        &class_attribute.attr,
 545        NULL,
 546};
 547
 548static void release_afu_config_record(struct kobject *kobj)
 549{
 550        struct afu_config_record *cr = to_cr(kobj);
 551
 552        kfree(cr);
 553}
 554
 555static 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
 561static 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;
 612err2:
 613        sysfs_remove_bin_file(&cr->kobj, &cr->config_attr);
 614err1:
 615        kobject_put(&cr->kobj);
 616        return ERR_PTR(rc);
 617err:
 618        kfree(cr);
 619        return ERR_PTR(rc);
 620}
 621
 622void 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
 645int 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
 691err1:
 692        cxl_sysfs_afu_remove(afu);
 693        return rc;
 694err:
 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
 707int 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
 723err:
 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
 733void 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