1 // SPDX-License-Identifier: GPL-2.0
3 * configfs to configure the PCI endpoint
5 * Copyright (C) 2017 Texas Instruments
6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
9 #include <linux/module.h>
10 #include <linux/idr.h>
11 #include <linux/slab.h>
13 #include <linux/pci-epc.h>
14 #include <linux/pci-epf.h>
15 #include <linux/pci-ep-cfs.h>
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
;
22 struct pci_epf_group
{
23 struct config_group group
;
28 struct pci_epc_group
{
29 struct config_group group
;
34 static inline struct pci_epf_group
*to_pci_epf_group(struct config_item
*item
)
36 return container_of(to_config_group(item
), struct pci_epf_group
, group
);
39 static inline struct pci_epc_group
*to_pci_epc_group(struct config_item
*item
)
41 return container_of(to_config_group(item
), struct pci_epc_group
, group
);
44 static ssize_t
pci_epc_start_store(struct config_item
*item
, const char *page
,
50 struct pci_epc_group
*epc_group
= to_pci_epc_group(item
);
54 ret
= kstrtobool(page
, &start
);
64 ret
= pci_epc_start(epc
);
66 dev_err(&epc
->dev
, "failed to start endpoint controller\n");
70 epc_group
->start
= start
;
75 static ssize_t
pci_epc_start_show(struct config_item
*item
, char *page
)
77 return sprintf(page
, "%d\n",
78 to_pci_epc_group(item
)->start
);
81 CONFIGFS_ATTR(pci_epc_
, start
);
83 static struct configfs_attribute
*pci_epc_attrs
[] = {
88 static int pci_epc_epf_link(struct config_item
*epc_item
,
89 struct config_item
*epf_item
)
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
;
97 ret
= pci_epc_add_epf(epc
, epf
);
101 ret
= pci_epf_bind(epf
);
103 pci_epc_remove_epf(epc
, epf
);
110 static void pci_epc_epf_unlink(struct config_item
*epc_item
,
111 struct config_item
*epf_item
)
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
);
118 WARN_ON_ONCE(epc_group
->start
);
120 epc
= epc_group
->epc
;
121 epf
= epf_group
->epf
;
123 pci_epc_remove_epf(epc
, epf
);
126 static struct configfs_item_operations pci_epc_item_ops
= {
127 .allow_link
= pci_epc_epf_link
,
128 .drop_link
= pci_epc_epf_unlink
,
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
,
137 struct config_group
*pci_ep_cfs_add_epc_group(const char *name
)
141 struct config_group
*group
;
142 struct pci_epc_group
*epc_group
;
144 epc_group
= kzalloc(sizeof(*epc_group
), GFP_KERNEL
);
150 group
= &epc_group
->group
;
152 config_group_init_type_name(group
, name
, &pci_epc_type
);
153 ret
= configfs_register_group(controllers_group
, group
);
155 pr_err("failed to register configfs group for %s\n", name
);
156 goto err_register_group
;
159 epc
= pci_epc_get(name
);
165 epc_group
->epc
= epc
;
170 configfs_unregister_group(group
);
178 EXPORT_SYMBOL(pci_ep_cfs_add_epc_group
);
180 void pci_ep_cfs_remove_epc_group(struct config_group
*group
)
182 struct pci_epc_group
*epc_group
;
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
);
192 EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group
);
194 #define PCI_EPF_HEADER_R(_name) \
195 static ssize_t pci_epf_##_name##_show(struct config_item *item, char *page) \
197 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
198 if (WARN_ON_ONCE(!epf->header)) \
200 return sprintf(page, "0x%04x\n", epf->header->_name); \
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) \
209 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
210 if (WARN_ON_ONCE(!epf->header)) \
212 ret = kstrtou32(page, 0, &val); \
215 epf->header->_name = val; \
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) \
225 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
226 if (WARN_ON_ONCE(!epf->header)) \
228 ret = kstrtou16(page, 0, &val); \
231 epf->header->_name = val; \
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) \
241 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
242 if (WARN_ON_ONCE(!epf->header)) \
244 ret = kstrtou8(page, 0, &val); \
247 epf->header->_name = val; \
251 static ssize_t
pci_epf_msi_interrupts_store(struct config_item
*item
,
252 const char *page
, size_t len
)
257 ret
= kstrtou8(page
, 0, &val
);
261 to_pci_epf_group(item
)->epf
->msi_interrupts
= val
;
266 static ssize_t
pci_epf_msi_interrupts_show(struct config_item
*item
,
269 return sprintf(page
, "%d\n",
270 to_pci_epf_group(item
)->epf
->msi_interrupts
);
273 static ssize_t
pci_epf_msix_interrupts_store(struct config_item
*item
,
274 const char *page
, size_t len
)
279 ret
= kstrtou16(page
, 0, &val
);
283 to_pci_epf_group(item
)->epf
->msix_interrupts
= val
;
288 static ssize_t
pci_epf_msix_interrupts_show(struct config_item
*item
,
291 return sprintf(page
, "%d\n",
292 to_pci_epf_group(item
)->epf
->msix_interrupts
);
295 PCI_EPF_HEADER_R(vendorid
)
296 PCI_EPF_HEADER_W_u16(vendorid
)
298 PCI_EPF_HEADER_R(deviceid
)
299 PCI_EPF_HEADER_W_u16(deviceid
)
301 PCI_EPF_HEADER_R(revid
)
302 PCI_EPF_HEADER_W_u8(revid
)
304 PCI_EPF_HEADER_R(progif_code
)
305 PCI_EPF_HEADER_W_u8(progif_code
)
307 PCI_EPF_HEADER_R(subclass_code
)
308 PCI_EPF_HEADER_W_u8(subclass_code
)
310 PCI_EPF_HEADER_R(baseclass_code
)
311 PCI_EPF_HEADER_W_u8(baseclass_code
)
313 PCI_EPF_HEADER_R(cache_line_size
)
314 PCI_EPF_HEADER_W_u8(cache_line_size
)
316 PCI_EPF_HEADER_R(subsys_vendor_id
)
317 PCI_EPF_HEADER_W_u16(subsys_vendor_id
)
319 PCI_EPF_HEADER_R(subsys_id
)
320 PCI_EPF_HEADER_W_u16(subsys_id
)
322 PCI_EPF_HEADER_R(interrupt_pin
)
323 PCI_EPF_HEADER_W_u8(interrupt_pin
)
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
);
338 static struct configfs_attribute
*pci_epf_attrs
[] = {
339 &pci_epf_attr_vendorid
,
340 &pci_epf_attr_deviceid
,
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
,
354 static void pci_epf_release(struct config_item
*item
)
356 struct pci_epf_group
*epf_group
= to_pci_epf_group(item
);
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
);
365 static struct configfs_item_operations pci_epf_ops
= {
366 .release
= pci_epf_release
,
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
,
375 static struct config_group
*pci_epf_make(struct config_group
*group
,
378 struct pci_epf_group
*epf_group
;
383 epf_group
= kzalloc(sizeof(*epf_group
), GFP_KERNEL
);
385 return ERR_PTR(-ENOMEM
);
387 mutex_lock(&functions_mutex
);
388 index
= idr_alloc(&functions_idr
, epf_group
, 0, 0, GFP_KERNEL
);
389 mutex_unlock(&functions_mutex
);
395 epf_group
->index
= index
;
397 config_group_init_type_name(&epf_group
->group
, name
, &pci_epf_type
);
399 epf_name
= kasprintf(GFP_KERNEL
, "%s.%d",
400 group
->cg_item
.ci_name
, epf_group
->index
);
406 epf
= pci_epf_create(epf_name
);
408 pr_err("failed to create endpoint function device\n");
413 epf_group
->epf
= epf
;
417 return &epf_group
->group
;
423 mutex_lock(&functions_mutex
);
424 idr_remove(&functions_idr
, epf_group
->index
);
425 mutex_unlock(&functions_mutex
);
433 static void pci_epf_drop(struct config_group
*group
, struct config_item
*item
)
435 config_item_put(item
);
438 static struct configfs_group_operations pci_epf_group_ops
= {
439 .make_group
= &pci_epf_make
,
440 .drop_item
= &pci_epf_drop
,
443 static const struct config_item_type pci_epf_group_type
= {
444 .ct_group_ops
= &pci_epf_group_ops
,
445 .ct_owner
= THIS_MODULE
,
448 struct config_group
*pci_ep_cfs_add_epf_group(const char *name
)
450 struct config_group
*group
;
452 group
= configfs_register_default_group(functions_group
, name
,
453 &pci_epf_group_type
);
455 pr_err("failed to register configfs group for %s function\n",
460 EXPORT_SYMBOL(pci_ep_cfs_add_epf_group
);
462 void pci_ep_cfs_remove_epf_group(struct config_group
*group
)
464 if (IS_ERR_OR_NULL(group
))
467 configfs_unregister_default_group(group
);
469 EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group
);
471 static const struct config_item_type pci_functions_type
= {
472 .ct_owner
= THIS_MODULE
,
475 static const struct config_item_type pci_controllers_type
= {
476 .ct_owner
= THIS_MODULE
,
479 static const struct config_item_type pci_ep_type
= {
480 .ct_owner
= THIS_MODULE
,
483 static struct configfs_subsystem pci_ep_cfs_subsys
= {
486 .ci_namebuf
= "pci_ep",
487 .ci_type
= &pci_ep_type
,
490 .su_mutex
= __MUTEX_INITIALIZER(pci_ep_cfs_subsys
.su_mutex
),
493 static int __init
pci_ep_cfs_init(void)
496 struct config_group
*root
= &pci_ep_cfs_subsys
.su_group
;
498 config_group_init(root
);
500 ret
= configfs_register_subsystem(&pci_ep_cfs_subsys
);
502 pr_err("Error %d while registering subsystem %s\n",
503 ret
, root
->cg_item
.ci_namebuf
);
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",
513 goto err_functions_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",
523 goto err_controllers_group
;
528 err_controllers_group
:
529 configfs_unregister_default_group(functions_group
);
532 configfs_unregister_subsystem(&pci_ep_cfs_subsys
);
537 module_init(pci_ep_cfs_init
);
539 static void __exit
pci_ep_cfs_exit(void)
541 configfs_unregister_default_group(controllers_group
);
542 configfs_unregister_default_group(functions_group
);
543 configfs_unregister_subsystem(&pci_ep_cfs_subsys
);
545 module_exit(pci_ep_cfs_exit
);
547 MODULE_DESCRIPTION("PCI EP CONFIGFS");
548 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
549 MODULE_LICENSE("GPL v2");