diff mbox

[U-Boot,3/6] dm: pci: Use complete bdf in all pci config read/write routines

Message ID BLU436-SMTP119F87F2E8947EC80928D9FBF870@phx.gbl
State Accepted
Delegated to: Simon Glass
Headers show

Commit Message

Bin Meng July 18, 2015, 4:20 p.m. UTC
Currently pci_bus_read_config() and pci_bus_write_config() are
called with bus number masked off in the parameter bdf, and bus
number is supposed to be added back in the bridge driver's pci
config read/write ops if the device is behind a pci bridge.
However this logic only works for a pci topology where there is
only one bridge off the root controller. If there is addtional
bridge in the system, the logic will create a non-existent bdf
where its bus number gets accumulated across bridges.

To correct this, we change all pci config read/write routines
to use complete bdf all the way up to the root controller.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
---

 drivers/pci/pci-uclass.c | 46 +++++++++++++++++++++++-----------------------
 1 file changed, 23 insertions(+), 23 deletions(-)

Comments

Simon Glass July 20, 2015, 1:59 a.m. UTC | #1
On 18 July 2015 at 10:20, Bin Meng <bmeng.cn@gmail.com> wrote:
> Currently pci_bus_read_config() and pci_bus_write_config() are
> called with bus number masked off in the parameter bdf, and bus
> number is supposed to be added back in the bridge driver's pci
> config read/write ops if the device is behind a pci bridge.
> However this logic only works for a pci topology where there is
> only one bridge off the root controller. If there is addtional
> bridge in the system, the logic will create a non-existent bdf
> where its bus number gets accumulated across bridges.
>
> To correct this, we change all pci config read/write routines
> to use complete bdf all the way up to the root controller.
>
> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
> ---
>
>  drivers/pci/pci-uclass.c | 46 +++++++++++++++++++++++-----------------------
>  1 file changed, 23 insertions(+), 23 deletions(-)

Acked-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
Simon Glass July 20, 2015, 3:01 p.m. UTC | #2
On 19 July 2015 at 19:59, Simon Glass <sjg@chromium.org> wrote:
> On 18 July 2015 at 10:20, Bin Meng <bmeng.cn@gmail.com> wrote:
>> Currently pci_bus_read_config() and pci_bus_write_config() are
>> called with bus number masked off in the parameter bdf, and bus
>> number is supposed to be added back in the bridge driver's pci
>> config read/write ops if the device is behind a pci bridge.
>> However this logic only works for a pci topology where there is
>> only one bridge off the root controller. If there is addtional
>> bridge in the system, the logic will create a non-existent bdf
>> where its bus number gets accumulated across bridges.
>>
>> To correct this, we change all pci config read/write routines
>> to use complete bdf all the way up to the root controller.
>>
>> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>> ---
>>
>>  drivers/pci/pci-uclass.c | 46 +++++++++++++++++++++++-----------------------
>>  1 file changed, 23 insertions(+), 23 deletions(-)
>
> Acked-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot-x86, thanks!
diff mbox

Patch

diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 5b91fe3..e92e4f3 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -199,8 +199,7 @@  int pci_write_config(pci_dev_t bdf, int offset, unsigned long value,
 	if (ret)
 		return ret;
 
-	return pci_bus_write_config(bus, PCI_MASK_BUS(bdf), offset, value,
-				    size);
+	return pci_bus_write_config(bus, bdf, offset, value, size);
 }
 
 int pci_write_config32(pci_dev_t bdf, int offset, u32 value)
@@ -239,8 +238,7 @@  int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep,
 	if (ret)
 		return ret;
 
-	return pci_bus_read_config(bus, PCI_MASK_BUS(bdf), offset, valuep,
-				   size);
+	return pci_bus_read_config(bus, bdf, offset, valuep, size);
 }
 
 int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep)
@@ -357,41 +355,43 @@  int pci_bind_bus_devices(struct udevice *bus)
 {
 	ulong vendor, device;
 	ulong header_type;
-	pci_dev_t devfn, end;
+	pci_dev_t bdf, end;
 	bool found_multi;
 	int ret;
 
 	found_multi = false;
-	end = PCI_DEVFN(PCI_MAX_PCI_DEVICES - 1, PCI_MAX_PCI_FUNCTIONS - 1);
-	for (devfn = PCI_DEVFN(0, 0); devfn < end; devfn += PCI_DEVFN(0, 1)) {
+	end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1,
+		      PCI_MAX_PCI_FUNCTIONS - 1);
+	for (bdf = PCI_BDF(bus->seq, 0, 0); bdf < end;
+	     bdf += PCI_BDF(0, 0, 1)) {
 		struct pci_child_platdata *pplat;
 		struct udevice *dev;
 		ulong class;
 
-		if (PCI_FUNC(devfn) && !found_multi)
+		if (PCI_FUNC(bdf) && !found_multi)
 			continue;
 		/* Check only the first access, we don't expect problems */
-		ret = pci_bus_read_config(bus, devfn, PCI_HEADER_TYPE,
+		ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE,
 					  &header_type, PCI_SIZE_8);
 		if (ret)
 			goto error;
-		pci_bus_read_config(bus, devfn, PCI_VENDOR_ID, &vendor,
+		pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor,
 				    PCI_SIZE_16);
 		if (vendor == 0xffff || vendor == 0x0000)
 			continue;
 
-		if (!PCI_FUNC(devfn))
+		if (!PCI_FUNC(bdf))
 			found_multi = header_type & 0x80;
 
 		debug("%s: bus %d/%s: found device %x, function %d\n", __func__,
-		      bus->seq, bus->name, PCI_DEV(devfn), PCI_FUNC(devfn));
-		pci_bus_read_config(bus, devfn, PCI_DEVICE_ID, &device,
+		      bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
+		pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device,
 				    PCI_SIZE_16);
-		pci_bus_read_config(bus, devfn, PCI_CLASS_DEVICE, &class,
+		pci_bus_read_config(bus, bdf, PCI_CLASS_DEVICE, &class,
 				    PCI_SIZE_16);
 
 		/* Find this device in the device tree */
-		ret = pci_bus_find_devfn(bus, devfn, &dev);
+		ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev);
 
 		/* If nothing in the device tree, bind a generic device */
 		if (ret == -ENODEV) {
@@ -399,7 +399,7 @@  int pci_bind_bus_devices(struct udevice *bus)
 			const char *drv;
 
 			sprintf(name, "pci_%x:%x.%x", bus->seq,
-				PCI_DEV(devfn), PCI_FUNC(devfn));
+				PCI_DEV(bdf), PCI_FUNC(bdf));
 			str = strdup(name);
 			if (!str)
 				return -ENOMEM;
@@ -412,7 +412,7 @@  int pci_bind_bus_devices(struct udevice *bus)
 
 		/* Update the platform data */
 		pplat = dev_get_parent_platdata(dev);
-		pplat->devfn = devfn;
+		pplat->devfn = PCI_MASK_BUS(bdf);
 		pplat->vendor = vendor;
 		pplat->device = device;
 		pplat->class = class;
@@ -583,20 +583,20 @@  static int pci_uclass_child_post_bind(struct udevice *dev)
 	return 0;
 }
 
-int pci_bridge_read_config(struct udevice *bus, pci_dev_t devfn, uint offset,
-			   ulong *valuep, enum pci_size_t size)
+static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf,
+				  uint offset, ulong *valuep,
+				  enum pci_size_t size)
 {
 	struct pci_controller *hose = bus->uclass_priv;
-	pci_dev_t bdf = PCI_ADD_BUS(bus->seq, devfn);
 
 	return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size);
 }
 
-int pci_bridge_write_config(struct udevice *bus, pci_dev_t devfn, uint offset,
-			    ulong value, enum pci_size_t size)
+static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf,
+				   uint offset, ulong value,
+				   enum pci_size_t size)
 {
 	struct pci_controller *hose = bus->uclass_priv;
-	pci_dev_t bdf = PCI_ADD_BUS(bus->seq, devfn);
 
 	return pci_bus_write_config(hose->ctlr, bdf, offset, value, size);
 }