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