pci-epc-mem uses a bitmap to manage the Endpoint outbound (OB) address region. This address region will be shared by multiple endpoint functions (in the case of multi function endpoint) and it has to be protected from concurrent access to avoid updating an inconsistent state. Use a mutex to protect bitmap updates to prevent the memory allocation API from returning incorrect addresses.
Unified · Split
| @@ -79,6 +79,7 @@ int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size, · 78 unmodified lines | |||
| 79 | mem->page_size = page_size; | 79 | mem->page_size = page_size; |
| 80 | mem->pages = pages; | 80 | mem->pages = pages; |
| 81 | mem->size = size; | 81 | mem->size = size; |
| 82 | mutex_init(&mem->lock); | ||
| 82 | 83 | ||
| 83 | epc->mem = mem; | 84 | epc->mem = mem; |
| 84 | 85 | ||
| @@ -122,7 +123,7 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, · 37 unmodified lines | |||
| 122 | phys_addr_t *phys_addr, size_t size) | 123 | phys_addr_t *phys_addr, size_t size) |
| 123 | { | 124 | { |
| 124 | int pageno; | 125 | int pageno; |
| 125 | void __iomem *virt_addr; | 126 | void __iomem *virt_addr = NULL; |
| 126 | struct pci_epc_mem *mem = epc->mem; | 127 | struct pci_epc_mem *mem = epc->mem; |
| 127 | unsigned int page_shift = ilog2(mem->page_size); | 128 | unsigned int page_shift = ilog2(mem->page_size); |
| 128 | int order; | 129 | int order; |
| @@ -130,15 +131,18 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, · 1 unmodified line | |||
| 130 | size = ALIGN(size, mem->page_size); | 131 | size = ALIGN(size, mem->page_size); |
| 131 | order = pci_epc_mem_get_order(mem, size); | 132 | order = pci_epc_mem_get_order(mem, size); |
| 132 | 133 | ||
| 134 | mutex_lock(&mem->lock); | ||
| 133 | pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order); | 135 | pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order); |
| 134 | if (pageno < 0) | 136 | if (pageno < 0) |
| 135 | return NULL; | 137 | goto ret; |
| 136 | 138 | ||
| 137 | *phys_addr = mem->phys_base + ((phys_addr_t)pageno << page_shift); | 139 | *phys_addr = mem->phys_base + ((phys_addr_t)pageno << page_shift); |
| 138 | virt_addr = ioremap(*phys_addr, size); | 140 | virt_addr = ioremap(*phys_addr, size); |
| 139 | if (!virt_addr) | 141 | if (!virt_addr) |
| 140 | bitmap_release_region(mem->bitmap, pageno, order); | 142 | bitmap_release_region(mem->bitmap, pageno, order); |
| 141 | 143 | ||
| 144 | ret: | ||
| 145 | mutex_unlock(&mem->lock); | ||
| 142 | return virt_addr; | 146 | return virt_addr; |
| 143 | } | 147 | } |
| 144 | EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr); | 148 | EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr); |
| @@ -164,7 +168,9 @@ void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr, · 19 unmodified lines | |||
| 164 | pageno = (phys_addr - mem->phys_base) >> page_shift; | 168 | pageno = (phys_addr - mem->phys_base) >> page_shift; |
| 165 | size = ALIGN(size, mem->page_size); | 169 | size = ALIGN(size, mem->page_size); |
| 166 | order = pci_epc_mem_get_order(mem, size); | 170 | order = pci_epc_mem_get_order(mem, size); |
| 171 | mutex_lock(&mem->lock); | ||
| 167 | bitmap_release_region(mem->bitmap, pageno, order); | 172 | bitmap_release_region(mem->bitmap, pageno, order); |
| 173 | mutex_unlock(&mem->lock); | ||
| 168 | } | 174 | } |
| 169 | EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr); | 175 | EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr); |
| 170 | 176 | ||
| @@ -71,6 +71,7 @@ struct pci_epc_ops { · 70 unmodified lines | |||
| 71 | * @bitmap: bitmap to manage the PCI address space | 71 | * @bitmap: bitmap to manage the PCI address space |
| 72 | * @pages: number of bits representing the address region | 72 | * @pages: number of bits representing the address region |
| 73 | * @page_size: size of each page | 73 | * @page_size: size of each page |
| 74 | * @lock: mutex to protect bitmap | ||
| 74 | */ | 75 | */ |
| 75 | struct pci_epc_mem { | 76 | struct pci_epc_mem { |
| 76 | phys_addr_t phys_base; | 77 | phys_addr_t phys_base; |
| @@ -78,6 +79,8 @@ struct pci_epc_mem { · 1 unmodified line | |||
| 78 | unsigned long *bitmap; | 79 | unsigned long *bitmap; |
| 79 | size_t page_size; | 80 | size_t page_size; |
| 80 | int pages; | 81 | int pages; |
| 82 | /* mutex to protect against concurrent access for memory allocation*/ | ||
| 83 | struct mutex lock; | ||
| 81 | }; | 84 | }; |
| 82 | 85 | ||
| 83 | /** | 86 | /** |