History

PCI: endpoint: Fix for concurrent memory allocation in OB address region

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.

Kishon Vijay Abraham I committed 6 years ago

Commit 04e046c1 parent 3d3248d2 files · +11 −2Browse files

Unified · Split

2 files
  1. drivers/pci/endpoint/pci-epc-mem.c +8 −2
  2. include/linux/pci-epc.h +3 −0
drivers/pci/endpoint/pci-epc-mem.c+8−2
@@ -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
144ret:
145 mutex_unlock(&mem->lock);
142 return virt_addr;146 return virt_addr;
143}147}
144EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);148EXPORT_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}
169EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr);175EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr);
170 176
include/linux/pci-epc.h+3−0
@@ -71,6 +71,7 @@ struct pci_epc_ops { · 70 unmodified lines
71 * @bitmap: bitmap to manage the PCI address space71 * @bitmap: bitmap to manage the PCI address space
72 * @pages: number of bits representing the address region72 * @pages: number of bits representing the address region
73 * @page_size: size of each page73 * @page_size: size of each page
74 * @lock: mutex to protect bitmap
74 */75 */
75struct pci_epc_mem {76struct 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/**