root/drivers/misc/cxl/sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. caia_version_show
  2. psl_revision_show
  3. base_image_show
  4. image_loaded_show
  5. psl_timebase_synced_show
  6. tunneled_ops_supported_show
  7. reset_adapter_store
  8. load_image_on_perst_show
  9. load_image_on_perst_store
  10. perst_reloads_same_image_show
  11. perst_reloads_same_image_store
  12. mmio_size_show_master
  13. pp_mmio_off_show
  14. pp_mmio_len_show
  15. mmio_size_show
  16. reset_store_afu
  17. irqs_min_show
  18. irqs_max_show
  19. irqs_max_store
  20. modes_supported_show
  21. prefault_mode_show
  22. prefault_mode_store
  23. mode_show
  24. mode_store
  25. api_version_show
  26. api_version_compatible_show
  27. afu_eb_read
  28. cxl_sysfs_adapter_add
  29. cxl_sysfs_adapter_remove
  30. vendor_show
  31. device_show
  32. class_show
  33. afu_read_config
  34. release_afu_config_record
  35. cxl_sysfs_afu_new_cr
  36. cxl_sysfs_afu_remove
  37. cxl_sysfs_afu_add
  38. cxl_sysfs_afu_m_add
  39. cxl_sysfs_afu_m_remove

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

/* [<][>][^][v][top][bottom][index][help] */