Re: [PATCH v4 5/5] PCI: Handle Enhanced Allocation (EA) capability for bridges

2015-10-05 Thread David Daney

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

2015-10-05 Thread Sean O. Stalley
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

2015-10-02 Thread David Daney
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