mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/5] PCI: add some useful debug output
@ 2016-11-01  8:58 Lucas Stach
  2016-11-01  8:58 ` [PATCH 2/5] PCI: only check specific flag for 64bit BAR Lucas Stach
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Lucas Stach @ 2016-11-01  8:58 UTC (permalink / raw)
  To: barebox

This makes diagnosing problems in address space allocation
much easier.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 drivers/pci/pci.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 191561da0368..46f5d5f7de36 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -179,6 +179,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 				pr_debug("BAR does not fit within bus IO res\n");
 				return;
 			}
+			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_io);
 			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
 			dev->resource[bar].flags = IORESOURCE_IO;
 			last_addr = last_io;
@@ -197,6 +198,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 				pr_debug("BAR does not fit within bus p-mem res\n");
 				return;
 			}
+			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_mem_pref);
 			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem_pref);
 			dev->resource[bar].flags = IORESOURCE_MEM |
 			                           IORESOURCE_PREFETCH;
@@ -215,6 +217,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 				pr_debug("BAR does not fit within bus np-mem res\n");
 				return;
 			}
+			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_mem);
 			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
 			dev->resource[bar].flags = IORESOURCE_MEM;
 			last_addr = last_mem;
@@ -286,18 +289,21 @@ static void postscan_setup_bridge(struct pci_dev *dev)
 
 	if (last_mem) {
 		last_mem = ALIGN(last_mem, SZ_1M);
+		pr_debug("bridge NP limit at 0x%08x\n", last_mem);
 		pci_write_config_word(dev, PCI_MEMORY_LIMIT,
 				      ((last_mem - 1) & 0xfff00000) >> 16);
 	}
 
 	if (last_mem_pref) {
 		last_mem_pref = ALIGN(last_mem_pref, SZ_1M);
+		pr_debug("bridge P limit at 0x%08x\n", last_mem_pref);
 		pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT,
 				      ((last_mem_pref - 1) & 0xfff00000) >> 16);
 	}
 
 	if (last_io) {
 		last_io = ALIGN(last_io, SZ_4K);
+		pr_debug("bridge IO limit at 0x%08x\n", last_io);
 		pci_write_config_byte(dev, PCI_IO_LIMIT,
 				((last_io - 1) & 0x0000f000) >> 8);
 		pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
-- 
2.10.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/5] PCI: only check specific flag for 64bit BAR
  2016-11-01  8:58 [PATCH 1/5] PCI: add some useful debug output Lucas Stach
@ 2016-11-01  8:58 ` Lucas Stach
  2016-11-01  8:58 ` [PATCH 3/5] PCI: align address range before scanning bridge Lucas Stach
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Lucas Stach @ 2016-11-01  8:58 UTC (permalink / raw)
  To: barebox

The memory type may include other flags, so just check for
the 64bit allocation flag to see if the BAR is a 64bit one.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 drivers/pci/pci.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 46f5d5f7de36..eb3ce0f3211a 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -227,8 +227,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 		dev->resource[bar].start = last_addr;
 		dev->resource[bar].end = last_addr + size - 1;
 
-		if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
-		    PCI_BASE_ADDRESS_MEM_TYPE_64) {
+		if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
 			dev->resource[bar].flags |= IORESOURCE_MEM_64;
 			pci_write_config_dword(dev,
 			       PCI_BASE_ADDRESS_1 + bar * 4, 0);
-- 
2.10.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/5] PCI: align address range before scanning bridge
  2016-11-01  8:58 [PATCH 1/5] PCI: add some useful debug output Lucas Stach
  2016-11-01  8:58 ` [PATCH 2/5] PCI: only check specific flag for 64bit BAR Lucas Stach
@ 2016-11-01  8:58 ` Lucas Stach
  2016-11-01  8:58 ` [PATCH 4/5] PCI: align BAR address to BAR size Lucas Stach
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Lucas Stach @ 2016-11-01  8:58 UTC (permalink / raw)
  To: barebox

Otherwise we may end up with a too low base address and push
requests for the upstream bus onto the downstream side.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 drivers/pci/pci.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index eb3ce0f3211a..19cda1f145bc 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -252,6 +252,7 @@ static void prescan_setup_bridge(struct pci_dev *dev)
 
 	if (last_mem) {
 		/* Set up memory and I/O filter limits, assume 32-bit I/O space */
+		last_mem = ALIGN(last_mem, SZ_1M);
 		pci_write_config_word(dev, PCI_MEMORY_BASE,
 				      (last_mem & 0xfff00000) >> 16);
 		cmdstat |= PCI_COMMAND_MEMORY;
@@ -259,6 +260,7 @@ static void prescan_setup_bridge(struct pci_dev *dev)
 
 	if (last_mem_pref) {
 		/* Set up memory and I/O filter limits, assume 32-bit I/O space */
+		last_mem_pref = ALIGN(last_mem_pref, SZ_1M);
 		pci_write_config_word(dev, PCI_PREF_MEMORY_BASE,
 				      (last_mem_pref & 0xfff00000) >> 16);
 		cmdstat |= PCI_COMMAND_MEMORY;
@@ -270,6 +272,7 @@ static void prescan_setup_bridge(struct pci_dev *dev)
 	}
 
 	if (last_io) {
+		last_io = ALIGN(last_io, SZ_4K);
 		pci_write_config_byte(dev, PCI_IO_BASE,
 				      (last_io & 0x0000f000) >> 8);
 		pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
-- 
2.10.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 4/5] PCI: align BAR address to BAR size
  2016-11-01  8:58 [PATCH 1/5] PCI: add some useful debug output Lucas Stach
  2016-11-01  8:58 ` [PATCH 2/5] PCI: only check specific flag for 64bit BAR Lucas Stach
  2016-11-01  8:58 ` [PATCH 3/5] PCI: align address range before scanning bridge Lucas Stach
@ 2016-11-01  8:58 ` Lucas Stach
  2016-11-01  8:58 ` [PATCH 5/5] PCI: split PCI hierarchy enumeration and config from device registration Lucas Stach
  2016-11-03  6:12 ` [PATCH 1/5] PCI: add some useful debug output Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Lucas Stach @ 2016-11-01  8:58 UTC (permalink / raw)
  To: barebox

PCI BARs require their address to be at least aligned to their
size, otherwise address decoding will fail as the base address
gets rounded down.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 drivers/pci/pci.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 19cda1f145bc..12aafccde578 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -174,11 +174,12 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 				continue;
 			}
 			pr_debug("pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
-			if (last_io + size >
+			if (ALIGN(last_io, size) + size >
 			    dev->bus->resource[PCI_BUS_RESOURCE_IO]->end) {
 				pr_debug("BAR does not fit within bus IO res\n");
 				return;
 			}
+			last_io = ALIGN(last_io, size);
 			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_io);
 			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
 			dev->resource[bar].flags = IORESOURCE_IO;
@@ -193,11 +194,12 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			}
 			pr_debug("pbar%d: mask=%08x P memory %d bytes\n",
 			    bar, mask, size);
-			if (last_mem_pref + size >
+			if (ALIGN(last_mem_pref, size) + size >
 			    dev->bus->resource[PCI_BUS_RESOURCE_MEM_PREF]->end) {
 				pr_debug("BAR does not fit within bus p-mem res\n");
 				return;
 			}
+			last_mem_pref = ALIGN(last_mem_pref, size);
 			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_mem_pref);
 			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem_pref);
 			dev->resource[bar].flags = IORESOURCE_MEM |
@@ -212,11 +214,12 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			}
 			pr_debug("pbar%d: mask=%08x NP memory %d bytes\n",
 			    bar, mask, size);
-			if (last_mem + size >
+			if (ALIGN(last_mem, size) + size >
 			    dev->bus->resource[PCI_BUS_RESOURCE_MEM]->end) {
 				pr_debug("BAR does not fit within bus np-mem res\n");
 				return;
 			}
+			last_mem = ALIGN(last_mem, size);
 			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_mem);
 			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
 			dev->resource[bar].flags = IORESOURCE_MEM;
-- 
2.10.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 5/5] PCI: split PCI hierarchy enumeration and config from device registration
  2016-11-01  8:58 [PATCH 1/5] PCI: add some useful debug output Lucas Stach
                   ` (2 preceding siblings ...)
  2016-11-01  8:58 ` [PATCH 4/5] PCI: align BAR address to BAR size Lucas Stach
@ 2016-11-01  8:58 ` Lucas Stach
  2016-11-03  6:12 ` [PATCH 1/5] PCI: add some useful debug output Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Lucas Stach @ 2016-11-01  8:58 UTC (permalink / raw)
  To: barebox

This gets rid of some of the special cases in the bus scanning function
by splitting hierarchy enumeration and configuration and the actual
device registration into 2 passes.

This ensures that the PCI hierarchy below a root port is completely
set up before any device driver is probed.

This simplifies the code and makes it less error prone, while moving
the PCI address space layout closer to the one used by Linux.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 drivers/pci/pci.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 12aafccde578..b2570eb15181 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -28,6 +28,20 @@ static struct pci_bus *pci_alloc_bus(void)
 	return b;
 }
 
+static void pci_bus_register_devices(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	struct pci_bus *child_bus;
+
+	/* activate all devices on this bus */
+	list_for_each_entry(dev, &bus->devices, bus_list)
+		pci_register_device(dev);
+
+	/* walk down the hierarchy */
+	list_for_each_entry(child_bus, &bus->children, node)
+		pci_bus_register_devices(child_bus);
+}
+
 void register_pci_controller(struct pci_controller *hose)
 {
 	struct pci_bus *bus;
@@ -64,6 +78,7 @@ void register_pci_controller(struct pci_controller *hose)
 		last_io = 0;
 
 	pci_scan_bus(bus);
+	pci_bus_register_devices(bus);
 
 	list_add_tail(&bus->node, &pci_root_buses);
 
@@ -384,16 +399,8 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
 			dev->rom_address = (l == 0xffffffff) ? 0 : l;
 
 			setup_device(dev, 6);
-			/*
-			 * If this device is on the root bus, there is no bridge
-			 * to configure, so we can activate it right away.
-			 */
-			if (!bus->parent_bus)
-				pci_register_device(dev);
 			break;
 		case PCI_HEADER_TYPE_BRIDGE:
-			setup_device(dev, 2);
-
 			child_bus = pci_alloc_bus();
 			/* inherit parent properties */
 			child_bus->host = bus->host;
@@ -412,18 +419,12 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
 			list_add_tail(&child_bus->node, &bus->children);
 			dev->subordinate = child_bus;
 
-			/* activate bridge device */
-			pci_register_device(dev);
-
 			/* scan pci hierarchy behind bridge */
 			prescan_setup_bridge(dev);
 			pci_scan_bus(child_bus);
 			postscan_setup_bridge(dev);
 
-			/* finally active all devices behind the bridge */
-			list_for_each_entry(dev, &child_bus->devices, bus_list)
-				if (!dev->subordinate)
-					pci_register_device(dev);
+			setup_device(dev, 2);
 			break;
 		default:
 		bad:
-- 
2.10.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/5] PCI: add some useful debug output
  2016-11-01  8:58 [PATCH 1/5] PCI: add some useful debug output Lucas Stach
                   ` (3 preceding siblings ...)
  2016-11-01  8:58 ` [PATCH 5/5] PCI: split PCI hierarchy enumeration and config from device registration Lucas Stach
@ 2016-11-03  6:12 ` Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2016-11-03  6:12 UTC (permalink / raw)
  To: Lucas Stach; +Cc: barebox

On Tue, Nov 01, 2016 at 09:58:51AM +0100, Lucas Stach wrote:
> This makes diagnosing problems in address space allocation
> much easier.
> 
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> ---
>  drivers/pci/pci.c | 6 ++++++
>  1 file changed, 6 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 191561da0368..46f5d5f7de36 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -179,6 +179,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
>  				pr_debug("BAR does not fit within bus IO res\n");
>  				return;
>  			}
> +			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_io);
>  			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
>  			dev->resource[bar].flags = IORESOURCE_IO;
>  			last_addr = last_io;
> @@ -197,6 +198,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
>  				pr_debug("BAR does not fit within bus p-mem res\n");
>  				return;
>  			}
> +			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_mem_pref);
>  			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem_pref);
>  			dev->resource[bar].flags = IORESOURCE_MEM |
>  			                           IORESOURCE_PREFETCH;
> @@ -215,6 +217,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
>  				pr_debug("BAR does not fit within bus np-mem res\n");
>  				return;
>  			}
> +			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_mem);
>  			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
>  			dev->resource[bar].flags = IORESOURCE_MEM;
>  			last_addr = last_mem;
> @@ -286,18 +289,21 @@ static void postscan_setup_bridge(struct pci_dev *dev)
>  
>  	if (last_mem) {
>  		last_mem = ALIGN(last_mem, SZ_1M);
> +		pr_debug("bridge NP limit at 0x%08x\n", last_mem);
>  		pci_write_config_word(dev, PCI_MEMORY_LIMIT,
>  				      ((last_mem - 1) & 0xfff00000) >> 16);
>  	}
>  
>  	if (last_mem_pref) {
>  		last_mem_pref = ALIGN(last_mem_pref, SZ_1M);
> +		pr_debug("bridge P limit at 0x%08x\n", last_mem_pref);
>  		pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT,
>  				      ((last_mem_pref - 1) & 0xfff00000) >> 16);
>  	}
>  
>  	if (last_io) {
>  		last_io = ALIGN(last_io, SZ_4K);
> +		pr_debug("bridge IO limit at 0x%08x\n", last_io);
>  		pci_write_config_byte(dev, PCI_IO_LIMIT,
>  				((last_io - 1) & 0x0000f000) >> 8);
>  		pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
> -- 
> 2.10.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-11-03  6:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-01  8:58 [PATCH 1/5] PCI: add some useful debug output Lucas Stach
2016-11-01  8:58 ` [PATCH 2/5] PCI: only check specific flag for 64bit BAR Lucas Stach
2016-11-01  8:58 ` [PATCH 3/5] PCI: align address range before scanning bridge Lucas Stach
2016-11-01  8:58 ` [PATCH 4/5] PCI: align BAR address to BAR size Lucas Stach
2016-11-01  8:58 ` [PATCH 5/5] PCI: split PCI hierarchy enumeration and config from device registration Lucas Stach
2016-11-03  6:12 ` [PATCH 1/5] PCI: add some useful debug output Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox