diff options
author | rstone <rstone@FreeBSD.org> | 2015-03-01 00:39:33 +0000 |
---|---|---|
committer | rstone <rstone@FreeBSD.org> | 2015-03-01 00:39:33 +0000 |
commit | eec79e939ebadf0bf9dd6f64959a689f8902c587 (patch) | |
tree | 8d5ed5ffa5e339e30c09bdfc915eefabddf21160 /sys/dev/pci/pci.c | |
parent | e228d5e92d9be44de199031eb339c8253de7dc61 (diff) | |
download | FreeBSD-src-eec79e939ebadf0bf9dd6f64959a689f8902c587.zip FreeBSD-src-eec79e939ebadf0bf9dd6f64959a689f8902c587.tar.gz |
Refactor PCI resource allocation
Refactor PCI resource allocation code to allow a request for a
memory-mapped I/O window that is a multiple of a requested size.
This is needed by the SR-IOV code because the VF BARs are all
allocated contiguously. We can't just allocate a resource that is
a multiple of a single VF BAR because the size of an allocation
implies its alignment requirement.
Differential Revision: https://reviews.freebsd.org/D71
Reviewed by: jhb
MFC after: 1 month
Sponsored by: Sandvine Inc.
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r-- | sys/dev/pci/pci.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 96ff11e..5cf5193 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$"); static int pci_has_quirk(uint32_t devid, int quirk); static pci_addr_t pci_mapbase(uint64_t mapreg); static const char *pci_maptype(uint64_t mapreg); -static int pci_mapsize(uint64_t testval); static int pci_maprange(uint64_t mapreg); static pci_addr_t pci_rombase(uint64_t mapreg); static int pci_romsize(uint64_t testval); @@ -487,7 +486,7 @@ pci_maptype(uint64_t mapreg) /* return log2 of map size decoded for memory or port map */ -static int +int pci_mapsize(uint64_t testval) { int ln2size; @@ -2620,8 +2619,9 @@ pci_memen(device_t dev) return (pci_read_config(dev, PCIR_COMMAND, 2) & PCIM_CMD_MEMEN) != 0; } -static void -pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp) +void +pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp, + int *bar64) { struct pci_devinfo *dinfo; pci_addr_t map, testval; @@ -2641,6 +2641,8 @@ pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp) pci_write_config(dev, reg, map, 4); *mapp = map; *testvalp = testval; + if (bar64 != NULL) + *bar64 = 0; return; } @@ -2682,6 +2684,8 @@ pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp) *mapp = map; *testvalp = testval; + if (bar64 != NULL) + *bar64 = (ln2range == 64); } static void @@ -2736,7 +2740,7 @@ pci_bar_enabled(device_t dev, struct pci_map *pm) return ((cmd & PCIM_CMD_PORTEN) != 0); } -static struct pci_map * +struct pci_map * pci_add_bar(device_t dev, int reg, pci_addr_t value, pci_addr_t size) { struct pci_devinfo *dinfo; @@ -2807,7 +2811,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl, return (barlen); } - pci_read_bar(dev, reg, &map, &testval); + pci_read_bar(dev, reg, &map, &testval, NULL); if (PCI_BAR_MEM(map)) { type = SYS_RES_MEMORY; if (map & PCIM_BAR_MEM_PREFETCH) @@ -4463,7 +4467,7 @@ DB_SHOW_COMMAND(pciregs, db_pci_dump) static struct resource * pci_reserve_map(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) + u_long start, u_long end, u_long count, u_int num, u_int flags) { struct pci_devinfo *dinfo = device_get_ivars(child); struct resource_list *rl = &dinfo->resources; @@ -4487,7 +4491,7 @@ pci_reserve_map(device_t dev, device_t child, int type, int *rid, * have a atapci device in legacy mode and it fails * here, that other code is broken. */ - pci_read_bar(child, *rid, &map, &testval); + pci_read_bar(child, *rid, &map, &testval, NULL); /* * Determine the size of the BAR and ignore BARs with a size @@ -4529,7 +4533,7 @@ pci_reserve_map(device_t dev, device_t child, int type, int *rid, * situation where we might allocate the excess to * another driver, which won't work. */ - count = (pci_addr_t)1 << mapsize; + count = ((pci_addr_t)1 << mapsize) * num; if (RF_ALIGNMENT(flags) < mapsize) flags = (flags & ~RF_ALIGNMENT_MASK) | RF_ALIGNMENT_LOG2(mapsize); if (PCI_BAR_MEM(map) && (map & PCIM_BAR_MEM_PREFETCH)) @@ -4560,8 +4564,8 @@ out: } struct resource * -pci_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) +pci_alloc_multi_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_long num, u_int flags) { struct pci_devinfo *dinfo; struct resource_list *rl; @@ -4569,10 +4573,6 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid, struct resource *res; pcicfgregs *cfg; - if (device_get_parent(child) != dev) - return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - type, rid, start, end, count, flags)); - /* * Perform lazy resource allocation */ @@ -4629,7 +4629,7 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid, rle = resource_list_find(rl, type, *rid); if (rle == NULL) { res = pci_reserve_map(dev, child, type, rid, start, end, - count, flags); + count, num, flags); if (res == NULL) return (NULL); } @@ -4638,6 +4638,19 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid, start, end, count, flags)); } +struct resource * +pci_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + + if (device_get_parent(child) != dev) + return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + type, rid, start, end, count, flags)); + + return (pci_alloc_multi_resource(dev, child, type, rid, start, end, + count, 1, flags)); +} + int pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) |