Zhao, Yu
2008-Sep-27 08:59 UTC
[Xen-devel] [PATCH 2/9] dom0 PCI: add new general functions
Centralize capability related functions into several new functions and put PCI resource definitions into an enum. Signed-off-by: Yu Zhao <yu.zhao@intel.com> diff -r 6301e7e967c0 -r 5020cef2bc39 drivers/pci/pci-sysfs.c --- a/drivers/pci/pci-sysfs.c Sat Sep 27 01:23:54 2008 -0400 +++ b/drivers/pci/pci-sysfs.c Sat Sep 27 01:25:05 2008 -0400 @@ -85,11 +85,11 @@ struct pci_dev * pci_dev = to_pci_dev(dev); char * str = buf; int i; - int max = 7; + int max; resource_size_t start, end; - if (pci_dev->subordinate) - max = DEVICE_COUNT_RESOURCE; + max = pci_dev->subordinate ? DEVICE_COUNT_RESOURCE : + PCI_BRIDGE_RESOURCES; for (i = 0; i < max; i++) { struct resource *res = &pci_dev->resource[i]; diff -r 6301e7e967c0 -r 5020cef2bc39 drivers/pci/pci.c --- a/drivers/pci/pci.c Sat Sep 27 01:23:54 2008 -0400 +++ b/drivers/pci/pci.c Sat Sep 27 01:25:05 2008 -0400 @@ -256,25 +256,10 @@ void pci_restore_bars(struct pci_dev *dev) { - int i, numres; + int i; - switch (dev->hdr_type) { - case PCI_HEADER_TYPE_NORMAL: - numres = 6; - break; - case PCI_HEADER_TYPE_BRIDGE: - numres = 2; - break; - case PCI_HEADER_TYPE_CARDBUS: - numres = 1; - break; - default: - /* Should never get here, but just in case... */ - return; - } - - for (i = 0; i < numres; i ++) - pci_update_resource(dev, &dev->resource[i], i); + for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) + pci_update_resource(dev, i); } int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t); @@ -927,6 +912,48 @@ } #endif +/** + * pci_resource_alignment - get a PCI BAR resource alignment + * @dev: the PCI device + * @resno: the resource number + * + * Returns alignment size on success, or 0 on error. + */ +int pci_resource_alignment(struct pci_dev *dev, int resno) +{ + struct resource *res = dev->resource + resno; + + if (resno <= PCI_ROM_RESOURCE) + return res->end - res->start + 1; + else if (resno <= PCI_BRIDGE_RES_END) + return res->start; + + dev_err(&dev->dev, "alignment: invalid resource #%d\n", resno); + return 0; +} + +/** + * pci_resource_bar - get position of the BAR associated with a resource + * @dev: the PCI device + * @resno: the resource number + * @type: the BAR type to be filled in + * + * Returns BAR position in config space, or 0 if the BAR is invalid. + */ +int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) +{ + if (resno < PCI_ROM_RESOURCE) { + *type = pci_bar_unknown; + return PCI_BASE_ADDRESS_0 + 4 * resno; + } else if (resno == PCI_ROM_RESOURCE) { + *type = pci_bar_rom; + return dev->rom_base_reg; + } + + dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno); + return 0; +} + static int __devinit pci_init(void) { struct pci_dev *dev = NULL; diff -r 6301e7e967c0 -r 5020cef2bc39 drivers/pci/pci.h --- a/drivers/pci/pci.h Sat Sep 27 01:23:54 2008 -0400 +++ b/drivers/pci/pci.h Sat Sep 27 01:25:05 2008 -0400 @@ -117,5 +117,8 @@ struct resource *res, unsigned int reg); extern struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr); +extern int pci_resource_alignment(struct pci_dev *dev, int resno); +extern int pci_resource_bar(struct pci_dev *dev, int resno, + enum pci_bar_type *type); #endif /* DRIVERS_PCI_H */ diff -r 6301e7e967c0 -r 5020cef2bc39 drivers/pci/probe.c --- a/drivers/pci/probe.c Sat Sep 27 01:23:54 2008 -0400 +++ b/drivers/pci/probe.c Sat Sep 27 01:25:05 2008 -0400 @@ -412,7 +412,7 @@ child->self = bridge; child->bridge = get_device(&bridge->dev); /* Set up default resource pointers and names.. */ - for (i = 0; i < 4; i++) { + for (i = 0; i < PCI_BRIDGE_RES_NUM; i++) { child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; child->resource[i]->name = child->name; } diff -r 6301e7e967c0 -r 5020cef2bc39 drivers/pci/proc.c --- a/drivers/pci/proc.c Sat Sep 27 01:23:54 2008 -0400 +++ b/drivers/pci/proc.c Sat Sep 27 01:25:05 2008 -0400 @@ -348,15 +348,16 @@ dev->vendor, dev->device, dev->irq); - /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */ - for (i=0; i<7; i++) { + + /* only print standard and ROM resources to preserve compatibility */ + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { resource_size_t start, end; pci_resource_to_user(dev, i, &dev->resource[i], &start, &end); seq_printf(m, "\t%16llx", (unsigned long long)(start | (dev->resource[i].flags & PCI_REGION_FLAG_MASK))); } - for (i=0; i<7; i++) { + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { resource_size_t start, end; pci_resource_to_user(dev, i, &dev->resource[i], &start, &end); seq_printf(m, "\t%16llx", diff -r 6301e7e967c0 -r 5020cef2bc39 drivers/pci/setup-bus.c --- a/drivers/pci/setup-bus.c Sat Sep 27 01:23:54 2008 -0400 +++ b/drivers/pci/setup-bus.c Sat Sep 27 01:25:05 2008 -0400 @@ -25,6 +25,7 @@ #include <linux/ioport.h> #include <linux/cache.h> #include <linux/slab.h> +#include "pci.h" #define DEBUG_CONFIG 1 @@ -352,8 +353,7 @@ if (r->parent || (r->flags & mask) != type) continue; r_size = r->end - r->start + 1; - /* For bridges size != alignment */ - align = (i < PCI_BRIDGE_RESOURCES) ? r_size : r->start; + align = pci_resource_alignment(dev, i); order = __ffs(align) - 20; if (order > 11) { printk(KERN_WARNING "PCI: region %s/%d " diff -r 6301e7e967c0 -r 5020cef2bc39 drivers/pci/setup-res.c --- a/drivers/pci/setup-res.c Sat Sep 27 01:23:54 2008 -0400 +++ b/drivers/pci/setup-res.c Sat Sep 27 01:25:05 2008 -0400 @@ -27,11 +27,13 @@ void -pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) +pci_update_resource(struct pci_dev *dev, int resno) { struct pci_bus_region region; u32 new, check, mask; int reg; + enum pci_bar_type type; + struct resource *res = dev->resource + resno; /* Ignore resources for unimplemented BARs and unused resource slots for 64 bit BARs. */ @@ -51,17 +53,13 @@ else mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; - if (resno < 6) { - reg = PCI_BASE_ADDRESS_0 + 4 * resno; - } else if (resno == PCI_ROM_RESOURCE) { + reg = pci_resource_bar(dev, resno, &type); + if (!reg) + return; + if (type == pci_bar_rom) { if (!(res->flags & IORESOURCE_ROM_ENABLE)) return; new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Hmm, non-standard resource. */ - - return; /* kill uninitialised var warning */ } pci_write_config_dword(dev, reg, new); @@ -126,10 +124,7 @@ size = res->end - res->start + 1; min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; - /* The bridge resources are special, as their - size != alignment. Sizing routines return - required alignment in the "start" field. */ - align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start; + align = pci_resource_alignment(dev, resno); /* First, try exact prefetching match.. */ ret = pci_bus_alloc_resource(bus, res, size, align, min, @@ -154,7 +149,7 @@ resno, (unsigned long long)size, (unsigned long long)res->start, pci_name(dev)); } else if (resno < PCI_BRIDGE_RESOURCES) { - pci_update_resource(dev, res, resno); + pci_update_resource(dev, resno); } return ret; @@ -192,7 +187,7 @@ resno, (unsigned long long)(res->end - res->start + 1), (unsigned long long)res->start, pci_name(dev)); } else if (resno < PCI_BRIDGE_RESOURCES) { - pci_update_resource(dev, res, resno); + pci_update_resource(dev, resno); } return ret; @@ -223,7 +218,7 @@ (unsigned long long)r->end, pci_name(dev)); continue; } - r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start; + r_align = pci_resource_alignment(dev, i); for (list = head; ; list = list->next) { resource_size_t align = 0; struct resource_list *ln = list->next; @@ -231,9 +226,7 @@ if (ln) { idx = ln->res - &ln->dev->resource[0]; - align = (idx < PCI_BRIDGE_RESOURCES) ? - ln->res->end - ln->res->start + 1 : - ln->res->start; + align = pci_resource_alignment(ln->dev, idx); } if (r_align > align) { tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); diff -r 6301e7e967c0 -r 5020cef2bc39 include/linux/pci.h --- a/include/linux/pci.h Sat Sep 27 01:23:54 2008 -0400 +++ b/include/linux/pci.h Sat Sep 27 01:25:05 2008 -0400 @@ -65,7 +65,31 @@ #define PCI_DMA_NONE 3 #define DEVICE_COUNT_COMPATIBLE 4 -#define DEVICE_COUNT_RESOURCE 12 + +/* + * For PCI devices, the region numbers are assigned this way: + */ +enum { + /* #0-5: standard PCI regions */ + PCI_STD_RESOURCES, + PCI_STD_RESOURCES_END = 5, + + /* #6: expansion ROM */ + PCI_ROM_RESOURCE, + + /* address space assigned to buses behind the bridge */ +#ifndef PCI_BRIDGE_RES_NUM +#define PCI_BRIDGE_RES_NUM 4 +#endif + PCI_BRIDGE_RESOURCES, + PCI_BRIDGE_RES_END = PCI_BRIDGE_RESOURCES + PCI_BRIDGE_RES_NUM - 1, + + /* total resources associated with a PCI device */ + PCI_NUM_RESOURCES, + + /* preserve this for compatibility */ + DEVICE_COUNT_RESOURCE +}; typedef int __bitwise pci_power_t; @@ -205,18 +229,6 @@ { hlist_del(&cap->next); } - -/* - * For PCI devices, the region numbers are assigned this way: - * - * 0-5 standard PCI regions - * 6 expansion ROM - * 7-10 bridges: address space assigned to buses behind the bridge - */ - -#define PCI_ROM_RESOURCE 6 -#define PCI_BRIDGE_RESOURCES 7 -#define PCI_NUM_RESOURCES 11 #ifndef PCI_BUS_NUM_RESOURCES #define PCI_BUS_NUM_RESOURCES 8 @@ -501,7 +513,7 @@ void pci_intx(struct pci_dev *dev, int enable); int pci_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); -void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); +void pci_update_resource(struct pci_dev *dev, int resno); int pci_assign_resource(struct pci_dev *dev, int i); int pci_assign_resource_fixed(struct pci_dev *dev, int i); void pci_restore_bars(struct pci_dev *dev); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel