1 // SPDX-License-Identifier: GPL-2.0
3 * PCI Endpoint *Function* (EPF) library
5 * Copyright (C) 2017 Texas Instruments
6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
9 #include <linux/device.h>
10 #include <linux/dma-mapping.h>
11 #include <linux/slab.h>
12 #include <linux/module.h>
14 #include <linux/pci-epc.h>
15 #include <linux/pci-epf.h>
16 #include <linux/pci-ep-cfs.h>
18 static DEFINE_MUTEX(pci_epf_mutex
);
20 static struct bus_type pci_epf_bus_type
;
21 static const struct device_type pci_epf_type
;
24 * pci_epf_unbind() - Notify the function driver that the binding between the
25 * EPF device and EPC device has been lost
26 * @epf: the EPF device which has lost the binding with the EPC device
28 * Invoke to notify the function driver that the binding between the EPF device
29 * and EPC device has been lost.
31 void pci_epf_unbind(struct pci_epf
*epf
)
34 dev_WARN(&epf
->dev
, "epf device not bound to driver\n");
38 mutex_lock(&epf
->lock
);
39 epf
->driver
->ops
->unbind(epf
);
40 mutex_unlock(&epf
->lock
);
41 module_put(epf
->driver
->owner
);
43 EXPORT_SYMBOL_GPL(pci_epf_unbind
);
46 * pci_epf_bind() - Notify the function driver that the EPF device has been
47 * bound to a EPC device
48 * @epf: the EPF device which has been bound to the EPC device
50 * Invoke to notify the function driver that it has been bound to a EPC device
52 int pci_epf_bind(struct pci_epf
*epf
)
57 dev_WARN(&epf
->dev
, "epf device not bound to driver\n");
61 if (!try_module_get(epf
->driver
->owner
))
64 mutex_lock(&epf
->lock
);
65 ret
= epf
->driver
->ops
->bind(epf
);
66 mutex_unlock(&epf
->lock
);
70 EXPORT_SYMBOL_GPL(pci_epf_bind
);
73 * pci_epf_free_space() - free the allocated PCI EPF register space
74 * @epf: the EPF device from whom to free the memory
75 * @addr: the virtual address of the PCI EPF register space
76 * @bar: the BAR number corresponding to the register space
78 * Invoke to free the allocated PCI EPF register space.
80 void pci_epf_free_space(struct pci_epf
*epf
, void *addr
, enum pci_barno bar
)
82 struct device
*dev
= epf
->epc
->dev
.parent
;
87 dma_free_coherent(dev
, epf
->bar
[bar
].size
, addr
,
88 epf
->bar
[bar
].phys_addr
);
90 epf
->bar
[bar
].phys_addr
= 0;
91 epf
->bar
[bar
].addr
= NULL
;
92 epf
->bar
[bar
].size
= 0;
93 epf
->bar
[bar
].barno
= 0;
94 epf
->bar
[bar
].flags
= 0;
96 EXPORT_SYMBOL_GPL(pci_epf_free_space
);
99 * pci_epf_alloc_space() - allocate memory for the PCI EPF register space
100 * @epf: the EPF device to whom allocate the memory
101 * @size: the size of the memory that has to be allocated
102 * @bar: the BAR number corresponding to the allocated register space
103 * @align: alignment size for the allocation region
105 * Invoke to allocate memory for the PCI EPF register space.
107 void *pci_epf_alloc_space(struct pci_epf
*epf
, size_t size
, enum pci_barno bar
,
111 struct device
*dev
= epf
->epc
->dev
.parent
;
112 dma_addr_t phys_addr
;
118 size
= ALIGN(size
, align
);
120 size
= roundup_pow_of_two(size
);
122 space
= dma_alloc_coherent(dev
, size
, &phys_addr
, GFP_KERNEL
);
124 dev_err(dev
, "failed to allocate mem space\n");
128 epf
->bar
[bar
].phys_addr
= phys_addr
;
129 epf
->bar
[bar
].addr
= space
;
130 epf
->bar
[bar
].size
= size
;
131 epf
->bar
[bar
].barno
= bar
;
132 epf
->bar
[bar
].flags
|= upper_32_bits(size
) ?
133 PCI_BASE_ADDRESS_MEM_TYPE_64
:
134 PCI_BASE_ADDRESS_MEM_TYPE_32
;
138 EXPORT_SYMBOL_GPL(pci_epf_alloc_space
);
140 static void pci_epf_remove_cfs(struct pci_epf_driver
*driver
)
142 struct config_group
*group
, *tmp
;
144 if (!IS_ENABLED(CONFIG_PCI_ENDPOINT_CONFIGFS
))
147 mutex_lock(&pci_epf_mutex
);
148 list_for_each_entry_safe(group
, tmp
, &driver
->epf_group
, group_entry
)
149 pci_ep_cfs_remove_epf_group(group
);
150 list_del(&driver
->epf_group
);
151 mutex_unlock(&pci_epf_mutex
);
155 * pci_epf_unregister_driver() - unregister the PCI EPF driver
156 * @driver: the PCI EPF driver that has to be unregistered
158 * Invoke to unregister the PCI EPF driver.
160 void pci_epf_unregister_driver(struct pci_epf_driver
*driver
)
162 pci_epf_remove_cfs(driver
);
163 driver_unregister(&driver
->driver
);
165 EXPORT_SYMBOL_GPL(pci_epf_unregister_driver
);
167 static int pci_epf_add_cfs(struct pci_epf_driver
*driver
)
169 struct config_group
*group
;
170 const struct pci_epf_device_id
*id
;
172 if (!IS_ENABLED(CONFIG_PCI_ENDPOINT_CONFIGFS
))
175 INIT_LIST_HEAD(&driver
->epf_group
);
177 id
= driver
->id_table
;
178 while (id
->name
[0]) {
179 group
= pci_ep_cfs_add_epf_group(id
->name
);
181 pci_epf_remove_cfs(driver
);
182 return PTR_ERR(group
);
185 mutex_lock(&pci_epf_mutex
);
186 list_add_tail(&group
->group_entry
, &driver
->epf_group
);
187 mutex_unlock(&pci_epf_mutex
);
195 * __pci_epf_register_driver() - register a new PCI EPF driver
196 * @driver: structure representing PCI EPF driver
197 * @owner: the owner of the module that registers the PCI EPF driver
199 * Invoke to register a new PCI EPF driver.
201 int __pci_epf_register_driver(struct pci_epf_driver
*driver
,
202 struct module
*owner
)
209 if (!driver
->ops
->bind
|| !driver
->ops
->unbind
)
212 driver
->driver
.bus
= &pci_epf_bus_type
;
213 driver
->driver
.owner
= owner
;
215 ret
= driver_register(&driver
->driver
);
219 pci_epf_add_cfs(driver
);
223 EXPORT_SYMBOL_GPL(__pci_epf_register_driver
);
226 * pci_epf_destroy() - destroy the created PCI EPF device
227 * @epf: the PCI EPF device that has to be destroyed.
229 * Invoke to destroy the PCI EPF device created by invoking pci_epf_create().
231 void pci_epf_destroy(struct pci_epf
*epf
)
233 device_unregister(&epf
->dev
);
235 EXPORT_SYMBOL_GPL(pci_epf_destroy
);
238 * pci_epf_create() - create a new PCI EPF device
239 * @name: the name of the PCI EPF device. This name will be used to bind the
240 * the EPF device to a EPF driver
242 * Invoke to create a new PCI EPF device by providing the name of the function
245 struct pci_epf
*pci_epf_create(const char *name
)
252 epf
= kzalloc(sizeof(*epf
), GFP_KERNEL
);
254 return ERR_PTR(-ENOMEM
);
256 len
= strchrnul(name
, '.') - name
;
257 epf
->name
= kstrndup(name
, len
, GFP_KERNEL
);
260 return ERR_PTR(-ENOMEM
);
264 device_initialize(dev
);
265 dev
->bus
= &pci_epf_bus_type
;
266 dev
->type
= &pci_epf_type
;
267 mutex_init(&epf
->lock
);
269 ret
= dev_set_name(dev
, "%s", name
);
275 ret
= device_add(dev
);
283 EXPORT_SYMBOL_GPL(pci_epf_create
);
285 const struct pci_epf_device_id
*
286 pci_epf_match_device(const struct pci_epf_device_id
*id
, struct pci_epf
*epf
)
292 if (strcmp(epf
->name
, id
->name
) == 0)
299 EXPORT_SYMBOL_GPL(pci_epf_match_device
);
301 static void pci_epf_dev_release(struct device
*dev
)
303 struct pci_epf
*epf
= to_pci_epf(dev
);
309 static const struct device_type pci_epf_type
= {
310 .release
= pci_epf_dev_release
,
314 pci_epf_match_id(const struct pci_epf_device_id
*id
, const struct pci_epf
*epf
)
316 while (id
->name
[0]) {
317 if (strcmp(epf
->name
, id
->name
) == 0)
325 static int pci_epf_device_match(struct device
*dev
, struct device_driver
*drv
)
327 struct pci_epf
*epf
= to_pci_epf(dev
);
328 struct pci_epf_driver
*driver
= to_pci_epf_driver(drv
);
330 if (driver
->id_table
)
331 return pci_epf_match_id(driver
->id_table
, epf
);
333 return !strcmp(epf
->name
, drv
->name
);
336 static int pci_epf_device_probe(struct device
*dev
)
338 struct pci_epf
*epf
= to_pci_epf(dev
);
339 struct pci_epf_driver
*driver
= to_pci_epf_driver(dev
->driver
);
344 epf
->driver
= driver
;
346 return driver
->probe(epf
);
349 static int pci_epf_device_remove(struct device
*dev
)
352 struct pci_epf
*epf
= to_pci_epf(dev
);
353 struct pci_epf_driver
*driver
= to_pci_epf_driver(dev
->driver
);
356 ret
= driver
->remove(epf
);
362 static struct bus_type pci_epf_bus_type
= {
364 .match
= pci_epf_device_match
,
365 .probe
= pci_epf_device_probe
,
366 .remove
= pci_epf_device_remove
,
369 static int __init
pci_epf_init(void)
373 ret
= bus_register(&pci_epf_bus_type
);
375 pr_err("failed to register pci epf bus --> %d\n", ret
);
381 module_init(pci_epf_init
);
383 static void __exit
pci_epf_exit(void)
385 bus_unregister(&pci_epf_bus_type
);
387 module_exit(pci_epf_exit
);
389 MODULE_DESCRIPTION("PCI EPF Library");
390 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
391 MODULE_LICENSE("GPL v2");