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_linkup() - Notify the function driver that EPC device has
25 * established a connection with the Root Complex.
26 * @epf: the EPF device bound to the EPC device which has established
27 * the connection with the host
29 * Invoke to notify the function driver that EPC device has established
30 * a connection with the Root Complex.
32 void pci_epf_linkup(struct pci_epf
*epf
)
35 dev_WARN(&epf
->dev
, "epf device not bound to driver\n");
39 epf
->driver
->ops
->linkup(epf
);
41 EXPORT_SYMBOL_GPL(pci_epf_linkup
);
44 * pci_epf_unbind() - Notify the function driver that the binding between the
45 * EPF device and EPC device has been lost
46 * @epf: the EPF device which has lost the binding with the EPC device
48 * Invoke to notify the function driver that the binding between the EPF device
49 * and EPC device has been lost.
51 void pci_epf_unbind(struct pci_epf
*epf
)
54 dev_WARN(&epf
->dev
, "epf device not bound to driver\n");
58 epf
->driver
->ops
->unbind(epf
);
59 module_put(epf
->driver
->owner
);
61 EXPORT_SYMBOL_GPL(pci_epf_unbind
);
64 * pci_epf_bind() - Notify the function driver that the EPF device has been
65 * bound to a EPC device
66 * @epf: the EPF device which has been bound to the EPC device
68 * Invoke to notify the function driver that it has been bound to a EPC device
70 int pci_epf_bind(struct pci_epf
*epf
)
73 dev_WARN(&epf
->dev
, "epf device not bound to driver\n");
77 if (!try_module_get(epf
->driver
->owner
))
80 return epf
->driver
->ops
->bind(epf
);
82 EXPORT_SYMBOL_GPL(pci_epf_bind
);
85 * pci_epf_free_space() - free the allocated PCI EPF register space
86 * @addr: the virtual address of the PCI EPF register space
87 * @bar: the BAR number corresponding to the register space
89 * Invoke to free the allocated PCI EPF register space.
91 void pci_epf_free_space(struct pci_epf
*epf
, void *addr
, enum pci_barno bar
)
93 struct device
*dev
= epf
->epc
->dev
.parent
;
98 dma_free_coherent(dev
, epf
->bar
[bar
].size
, addr
,
99 epf
->bar
[bar
].phys_addr
);
101 epf
->bar
[bar
].phys_addr
= 0;
102 epf
->bar
[bar
].size
= 0;
103 epf
->bar
[bar
].barno
= 0;
104 epf
->bar
[bar
].flags
= 0;
106 EXPORT_SYMBOL_GPL(pci_epf_free_space
);
109 * pci_epf_alloc_space() - allocate memory for the PCI EPF register space
110 * @size: the size of the memory that has to be allocated
111 * @bar: the BAR number corresponding to the allocated register space
113 * Invoke to allocate memory for the PCI EPF register space.
115 void *pci_epf_alloc_space(struct pci_epf
*epf
, size_t size
, enum pci_barno bar
)
118 struct device
*dev
= epf
->epc
->dev
.parent
;
119 dma_addr_t phys_addr
;
123 size
= roundup_pow_of_two(size
);
125 space
= dma_alloc_coherent(dev
, size
, &phys_addr
, GFP_KERNEL
);
127 dev_err(dev
, "failed to allocate mem space\n");
131 epf
->bar
[bar
].phys_addr
= phys_addr
;
132 epf
->bar
[bar
].size
= size
;
133 epf
->bar
[bar
].barno
= bar
;
134 epf
->bar
[bar
].flags
= PCI_BASE_ADDRESS_SPACE_MEMORY
;
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
|| !driver
->ops
->linkup
)
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
;
268 ret
= dev_set_name(dev
, "%s", name
);
274 ret
= device_add(dev
);
282 EXPORT_SYMBOL_GPL(pci_epf_create
);
284 const struct pci_epf_device_id
*
285 pci_epf_match_device(const struct pci_epf_device_id
*id
, struct pci_epf
*epf
)
291 if (strcmp(epf
->name
, id
->name
) == 0)
298 EXPORT_SYMBOL_GPL(pci_epf_match_device
);
300 static void pci_epf_dev_release(struct device
*dev
)
302 struct pci_epf
*epf
= to_pci_epf(dev
);
308 static const struct device_type pci_epf_type
= {
309 .release
= pci_epf_dev_release
,
313 pci_epf_match_id(const struct pci_epf_device_id
*id
, const struct pci_epf
*epf
)
315 while (id
->name
[0]) {
316 if (strcmp(epf
->name
, id
->name
) == 0)
324 static int pci_epf_device_match(struct device
*dev
, struct device_driver
*drv
)
326 struct pci_epf
*epf
= to_pci_epf(dev
);
327 struct pci_epf_driver
*driver
= to_pci_epf_driver(drv
);
329 if (driver
->id_table
)
330 return pci_epf_match_id(driver
->id_table
, epf
);
332 return !strcmp(epf
->name
, drv
->name
);
335 static int pci_epf_device_probe(struct device
*dev
)
337 struct pci_epf
*epf
= to_pci_epf(dev
);
338 struct pci_epf_driver
*driver
= to_pci_epf_driver(dev
->driver
);
343 epf
->driver
= driver
;
345 return driver
->probe(epf
);
348 static int pci_epf_device_remove(struct device
*dev
)
351 struct pci_epf
*epf
= to_pci_epf(dev
);
352 struct pci_epf_driver
*driver
= to_pci_epf_driver(dev
->driver
);
355 ret
= driver
->remove(epf
);
361 static struct bus_type pci_epf_bus_type
= {
363 .match
= pci_epf_device_match
,
364 .probe
= pci_epf_device_probe
,
365 .remove
= pci_epf_device_remove
,
368 static int __init
pci_epf_init(void)
372 ret
= bus_register(&pci_epf_bus_type
);
374 pr_err("failed to register pci epf bus --> %d\n", ret
);
380 module_init(pci_epf_init
);
382 static void __exit
pci_epf_exit(void)
384 bus_unregister(&pci_epf_bus_type
);
386 module_exit(pci_epf_exit
);
388 MODULE_DESCRIPTION("PCI EPF Library");
389 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
390 MODULE_LICENSE("GPL v2");