diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/Makefile | 2 | ||||
-rw-r--r-- | drivers/pci/Kconfig | 1 | ||||
-rw-r--r-- | drivers/pci/endpoint/Kconfig | 20 | ||||
-rw-r--r-- | drivers/pci/endpoint/Makefile | 6 | ||||
-rw-r--r-- | drivers/pci/endpoint/pci-epc-core.c | 576 | ||||
-rw-r--r-- | drivers/pci/endpoint/pci-epc-mem.c | 143 | ||||
-rw-r--r-- | drivers/pci/endpoint/pci-epf-core.c | 355 |
7 files changed, 1103 insertions, 0 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index 2eced9afba53..a5f8e43b2c4d 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -14,7 +14,9 @@ obj-$(CONFIG_GENERIC_PHY) += phy/ | |||
14 | obj-$(CONFIG_PINCTRL) += pinctrl/ | 14 | obj-$(CONFIG_PINCTRL) += pinctrl/ |
15 | obj-$(CONFIG_GPIOLIB) += gpio/ | 15 | obj-$(CONFIG_GPIOLIB) += gpio/ |
16 | obj-y += pwm/ | 16 | obj-y += pwm/ |
17 | |||
17 | obj-$(CONFIG_PCI) += pci/ | 18 | obj-$(CONFIG_PCI) += pci/ |
19 | obj-$(CONFIG_PCI_ENDPOINT) += pci/endpoint/ | ||
18 | # PCI dwc controller drivers | 20 | # PCI dwc controller drivers |
19 | obj-y += pci/dwc/ | 21 | obj-y += pci/dwc/ |
20 | 22 | ||
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index df141420c902..9747c1ec8c74 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
@@ -134,3 +134,4 @@ config PCI_HYPERV | |||
134 | source "drivers/pci/hotplug/Kconfig" | 134 | source "drivers/pci/hotplug/Kconfig" |
135 | source "drivers/pci/dwc/Kconfig" | 135 | source "drivers/pci/dwc/Kconfig" |
136 | source "drivers/pci/host/Kconfig" | 136 | source "drivers/pci/host/Kconfig" |
137 | source "drivers/pci/endpoint/Kconfig" | ||
diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig new file mode 100644 index 000000000000..a5442ace7077 --- /dev/null +++ b/drivers/pci/endpoint/Kconfig | |||
@@ -0,0 +1,20 @@ | |||
1 | # | ||
2 | # PCI Endpoint Support | ||
3 | # | ||
4 | |||
5 | menu "PCI Endpoint" | ||
6 | |||
7 | config PCI_ENDPOINT | ||
8 | bool "PCI Endpoint Support" | ||
9 | help | ||
10 | Enable this configuration option to support configurable PCI | ||
11 | endpoint. This should be enabled if the platform has a PCI | ||
12 | controller that can operate in endpoint mode. | ||
13 | |||
14 | Enabling this option will build the endpoint library, which | ||
15 | includes endpoint controller library and endpoint function | ||
16 | library. | ||
17 | |||
18 | If in doubt, say "N" to disable Endpoint support. | ||
19 | |||
20 | endmenu | ||
diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile new file mode 100644 index 000000000000..dc1bc16491e6 --- /dev/null +++ b/drivers/pci/endpoint/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for PCI Endpoint Support | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_PCI_ENDPOINT) += pci-epc-core.o pci-epf-core.o\ | ||
6 | pci-epc-mem.o | ||
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c new file mode 100644 index 000000000000..7c71dd94721c --- /dev/null +++ b/drivers/pci/endpoint/pci-epc-core.c | |||
@@ -0,0 +1,576 @@ | |||
1 | /** | ||
2 | * PCI Endpoint *Controller* (EPC) library | ||
3 | * | ||
4 | * Copyright (C) 2017 Texas Instruments | ||
5 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | ||
6 | * | ||
7 | * This program is free software: you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 of | ||
9 | * the License as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/device.h> | ||
21 | #include <linux/dma-mapping.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/module.h> | ||
24 | |||
25 | #include <linux/pci-epc.h> | ||
26 | #include <linux/pci-epf.h> | ||
27 | |||
28 | static struct class *pci_epc_class; | ||
29 | |||
30 | static void devm_pci_epc_release(struct device *dev, void *res) | ||
31 | { | ||
32 | struct pci_epc *epc = *(struct pci_epc **)res; | ||
33 | |||
34 | pci_epc_destroy(epc); | ||
35 | } | ||
36 | |||
37 | static int devm_pci_epc_match(struct device *dev, void *res, void *match_data) | ||
38 | { | ||
39 | struct pci_epc **epc = res; | ||
40 | |||
41 | return *epc == match_data; | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * pci_epc_put() - release the PCI endpoint controller | ||
46 | * @epc: epc returned by pci_epc_get() | ||
47 | * | ||
48 | * release the refcount the caller obtained by invoking pci_epc_get() | ||
49 | */ | ||
50 | void pci_epc_put(struct pci_epc *epc) | ||
51 | { | ||
52 | if (!epc || IS_ERR(epc)) | ||
53 | return; | ||
54 | |||
55 | module_put(epc->ops->owner); | ||
56 | put_device(&epc->dev); | ||
57 | } | ||
58 | EXPORT_SYMBOL_GPL(pci_epc_put); | ||
59 | |||
60 | /** | ||
61 | * pci_epc_get() - get the PCI endpoint controller | ||
62 | * @epc_name: device name of the endpoint controller | ||
63 | * | ||
64 | * Invoke to get struct pci_epc * corresponding to the device name of the | ||
65 | * endpoint controller | ||
66 | */ | ||
67 | struct pci_epc *pci_epc_get(const char *epc_name) | ||
68 | { | ||
69 | int ret = -EINVAL; | ||
70 | struct pci_epc *epc; | ||
71 | struct device *dev; | ||
72 | struct class_dev_iter iter; | ||
73 | |||
74 | class_dev_iter_init(&iter, pci_epc_class, NULL, NULL); | ||
75 | while ((dev = class_dev_iter_next(&iter))) { | ||
76 | if (strcmp(epc_name, dev_name(dev))) | ||
77 | continue; | ||
78 | |||
79 | epc = to_pci_epc(dev); | ||
80 | if (!try_module_get(epc->ops->owner)) { | ||
81 | ret = -EINVAL; | ||
82 | goto err; | ||
83 | } | ||
84 | |||
85 | class_dev_iter_exit(&iter); | ||
86 | get_device(&epc->dev); | ||
87 | return epc; | ||
88 | } | ||
89 | |||
90 | err: | ||
91 | class_dev_iter_exit(&iter); | ||
92 | return ERR_PTR(ret); | ||
93 | } | ||
94 | EXPORT_SYMBOL_GPL(pci_epc_get); | ||
95 | |||
96 | /** | ||
97 | * pci_epc_stop() - stop the PCI link | ||
98 | * @epc: the link of the EPC device that has to be stopped | ||
99 | * | ||
100 | * Invoke to stop the PCI link | ||
101 | */ | ||
102 | void pci_epc_stop(struct pci_epc *epc) | ||
103 | { | ||
104 | unsigned long flags; | ||
105 | |||
106 | if (IS_ERR(epc) || !epc->ops->stop) | ||
107 | return; | ||
108 | |||
109 | spin_lock_irqsave(&epc->lock, flags); | ||
110 | epc->ops->stop(epc); | ||
111 | spin_unlock_irqrestore(&epc->lock, flags); | ||
112 | } | ||
113 | EXPORT_SYMBOL_GPL(pci_epc_stop); | ||
114 | |||
115 | /** | ||
116 | * pci_epc_start() - start the PCI link | ||
117 | * @epc: the link of *this* EPC device has to be started | ||
118 | * | ||
119 | * Invoke to start the PCI link | ||
120 | */ | ||
121 | int pci_epc_start(struct pci_epc *epc) | ||
122 | { | ||
123 | int ret; | ||
124 | unsigned long flags; | ||
125 | |||
126 | if (IS_ERR(epc)) | ||
127 | return -EINVAL; | ||
128 | |||
129 | if (!epc->ops->start) | ||
130 | return 0; | ||
131 | |||
132 | spin_lock_irqsave(&epc->lock, flags); | ||
133 | ret = epc->ops->start(epc); | ||
134 | spin_unlock_irqrestore(&epc->lock, flags); | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | EXPORT_SYMBOL_GPL(pci_epc_start); | ||
139 | |||
140 | /** | ||
141 | * pci_epc_raise_irq() - interrupt the host system | ||
142 | * @epc: the EPC device which has to interrupt the host | ||
143 | * @type: specify the type of interrupt; legacy or MSI | ||
144 | * @interrupt_num: the MSI interrupt number | ||
145 | * | ||
146 | * Invoke to raise an MSI or legacy interrupt | ||
147 | */ | ||
148 | int pci_epc_raise_irq(struct pci_epc *epc, enum pci_epc_irq_type type, | ||
149 | u8 interrupt_num) | ||
150 | { | ||
151 | int ret; | ||
152 | unsigned long flags; | ||
153 | |||
154 | if (IS_ERR(epc)) | ||
155 | return -EINVAL; | ||
156 | |||
157 | if (!epc->ops->raise_irq) | ||
158 | return 0; | ||
159 | |||
160 | spin_lock_irqsave(&epc->lock, flags); | ||
161 | ret = epc->ops->raise_irq(epc, type, interrupt_num); | ||
162 | spin_unlock_irqrestore(&epc->lock, flags); | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | EXPORT_SYMBOL_GPL(pci_epc_raise_irq); | ||
167 | |||
168 | /** | ||
169 | * pci_epc_get_msi() - get the number of MSI interrupt numbers allocated | ||
170 | * @epc: the EPC device to which MSI interrupts was requested | ||
171 | * | ||
172 | * Invoke to get the number of MSI interrupts allocated by the RC | ||
173 | */ | ||
174 | int pci_epc_get_msi(struct pci_epc *epc) | ||
175 | { | ||
176 | int interrupt; | ||
177 | unsigned long flags; | ||
178 | |||
179 | if (IS_ERR(epc)) | ||
180 | return 0; | ||
181 | |||
182 | if (!epc->ops->get_msi) | ||
183 | return 0; | ||
184 | |||
185 | spin_lock_irqsave(&epc->lock, flags); | ||
186 | interrupt = epc->ops->get_msi(epc); | ||
187 | spin_unlock_irqrestore(&epc->lock, flags); | ||
188 | |||
189 | if (interrupt < 0) | ||
190 | return 0; | ||
191 | |||
192 | interrupt = 1 << interrupt; | ||
193 | |||
194 | return interrupt; | ||
195 | } | ||
196 | EXPORT_SYMBOL_GPL(pci_epc_get_msi); | ||
197 | |||
198 | /** | ||
199 | * pci_epc_set_msi() - set the number of MSI interrupt numbers required | ||
200 | * @epc: the EPC device on which MSI has to be configured | ||
201 | * @interrupts: number of MSI interrupts required by the EPF | ||
202 | * | ||
203 | * Invoke to set the required number of MSI interrupts. | ||
204 | */ | ||
205 | int pci_epc_set_msi(struct pci_epc *epc, u8 interrupts) | ||
206 | { | ||
207 | int ret; | ||
208 | u8 encode_int; | ||
209 | unsigned long flags; | ||
210 | |||
211 | if (IS_ERR(epc)) | ||
212 | return -EINVAL; | ||
213 | |||
214 | if (!epc->ops->set_msi) | ||
215 | return 0; | ||
216 | |||
217 | encode_int = order_base_2(interrupts); | ||
218 | |||
219 | spin_lock_irqsave(&epc->lock, flags); | ||
220 | ret = epc->ops->set_msi(epc, encode_int); | ||
221 | spin_unlock_irqrestore(&epc->lock, flags); | ||
222 | |||
223 | return ret; | ||
224 | } | ||
225 | EXPORT_SYMBOL_GPL(pci_epc_set_msi); | ||
226 | |||
227 | /** | ||
228 | * pci_epc_unmap_addr() - unmap CPU address from PCI address | ||
229 | * @epc: the EPC device on which address is allocated | ||
230 | * @phys_addr: physical address of the local system | ||
231 | * | ||
232 | * Invoke to unmap the CPU address from PCI address. | ||
233 | */ | ||
234 | void pci_epc_unmap_addr(struct pci_epc *epc, phys_addr_t phys_addr) | ||
235 | { | ||
236 | unsigned long flags; | ||
237 | |||
238 | if (IS_ERR(epc)) | ||
239 | return; | ||
240 | |||
241 | if (!epc->ops->unmap_addr) | ||
242 | return; | ||
243 | |||
244 | spin_lock_irqsave(&epc->lock, flags); | ||
245 | epc->ops->unmap_addr(epc, phys_addr); | ||
246 | spin_unlock_irqrestore(&epc->lock, flags); | ||
247 | } | ||
248 | EXPORT_SYMBOL_GPL(pci_epc_unmap_addr); | ||
249 | |||
250 | /** | ||
251 | * pci_epc_map_addr() - map CPU address to PCI address | ||
252 | * @epc: the EPC device on which address is allocated | ||
253 | * @phys_addr: physical address of the local system | ||
254 | * @pci_addr: PCI address to which the physical address should be mapped | ||
255 | * @size: the size of the allocation | ||
256 | * | ||
257 | * Invoke to map CPU address with PCI address. | ||
258 | */ | ||
259 | int pci_epc_map_addr(struct pci_epc *epc, phys_addr_t phys_addr, | ||
260 | u64 pci_addr, size_t size) | ||
261 | { | ||
262 | int ret; | ||
263 | unsigned long flags; | ||
264 | |||
265 | if (IS_ERR(epc)) | ||
266 | return -EINVAL; | ||
267 | |||
268 | if (!epc->ops->map_addr) | ||
269 | return 0; | ||
270 | |||
271 | spin_lock_irqsave(&epc->lock, flags); | ||
272 | ret = epc->ops->map_addr(epc, phys_addr, pci_addr, size); | ||
273 | spin_unlock_irqrestore(&epc->lock, flags); | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | EXPORT_SYMBOL_GPL(pci_epc_map_addr); | ||
278 | |||
279 | /** | ||
280 | * pci_epc_clear_bar() - reset the BAR | ||
281 | * @epc: the EPC device for which the BAR has to be cleared | ||
282 | * @bar: the BAR number that has to be reset | ||
283 | * | ||
284 | * Invoke to reset the BAR of the endpoint device. | ||
285 | */ | ||
286 | void pci_epc_clear_bar(struct pci_epc *epc, int bar) | ||
287 | { | ||
288 | unsigned long flags; | ||
289 | |||
290 | if (IS_ERR(epc)) | ||
291 | return; | ||
292 | |||
293 | if (!epc->ops->clear_bar) | ||
294 | return; | ||
295 | |||
296 | spin_lock_irqsave(&epc->lock, flags); | ||
297 | epc->ops->clear_bar(epc, bar); | ||
298 | spin_unlock_irqrestore(&epc->lock, flags); | ||
299 | } | ||
300 | EXPORT_SYMBOL_GPL(pci_epc_clear_bar); | ||
301 | |||
302 | /** | ||
303 | * pci_epc_set_bar() - configure BAR in order for host to assign PCI addr space | ||
304 | * @epc: the EPC device on which BAR has to be configured | ||
305 | * @bar: the BAR number that has to be configured | ||
306 | * @size: the size of the addr space | ||
307 | * @flags: specify memory allocation/io allocation/32bit address/64 bit address | ||
308 | * | ||
309 | * Invoke to configure the BAR of the endpoint device. | ||
310 | */ | ||
311 | int pci_epc_set_bar(struct pci_epc *epc, enum pci_barno bar, | ||
312 | dma_addr_t bar_phys, size_t size, int flags) | ||
313 | { | ||
314 | int ret; | ||
315 | unsigned long irq_flags; | ||
316 | |||
317 | if (IS_ERR(epc)) | ||
318 | return -EINVAL; | ||
319 | |||
320 | if (!epc->ops->set_bar) | ||
321 | return 0; | ||
322 | |||
323 | spin_lock_irqsave(&epc->lock, irq_flags); | ||
324 | ret = epc->ops->set_bar(epc, bar, bar_phys, size, flags); | ||
325 | spin_unlock_irqrestore(&epc->lock, irq_flags); | ||
326 | |||
327 | return ret; | ||
328 | } | ||
329 | EXPORT_SYMBOL_GPL(pci_epc_set_bar); | ||
330 | |||
331 | /** | ||
332 | * pci_epc_write_header() - write standard configuration header | ||
333 | * @epc: the EPC device to which the configuration header should be written | ||
334 | * @header: standard configuration header fields | ||
335 | * | ||
336 | * Invoke to write the configuration header to the endpoint controller. Every | ||
337 | * endpoint controller will have a dedicated location to which the standard | ||
338 | * configuration header would be written. The callback function should write | ||
339 | * the header fields to this dedicated location. | ||
340 | */ | ||
341 | int pci_epc_write_header(struct pci_epc *epc, struct pci_epf_header *header) | ||
342 | { | ||
343 | int ret; | ||
344 | unsigned long flags; | ||
345 | |||
346 | if (IS_ERR(epc)) | ||
347 | return -EINVAL; | ||
348 | |||
349 | if (!epc->ops->write_header) | ||
350 | return 0; | ||
351 | |||
352 | spin_lock_irqsave(&epc->lock, flags); | ||
353 | ret = epc->ops->write_header(epc, header); | ||
354 | spin_unlock_irqrestore(&epc->lock, flags); | ||
355 | |||
356 | return ret; | ||
357 | } | ||
358 | EXPORT_SYMBOL_GPL(pci_epc_write_header); | ||
359 | |||
360 | /** | ||
361 | * pci_epc_add_epf() - bind PCI endpoint function to an endpoint controller | ||
362 | * @epc: the EPC device to which the endpoint function should be added | ||
363 | * @epf: the endpoint function to be added | ||
364 | * | ||
365 | * A PCI endpoint device can have one or more functions. In the case of PCIe, | ||
366 | * the specification allows up to 8 PCIe endpoint functions. Invoke | ||
367 | * pci_epc_add_epf() to add a PCI endpoint function to an endpoint controller. | ||
368 | */ | ||
369 | int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf) | ||
370 | { | ||
371 | unsigned long flags; | ||
372 | |||
373 | if (epf->epc) | ||
374 | return -EBUSY; | ||
375 | |||
376 | if (IS_ERR(epc)) | ||
377 | return -EINVAL; | ||
378 | |||
379 | if (epf->func_no > epc->max_functions - 1) | ||
380 | return -EINVAL; | ||
381 | |||
382 | epf->epc = epc; | ||
383 | dma_set_coherent_mask(&epf->dev, epc->dev.coherent_dma_mask); | ||
384 | epf->dev.dma_mask = epc->dev.dma_mask; | ||
385 | |||
386 | spin_lock_irqsave(&epc->lock, flags); | ||
387 | list_add_tail(&epf->list, &epc->pci_epf); | ||
388 | spin_unlock_irqrestore(&epc->lock, flags); | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | EXPORT_SYMBOL_GPL(pci_epc_add_epf); | ||
393 | |||
394 | /** | ||
395 | * pci_epc_remove_epf() - remove PCI endpoint function from endpoint controller | ||
396 | * @epc: the EPC device from which the endpoint function should be removed | ||
397 | * @epf: the endpoint function to be removed | ||
398 | * | ||
399 | * Invoke to remove PCI endpoint function from the endpoint controller. | ||
400 | */ | ||
401 | void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf) | ||
402 | { | ||
403 | unsigned long flags; | ||
404 | |||
405 | if (!epc || IS_ERR(epc)) | ||
406 | return; | ||
407 | |||
408 | spin_lock_irqsave(&epc->lock, flags); | ||
409 | list_del(&epf->list); | ||
410 | spin_unlock_irqrestore(&epc->lock, flags); | ||
411 | } | ||
412 | EXPORT_SYMBOL_GPL(pci_epc_remove_epf); | ||
413 | |||
414 | /** | ||
415 | * pci_epc_linkup() - Notify the EPF device that EPC device has established a | ||
416 | * connection with the Root Complex. | ||
417 | * @epc: the EPC device which has established link with the host | ||
418 | * | ||
419 | * Invoke to Notify the EPF device that the EPC device has established a | ||
420 | * connection with the Root Complex. | ||
421 | */ | ||
422 | void pci_epc_linkup(struct pci_epc *epc) | ||
423 | { | ||
424 | unsigned long flags; | ||
425 | struct pci_epf *epf; | ||
426 | |||
427 | if (!epc || IS_ERR(epc)) | ||
428 | return; | ||
429 | |||
430 | spin_lock_irqsave(&epc->lock, flags); | ||
431 | list_for_each_entry(epf, &epc->pci_epf, list) | ||
432 | pci_epf_linkup(epf); | ||
433 | spin_unlock_irqrestore(&epc->lock, flags); | ||
434 | } | ||
435 | EXPORT_SYMBOL_GPL(pci_epc_linkup); | ||
436 | |||
437 | /** | ||
438 | * pci_epc_destroy() - destroy the EPC device | ||
439 | * @epc: the EPC device that has to be destroyed | ||
440 | * | ||
441 | * Invoke to destroy the PCI EPC device | ||
442 | */ | ||
443 | void pci_epc_destroy(struct pci_epc *epc) | ||
444 | { | ||
445 | device_unregister(&epc->dev); | ||
446 | kfree(epc); | ||
447 | } | ||
448 | EXPORT_SYMBOL_GPL(pci_epc_destroy); | ||
449 | |||
450 | /** | ||
451 | * devm_pci_epc_destroy() - destroy the EPC device | ||
452 | * @dev: device that wants to destroy the EPC | ||
453 | * @epc: the EPC device that has to be destroyed | ||
454 | * | ||
455 | * Invoke to destroy the devres associated with this | ||
456 | * pci_epc and destroy the EPC device. | ||
457 | */ | ||
458 | void devm_pci_epc_destroy(struct device *dev, struct pci_epc *epc) | ||
459 | { | ||
460 | int r; | ||
461 | |||
462 | r = devres_destroy(dev, devm_pci_epc_release, devm_pci_epc_match, | ||
463 | epc); | ||
464 | dev_WARN_ONCE(dev, r, "couldn't find PCI EPC resource\n"); | ||
465 | } | ||
466 | EXPORT_SYMBOL_GPL(devm_pci_epc_destroy); | ||
467 | |||
468 | /** | ||
469 | * __pci_epc_create() - create a new endpoint controller (EPC) device | ||
470 | * @dev: device that is creating the new EPC | ||
471 | * @ops: function pointers for performing EPC operations | ||
472 | * @owner: the owner of the module that creates the EPC device | ||
473 | * | ||
474 | * Invoke to create a new EPC device and add it to pci_epc class. | ||
475 | */ | ||
476 | struct pci_epc * | ||
477 | __pci_epc_create(struct device *dev, const struct pci_epc_ops *ops, | ||
478 | struct module *owner) | ||
479 | { | ||
480 | int ret; | ||
481 | struct pci_epc *epc; | ||
482 | |||
483 | if (WARN_ON(!dev)) { | ||
484 | ret = -EINVAL; | ||
485 | goto err_ret; | ||
486 | } | ||
487 | |||
488 | epc = kzalloc(sizeof(*epc), GFP_KERNEL); | ||
489 | if (!epc) { | ||
490 | ret = -ENOMEM; | ||
491 | goto err_ret; | ||
492 | } | ||
493 | |||
494 | spin_lock_init(&epc->lock); | ||
495 | INIT_LIST_HEAD(&epc->pci_epf); | ||
496 | |||
497 | device_initialize(&epc->dev); | ||
498 | dma_set_coherent_mask(&epc->dev, dev->coherent_dma_mask); | ||
499 | epc->dev.class = pci_epc_class; | ||
500 | epc->dev.dma_mask = dev->dma_mask; | ||
501 | epc->ops = ops; | ||
502 | |||
503 | ret = dev_set_name(&epc->dev, "%s", dev_name(dev)); | ||
504 | if (ret) | ||
505 | goto put_dev; | ||
506 | |||
507 | ret = device_add(&epc->dev); | ||
508 | if (ret) | ||
509 | goto put_dev; | ||
510 | |||
511 | return epc; | ||
512 | |||
513 | put_dev: | ||
514 | put_device(&epc->dev); | ||
515 | kfree(epc); | ||
516 | |||
517 | err_ret: | ||
518 | return ERR_PTR(ret); | ||
519 | } | ||
520 | EXPORT_SYMBOL_GPL(__pci_epc_create); | ||
521 | |||
522 | /** | ||
523 | * __devm_pci_epc_create() - create a new endpoint controller (EPC) device | ||
524 | * @dev: device that is creating the new EPC | ||
525 | * @ops: function pointers for performing EPC operations | ||
526 | * @owner: the owner of the module that creates the EPC device | ||
527 | * | ||
528 | * Invoke to create a new EPC device and add it to pci_epc class. | ||
529 | * While at that, it also associates the device with the pci_epc using devres. | ||
530 | * On driver detach, release function is invoked on the devres data, | ||
531 | * then, devres data is freed. | ||
532 | */ | ||
533 | struct pci_epc * | ||
534 | __devm_pci_epc_create(struct device *dev, const struct pci_epc_ops *ops, | ||
535 | struct module *owner) | ||
536 | { | ||
537 | struct pci_epc **ptr, *epc; | ||
538 | |||
539 | ptr = devres_alloc(devm_pci_epc_release, sizeof(*ptr), GFP_KERNEL); | ||
540 | if (!ptr) | ||
541 | return ERR_PTR(-ENOMEM); | ||
542 | |||
543 | epc = __pci_epc_create(dev, ops, owner); | ||
544 | if (!IS_ERR(epc)) { | ||
545 | *ptr = epc; | ||
546 | devres_add(dev, ptr); | ||
547 | } else { | ||
548 | devres_free(ptr); | ||
549 | } | ||
550 | |||
551 | return epc; | ||
552 | } | ||
553 | EXPORT_SYMBOL_GPL(__devm_pci_epc_create); | ||
554 | |||
555 | static int __init pci_epc_init(void) | ||
556 | { | ||
557 | pci_epc_class = class_create(THIS_MODULE, "pci_epc"); | ||
558 | if (IS_ERR(pci_epc_class)) { | ||
559 | pr_err("failed to create pci epc class --> %ld\n", | ||
560 | PTR_ERR(pci_epc_class)); | ||
561 | return PTR_ERR(pci_epc_class); | ||
562 | } | ||
563 | |||
564 | return 0; | ||
565 | } | ||
566 | module_init(pci_epc_init); | ||
567 | |||
568 | static void __exit pci_epc_exit(void) | ||
569 | { | ||
570 | class_destroy(pci_epc_class); | ||
571 | } | ||
572 | module_exit(pci_epc_exit); | ||
573 | |||
574 | MODULE_DESCRIPTION("PCI EPC Library"); | ||
575 | MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); | ||
576 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/endpoint/pci-epc-mem.c b/drivers/pci/endpoint/pci-epc-mem.c new file mode 100644 index 000000000000..3a94cc1caf22 --- /dev/null +++ b/drivers/pci/endpoint/pci-epc-mem.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /** | ||
2 | * PCI Endpoint *Controller* Address Space Management | ||
3 | * | ||
4 | * Copyright (C) 2017 Texas Instruments | ||
5 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | ||
6 | * | ||
7 | * This program is free software: you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 of | ||
9 | * the License as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/io.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | #include <linux/pci-epc.h> | ||
25 | |||
26 | /** | ||
27 | * pci_epc_mem_init() - initialize the pci_epc_mem structure | ||
28 | * @epc: the EPC device that invoked pci_epc_mem_init | ||
29 | * @phys_base: the physical address of the base | ||
30 | * @size: the size of the address space | ||
31 | * | ||
32 | * Invoke to initialize the pci_epc_mem structure used by the | ||
33 | * endpoint functions to allocate mapped PCI address. | ||
34 | */ | ||
35 | int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size) | ||
36 | { | ||
37 | int ret; | ||
38 | struct pci_epc_mem *mem; | ||
39 | unsigned long *bitmap; | ||
40 | int pages = size >> PAGE_SHIFT; | ||
41 | int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long); | ||
42 | |||
43 | mem = kzalloc(sizeof(*mem), GFP_KERNEL); | ||
44 | if (!mem) { | ||
45 | ret = -ENOMEM; | ||
46 | goto err; | ||
47 | } | ||
48 | |||
49 | bitmap = kzalloc(bitmap_size, GFP_KERNEL); | ||
50 | if (!bitmap) { | ||
51 | ret = -ENOMEM; | ||
52 | goto err_mem; | ||
53 | } | ||
54 | |||
55 | mem->bitmap = bitmap; | ||
56 | mem->phys_base = phys_base; | ||
57 | mem->pages = pages; | ||
58 | mem->size = size; | ||
59 | |||
60 | epc->mem = mem; | ||
61 | |||
62 | return 0; | ||
63 | |||
64 | err_mem: | ||
65 | kfree(mem); | ||
66 | |||
67 | err: | ||
68 | return ret; | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(pci_epc_mem_init); | ||
71 | |||
72 | /** | ||
73 | * pci_epc_mem_exit() - cleanup the pci_epc_mem structure | ||
74 | * @epc: the EPC device that invoked pci_epc_mem_exit | ||
75 | * | ||
76 | * Invoke to cleanup the pci_epc_mem structure allocated in | ||
77 | * pci_epc_mem_init(). | ||
78 | */ | ||
79 | void pci_epc_mem_exit(struct pci_epc *epc) | ||
80 | { | ||
81 | struct pci_epc_mem *mem = epc->mem; | ||
82 | |||
83 | epc->mem = NULL; | ||
84 | kfree(mem->bitmap); | ||
85 | kfree(mem); | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(pci_epc_mem_exit); | ||
88 | |||
89 | /** | ||
90 | * pci_epc_mem_alloc_addr() - allocate memory address from EPC addr space | ||
91 | * @epc: the EPC device on which memory has to be allocated | ||
92 | * @phys_addr: populate the allocated physical address here | ||
93 | * @size: the size of the address space that has to be allocated | ||
94 | * | ||
95 | * Invoke to allocate memory address from the EPC address space. This | ||
96 | * is usually done to map the remote RC address into the local system. | ||
97 | */ | ||
98 | void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, | ||
99 | phys_addr_t *phys_addr, size_t size) | ||
100 | { | ||
101 | int pageno; | ||
102 | void __iomem *virt_addr; | ||
103 | struct pci_epc_mem *mem = epc->mem; | ||
104 | int order = get_order(size); | ||
105 | |||
106 | pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order); | ||
107 | if (pageno < 0) | ||
108 | return NULL; | ||
109 | |||
110 | *phys_addr = mem->phys_base + (pageno << PAGE_SHIFT); | ||
111 | virt_addr = ioremap(*phys_addr, size); | ||
112 | if (!virt_addr) | ||
113 | bitmap_release_region(mem->bitmap, pageno, order); | ||
114 | |||
115 | return virt_addr; | ||
116 | } | ||
117 | EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr); | ||
118 | |||
119 | /** | ||
120 | * pci_epc_mem_free_addr() - free the allocated memory address | ||
121 | * @epc: the EPC device on which memory was allocated | ||
122 | * @phys_addr: the allocated physical address | ||
123 | * @virt_addr: virtual address of the allocated mem space | ||
124 | * @size: the size of the allocated address space | ||
125 | * | ||
126 | * Invoke to free the memory allocated using pci_epc_mem_alloc_addr. | ||
127 | */ | ||
128 | void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr, | ||
129 | void __iomem *virt_addr, size_t size) | ||
130 | { | ||
131 | int pageno; | ||
132 | int order = get_order(size); | ||
133 | struct pci_epc_mem *mem = epc->mem; | ||
134 | |||
135 | iounmap(virt_addr); | ||
136 | pageno = (phys_addr - mem->phys_base) >> PAGE_SHIFT; | ||
137 | bitmap_release_region(mem->bitmap, pageno, order); | ||
138 | } | ||
139 | EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr); | ||
140 | |||
141 | MODULE_DESCRIPTION("PCI EPC Address Space Management"); | ||
142 | MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); | ||
143 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c new file mode 100644 index 000000000000..a281c599a504 --- /dev/null +++ b/drivers/pci/endpoint/pci-epf-core.c | |||
@@ -0,0 +1,355 @@ | |||
1 | /** | ||
2 | * PCI Endpoint *Function* (EPF) library | ||
3 | * | ||
4 | * Copyright (C) 2017 Texas Instruments | ||
5 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | ||
6 | * | ||
7 | * This program is free software: you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 of | ||
9 | * the License as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/device.h> | ||
21 | #include <linux/dma-mapping.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/module.h> | ||
24 | |||
25 | #include <linux/pci-epc.h> | ||
26 | #include <linux/pci-epf.h> | ||
27 | |||
28 | static struct bus_type pci_epf_bus_type; | ||
29 | static struct device_type pci_epf_type; | ||
30 | |||
31 | /** | ||
32 | * pci_epf_linkup() - Notify the function driver that EPC device has | ||
33 | * established a connection with the Root Complex. | ||
34 | * @epf: the EPF device bound to the EPC device which has established | ||
35 | * the connection with the host | ||
36 | * | ||
37 | * Invoke to notify the function driver that EPC device has established | ||
38 | * a connection with the Root Complex. | ||
39 | */ | ||
40 | void pci_epf_linkup(struct pci_epf *epf) | ||
41 | { | ||
42 | if (!epf->driver) { | ||
43 | dev_WARN(&epf->dev, "epf device not bound to driver\n"); | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | epf->driver->ops->linkup(epf); | ||
48 | } | ||
49 | EXPORT_SYMBOL_GPL(pci_epf_linkup); | ||
50 | |||
51 | /** | ||
52 | * pci_epf_unbind() - Notify the function driver that the binding between the | ||
53 | * EPF device and EPC device has been lost | ||
54 | * @epf: the EPF device which has lost the binding with the EPC device | ||
55 | * | ||
56 | * Invoke to notify the function driver that the binding between the EPF device | ||
57 | * and EPC device has been lost. | ||
58 | */ | ||
59 | void pci_epf_unbind(struct pci_epf *epf) | ||
60 | { | ||
61 | if (!epf->driver) { | ||
62 | dev_WARN(&epf->dev, "epf device not bound to driver\n"); | ||
63 | return; | ||
64 | } | ||
65 | |||
66 | epf->driver->ops->unbind(epf); | ||
67 | module_put(epf->driver->owner); | ||
68 | } | ||
69 | EXPORT_SYMBOL_GPL(pci_epf_unbind); | ||
70 | |||
71 | /** | ||
72 | * pci_epf_bind() - Notify the function driver that the EPF device has been | ||
73 | * bound to a EPC device | ||
74 | * @epf: the EPF device which has been bound to the EPC device | ||
75 | * | ||
76 | * Invoke to notify the function driver that it has been bound to a EPC device | ||
77 | */ | ||
78 | int pci_epf_bind(struct pci_epf *epf) | ||
79 | { | ||
80 | if (!epf->driver) { | ||
81 | dev_WARN(&epf->dev, "epf device not bound to driver\n"); | ||
82 | return -EINVAL; | ||
83 | } | ||
84 | |||
85 | if (!try_module_get(epf->driver->owner)) | ||
86 | return -EAGAIN; | ||
87 | |||
88 | return epf->driver->ops->bind(epf); | ||
89 | } | ||
90 | EXPORT_SYMBOL_GPL(pci_epf_bind); | ||
91 | |||
92 | /** | ||
93 | * pci_epf_free_space() - free the allocated PCI EPF register space | ||
94 | * @addr: the virtual address of the PCI EPF register space | ||
95 | * @bar: the BAR number corresponding to the register space | ||
96 | * | ||
97 | * Invoke to free the allocated PCI EPF register space. | ||
98 | */ | ||
99 | void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar) | ||
100 | { | ||
101 | struct device *dev = &epf->dev; | ||
102 | |||
103 | if (!addr) | ||
104 | return; | ||
105 | |||
106 | dma_free_coherent(dev, epf->bar[bar].size, addr, | ||
107 | epf->bar[bar].phys_addr); | ||
108 | |||
109 | epf->bar[bar].phys_addr = 0; | ||
110 | epf->bar[bar].size = 0; | ||
111 | } | ||
112 | EXPORT_SYMBOL_GPL(pci_epf_free_space); | ||
113 | |||
114 | /** | ||
115 | * pci_epf_alloc_space() - allocate memory for the PCI EPF register space | ||
116 | * @size: the size of the memory that has to be allocated | ||
117 | * @bar: the BAR number corresponding to the allocated register space | ||
118 | * | ||
119 | * Invoke to allocate memory for the PCI EPF register space. | ||
120 | */ | ||
121 | void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar) | ||
122 | { | ||
123 | void *space; | ||
124 | struct device *dev = &epf->dev; | ||
125 | dma_addr_t phys_addr; | ||
126 | |||
127 | if (size < 128) | ||
128 | size = 128; | ||
129 | size = roundup_pow_of_two(size); | ||
130 | |||
131 | space = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL); | ||
132 | if (!space) { | ||
133 | dev_err(dev, "failed to allocate mem space\n"); | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | epf->bar[bar].phys_addr = phys_addr; | ||
138 | epf->bar[bar].size = size; | ||
139 | |||
140 | return space; | ||
141 | } | ||
142 | EXPORT_SYMBOL_GPL(pci_epf_alloc_space); | ||
143 | |||
144 | /** | ||
145 | * pci_epf_unregister_driver() - unregister the PCI EPF driver | ||
146 | * @driver: the PCI EPF driver that has to be unregistered | ||
147 | * | ||
148 | * Invoke to unregister the PCI EPF driver. | ||
149 | */ | ||
150 | void pci_epf_unregister_driver(struct pci_epf_driver *driver) | ||
151 | { | ||
152 | driver_unregister(&driver->driver); | ||
153 | } | ||
154 | EXPORT_SYMBOL_GPL(pci_epf_unregister_driver); | ||
155 | |||
156 | /** | ||
157 | * __pci_epf_register_driver() - register a new PCI EPF driver | ||
158 | * @driver: structure representing PCI EPF driver | ||
159 | * @owner: the owner of the module that registers the PCI EPF driver | ||
160 | * | ||
161 | * Invoke to register a new PCI EPF driver. | ||
162 | */ | ||
163 | int __pci_epf_register_driver(struct pci_epf_driver *driver, | ||
164 | struct module *owner) | ||
165 | { | ||
166 | int ret; | ||
167 | |||
168 | if (!driver->ops) | ||
169 | return -EINVAL; | ||
170 | |||
171 | if (!driver->ops->bind || !driver->ops->unbind || !driver->ops->linkup) | ||
172 | return -EINVAL; | ||
173 | |||
174 | driver->driver.bus = &pci_epf_bus_type; | ||
175 | driver->driver.owner = owner; | ||
176 | |||
177 | ret = driver_register(&driver->driver); | ||
178 | if (ret) | ||
179 | return ret; | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | EXPORT_SYMBOL_GPL(__pci_epf_register_driver); | ||
184 | |||
185 | /** | ||
186 | * pci_epf_destroy() - destroy the created PCI EPF device | ||
187 | * @epf: the PCI EPF device that has to be destroyed. | ||
188 | * | ||
189 | * Invoke to destroy the PCI EPF device created by invoking pci_epf_create(). | ||
190 | */ | ||
191 | void pci_epf_destroy(struct pci_epf *epf) | ||
192 | { | ||
193 | device_unregister(&epf->dev); | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(pci_epf_destroy); | ||
196 | |||
197 | /** | ||
198 | * pci_epf_create() - create a new PCI EPF device | ||
199 | * @name: the name of the PCI EPF device. This name will be used to bind the | ||
200 | * the EPF device to a EPF driver | ||
201 | * | ||
202 | * Invoke to create a new PCI EPF device by providing the name of the function | ||
203 | * device. | ||
204 | */ | ||
205 | struct pci_epf *pci_epf_create(const char *name) | ||
206 | { | ||
207 | int ret; | ||
208 | struct pci_epf *epf; | ||
209 | struct device *dev; | ||
210 | char *func_name; | ||
211 | char *buf; | ||
212 | |||
213 | epf = kzalloc(sizeof(*epf), GFP_KERNEL); | ||
214 | if (!epf) { | ||
215 | ret = -ENOMEM; | ||
216 | goto err_ret; | ||
217 | } | ||
218 | |||
219 | buf = kstrdup(name, GFP_KERNEL); | ||
220 | if (!buf) { | ||
221 | ret = -ENOMEM; | ||
222 | goto free_epf; | ||
223 | } | ||
224 | |||
225 | func_name = buf; | ||
226 | buf = strchrnul(buf, '.'); | ||
227 | *buf = '\0'; | ||
228 | |||
229 | epf->name = kstrdup(func_name, GFP_KERNEL); | ||
230 | if (!epf->name) { | ||
231 | ret = -ENOMEM; | ||
232 | goto free_func_name; | ||
233 | } | ||
234 | |||
235 | dev = &epf->dev; | ||
236 | device_initialize(dev); | ||
237 | dev->bus = &pci_epf_bus_type; | ||
238 | dev->type = &pci_epf_type; | ||
239 | |||
240 | ret = dev_set_name(dev, "%s", name); | ||
241 | if (ret) | ||
242 | goto put_dev; | ||
243 | |||
244 | ret = device_add(dev); | ||
245 | if (ret) | ||
246 | goto put_dev; | ||
247 | |||
248 | kfree(func_name); | ||
249 | return epf; | ||
250 | |||
251 | put_dev: | ||
252 | put_device(dev); | ||
253 | kfree(epf->name); | ||
254 | |||
255 | free_func_name: | ||
256 | kfree(func_name); | ||
257 | |||
258 | free_epf: | ||
259 | kfree(epf); | ||
260 | |||
261 | err_ret: | ||
262 | return ERR_PTR(ret); | ||
263 | } | ||
264 | EXPORT_SYMBOL_GPL(pci_epf_create); | ||
265 | |||
266 | static void pci_epf_dev_release(struct device *dev) | ||
267 | { | ||
268 | struct pci_epf *epf = to_pci_epf(dev); | ||
269 | |||
270 | kfree(epf->name); | ||
271 | kfree(epf); | ||
272 | } | ||
273 | |||
274 | static struct device_type pci_epf_type = { | ||
275 | .release = pci_epf_dev_release, | ||
276 | }; | ||
277 | |||
278 | static int | ||
279 | pci_epf_match_id(const struct pci_epf_device_id *id, const struct pci_epf *epf) | ||
280 | { | ||
281 | while (id->name[0]) { | ||
282 | if (strcmp(epf->name, id->name) == 0) | ||
283 | return true; | ||
284 | id++; | ||
285 | } | ||
286 | |||
287 | return false; | ||
288 | } | ||
289 | |||
290 | static int pci_epf_device_match(struct device *dev, struct device_driver *drv) | ||
291 | { | ||
292 | struct pci_epf *epf = to_pci_epf(dev); | ||
293 | struct pci_epf_driver *driver = to_pci_epf_driver(drv); | ||
294 | |||
295 | if (driver->id_table) | ||
296 | return pci_epf_match_id(driver->id_table, epf); | ||
297 | |||
298 | return !strcmp(epf->name, drv->name); | ||
299 | } | ||
300 | |||
301 | static int pci_epf_device_probe(struct device *dev) | ||
302 | { | ||
303 | struct pci_epf *epf = to_pci_epf(dev); | ||
304 | struct pci_epf_driver *driver = to_pci_epf_driver(dev->driver); | ||
305 | |||
306 | if (!driver->probe) | ||
307 | return -ENODEV; | ||
308 | |||
309 | epf->driver = driver; | ||
310 | |||
311 | return driver->probe(epf); | ||
312 | } | ||
313 | |||
314 | static int pci_epf_device_remove(struct device *dev) | ||
315 | { | ||
316 | int ret; | ||
317 | struct pci_epf *epf = to_pci_epf(dev); | ||
318 | struct pci_epf_driver *driver = to_pci_epf_driver(dev->driver); | ||
319 | |||
320 | ret = driver->remove(epf); | ||
321 | epf->driver = NULL; | ||
322 | |||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | static struct bus_type pci_epf_bus_type = { | ||
327 | .name = "pci-epf", | ||
328 | .match = pci_epf_device_match, | ||
329 | .probe = pci_epf_device_probe, | ||
330 | .remove = pci_epf_device_remove, | ||
331 | }; | ||
332 | |||
333 | static int __init pci_epf_init(void) | ||
334 | { | ||
335 | int ret; | ||
336 | |||
337 | ret = bus_register(&pci_epf_bus_type); | ||
338 | if (ret) { | ||
339 | pr_err("failed to register pci epf bus --> %d\n", ret); | ||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | module_init(pci_epf_init); | ||
346 | |||
347 | static void __exit pci_epf_exit(void) | ||
348 | { | ||
349 | bus_unregister(&pci_epf_bus_type); | ||
350 | } | ||
351 | module_exit(pci_epf_exit); | ||
352 | |||
353 | MODULE_DESCRIPTION("PCI EPF Library"); | ||
354 | MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); | ||
355 | MODULE_LICENSE("GPL v2"); | ||