.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
---|
2 | | -/** |
---|
| 2 | +/* |
---|
3 | 3 | * PCI Endpoint *Function* (EPF) library |
---|
4 | 4 | * |
---|
5 | 5 | * Copyright (C) 2017 Texas Instruments |
---|
.. | .. |
---|
21 | 21 | static const struct device_type pci_epf_type; |
---|
22 | 22 | |
---|
23 | 23 | /** |
---|
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 |
---|
28 | | - * |
---|
29 | | - * Invoke to notify the function driver that EPC device has established |
---|
30 | | - * a connection with the Root Complex. |
---|
31 | | - */ |
---|
32 | | -void pci_epf_linkup(struct pci_epf *epf) |
---|
33 | | -{ |
---|
34 | | - if (!epf->driver) { |
---|
35 | | - dev_WARN(&epf->dev, "epf device not bound to driver\n"); |
---|
36 | | - return; |
---|
37 | | - } |
---|
38 | | - |
---|
39 | | - epf->driver->ops->linkup(epf); |
---|
40 | | -} |
---|
41 | | -EXPORT_SYMBOL_GPL(pci_epf_linkup); |
---|
42 | | - |
---|
43 | | -/** |
---|
44 | 24 | * pci_epf_unbind() - Notify the function driver that the binding between the |
---|
45 | 25 | * EPF device and EPC device has been lost |
---|
46 | 26 | * @epf: the EPF device which has lost the binding with the EPC device |
---|
.. | .. |
---|
55 | 35 | return; |
---|
56 | 36 | } |
---|
57 | 37 | |
---|
| 38 | + mutex_lock(&epf->lock); |
---|
58 | 39 | epf->driver->ops->unbind(epf); |
---|
| 40 | + mutex_unlock(&epf->lock); |
---|
59 | 41 | module_put(epf->driver->owner); |
---|
60 | 42 | } |
---|
61 | 43 | EXPORT_SYMBOL_GPL(pci_epf_unbind); |
---|
.. | .. |
---|
69 | 51 | */ |
---|
70 | 52 | int pci_epf_bind(struct pci_epf *epf) |
---|
71 | 53 | { |
---|
| 54 | + int ret; |
---|
| 55 | + |
---|
72 | 56 | if (!epf->driver) { |
---|
73 | 57 | dev_WARN(&epf->dev, "epf device not bound to driver\n"); |
---|
74 | 58 | return -EINVAL; |
---|
.. | .. |
---|
77 | 61 | if (!try_module_get(epf->driver->owner)) |
---|
78 | 62 | return -EAGAIN; |
---|
79 | 63 | |
---|
80 | | - return epf->driver->ops->bind(epf); |
---|
| 64 | + mutex_lock(&epf->lock); |
---|
| 65 | + ret = epf->driver->ops->bind(epf); |
---|
| 66 | + mutex_unlock(&epf->lock); |
---|
| 67 | + |
---|
| 68 | + return ret; |
---|
81 | 69 | } |
---|
82 | 70 | EXPORT_SYMBOL_GPL(pci_epf_bind); |
---|
83 | 71 | |
---|
84 | 72 | /** |
---|
85 | 73 | * pci_epf_free_space() - free the allocated PCI EPF register space |
---|
| 74 | + * @epf: the EPF device from whom to free the memory |
---|
86 | 75 | * @addr: the virtual address of the PCI EPF register space |
---|
87 | 76 | * @bar: the BAR number corresponding to the register space |
---|
88 | 77 | * |
---|
.. | .. |
---|
99 | 88 | epf->bar[bar].phys_addr); |
---|
100 | 89 | |
---|
101 | 90 | epf->bar[bar].phys_addr = 0; |
---|
| 91 | + epf->bar[bar].addr = NULL; |
---|
102 | 92 | epf->bar[bar].size = 0; |
---|
103 | 93 | epf->bar[bar].barno = 0; |
---|
104 | 94 | epf->bar[bar].flags = 0; |
---|
.. | .. |
---|
107 | 97 | |
---|
108 | 98 | /** |
---|
109 | 99 | * pci_epf_alloc_space() - allocate memory for the PCI EPF register space |
---|
| 100 | + * @epf: the EPF device to whom allocate the memory |
---|
110 | 101 | * @size: the size of the memory that has to be allocated |
---|
111 | 102 | * @bar: the BAR number corresponding to the allocated register space |
---|
| 103 | + * @align: alignment size for the allocation region |
---|
112 | 104 | * |
---|
113 | 105 | * Invoke to allocate memory for the PCI EPF register space. |
---|
114 | 106 | */ |
---|
115 | | -void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar) |
---|
| 107 | +void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar, |
---|
| 108 | + size_t align) |
---|
116 | 109 | { |
---|
117 | 110 | void *space; |
---|
118 | 111 | struct device *dev = epf->epc->dev.parent; |
---|
.. | .. |
---|
120 | 113 | |
---|
121 | 114 | if (size < 128) |
---|
122 | 115 | size = 128; |
---|
123 | | - size = roundup_pow_of_two(size); |
---|
| 116 | + |
---|
| 117 | + if (align) |
---|
| 118 | + size = ALIGN(size, align); |
---|
| 119 | + else |
---|
| 120 | + size = roundup_pow_of_two(size); |
---|
124 | 121 | |
---|
125 | 122 | space = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL); |
---|
126 | 123 | if (!space) { |
---|
.. | .. |
---|
129 | 126 | } |
---|
130 | 127 | |
---|
131 | 128 | epf->bar[bar].phys_addr = phys_addr; |
---|
| 129 | + epf->bar[bar].addr = space; |
---|
132 | 130 | epf->bar[bar].size = size; |
---|
133 | 131 | epf->bar[bar].barno = bar; |
---|
134 | | - epf->bar[bar].flags = PCI_BASE_ADDRESS_SPACE_MEMORY; |
---|
| 132 | + epf->bar[bar].flags |= upper_32_bits(size) ? |
---|
| 133 | + PCI_BASE_ADDRESS_MEM_TYPE_64 : |
---|
| 134 | + PCI_BASE_ADDRESS_MEM_TYPE_32; |
---|
135 | 135 | |
---|
136 | 136 | return space; |
---|
137 | 137 | } |
---|
.. | .. |
---|
206 | 206 | if (!driver->ops) |
---|
207 | 207 | return -EINVAL; |
---|
208 | 208 | |
---|
209 | | - if (!driver->ops->bind || !driver->ops->unbind || !driver->ops->linkup) |
---|
| 209 | + if (!driver->ops->bind || !driver->ops->unbind) |
---|
210 | 210 | return -EINVAL; |
---|
211 | 211 | |
---|
212 | 212 | driver->driver.bus = &pci_epf_bus_type; |
---|
.. | .. |
---|
264 | 264 | device_initialize(dev); |
---|
265 | 265 | dev->bus = &pci_epf_bus_type; |
---|
266 | 266 | dev->type = &pci_epf_type; |
---|
| 267 | + mutex_init(&epf->lock); |
---|
267 | 268 | |
---|
268 | 269 | ret = dev_set_name(dev, "%s", name); |
---|
269 | 270 | if (ret) { |
---|