]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/pci/endpoint/pci-ep-cfs.c
3710adf51912de68207fa021ee5325eb8af9782a
[mirror_ubuntu-jammy-kernel.git] / drivers / pci / endpoint / pci-ep-cfs.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * configfs to configure the PCI endpoint
4 *
5 * Copyright (C) 2017 Texas Instruments
6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
7 */
8
9 #include <linux/module.h>
10 #include <linux/idr.h>
11 #include <linux/slab.h>
12
13 #include <linux/pci-epc.h>
14 #include <linux/pci-epf.h>
15 #include <linux/pci-ep-cfs.h>
16
17 static DEFINE_IDR(functions_idr);
18 static DEFINE_MUTEX(functions_mutex);
19 static struct config_group *functions_group;
20 static struct config_group *controllers_group;
21
22 struct pci_epf_group {
23 struct config_group group;
24 struct pci_epf *epf;
25 int index;
26 };
27
28 struct pci_epc_group {
29 struct config_group group;
30 struct pci_epc *epc;
31 bool start;
32 };
33
34 static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item)
35 {
36 return container_of(to_config_group(item), struct pci_epf_group, group);
37 }
38
39 static inline struct pci_epc_group *to_pci_epc_group(struct config_item *item)
40 {
41 return container_of(to_config_group(item), struct pci_epc_group, group);
42 }
43
44 static ssize_t pci_epc_start_store(struct config_item *item, const char *page,
45 size_t len)
46 {
47 int ret;
48 bool start;
49 struct pci_epc *epc;
50 struct pci_epc_group *epc_group = to_pci_epc_group(item);
51
52 epc = epc_group->epc;
53
54 ret = kstrtobool(page, &start);
55 if (ret)
56 return ret;
57
58 if (!start) {
59 pci_epc_stop(epc);
60 epc_group->start = 0;
61 return len;
62 }
63
64 ret = pci_epc_start(epc);
65 if (ret) {
66 dev_err(&epc->dev, "failed to start endpoint controller\n");
67 return -EINVAL;
68 }
69
70 epc_group->start = start;
71
72 return len;
73 }
74
75 static ssize_t pci_epc_start_show(struct config_item *item, char *page)
76 {
77 return sprintf(page, "%d\n",
78 to_pci_epc_group(item)->start);
79 }
80
81 CONFIGFS_ATTR(pci_epc_, start);
82
83 static struct configfs_attribute *pci_epc_attrs[] = {
84 &pci_epc_attr_start,
85 NULL,
86 };
87
88 static int pci_epc_epf_link(struct config_item *epc_item,
89 struct config_item *epf_item)
90 {
91 int ret;
92 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
93 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
94 struct pci_epc *epc = epc_group->epc;
95 struct pci_epf *epf = epf_group->epf;
96
97 ret = pci_epc_add_epf(epc, epf);
98 if (ret)
99 return ret;
100
101 ret = pci_epf_bind(epf);
102 if (ret) {
103 pci_epc_remove_epf(epc, epf);
104 return ret;
105 }
106
107 return 0;
108 }
109
110 static void pci_epc_epf_unlink(struct config_item *epc_item,
111 struct config_item *epf_item)
112 {
113 struct pci_epc *epc;
114 struct pci_epf *epf;
115 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
116 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
117
118 WARN_ON_ONCE(epc_group->start);
119
120 epc = epc_group->epc;
121 epf = epf_group->epf;
122 pci_epf_unbind(epf);
123 pci_epc_remove_epf(epc, epf);
124 }
125
126 static struct configfs_item_operations pci_epc_item_ops = {
127 .allow_link = pci_epc_epf_link,
128 .drop_link = pci_epc_epf_unlink,
129 };
130
131 static const struct config_item_type pci_epc_type = {
132 .ct_item_ops = &pci_epc_item_ops,
133 .ct_attrs = pci_epc_attrs,
134 .ct_owner = THIS_MODULE,
135 };
136
137 struct config_group *pci_ep_cfs_add_epc_group(const char *name)
138 {
139 int ret;
140 struct pci_epc *epc;
141 struct config_group *group;
142 struct pci_epc_group *epc_group;
143
144 epc_group = kzalloc(sizeof(*epc_group), GFP_KERNEL);
145 if (!epc_group) {
146 ret = -ENOMEM;
147 goto err;
148 }
149
150 group = &epc_group->group;
151
152 config_group_init_type_name(group, name, &pci_epc_type);
153 ret = configfs_register_group(controllers_group, group);
154 if (ret) {
155 pr_err("failed to register configfs group for %s\n", name);
156 goto err_register_group;
157 }
158
159 epc = pci_epc_get(name);
160 if (IS_ERR(epc)) {
161 ret = PTR_ERR(epc);
162 goto err_epc_get;
163 }
164
165 epc_group->epc = epc;
166
167 return group;
168
169 err_epc_get:
170 configfs_unregister_group(group);
171
172 err_register_group:
173 kfree(epc_group);
174
175 err:
176 return ERR_PTR(ret);
177 }
178 EXPORT_SYMBOL(pci_ep_cfs_add_epc_group);
179
180 void pci_ep_cfs_remove_epc_group(struct config_group *group)
181 {
182 struct pci_epc_group *epc_group;
183
184 if (!group)
185 return;
186
187 epc_group = container_of(group, struct pci_epc_group, group);
188 pci_epc_put(epc_group->epc);
189 configfs_unregister_group(&epc_group->group);
190 kfree(epc_group);
191 }
192 EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group);
193
194 #define PCI_EPF_HEADER_R(_name) \
195 static ssize_t pci_epf_##_name##_show(struct config_item *item, char *page) \
196 { \
197 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
198 if (WARN_ON_ONCE(!epf->header)) \
199 return -EINVAL; \
200 return sprintf(page, "0x%04x\n", epf->header->_name); \
201 }
202
203 #define PCI_EPF_HEADER_W_u32(_name) \
204 static ssize_t pci_epf_##_name##_store(struct config_item *item, \
205 const char *page, size_t len) \
206 { \
207 u32 val; \
208 int ret; \
209 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
210 if (WARN_ON_ONCE(!epf->header)) \
211 return -EINVAL; \
212 ret = kstrtou32(page, 0, &val); \
213 if (ret) \
214 return ret; \
215 epf->header->_name = val; \
216 return len; \
217 }
218
219 #define PCI_EPF_HEADER_W_u16(_name) \
220 static ssize_t pci_epf_##_name##_store(struct config_item *item, \
221 const char *page, size_t len) \
222 { \
223 u16 val; \
224 int ret; \
225 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
226 if (WARN_ON_ONCE(!epf->header)) \
227 return -EINVAL; \
228 ret = kstrtou16(page, 0, &val); \
229 if (ret) \
230 return ret; \
231 epf->header->_name = val; \
232 return len; \
233 }
234
235 #define PCI_EPF_HEADER_W_u8(_name) \
236 static ssize_t pci_epf_##_name##_store(struct config_item *item, \
237 const char *page, size_t len) \
238 { \
239 u8 val; \
240 int ret; \
241 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
242 if (WARN_ON_ONCE(!epf->header)) \
243 return -EINVAL; \
244 ret = kstrtou8(page, 0, &val); \
245 if (ret) \
246 return ret; \
247 epf->header->_name = val; \
248 return len; \
249 }
250
251 static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
252 const char *page, size_t len)
253 {
254 u8 val;
255 int ret;
256
257 ret = kstrtou8(page, 0, &val);
258 if (ret)
259 return ret;
260
261 to_pci_epf_group(item)->epf->msi_interrupts = val;
262
263 return len;
264 }
265
266 static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
267 char *page)
268 {
269 return sprintf(page, "%d\n",
270 to_pci_epf_group(item)->epf->msi_interrupts);
271 }
272
273 static ssize_t pci_epf_msix_interrupts_store(struct config_item *item,
274 const char *page, size_t len)
275 {
276 u16 val;
277 int ret;
278
279 ret = kstrtou16(page, 0, &val);
280 if (ret)
281 return ret;
282
283 to_pci_epf_group(item)->epf->msix_interrupts = val;
284
285 return len;
286 }
287
288 static ssize_t pci_epf_msix_interrupts_show(struct config_item *item,
289 char *page)
290 {
291 return sprintf(page, "%d\n",
292 to_pci_epf_group(item)->epf->msix_interrupts);
293 }
294
295 PCI_EPF_HEADER_R(vendorid)
296 PCI_EPF_HEADER_W_u16(vendorid)
297
298 PCI_EPF_HEADER_R(deviceid)
299 PCI_EPF_HEADER_W_u16(deviceid)
300
301 PCI_EPF_HEADER_R(revid)
302 PCI_EPF_HEADER_W_u8(revid)
303
304 PCI_EPF_HEADER_R(progif_code)
305 PCI_EPF_HEADER_W_u8(progif_code)
306
307 PCI_EPF_HEADER_R(subclass_code)
308 PCI_EPF_HEADER_W_u8(subclass_code)
309
310 PCI_EPF_HEADER_R(baseclass_code)
311 PCI_EPF_HEADER_W_u8(baseclass_code)
312
313 PCI_EPF_HEADER_R(cache_line_size)
314 PCI_EPF_HEADER_W_u8(cache_line_size)
315
316 PCI_EPF_HEADER_R(subsys_vendor_id)
317 PCI_EPF_HEADER_W_u16(subsys_vendor_id)
318
319 PCI_EPF_HEADER_R(subsys_id)
320 PCI_EPF_HEADER_W_u16(subsys_id)
321
322 PCI_EPF_HEADER_R(interrupt_pin)
323 PCI_EPF_HEADER_W_u8(interrupt_pin)
324
325 CONFIGFS_ATTR(pci_epf_, vendorid);
326 CONFIGFS_ATTR(pci_epf_, deviceid);
327 CONFIGFS_ATTR(pci_epf_, revid);
328 CONFIGFS_ATTR(pci_epf_, progif_code);
329 CONFIGFS_ATTR(pci_epf_, subclass_code);
330 CONFIGFS_ATTR(pci_epf_, baseclass_code);
331 CONFIGFS_ATTR(pci_epf_, cache_line_size);
332 CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
333 CONFIGFS_ATTR(pci_epf_, subsys_id);
334 CONFIGFS_ATTR(pci_epf_, interrupt_pin);
335 CONFIGFS_ATTR(pci_epf_, msi_interrupts);
336 CONFIGFS_ATTR(pci_epf_, msix_interrupts);
337
338 static struct configfs_attribute *pci_epf_attrs[] = {
339 &pci_epf_attr_vendorid,
340 &pci_epf_attr_deviceid,
341 &pci_epf_attr_revid,
342 &pci_epf_attr_progif_code,
343 &pci_epf_attr_subclass_code,
344 &pci_epf_attr_baseclass_code,
345 &pci_epf_attr_cache_line_size,
346 &pci_epf_attr_subsys_vendor_id,
347 &pci_epf_attr_subsys_id,
348 &pci_epf_attr_interrupt_pin,
349 &pci_epf_attr_msi_interrupts,
350 &pci_epf_attr_msix_interrupts,
351 NULL,
352 };
353
354 static void pci_epf_release(struct config_item *item)
355 {
356 struct pci_epf_group *epf_group = to_pci_epf_group(item);
357
358 mutex_lock(&functions_mutex);
359 idr_remove(&functions_idr, epf_group->index);
360 mutex_unlock(&functions_mutex);
361 pci_epf_destroy(epf_group->epf);
362 kfree(epf_group);
363 }
364
365 static struct configfs_item_operations pci_epf_ops = {
366 .release = pci_epf_release,
367 };
368
369 static const struct config_item_type pci_epf_type = {
370 .ct_item_ops = &pci_epf_ops,
371 .ct_attrs = pci_epf_attrs,
372 .ct_owner = THIS_MODULE,
373 };
374
375 static struct config_group *pci_epf_make(struct config_group *group,
376 const char *name)
377 {
378 struct pci_epf_group *epf_group;
379 struct pci_epf *epf;
380 char *epf_name;
381 int index, err;
382
383 epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
384 if (!epf_group)
385 return ERR_PTR(-ENOMEM);
386
387 mutex_lock(&functions_mutex);
388 index = idr_alloc(&functions_idr, epf_group, 0, 0, GFP_KERNEL);
389 mutex_unlock(&functions_mutex);
390 if (index < 0) {
391 err = index;
392 goto free_group;
393 }
394
395 epf_group->index = index;
396
397 config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
398
399 epf_name = kasprintf(GFP_KERNEL, "%s.%d",
400 group->cg_item.ci_name, epf_group->index);
401 if (!epf_name) {
402 err = -ENOMEM;
403 goto remove_idr;
404 }
405
406 epf = pci_epf_create(epf_name);
407 if (IS_ERR(epf)) {
408 pr_err("failed to create endpoint function device\n");
409 err = -EINVAL;
410 goto free_name;
411 }
412
413 epf_group->epf = epf;
414
415 kfree(epf_name);
416
417 return &epf_group->group;
418
419 free_name:
420 kfree(epf_name);
421
422 remove_idr:
423 mutex_lock(&functions_mutex);
424 idr_remove(&functions_idr, epf_group->index);
425 mutex_unlock(&functions_mutex);
426
427 free_group:
428 kfree(epf_group);
429
430 return ERR_PTR(err);
431 }
432
433 static void pci_epf_drop(struct config_group *group, struct config_item *item)
434 {
435 config_item_put(item);
436 }
437
438 static struct configfs_group_operations pci_epf_group_ops = {
439 .make_group = &pci_epf_make,
440 .drop_item = &pci_epf_drop,
441 };
442
443 static const struct config_item_type pci_epf_group_type = {
444 .ct_group_ops = &pci_epf_group_ops,
445 .ct_owner = THIS_MODULE,
446 };
447
448 struct config_group *pci_ep_cfs_add_epf_group(const char *name)
449 {
450 struct config_group *group;
451
452 group = configfs_register_default_group(functions_group, name,
453 &pci_epf_group_type);
454 if (IS_ERR(group))
455 pr_err("failed to register configfs group for %s function\n",
456 name);
457
458 return group;
459 }
460 EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
461
462 void pci_ep_cfs_remove_epf_group(struct config_group *group)
463 {
464 if (IS_ERR_OR_NULL(group))
465 return;
466
467 configfs_unregister_default_group(group);
468 }
469 EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
470
471 static const struct config_item_type pci_functions_type = {
472 .ct_owner = THIS_MODULE,
473 };
474
475 static const struct config_item_type pci_controllers_type = {
476 .ct_owner = THIS_MODULE,
477 };
478
479 static const struct config_item_type pci_ep_type = {
480 .ct_owner = THIS_MODULE,
481 };
482
483 static struct configfs_subsystem pci_ep_cfs_subsys = {
484 .su_group = {
485 .cg_item = {
486 .ci_namebuf = "pci_ep",
487 .ci_type = &pci_ep_type,
488 },
489 },
490 .su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
491 };
492
493 static int __init pci_ep_cfs_init(void)
494 {
495 int ret;
496 struct config_group *root = &pci_ep_cfs_subsys.su_group;
497
498 config_group_init(root);
499
500 ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
501 if (ret) {
502 pr_err("Error %d while registering subsystem %s\n",
503 ret, root->cg_item.ci_namebuf);
504 goto err;
505 }
506
507 functions_group = configfs_register_default_group(root, "functions",
508 &pci_functions_type);
509 if (IS_ERR(functions_group)) {
510 ret = PTR_ERR(functions_group);
511 pr_err("Error %d while registering functions group\n",
512 ret);
513 goto err_functions_group;
514 }
515
516 controllers_group =
517 configfs_register_default_group(root, "controllers",
518 &pci_controllers_type);
519 if (IS_ERR(controllers_group)) {
520 ret = PTR_ERR(controllers_group);
521 pr_err("Error %d while registering controllers group\n",
522 ret);
523 goto err_controllers_group;
524 }
525
526 return 0;
527
528 err_controllers_group:
529 configfs_unregister_default_group(functions_group);
530
531 err_functions_group:
532 configfs_unregister_subsystem(&pci_ep_cfs_subsys);
533
534 err:
535 return ret;
536 }
537 module_init(pci_ep_cfs_init);
538
539 static void __exit pci_ep_cfs_exit(void)
540 {
541 configfs_unregister_default_group(controllers_group);
542 configfs_unregister_default_group(functions_group);
543 configfs_unregister_subsystem(&pci_ep_cfs_subsys);
544 }
545 module_exit(pci_ep_cfs_exit);
546
547 MODULE_DESCRIPTION("PCI EP CONFIGFS");
548 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
549 MODULE_LICENSE("GPL v2");