xref: /openbmc/linux/drivers/misc/cxl/sysfs.c (revision 63064451)
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 
caia_version_show(struct device * device,struct device_attribute * attr,char * buf)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 
psl_revision_show(struct device * device,struct device_attribute * attr,char * buf)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 
base_image_show(struct device * device,struct device_attribute * attr,char * buf)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 
image_loaded_show(struct device * device,struct device_attribute * attr,char * buf)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 
psl_timebase_synced_show(struct device * device,struct device_attribute * attr,char * buf)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 
tunneled_ops_supported_show(struct device * device,struct device_attribute * attr,char * buf)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 
reset_adapter_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)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 
load_image_on_perst_show(struct device * device,struct device_attribute * attr,char * buf)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 
load_image_on_perst_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)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 
perst_reloads_same_image_show(struct device * device,struct device_attribute * attr,char * buf)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 
perst_reloads_same_image_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)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);
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 
mmio_size_show_master(struct device * device,struct device_attribute * attr,char * buf)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 
pp_mmio_off_show(struct device * device,struct device_attribute * attr,char * buf)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 
pp_mmio_len_show(struct device * device,struct device_attribute * attr,char * buf)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 
mmio_size_show(struct device * device,struct device_attribute * attr,char * buf)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 
reset_store_afu(struct device * device,struct device_attribute * attr,const char * buf,size_t count)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 
irqs_min_show(struct device * device,struct device_attribute * attr,char * buf)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 
irqs_max_show(struct device * device,struct device_attribute * attr,char * buf)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 
irqs_max_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)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 
modes_supported_show(struct device * device,struct device_attribute * attr,char * buf)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 
prefault_mode_show(struct device * device,struct device_attribute * attr,char * buf)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 
prefault_mode_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)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 
mode_show(struct device * device,struct device_attribute * attr,char * buf)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 
mode_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)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 
api_version_show(struct device * device,struct device_attribute * attr,char * buf)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 
api_version_compatible_show(struct device * device,struct device_attribute * attr,char * buf)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 
afu_eb_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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 
cxl_sysfs_adapter_add(struct cxl * adapter)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 
cxl_sysfs_adapter_remove(struct cxl * adapter)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 
vendor_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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 
device_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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 
class_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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 
afu_read_config(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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 ATTRIBUTE_GROUPS(afu_cr);
574 
release_afu_config_record(struct kobject * kobj)575 static void release_afu_config_record(struct kobject *kobj)
576 {
577 	struct afu_config_record *cr = to_cr(kobj);
578 
579 	kfree(cr);
580 }
581 
582 static struct kobj_type afu_config_record_type = {
583 	.sysfs_ops = &kobj_sysfs_ops,
584 	.release = release_afu_config_record,
585 	.default_groups = afu_cr_groups,
586 };
587 
cxl_sysfs_afu_new_cr(struct cxl_afu * afu,int cr_idx)588 static struct afu_config_record *cxl_sysfs_afu_new_cr(struct cxl_afu *afu, int cr_idx)
589 {
590 	struct afu_config_record *cr;
591 	int rc;
592 
593 	cr = kzalloc(sizeof(struct afu_config_record), GFP_KERNEL);
594 	if (!cr)
595 		return ERR_PTR(-ENOMEM);
596 
597 	cr->cr = cr_idx;
598 
599 	rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID, &cr->device);
600 	if (rc)
601 		goto err;
602 	rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID, &cr->vendor);
603 	if (rc)
604 		goto err;
605 	rc = cxl_ops->afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION, &cr->class);
606 	if (rc)
607 		goto err;
608 	cr->class >>= 8;
609 
610 	/*
611 	 * Export raw AFU PCIe like config record. For now this is read only by
612 	 * root - we can expand that later to be readable by non-root and maybe
613 	 * even writable provided we have a good use-case. Once we support
614 	 * exposing AFUs through a virtual PHB they will get that for free from
615 	 * Linux' PCI infrastructure, but until then it's not clear that we
616 	 * need it for anything since the main use case is just identifying
617 	 * AFUs, which can be done via the vendor, device and class attributes.
618 	 */
619 	sysfs_bin_attr_init(&cr->config_attr);
620 	cr->config_attr.attr.name = "config";
621 	cr->config_attr.attr.mode = S_IRUSR;
622 	cr->config_attr.size = afu->crs_len;
623 	cr->config_attr.read = afu_read_config;
624 
625 	rc = kobject_init_and_add(&cr->kobj, &afu_config_record_type,
626 				  &afu->dev.kobj, "cr%i", cr->cr);
627 	if (rc)
628 		goto err1;
629 
630 	rc = sysfs_create_bin_file(&cr->kobj, &cr->config_attr);
631 	if (rc)
632 		goto err1;
633 
634 	rc = kobject_uevent(&cr->kobj, KOBJ_ADD);
635 	if (rc)
636 		goto err2;
637 
638 	return cr;
639 err2:
640 	sysfs_remove_bin_file(&cr->kobj, &cr->config_attr);
641 err1:
642 	kobject_put(&cr->kobj);
643 	return ERR_PTR(rc);
644 err:
645 	kfree(cr);
646 	return ERR_PTR(rc);
647 }
648 
cxl_sysfs_afu_remove(struct cxl_afu * afu)649 void cxl_sysfs_afu_remove(struct cxl_afu *afu)
650 {
651 	struct device_attribute *dev_attr;
652 	struct afu_config_record *cr, *tmp;
653 	int i;
654 
655 	/* remove the err buffer bin attribute */
656 	if (afu->eb_len)
657 		device_remove_bin_file(&afu->dev, &afu->attr_eb);
658 
659 	for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) {
660 		dev_attr = &afu_attrs[i];
661 		if (cxl_ops->support_attributes(dev_attr->attr.name,
662 						CXL_AFU_ATTRS))
663 			device_remove_file(&afu->dev, &afu_attrs[i]);
664 	}
665 
666 	list_for_each_entry_safe(cr, tmp, &afu->crs, list) {
667 		sysfs_remove_bin_file(&cr->kobj, &cr->config_attr);
668 		kobject_put(&cr->kobj);
669 	}
670 }
671 
cxl_sysfs_afu_add(struct cxl_afu * afu)672 int cxl_sysfs_afu_add(struct cxl_afu *afu)
673 {
674 	struct device_attribute *dev_attr;
675 	struct afu_config_record *cr;
676 	int i, rc;
677 
678 	INIT_LIST_HEAD(&afu->crs);
679 
680 	for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) {
681 		dev_attr = &afu_attrs[i];
682 		if (cxl_ops->support_attributes(dev_attr->attr.name,
683 						CXL_AFU_ATTRS)) {
684 			if ((rc = device_create_file(&afu->dev, &afu_attrs[i])))
685 				goto err;
686 		}
687 	}
688 
689 	/* conditionally create the add the binary file for error info buffer */
690 	if (afu->eb_len) {
691 		sysfs_attr_init(&afu->attr_eb.attr);
692 
693 		afu->attr_eb.attr.name = "afu_err_buff";
694 		afu->attr_eb.attr.mode = S_IRUGO;
695 		afu->attr_eb.size = afu->eb_len;
696 		afu->attr_eb.read = afu_eb_read;
697 
698 		rc = device_create_bin_file(&afu->dev, &afu->attr_eb);
699 		if (rc) {
700 			dev_err(&afu->dev,
701 				"Unable to create eb attr for the afu. Err(%d)\n",
702 				rc);
703 			goto err;
704 		}
705 	}
706 
707 	for (i = 0; i < afu->crs_num; i++) {
708 		cr = cxl_sysfs_afu_new_cr(afu, i);
709 		if (IS_ERR(cr)) {
710 			rc = PTR_ERR(cr);
711 			goto err1;
712 		}
713 		list_add(&cr->list, &afu->crs);
714 	}
715 
716 	return 0;
717 
718 err1:
719 	cxl_sysfs_afu_remove(afu);
720 	return rc;
721 err:
722 	/* reset the eb_len as we havent created the bin attr */
723 	afu->eb_len = 0;
724 
725 	for (i--; i >= 0; i--) {
726 		dev_attr = &afu_attrs[i];
727 		if (cxl_ops->support_attributes(dev_attr->attr.name,
728 						CXL_AFU_ATTRS))
729 		device_remove_file(&afu->dev, &afu_attrs[i]);
730 	}
731 	return rc;
732 }
733 
cxl_sysfs_afu_m_add(struct cxl_afu * afu)734 int cxl_sysfs_afu_m_add(struct cxl_afu *afu)
735 {
736 	struct device_attribute *dev_attr;
737 	int i, rc;
738 
739 	for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) {
740 		dev_attr = &afu_master_attrs[i];
741 		if (cxl_ops->support_attributes(dev_attr->attr.name,
742 						CXL_AFU_MASTER_ATTRS)) {
743 			if ((rc = device_create_file(afu->chardev_m, &afu_master_attrs[i])))
744 				goto err;
745 		}
746 	}
747 
748 	return 0;
749 
750 err:
751 	for (i--; i >= 0; i--) {
752 		dev_attr = &afu_master_attrs[i];
753 		if (cxl_ops->support_attributes(dev_attr->attr.name,
754 						CXL_AFU_MASTER_ATTRS))
755 			device_remove_file(afu->chardev_m, &afu_master_attrs[i]);
756 	}
757 	return rc;
758 }
759 
cxl_sysfs_afu_m_remove(struct cxl_afu * afu)760 void cxl_sysfs_afu_m_remove(struct cxl_afu *afu)
761 {
762 	struct device_attribute *dev_attr;
763 	int i;
764 
765 	for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) {
766 		dev_attr = &afu_master_attrs[i];
767 		if (cxl_ops->support_attributes(dev_attr->attr.name,
768 						CXL_AFU_MASTER_ATTRS))
769 			device_remove_file(afu->chardev_m, &afu_master_attrs[i]);
770 	}
771 }
772