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
7979 mem->page_size = page_size;
8080 mem->pages = pages;
8181 mem->size = size;
82+ mutex_init(&mem->lock);
8283
8384 epc->mem = mem;
8485
@@ -122,7 +123,7 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, · 37 unmodified lines
122123 phys_addr_t *phys_addr, size_t size)
123124 {
124125 int pageno;
125− void __iomem *virt_addr;
126+ void __iomem *virt_addr = NULL;
126127 struct pci_epc_mem *mem = epc->mem;
127128 unsigned int page_shift = ilog2(mem->page_size);
128129 int order;
@@ -130,15 +131,18 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, · 1 unmodified line
130131 size = ALIGN(size, mem->page_size);
131132 order = pci_epc_mem_get_order(mem, size);
132133
134+ mutex_lock(&mem->lock);
133135 pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order);
134136 if (pageno < 0)
135− return NULL;
137+ goto ret;
136138
137139 *phys_addr = mem->phys_base + ((phys_addr_t)pageno << page_shift);
138140 virt_addr = ioremap(*phys_addr, size);
139141 if (!virt_addr)
140142 bitmap_release_region(mem->bitmap, pageno, order);
141143
144+ret:
145+ mutex_unlock(&mem->lock);
142146 return virt_addr;
143147 }
144148 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
164168 pageno = (phys_addr - mem->phys_base) >> page_shift;
165169 size = ALIGN(size, mem->page_size);
166170 order = pci_epc_mem_get_order(mem, size);
171+ mutex_lock(&mem->lock);
167172 bitmap_release_region(mem->bitmap, pageno, order);
173+ mutex_unlock(&mem->lock);
168174 }
169175 EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr);
170176
include/linux/pci-epc.h+3−0
@@ -71,6 +71,7 @@ struct pci_epc_ops { · 70 unmodified lines
7171 * @bitmap: bitmap to manage the PCI address space
7272 * @pages: number of bits representing the address region
7373 * @page_size: size of each page
74+ * @lock: mutex to protect bitmap
7475 */
7576 struct pci_epc_mem {
7677 phys_addr_t phys_base;
@@ -78,6 +79,8 @@ struct pci_epc_mem { · 1 unmodified line
7879 unsigned long *bitmap;
7980 size_t page_size;
8081 int pages;
82+ /* mutex to protect against concurrent access for memory allocation*/
83+ struct mutex lock;
8184 };
8285
8386 /**