aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2013-12-20 12:55:44 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-01-07 18:24:33 -0500
commitd56dbf5bab8ce44c5407bb099f71987f58d18bb4 (patch)
treeeb75a24b8515218bea59898b6da37e1152cbbe0f /drivers/pci
parentf75b99d5a77d63f20e07bd276d5a427808ac8ef6 (diff)
PCI: Allocate 64-bit BARs above 4G when possible
Try to allocate space for 64-bit BARs above 4G first, to preserve the space below 4G for 32-bit BARs. If there's no space above 4G available, fall back to allocating anywhere. [bhelgaas: reworked starting from http://lkml.kernel.org/r/1387485843-17403-2-git-send-email-yinghai@kernel.org] Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/bus.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index c30baae929f4..86fb8ec5e448 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -102,6 +102,8 @@ static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
102#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 102#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
103static struct pci_bus_region pci_64_bit = {0, 103static struct pci_bus_region pci_64_bit = {0,
104 (dma_addr_t) 0xffffffffffffffffULL}; 104 (dma_addr_t) 0xffffffffffffffffULL};
105static struct pci_bus_region pci_high = {(dma_addr_t) 0x100000000ULL,
106 (dma_addr_t) 0xffffffffffffffffULL};
105#endif 107#endif
106 108
107/* 109/*
@@ -198,8 +200,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
198 * alignment and type, try to find an acceptable resource allocation 200 * alignment and type, try to find an acceptable resource allocation
199 * for a specific device resource. 201 * for a specific device resource.
200 */ 202 */
201int 203int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
202pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
203 resource_size_t size, resource_size_t align, 204 resource_size_t size, resource_size_t align,
204 resource_size_t min, unsigned int type_mask, 205 resource_size_t min, unsigned int type_mask,
205 resource_size_t (*alignf)(void *, 206 resource_size_t (*alignf)(void *,
@@ -209,10 +210,19 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
209 void *alignf_data) 210 void *alignf_data)
210{ 211{
211#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 212#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
212 if (res->flags & IORESOURCE_MEM_64) 213 int rc;
214
215 if (res->flags & IORESOURCE_MEM_64) {
216 rc = pci_bus_alloc_from_region(bus, res, size, align, min,
217 type_mask, alignf, alignf_data,
218 &pci_high);
219 if (rc == 0)
220 return 0;
221
213 return pci_bus_alloc_from_region(bus, res, size, align, min, 222 return pci_bus_alloc_from_region(bus, res, size, align, min,
214 type_mask, alignf, alignf_data, 223 type_mask, alignf, alignf_data,
215 &pci_64_bit); 224 &pci_64_bit);
225 }
216#endif 226#endif
217 227
218 return pci_bus_alloc_from_region(bus, res, size, align, min, 228 return pci_bus_alloc_from_region(bus, res, size, align, min,