From 94df1e8e89f9065c00c0308573407886b5986857 Mon Sep 17 00:00:00 2001 From: Ryan Stone Date: Tue, 15 Apr 2014 22:03:57 -0400 Subject: [PATCH 02/21] 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. --- sys/dev/pci/pci.c | 45 +++++++++++++++++++++++++++++---------------- sys/dev/pci/pci_private.h | 10 ++++++++++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 1d7c0b7..e18ffc0 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -77,7 +77,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); @@ -477,7 +476,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; @@ -2609,8 +2608,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; @@ -2630,6 +2630,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; } @@ -2671,6 +2673,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 @@ -2725,7 +2729,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; @@ -2796,7 +2800,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) @@ -4452,7 +4456,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; @@ -4476,7 +4480,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 @@ -4518,7 +4522,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)) @@ -4549,8 +4553,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; @@ -4558,10 +4562,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 */ @@ -4618,7 +4618,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); } @@ -4627,6 +4627,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) diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h index 0223ee8..a6d8cc8 100644 --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -133,4 +133,14 @@ void pci_cfg_restore(device_t, struct pci_devinfo *); */ void pci_cfg_save(device_t, struct pci_devinfo *, int); +int pci_mapsize(uint64_t testval); +void pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, + pci_addr_t *testvalp, int *bar64); +struct pci_map *pci_add_bar(device_t dev, int reg, pci_addr_t value, + pci_addr_t size); + +struct resource *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); + #endif /* _PCI_PRIVATE_H_ */ -- 1.9.2