| .. | .. |
|---|
| 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) { |
|---|