Re: [PATCH v4 5/5] PCI: Handle Enhanced Allocation (EA) capability for bridges
On 10/05/2015 03:54 PM, Sean O. Stalley wrote: On Fri, Oct 02, 2015 at 03:37:56PM -0700, David Daney wrote: From: David Daney PCI bridges may have their properties be specified via EA entries. Extend the EA parser to extract the bridge resources, and modify pci_read_bridge_{io,mmio,mmio_pref}() to use resources previously obtained via EA. Save the offset to the EA capability in struct pci_dev, and use it to easily find the EA bridge subordinate and secondary bus numbers. When assigning the bridge resources a couple of changes are required so that the EA obtained IORESOURCE_PCI_FIXED are not resized, and correctly linked into the resource tree. 1) In pbus_size_mem() do not attempt to resize the bridge resources if they are marked as IORESOURCE_PCI_FIXED. 2) In pci_bus_alloc_from_region()for IORESOURCE_PCI_FIXED resources, just try to request the resource as is, without attempting to resize it. Signed-off-by: David Daney --- drivers/pci/bus.c | 7 +++ drivers/pci/pci.c | 13 + drivers/pci/probe.c | 31 +-- drivers/pci/setup-bus.c | 3 +++ include/linux/pci.h | 1 + 5 files changed, 53 insertions(+), 2 deletions(-) @@ -801,8 +813,23 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); primary = buses & 0xFF; - secondary = (buses >> 8) & 0xFF; - subordinate = (buses >> 16) & 0xFF; + if (dev->ea_cap) { + u32 dw1; + + pci_read_config_dword(dev, dev->ea_cap + 4, &dw1); + if (dw1 & 0xFF) + secondary = dw1 & 0xFF; + else + secondary = (buses >> 8) & 0xFF; + + if ((dw1 >> 8) & 0xFF) + subordinate = (dw1 >> 8) & 0xFF; + else + subordinate = (buses >> 16) & 0xFF; + } else { + secondary = (buses >> 8) & 0xFF; + subordinate = (buses >> 16) & 0xFF; + } We can refactor this to make it cleaner/more compact. from V3 review: secondary = (buses >> 8) & 0xFF; subordinate = (buses >> 16) & 0xFF; if (dev->ea_cap) { u32 sdw; pci_read_config_dword(dev, dev->ea_cap + 4, &sdw); if (sdw & 0xFF) secondary = sdw & 0xFF; sdw >>= 8; if (sdw & 0xFF) subordinate = sdw & 0xFF; } Yes, that is cleaner. I think I didn't read the comments on v3 closely enough. I will switch to doing it this way. Thanks, David Daney -Sean -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v4 5/5] PCI: Handle Enhanced Allocation (EA) capability for bridges
On Fri, Oct 02, 2015 at 03:37:56PM -0700, David Daney wrote: > From: David Daney > > PCI bridges may have their properties be specified via EA entries. > > Extend the EA parser to extract the bridge resources, and modify > pci_read_bridge_{io,mmio,mmio_pref}() to use resources previously > obtained via EA. > > Save the offset to the EA capability in struct pci_dev, and use it to > easily find the EA bridge subordinate and secondary bus numbers. > > When assigning the bridge resources a couple of changes are required > so that the EA obtained IORESOURCE_PCI_FIXED are not resized, and > correctly linked into the resource tree. > > 1) In pbus_size_mem() do not attempt to resize the bridge resources if >they are marked as IORESOURCE_PCI_FIXED. > > 2) In pci_bus_alloc_from_region()for IORESOURCE_PCI_FIXED resources, just >try to request the resource as is, without attempting to resize it. > > Signed-off-by: David Daney > --- > drivers/pci/bus.c | 7 +++ > drivers/pci/pci.c | 13 + > drivers/pci/probe.c | 31 +-- > drivers/pci/setup-bus.c | 3 +++ > include/linux/pci.h | 1 + > 5 files changed, 53 insertions(+), 2 deletions(-) > @@ -801,8 +813,23 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev > *dev, int max, int pass) > > pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); > primary = buses & 0xFF; > - secondary = (buses >> 8) & 0xFF; > - subordinate = (buses >> 16) & 0xFF; > + if (dev->ea_cap) { > + u32 dw1; > + > + pci_read_config_dword(dev, dev->ea_cap + 4, &dw1); > + if (dw1 & 0xFF) > + secondary = dw1 & 0xFF; > + else > + secondary = (buses >> 8) & 0xFF; > + > + if ((dw1 >> 8) & 0xFF) > + subordinate = (dw1 >> 8) & 0xFF; > + else > + subordinate = (buses >> 16) & 0xFF; > + } else { > + secondary = (buses >> 8) & 0xFF; > + subordinate = (buses >> 16) & 0xFF; > + } We can refactor this to make it cleaner/more compact. from V3 review: secondary = (buses >> 8) & 0xFF; subordinate = (buses >> 16) & 0xFF; if (dev->ea_cap) { u32 sdw; pci_read_config_dword(dev, dev->ea_cap + 4, &sdw); if (sdw & 0xFF) secondary = sdw & 0xFF; sdw >>= 8; if (sdw & 0xFF) subordinate = sdw & 0xFF; } -Sean -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 5/5] PCI: Handle Enhanced Allocation (EA) capability for bridges
From: David Daney PCI bridges may have their properties be specified via EA entries. Extend the EA parser to extract the bridge resources, and modify pci_read_bridge_{io,mmio,mmio_pref}() to use resources previously obtained via EA. Save the offset to the EA capability in struct pci_dev, and use it to easily find the EA bridge subordinate and secondary bus numbers. When assigning the bridge resources a couple of changes are required so that the EA obtained IORESOURCE_PCI_FIXED are not resized, and correctly linked into the resource tree. 1) In pbus_size_mem() do not attempt to resize the bridge resources if they are marked as IORESOURCE_PCI_FIXED. 2) In pci_bus_alloc_from_region()for IORESOURCE_PCI_FIXED resources, just try to request the resource as is, without attempting to resize it. Signed-off-by: David Daney --- drivers/pci/bus.c | 7 +++ drivers/pci/pci.c | 13 + drivers/pci/probe.c | 31 +-- drivers/pci/setup-bus.c | 3 +++ include/linux/pci.h | 1 + 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 6fbd3f2..0556b33 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -153,6 +153,13 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, !(res->flags & IORESOURCE_PREFETCH)) continue; + if (res->flags & IORESOURCE_PCI_FIXED) { + /* Cannot change it, just try to claim it. */ + if (request_resource(r, res)) + continue; + return 0; + } + avail = *r; pci_clip_resource_to_region(bus, &avail, region); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6750edf..c857632 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2183,6 +2183,17 @@ static struct resource *pci_ea_get_resource(struct pci_dev *dev, u8 bei, u8 prop (prop == PCI_EA_P_VIRT_MEM || prop == PCI_EA_P_VIRT_MEM_PREFETCH)) return &dev->resource[PCI_IOV_RESOURCES + bei - PCI_EA_BEI_VF_BAR0]; #endif + else if (bei == PCI_EA_BEI_BRIDGE) + switch (prop) { + case PCI_EA_P_BRIDGE_IO: + return &dev->resource[PCI_BRIDGE_RESOURCES + 0]; + case PCI_EA_P_BRIDGE_MEM: + return &dev->resource[PCI_BRIDGE_RESOURCES + 1]; + case PCI_EA_P_BRIDGE_MEM_PREFETCH: + return &dev->resource[PCI_BRIDGE_RESOURCES + 2]; + default: + return NULL; + } else if (bei == PCI_EA_BEI_ROM) return &dev->resource[PCI_ROM_RESOURCE]; else @@ -2321,6 +2332,8 @@ void pci_ea_init(struct pci_dev *dev) if (!ea) return; + dev->ea_cap = ea; + /* determine the number of entries */ pci_bus_read_config_byte(dev->bus, dev->devfn, ea + PCI_EA_NUM_ENT, &num_ent); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 4293eec..e4bcb0b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -348,6 +348,10 @@ static void pci_read_bridge_io(struct pci_bus *child) } res = child->resource[0]; + if (res->flags & IORESOURCE_PCI_FIXED) { + dev_dbg(&dev->dev, " bridge window %pR (fixed)\n", res); + return; + } pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); base = (io_base_lo & io_mask) << 8; @@ -380,6 +384,10 @@ static void pci_read_bridge_mmio(struct pci_bus *child) struct resource *res; res = child->resource[1]; + if (res->flags & IORESOURCE_PCI_FIXED) { + dev_dbg(&dev->dev, " bridge window %pR (fixed)\n", res); + return; + } pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); base = ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; @@ -403,6 +411,10 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) struct resource *res; res = child->resource[2]; + if (res->flags & IORESOURCE_PCI_FIXED) { + dev_dbg(&dev->dev, " bridge window %pR (fixed)\n", res); + return; + } pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; @@ -801,8 +813,23 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); primary = buses & 0xFF; - secondary = (buses >> 8) & 0xFF; - subordinate