diff mbox

[OpenWrt-Devel,6/6] bcm53xx: R8000 handle PEX8603 switch

Message ID 20150310033038.9542.63440.stgit@perseus.themaw.net
State Changes Requested
Delegated to: Rafał Miłecki
Headers show

Commit Message

Ian Kent March 10, 2015, 3:30 a.m. UTC
The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
it isn't configured during the bus scan the PCI layer goes crazy
trying to configure phantom devices.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
 .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
 2 files changed, 450 insertions(+)
 create mode 100644 target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch
 create mode 100644 target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch

Comments

Rafał Miłecki June 21, 2015, 5:19 p.m. UTC | #1
On 10 March 2015 at 04:30, Ian Kent <raven@themaw.net> wrote:
> The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
> it isn't configured during the bus scan the PCI layer goes crazy
> trying to configure phantom devices.

This is kind of magic for me.
Hauke: are you able to review this?
Ian Kent June 22, 2015, 12:51 a.m. UTC | #2
On Sun, 2015-06-21 at 19:19 +0200, Rafał Miłecki wrote:
> On 10 March 2015 at 04:30, Ian Kent <raven@themaw.net> wrote:
> > The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
> > it isn't configured during the bus scan the PCI layer goes crazy
> > trying to configure phantom devices.
> 
> This is kind of magic for me.
> Hauke: are you able to review this?

Yeah, it's a bridge so it needs upstream and downstream bus ids set but
the main issue is that it doesn't respond with appropriate return values
for non-existent devices.

I modelled the code on the corresponding source from the Broadcom SDK
file that this source was originally developed from (at least it
appeared to match).

I confirmed that PEX860X devices don't return proper return code from
another PEX driver, from the WRT1900 source I think, its been a while
now.

Ian
Hauke Mehrtens June 22, 2015, 8:10 a.m. UTC | #3
On 06/22/2015 02:51 AM, Ian Kent wrote:
> On Sun, 2015-06-21 at 19:19 +0200, Rafał Miłecki wrote:
>> On 10 March 2015 at 04:30, Ian Kent <raven@themaw.net> wrote:
>>> The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
>>> it isn't configured during the bus scan the PCI layer goes crazy
>>> trying to configure phantom devices.
>>
>> This is kind of magic for me.
>> Hauke: are you able to review this?
> 
> Yeah, it's a bridge so it needs upstream and downstream bus ids set but
> the main issue is that it doesn't respond with appropriate return values
> for non-existent devices.
> 
> I modelled the code on the corresponding source from the Broadcom SDK
> file that this source was originally developed from (at least it
> appeared to match).
> 
> I confirmed that PEX860X devices don't return proper return code from
> another PEX driver, from the WRT1900 source I think, its been a while
> now.
> 
> Ian

Hi,

I completely missed these patches, thanks for pointing me to them again.
I will try to review them in the net days. I already saw this code in
the vendor driver but did not add it because my devices did not use it.
We will change to a different PCIe driver with the next kernel in
OpenWrt, because Broadcom added a kernel for this PCIe core into the
mainline kernel. We should get it into this new driver. Then also some
people from Broadcom can review this.

Hauke
Rafał Miłecki June 22, 2015, 8:34 a.m. UTC | #4
On 22 June 2015 at 10:10, Hauke Mehrtens <hauke@hauke-m.de> wrote:
> On 06/22/2015 02:51 AM, Ian Kent wrote:
>> On Sun, 2015-06-21 at 19:19 +0200, Rafał Miłecki wrote:
>>> On 10 March 2015 at 04:30, Ian Kent <raven@themaw.net> wrote:
>>>> The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
>>>> it isn't configured during the bus scan the PCI layer goes crazy
>>>> trying to configure phantom devices.
>>>
>>> This is kind of magic for me.
>>> Hauke: are you able to review this?
>>
>> Yeah, it's a bridge so it needs upstream and downstream bus ids set but
>> the main issue is that it doesn't respond with appropriate return values
>> for non-existent devices.
>>
>> I modelled the code on the corresponding source from the Broadcom SDK
>> file that this source was originally developed from (at least it
>> appeared to match).
>>
>> I confirmed that PEX860X devices don't return proper return code from
>> another PEX driver, from the WRT1900 source I think, its been a while
>> now.
>>
>> Ian
>
> Hi,
>
> I completely missed these patches, thanks for pointing me to them again.
> I will try to review them in the net days. I already saw this code in
> the vendor driver but did not add it because my devices did not use it.
> We will change to a different PCIe driver with the next kernel in
> OpenWrt, because Broadcom added a kernel for this PCIe core into the
> mainline kernel. We should get it into this new driver. Then also some
> people from Broadcom can review this.

This would be nice to patch the old driver in CC branch. To get R8000
supported by CC.
Hauke Mehrtens June 22, 2015, 4:42 p.m. UTC | #5
On 03/10/2015 04:30 AM, Ian Kent wrote:
> The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
> it isn't configured during the bus scan the PCI layer goes crazy
> trying to configure phantom devices.

Could you provide some diagram how this is connected?

My current assumption is that on one of the 3 PCIe ports is this switch,
so the scan will find this switch as a PCIe device, bu how does it go
from there?
From the vendor driver I would assume that that the two devices behind
the switch are device function 0x08 and 0x10 on the switch device.

Can you also post the output of lspci on your device?

> 
> Signed-off-by: Ian Kent <raven@themaw.net>
> ---
>  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
>  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
>  2 files changed, 450 insertions(+)
>  create mode 100644 target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch
>  create mode 100644 target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> 


......


> diff --git a/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> new file mode 100644
> index 0000000..fc606b4
> --- /dev/null
> +++ b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> @@ -0,0 +1,225 @@
> +bcm53xx: R8000 handle PEX8603 switch
> +
> +The Netgear R8000 has a PEX8603 which, if not configured at
> +bus probe results in quite a few phantom devices as it doesn't
> +respond properly to configuration requests. The device needs
> +to be configured when seen.
> +
> +Signed-off-by: Ian Kent <raven@themaw.net>
> +
> +--- a/drivers/pci/host/pci-host-bcm5301x.c
> ++++ b/drivers/pci/host/pci-host-bcm5301x.c
> +@@ -29,6 +29,21 @@
> + #define PCI_TARGET_LINK_SPEED_GEN2    0x2
> + #define PCI_TARGET_LINK_SPEED_GEN1    0x1
> + 
> ++#define PCI_MAX_BUS			4
> ++#define PLX_PRIM_SEC_BUS_NUM		(0x00000201 | (PCI_MAX_BUS << 16))
> ++
> ++#ifndef SZ_48M
> ++#define SZ_48M	(SZ_32M + SZ_16M)
> ++#endif

Please remove the ifndef, it should fail if this gets added.


> ++
> ++struct pex86xx_info {
> ++	u8 busno;	/* Upstream bus PEX is on */
> ++	u8 slot;	/* Upstream slot PEX is at */
> ++	u16 active;	/* Active port count */
> ++	u16 ports;	/* Active port bit map */
> ++};
> ++struct pex86xx_info pex8603;
> ++
> + static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> + {
> + 	struct pci_sys_data *sys = pdev->sysdata;
> +@@ -115,6 +130,39 @@ static int bcma_pcie2_read_config_pci(st
> + 	struct pci_sys_data *sys = bus->sysdata;
> + 	struct bcma_device *bdev = sys->private_data;
> + 
> ++	/* The PEX8603 won't return sensible values to the PCI layer so
> ++	 * we have to do that ourselves.
> ++	 */
> ++	if (pex8603.busno) {
> ++		u16 slot = PCI_SLOT(devfn);
> ++
> ++		/* Not the PEX upstream slot */
> ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> ++			goto done;
> ++
> ++		/* Not the PEX downstream bus? */
> ++		if (bus->number < pex8603.busno ||
> ++		    bus->number > pex8603.busno + 1)
> ++			goto done;
> ++
> ++		switch (bus->number - pex8603.busno) {
> ++		case 0:
> ++			/* Upstream port */
> ++			break;
> ++
> ++		case 1:
> ++			/* PEX8603, not present for slots other than 1 or 2 */
> ++			if (!(slot == 1 || slot == 2)) {
> ++				*val = 0xffffffff;
> ++				return PCIBIOS_SUCCESSFUL;
> ++			}
> ++			break;
> ++
> ++		default:
> ++			break;
> ++		}
> ++	}
> ++done:
> + 	*val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size);
> + 
> + 	return PCIBIOS_SUCCESSFUL;
> +@@ -126,6 +174,37 @@ static int bcma_pcie2_write_config_pci(s
> + 	struct pci_sys_data *sys = bus->sysdata;
> + 	struct bcma_device *bdev = sys->private_data;
> + 
> ++	/* Don't try and set anything on the PEX8603 if it isn't
> ++	 * valid.
> ++	 */
> ++	if (pex8603.busno) {
> ++		u16 slot = PCI_SLOT(devfn);
> ++
> ++		/* Not the PEX upstream slot */
> ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> ++			goto done;
> ++
> ++		/* Not the PEX downstream bus? */
> ++		if (bus->number < pex8603.busno ||
> ++		    bus->number > pex8603.busno + 1)
> ++			goto done;
> ++
> ++		switch (bus->number - pex8603.busno) {
> ++		case 0:
> ++			/* Upstream port */
> ++			break;
> ++
> ++		case 1:
> ++			/* PEX8603 slots only slots 1 and 2 present */
> ++			if (!(slot == 1 || slot == 2))
> ++				return PCIBIOS_SUCCESSFUL;
> ++			break;
> ++
> ++		default:
> ++			break;
> ++		}
> ++	}
> ++done:
> + 	bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val);
> + 
> + 	return PCIBIOS_SUCCESSFUL;
> +@@ -147,6 +226,113 @@ static void bcma_pcie2_fixup_class(struc
> + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class);
> + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class);
> + 
> ++static void bcma_pcie2_pex_switch_setup(struct pci_dev *dev)
> ++{
> ++	struct pci_sys_data *sys = dev->sysdata;
> ++	struct bcma_device *bdev = sys->private_data;
> ++	unsigned char busno = dev->bus->number;
> ++	unsigned int devfn = dev->devfn;
> ++	unsigned int slot = PCI_SLOT(devfn);
> ++	u32 addr = bdev->addr_s[0];
> ++	u32 tmp32;
> ++	u16 tmp16;
> ++
> ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x100, 4);
> ++	if (!tmp32) {
> ++		dev_info(&bdev->dev, "failed to read PEX switch\n");
> ++		return;
> ++	}
> ++
> ++	/* Debug control register. */
> ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x1dc, 4);
> ++	tmp32 &= ~(1<<22);
> ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x1dc, 4, tmp32);
> ++
> ++	/* Set GPIO enable. */
> ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x62c, 4);
> ++	tmp32 &= ~((1 << 0) | (1 << 1) | (1 << 3));
> ++	tmp32 |= ((1 << 4) | (1 << 5) | (1 << 7));
> ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> ++
> ++	mdelay(50);

You should use msleep(50) here.

> ++
> ++	tmp32 |= ((1<<0)|(1<<1));
> ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> ++
> ++	/* Bus master */
> ++	tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x4, 2);
> ++	tmp16 |= 0x06;
> ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x4, 2, tmp16);
> ++
> ++	switch (slot) {

Are you sure this is correct?

Why does the vendor driver use the bus number and afterwards the device
function for the last two spaces and you are using only the slot number?

> ++	case 0:
> ++		/* Upstream port busno and slot */
> ++		pex8603.busno = busno;
> ++		pex8603.slot = slot;
> ++
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, 0x18, 4, PLX_PRIM_SEC_BUS_NUM);
> ++
> ++		/* TODO: We need to scan all outgoing windows,
> ++		 * to look for a base limit pair for this register.
> ++		 */
> ++		/* MEM_BASE, MEM_LIM require 1MB alignment */
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_BASE, 2,
> ++					addr >> 16);
> ++		BUG_ON(((addr + SZ_32M) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_LIMIT, 2,
> ++					(addr + SZ_32M) >> 16);
> ++		break;
> ++
> ++	case 1:
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, 0x18, 4,
> ++					(((busno + slot) << 16) |
> ++					 ((busno + slot) << 8) | busno));
> ++		BUG_ON(((addr + SZ_48M) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_BASE, 4,
> ++					(addr + SZ_48M) >> 16);
> ++		BUG_ON(((addr + SZ_48M + SZ_32M) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_LIMIT, 4,
> ++					(addr + SZ_48M + SZ_32M) >> 16);
> ++
> ++		/* Mark port bit number as active if successful */
> ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> ++			pex8603.active++;
> ++		}
> ++		break;
> ++
> ++	case 2:
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, 0x18, 4,
> ++					(((busno + slot) << 16) |
> ++					 ((busno + slot) << 8) | busno));
> ++		BUG_ON(((addr + (SZ_48M * 2)) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_BASE, 4,
> ++					(addr + (SZ_48M * 2)) >> 16);
> ++		BUG_ON(((addr + (SZ_48M * 2) + SZ_32M) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_LIMIT, 4,
> ++					(addr + (SZ_48M * 2) + SZ_32M) >> 16);
> ++
> ++		/* Mark port bit number as active if successful */
> ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> ++			pex8603.active++;
> ++		}
> ++		break;
> ++	}
> ++}
> ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8603, bcma_pcie2_pex_switch_setup);
> ++
> + /*
> +  * Check link status, return 0 if link is up in RC mode,
> +  * otherwise return non-zero
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
>
Ian Kent June 22, 2015, 11:58 p.m. UTC | #6
On Mon, 2015-06-22 at 18:42 +0200, Hauke Mehrtens wrote:
> 
> On 03/10/2015 04:30 AM, Ian Kent wrote:
> > The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
> > it isn't configured during the bus scan the PCI layer goes crazy
> > trying to configure phantom devices.
> 
> Could you provide some diagram how this is connected?

I could try, when I get a chance, ascii art isn't my strong suit.

> 
> My current assumption is that on one of the 3 PCIe ports is this switch,
> so the scan will find this switch as a PCIe device, bu how does it go
> from there?

I can only infer from looking at sysfs, which is what I have done.

Perhaps I'm not correct but it looks to me that there are is a BCM53012
connected with two legs, one has one wireless device, and the other has
a PEX8603 bridge which has two legs, each with a wireless device.

> From the vendor driver I would assume that that the two devices behind
> the switch are device function 0x08 and 0x10 on the switch device.

I'll have to reacquaint myself with the code before I respond to the
comments below, its been a while.
 
> 
> Can you also post the output of lspci on your device?

Don't think I have lspci in the build I was using, I'll need to add it
and rebuild. That probably won't be until the weekend.

> 
> > 
> > Signed-off-by: Ian Kent <raven@themaw.net>
> > ---
> >  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
> >  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
> >  2 files changed, 450 insertions(+)
> >  create mode 100644 target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> >  create mode 100644 target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > 
> 
> 
> ......
> 
> 
> > diff --git a/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > new file mode 100644
> > index 0000000..fc606b4
> > --- /dev/null
> > +++ b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > @@ -0,0 +1,225 @@
> > +bcm53xx: R8000 handle PEX8603 switch
> > +
> > +The Netgear R8000 has a PEX8603 which, if not configured at
> > +bus probe results in quite a few phantom devices as it doesn't
> > +respond properly to configuration requests. The device needs
> > +to be configured when seen.
> > +
> > +Signed-off-by: Ian Kent <raven@themaw.net>
> > +
> > +--- a/drivers/pci/host/pci-host-bcm5301x.c
> > ++++ b/drivers/pci/host/pci-host-bcm5301x.c
> > +@@ -29,6 +29,21 @@
> > + #define PCI_TARGET_LINK_SPEED_GEN2    0x2
> > + #define PCI_TARGET_LINK_SPEED_GEN1    0x1
> > + 
> > ++#define PCI_MAX_BUS			4
> > ++#define PLX_PRIM_SEC_BUS_NUM		(0x00000201 | (PCI_MAX_BUS << 16))
> > ++
> > ++#ifndef SZ_48M
> > ++#define SZ_48M	(SZ_32M + SZ_16M)
> > ++#endif
> 
> Please remove the ifndef, it should fail if this gets added.
> 
> 
> > ++
> > ++struct pex86xx_info {
> > ++	u8 busno;	/* Upstream bus PEX is on */
> > ++	u8 slot;	/* Upstream slot PEX is at */
> > ++	u16 active;	/* Active port count */
> > ++	u16 ports;	/* Active port bit map */
> > ++};
> > ++struct pex86xx_info pex8603;
> > ++
> > + static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> > + {
> > + 	struct pci_sys_data *sys = pdev->sysdata;
> > +@@ -115,6 +130,39 @@ static int bcma_pcie2_read_config_pci(st
> > + 	struct pci_sys_data *sys = bus->sysdata;
> > + 	struct bcma_device *bdev = sys->private_data;
> > + 
> > ++	/* The PEX8603 won't return sensible values to the PCI layer so
> > ++	 * we have to do that ourselves.
> > ++	 */
> > ++	if (pex8603.busno) {
> > ++		u16 slot = PCI_SLOT(devfn);
> > ++
> > ++		/* Not the PEX upstream slot */
> > ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> > ++			goto done;
> > ++
> > ++		/* Not the PEX downstream bus? */
> > ++		if (bus->number < pex8603.busno ||
> > ++		    bus->number > pex8603.busno + 1)
> > ++			goto done;
> > ++
> > ++		switch (bus->number - pex8603.busno) {
> > ++		case 0:
> > ++			/* Upstream port */
> > ++			break;
> > ++
> > ++		case 1:
> > ++			/* PEX8603, not present for slots other than 1 or 2 */
> > ++			if (!(slot == 1 || slot == 2)) {
> > ++				*val = 0xffffffff;
> > ++				return PCIBIOS_SUCCESSFUL;
> > ++			}
> > ++			break;
> > ++
> > ++		default:
> > ++			break;
> > ++		}
> > ++	}
> > ++done:
> > + 	*val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size);
> > + 
> > + 	return PCIBIOS_SUCCESSFUL;
> > +@@ -126,6 +174,37 @@ static int bcma_pcie2_write_config_pci(s
> > + 	struct pci_sys_data *sys = bus->sysdata;
> > + 	struct bcma_device *bdev = sys->private_data;
> > + 
> > ++	/* Don't try and set anything on the PEX8603 if it isn't
> > ++	 * valid.
> > ++	 */
> > ++	if (pex8603.busno) {
> > ++		u16 slot = PCI_SLOT(devfn);
> > ++
> > ++		/* Not the PEX upstream slot */
> > ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> > ++			goto done;
> > ++
> > ++		/* Not the PEX downstream bus? */
> > ++		if (bus->number < pex8603.busno ||
> > ++		    bus->number > pex8603.busno + 1)
> > ++			goto done;
> > ++
> > ++		switch (bus->number - pex8603.busno) {
> > ++		case 0:
> > ++			/* Upstream port */
> > ++			break;
> > ++
> > ++		case 1:
> > ++			/* PEX8603 slots only slots 1 and 2 present */
> > ++			if (!(slot == 1 || slot == 2))
> > ++				return PCIBIOS_SUCCESSFUL;
> > ++			break;
> > ++
> > ++		default:
> > ++			break;
> > ++		}
> > ++	}
> > ++done:
> > + 	bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val);
> > + 
> > + 	return PCIBIOS_SUCCESSFUL;
> > +@@ -147,6 +226,113 @@ static void bcma_pcie2_fixup_class(struc
> > + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class);
> > + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class);
> > + 
> > ++static void bcma_pcie2_pex_switch_setup(struct pci_dev *dev)
> > ++{
> > ++	struct pci_sys_data *sys = dev->sysdata;
> > ++	struct bcma_device *bdev = sys->private_data;
> > ++	unsigned char busno = dev->bus->number;
> > ++	unsigned int devfn = dev->devfn;
> > ++	unsigned int slot = PCI_SLOT(devfn);
> > ++	u32 addr = bdev->addr_s[0];
> > ++	u32 tmp32;
> > ++	u16 tmp16;
> > ++
> > ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x100, 4);
> > ++	if (!tmp32) {
> > ++		dev_info(&bdev->dev, "failed to read PEX switch\n");
> > ++		return;
> > ++	}
> > ++
> > ++	/* Debug control register. */
> > ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x1dc, 4);
> > ++	tmp32 &= ~(1<<22);
> > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x1dc, 4, tmp32);
> > ++
> > ++	/* Set GPIO enable. */
> > ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x62c, 4);
> > ++	tmp32 &= ~((1 << 0) | (1 << 1) | (1 << 3));
> > ++	tmp32 |= ((1 << 4) | (1 << 5) | (1 << 7));
> > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> > ++
> > ++	mdelay(50);
> 
> You should use msleep(50) here.
> 
> > ++
> > ++	tmp32 |= ((1<<0)|(1<<1));
> > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> > ++
> > ++	/* Bus master */
> > ++	tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x4, 2);
> > ++	tmp16 |= 0x06;
> > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x4, 2, tmp16);
> > ++
> > ++	switch (slot) {
> 
> Are you sure this is correct?
> 
> Why does the vendor driver use the bus number and afterwards the device
> function for the last two spaces and you are using only the slot number?
> 
> > ++	case 0:
> > ++		/* Upstream port busno and slot */
> > ++		pex8603.busno = busno;
> > ++		pex8603.slot = slot;
> > ++
> > ++		bcma_pcie2_write_config(bdev, busno,
> > ++					devfn, 0x18, 4, PLX_PRIM_SEC_BUS_NUM);
> > ++
> > ++		/* TODO: We need to scan all outgoing windows,
> > ++		 * to look for a base limit pair for this register.
> > ++		 */
> > ++		/* MEM_BASE, MEM_LIM require 1MB alignment */
> > ++		bcma_pcie2_write_config(bdev, busno,
> > ++					devfn, PCI_MEMORY_BASE, 2,
> > ++					addr >> 16);
> > ++		BUG_ON(((addr + SZ_32M) >> 16) & 0xf);
> > ++		bcma_pcie2_write_config(bdev, busno,
> > ++					devfn, PCI_MEMORY_LIMIT, 2,
> > ++					(addr + SZ_32M) >> 16);
> > ++		break;
> > ++
> > ++	case 1:
> > ++		bcma_pcie2_write_config(bdev, busno,
> > ++					devfn, 0x18, 4,
> > ++					(((busno + slot) << 16) |
> > ++					 ((busno + slot) << 8) | busno));
> > ++		BUG_ON(((addr + SZ_48M) >> 16) & 0xf);
> > ++		bcma_pcie2_write_config(bdev, busno,
> > ++					devfn, PCI_MEMORY_BASE, 4,
> > ++					(addr + SZ_48M) >> 16);
> > ++		BUG_ON(((addr + SZ_48M + SZ_32M) >> 16) & 0xf);
> > ++		bcma_pcie2_write_config(bdev, busno,
> > ++					devfn, PCI_MEMORY_LIMIT, 4,
> > ++					(addr + SZ_48M + SZ_32M) >> 16);
> > ++
> > ++		/* Mark port bit number as active if successful */
> > ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> > ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> > ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> > ++			pex8603.active++;
> > ++		}
> > ++		break;
> > ++
> > ++	case 2:
> > ++		bcma_pcie2_write_config(bdev, busno,
> > ++					devfn, 0x18, 4,
> > ++					(((busno + slot) << 16) |
> > ++					 ((busno + slot) << 8) | busno));
> > ++		BUG_ON(((addr + (SZ_48M * 2)) >> 16) & 0xf);
> > ++		bcma_pcie2_write_config(bdev, busno,
> > ++					devfn, PCI_MEMORY_BASE, 4,
> > ++					(addr + (SZ_48M * 2)) >> 16);
> > ++		BUG_ON(((addr + (SZ_48M * 2) + SZ_32M) >> 16) & 0xf);
> > ++		bcma_pcie2_write_config(bdev, busno,
> > ++					devfn, PCI_MEMORY_LIMIT, 4,
> > ++					(addr + (SZ_48M * 2) + SZ_32M) >> 16);
> > ++
> > ++		/* Mark port bit number as active if successful */
> > ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> > ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> > ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> > ++			pex8603.active++;
> > ++		}
> > ++		break;
> > ++	}
> > ++}
> > ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8603, bcma_pcie2_pex_switch_setup);
> > ++
> > + /*
> > +  * Check link status, return 0 if link is up in RC mode,
> > +  * otherwise return non-zero
> > _______________________________________________
> > openwrt-devel mailing list
> > openwrt-devel@lists.openwrt.org
> > https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
> >
Ian Kent June 28, 2015, 3:37 a.m. UTC | #7
On Tue, 2015-06-23 at 07:58 +0800, Ian Kent wrote:
> On Mon, 2015-06-22 at 18:42 +0200, Hauke Mehrtens wrote:
> > 
> > On 03/10/2015 04:30 AM, Ian Kent wrote:
> > > The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
> > > it isn't configured during the bus scan the PCI layer goes crazy
> > > trying to configure phantom devices.
> > 
> > Could you provide some diagram how this is connected?
> 
> I could try, when I get a chance, ascii art isn't my strong suit.
> 
> > 
> > My current assumption is that on one of the 3 PCIe ports is this switch,
> > so the scan will find this switch as a PCIe device, bu how does it go
> > from there?
> 
> I can only infer from looking at sysfs, which is what I have done.
> 
> Perhaps I'm not correct but it looks to me that there are is a BCM53012
> connected with two legs, one has one wireless device, and the other has
> a PEX8603 bridge which has two legs, each with a wireless device.

I still think this is the correct topology and IIRC that was also
inferred by looking at sysfs with vendor firmware installed. But maybe
my recollection fails me, I'll need to check.

> 
> > From the vendor driver I would assume that that the two devices behind
> > the switch are device function 0x08 and 0x10 on the switch device.
> 
> I'll have to reacquaint myself with the code before I respond to the
> comments below, its been a while.

Yes, looking at the code again they are "upstream port bus number + 1,
devfn 0x08 (aka. slot 1)" and "upstream port bus number + 2, devfn 0x10
(aka. slot 2)" so the slot number can't be used alone.

>  
> > 
> > Can you also post the output of lspci on your device?
> 
> Don't think I have lspci in the build I was using, I'll need to add it
> and rebuild. That probably won't be until the weekend.

I'll get this when the ncurses build breakage is fixed or perhaps by
deselecting ncurses dependencies if it takes too long for it to be
fixed.

> 
> > 
> > > 
> > > Signed-off-by: Ian Kent <raven@themaw.net>
> > > ---
> > >  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
> > >  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
> > >  2 files changed, 450 insertions(+)
> > >  create mode 100644 target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > >  create mode 100644 target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > > 
> > 
> > 
> > ......
> > 
> > 
> > > diff --git a/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > > new file mode 100644
> > > index 0000000..fc606b4
> > > --- /dev/null
> > > +++ b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > > @@ -0,0 +1,225 @@
> > > +bcm53xx: R8000 handle PEX8603 switch
> > > +
> > > +The Netgear R8000 has a PEX8603 which, if not configured at
> > > +bus probe results in quite a few phantom devices as it doesn't
> > > +respond properly to configuration requests. The device needs
> > > +to be configured when seen.
> > > +
> > > +Signed-off-by: Ian Kent <raven@themaw.net>
> > > +
> > > +--- a/drivers/pci/host/pci-host-bcm5301x.c
> > > ++++ b/drivers/pci/host/pci-host-bcm5301x.c
> > > +@@ -29,6 +29,21 @@
> > > + #define PCI_TARGET_LINK_SPEED_GEN2    0x2
> > > + #define PCI_TARGET_LINK_SPEED_GEN1    0x1
> > > + 
> > > ++#define PCI_MAX_BUS			4
> > > ++#define PLX_PRIM_SEC_BUS_NUM		(0x00000201 | (PCI_MAX_BUS << 16))
> > > ++
> > > ++#ifndef SZ_48M
> > > ++#define SZ_48M	(SZ_32M + SZ_16M)
> > > ++#endif
> > 
> > Please remove the ifndef, it should fail if this gets added.

OK, I put the conditional in thinking this might be added to
linux/sizes.h at some point but looking at sizes.h again we probably
won't see the 48 variant being added.

> > 
> > 
> > > ++
> > > ++struct pex86xx_info {
> > > ++	u8 busno;	/* Upstream bus PEX is on */
> > > ++	u8 slot;	/* Upstream slot PEX is at */
> > > ++	u16 active;	/* Active port count */
> > > ++	u16 ports;	/* Active port bit map */
> > > ++};
> > > ++struct pex86xx_info pex8603;
> > > ++
> > > + static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> > > + {
> > > + 	struct pci_sys_data *sys = pdev->sysdata;
> > > +@@ -115,6 +130,39 @@ static int bcma_pcie2_read_config_pci(st
> > > + 	struct pci_sys_data *sys = bus->sysdata;
> > > + 	struct bcma_device *bdev = sys->private_data;
> > > + 
> > > ++	/* The PEX8603 won't return sensible values to the PCI layer so
> > > ++	 * we have to do that ourselves.
> > > ++	 */
> > > ++	if (pex8603.busno) {
> > > ++		u16 slot = PCI_SLOT(devfn);
> > > ++
> > > ++		/* Not the PEX upstream slot */
> > > ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> > > ++			goto done;
> > > ++
> > > ++		/* Not the PEX downstream bus? */
> > > ++		if (bus->number < pex8603.busno ||
> > > ++		    bus->number > pex8603.busno + 1)
> > > ++			goto done;
> > > ++
> > > ++		switch (bus->number - pex8603.busno) {
> > > ++		case 0:
> > > ++			/* Upstream port */
> > > ++			break;
> > > ++
> > > ++		case 1:
> > > ++			/* PEX8603, not present for slots other than 1 or 2 */
> > > ++			if (!(slot == 1 || slot == 2)) {
> > > ++				*val = 0xffffffff;
> > > ++				return PCIBIOS_SUCCESSFUL;
> > > ++			}
> > > ++			break;
> > > ++
> > > ++		default:
> > > ++			break;
> > > ++		}
> > > ++	}
> > > ++done:
> > > + 	*val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size);
> > > + 
> > > + 	return PCIBIOS_SUCCESSFUL;
> > > +@@ -126,6 +174,37 @@ static int bcma_pcie2_write_config_pci(s
> > > + 	struct pci_sys_data *sys = bus->sysdata;
> > > + 	struct bcma_device *bdev = sys->private_data;
> > > + 
> > > ++	/* Don't try and set anything on the PEX8603 if it isn't
> > > ++	 * valid.
> > > ++	 */
> > > ++	if (pex8603.busno) {
> > > ++		u16 slot = PCI_SLOT(devfn);
> > > ++
> > > ++		/* Not the PEX upstream slot */
> > > ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> > > ++			goto done;
> > > ++
> > > ++		/* Not the PEX downstream bus? */
> > > ++		if (bus->number < pex8603.busno ||
> > > ++		    bus->number > pex8603.busno + 1)
> > > ++			goto done;
> > > ++
> > > ++		switch (bus->number - pex8603.busno) {
> > > ++		case 0:
> > > ++			/* Upstream port */
> > > ++			break;
> > > ++
> > > ++		case 1:
> > > ++			/* PEX8603 slots only slots 1 and 2 present */
> > > ++			if (!(slot == 1 || slot == 2))
> > > ++				return PCIBIOS_SUCCESSFUL;
> > > ++			break;
> > > ++
> > > ++		default:
> > > ++			break;
> > > ++		}
> > > ++	}
> > > ++done:
> > > + 	bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val);
> > > + 
> > > + 	return PCIBIOS_SUCCESSFUL;
> > > +@@ -147,6 +226,113 @@ static void bcma_pcie2_fixup_class(struc
> > > + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class);
> > > + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class);
> > > + 
> > > ++static void bcma_pcie2_pex_switch_setup(struct pci_dev *dev)
> > > ++{
> > > ++	struct pci_sys_data *sys = dev->sysdata;
> > > ++	struct bcma_device *bdev = sys->private_data;
> > > ++	unsigned char busno = dev->bus->number;
> > > ++	unsigned int devfn = dev->devfn;
> > > ++	unsigned int slot = PCI_SLOT(devfn);
> > > ++	u32 addr = bdev->addr_s[0];
> > > ++	u32 tmp32;
> > > ++	u16 tmp16;
> > > ++
> > > ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x100, 4);
> > > ++	if (!tmp32) {
> > > ++		dev_info(&bdev->dev, "failed to read PEX switch\n");
> > > ++		return;
> > > ++	}
> > > ++
> > > ++	/* Debug control register. */
> > > ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x1dc, 4);
> > > ++	tmp32 &= ~(1<<22);
> > > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x1dc, 4, tmp32);
> > > ++
> > > ++	/* Set GPIO enable. */
> > > ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x62c, 4);
> > > ++	tmp32 &= ~((1 << 0) | (1 << 1) | (1 << 3));
> > > ++	tmp32 |= ((1 << 4) | (1 << 5) | (1 << 7));
> > > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> > > ++
> > > ++	mdelay(50);
> > 
> > You should use msleep(50) here.

Will do.

> > 
> > > ++
> > > ++	tmp32 |= ((1<<0)|(1<<1));
> > > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> > > ++
> > > ++	/* Bus master */
> > > ++	tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x4, 2);
> > > ++	tmp16 |= 0x06;
> > > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x4, 2, tmp16);
> > > ++
> > > ++	switch (slot) {
> > 
> > Are you sure this is correct?

Looking at this again, I think it isn't correct at all.

This is the first time I've looked at the PCI subsystem so I'm not
surprised I've made mistakes, fortunately you noticed something looked
wrong.  

> > 
> > Why does the vendor driver use the bus number and afterwards the device
> > function for the last two spaces and you are using only the slot number?

I think my usage causes initialization settings to be applied multiple
times most of which end with incorrect settings for the bridge. There
are other problems with it too.

I don't think the domain number can (should) be used to derive the
upstream port bus number as it is in the vendor code because it assumes
a topology of earlier connected devices that might not always be
accurate.

But I think the first time this function is called it will always be
called with the upstream bus number that's needed, due to the
enumeration that's being done, so I believe I can use that.

Let me rework this using the bus number as you recommend.
I'll repost my updated patch series once I've done that.

Thanks for reviewing the patch.
Ian
 
> > 
> > > ++	case 0:
> > > ++		/* Upstream port busno and slot */
> > > ++		pex8603.busno = busno;
> > > ++		pex8603.slot = slot;
> > > ++
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, 0x18, 4, PLX_PRIM_SEC_BUS_NUM);
> > > ++
> > > ++		/* TODO: We need to scan all outgoing windows,
> > > ++		 * to look for a base limit pair for this register.
> > > ++		 */
> > > ++		/* MEM_BASE, MEM_LIM require 1MB alignment */
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_BASE, 2,
> > > ++					addr >> 16);
> > > ++		BUG_ON(((addr + SZ_32M) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_LIMIT, 2,
> > > ++					(addr + SZ_32M) >> 16);
> > > ++		break;
> > > ++
> > > ++	case 1:
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, 0x18, 4,
> > > ++					(((busno + slot) << 16) |
> > > ++					 ((busno + slot) << 8) | busno));
> > > ++		BUG_ON(((addr + SZ_48M) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_BASE, 4,
> > > ++					(addr + SZ_48M) >> 16);
> > > ++		BUG_ON(((addr + SZ_48M + SZ_32M) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_LIMIT, 4,
> > > ++					(addr + SZ_48M + SZ_32M) >> 16);
> > > ++
> > > ++		/* Mark port bit number as active if successful */
> > > ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> > > ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> > > ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> > > ++			pex8603.active++;
> > > ++		}
> > > ++		break;
> > > ++
> > > ++	case 2:
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, 0x18, 4,
> > > ++					(((busno + slot) << 16) |
> > > ++					 ((busno + slot) << 8) | busno));
> > > ++		BUG_ON(((addr + (SZ_48M * 2)) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_BASE, 4,
> > > ++					(addr + (SZ_48M * 2)) >> 16);
> > > ++		BUG_ON(((addr + (SZ_48M * 2) + SZ_32M) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_LIMIT, 4,
> > > ++					(addr + (SZ_48M * 2) + SZ_32M) >> 16);
> > > ++
> > > ++		/* Mark port bit number as active if successful */
> > > ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> > > ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> > > ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> > > ++			pex8603.active++;
> > > ++		}
> > > ++		break;
> > > ++	}
> > > ++}
> > > ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8603, bcma_pcie2_pex_switch_setup);
> > > ++
> > > + /*
> > > +  * Check link status, return 0 if link is up in RC mode,
> > > +  * otherwise return non-zero
> > > _______________________________________________
> > > openwrt-devel mailing list
> > > openwrt-devel@lists.openwrt.org
> > > https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
> > > 
>
Rafał Miłecki July 14, 2015, 4:19 p.m. UTC | #8
On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
> Let me rework this using the bus number as you recommend.
> I'll repost my updated patch series once I've done that.

Hi Ian,

Is there any chance you'll find a moment for it anytime soon? It'd be
awesome to get R8000 support for CC release.
Ian Kent July 15, 2015, 10:11 a.m. UTC | #9
On Tue, 2015-07-14 at 18:19 +0200, Rafał Miłecki wrote:
> On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
> > Let me rework this using the bus number as you recommend.
> > I'll repost my updated patch series once I've done that.
> 
> Hi Ian,
> 
> Is there any chance you'll find a moment for it anytime soon? It'd be
> awesome to get R8000 support for CC release.

I have reworked the patch and a broken package build problem I had is
gone but I didn't get time to fix build problems with a third patch I
have.

Just didn't get time last weekend and this week has been quite busy too.
I'll try and get onto this in the next few days.

Ian
Rafał Miłecki July 30, 2015, 6:59 a.m. UTC | #10
On 15 July 2015 at 12:11, Ian Kent <raven@themaw.net> wrote:
> On Tue, 2015-07-14 at 18:19 +0200, Rafał Miłecki wrote:
>> On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
>> > Let me rework this using the bus number as you recommend.
>> > I'll repost my updated patch series once I've done that.
>>
>> Hi Ian,
>>
>> Is there any chance you'll find a moment for it anytime soon? It'd be
>> awesome to get R8000 support for CC release.
>
> I have reworked the patch and a broken package build problem I had is
> gone but I didn't get time to fix build problems with a third patch I
> have.
>
> Just didn't get time last weekend and this week has been quite busy too.
> I'll try and get onto this in the next few days.

Ping, guys? :) Is this initial Ian's patch acceptable to pick it for
CC release since we don't really seem to have time to improve it?
Hauke Mehrtens Aug. 12, 2015, 8:01 p.m. UTC | #11
On 07/15/2015 12:11 PM, Ian Kent wrote:
> On Tue, 2015-07-14 at 18:19 +0200, Rafał Miłecki wrote:
>> On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
>>> Let me rework this using the bus number as you recommend.
>>> I'll repost my updated patch series once I've done that.
>>
>> Hi Ian,
>>
>> Is there any chance you'll find a moment for it anytime soon? It'd be
>> awesome to get R8000 support for CC release.
> 
> I have reworked the patch and a broken package build problem I had is
> gone but I didn't get time to fix build problems with a third patch I
> have.
> 
> Just didn't get time last weekend and this week has been quite busy too.
> I'll try and get onto this in the next few days.
> 
> Ian

Hi Ian,

you patch looks better than the hack Broadcom did in their vendor driver.

Could you send me a lspci output or the content of /proc/bus/pci/devices
of the original firmware or of OpenWrt with your patch applied? I would
prefer lspci because it is easier to read but cat from
/proc/bus/pci/devices also works. I do not have such a device and want
to understand how this PCIe switch looks like on the software side, so
we can fix the domain, bus, slot, function mixup.

On the hardware side this SoC has 3 PCIe controllers, but one shares a
PHY with the USB 3.0 controller. Instead of using the 3rd PCIe
controller they used USB 3.0 and split one of the PCIe controllers into
2 PCIE lanes.

If someone else has an Netgear R8000 or any other device with this PCIe
switch also feel free to send some information about the PCIe switch.

Hauke
Ian Kent Aug. 14, 2015, 4:03 a.m. UTC | #12
On Wed, 2015-08-12 at 22:01 +0200, Hauke Mehrtens wrote:
> On 07/15/2015 12:11 PM, Ian Kent wrote:
> > On Tue, 2015-07-14 at 18:19 +0200, Rafał Miłecki wrote:
> >> On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
> >>> Let me rework this using the bus number as you recommend.
> >>> I'll repost my updated patch series once I've done that.
> >>
> >> Hi Ian,
> >>
> >> Is there any chance you'll find a moment for it anytime soon? It'd be
> >> awesome to get R8000 support for CC release.
> > 
> > I have reworked the patch and a broken package build problem I had is
> > gone but I didn't get time to fix build problems with a third patch I
> > have.
> > 
> > Just didn't get time last weekend and this week has been quite busy too.
> > I'll try and get onto this in the next few days.
> > 
> > Ian
> 
> Hi Ian,
> 
> you patch looks better than the hack Broadcom did in their vendor driver.

I thought so, ;)

> 
> Could you send me a lspci output or the content of /proc/bus/pci/devices
> of the original firmware or of OpenWrt with your patch applied? I would
> prefer lspci because it is easier to read but cat from
> /proc/bus/pci/devices also works. I do not have such a device and want
> to understand how this PCIe switch looks like on the software side, so
> we can fix the domain, bus, slot, function mixup.

I haven't been able to build OpenWrt for a while now and that's why I
haven't been able to test my changes to the patch.

I really wish we could avoid committing changes that don't build but I
know it isn't that simple.

I have got some other lists (around somewhere) based on output, mostly
from the Vendor firmware, and one where I went through the devices and
listed what they are along with and their pci ids so I could try and
understand what was going on.

I could try and find that and post it if it would be useful.
Note that it was just used to understand what was what so it isn't
pretty but should have quite a bit of info in it.

There's no question the current patch is wrong so I don't recommend it
be used.

I can however post my updated patch now on the understanding that it
hasn't been tested at all, which might be good for initial review
anyway.

> 
> On the hardware side this SoC has 3 PCIe controllers, but one shares a
> PHY with the USB 3.0 controller. Instead of using the 3rd PCIe
> controller they used USB 3.0 and split one of the PCIe controllers into
> 2 PCIE lanes.

Right, I didn't get that, mmm ...

Ian
Hauke Mehrtens Aug. 14, 2015, 5:55 p.m. UTC | #13
On 08/14/2015 06:03 AM, Ian Kent wrote:
> On Wed, 2015-08-12 at 22:01 +0200, Hauke Mehrtens wrote:
>> On 07/15/2015 12:11 PM, Ian Kent wrote:
>>> On Tue, 2015-07-14 at 18:19 +0200, Rafał Miłecki wrote:
>>>> On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
>>>>> Let me rework this using the bus number as you recommend.
>>>>> I'll repost my updated patch series once I've done that.
>>>>
>>>> Hi Ian,
>>>>
>>>> Is there any chance you'll find a moment for it anytime soon? It'd be
>>>> awesome to get R8000 support for CC release.
>>>
>>> I have reworked the patch and a broken package build problem I had is
>>> gone but I didn't get time to fix build problems with a third patch I
>>> have.
>>>
>>> Just didn't get time last weekend and this week has been quite busy too.
>>> I'll try and get onto this in the next few days.
>>>
>>> Ian
>>
>> Hi Ian,
>>
>> you patch looks better than the hack Broadcom did in their vendor driver.
> 
> I thought so, ;)
> 
>>
>> Could you send me a lspci output or the content of /proc/bus/pci/devices
>> of the original firmware or of OpenWrt with your patch applied? I would
>> prefer lspci because it is easier to read but cat from
>> /proc/bus/pci/devices also works. I do not have such a device and want
>> to understand how this PCIe switch looks like on the software side, so
>> we can fix the domain, bus, slot, function mixup.
> 
> I haven't been able to build OpenWrt for a while now and that's why I
> haven't been able to test my changes to the patch.

I haven't noticed a problem in the OpenWrt build system, do you still
have this problem? Have you tried to clean and rebuild again?

> I really wish we could avoid committing changes that don't build but I
> know it isn't that simple.
> 
> I have got some other lists (around somewhere) based on output, mostly
> from the Vendor firmware, and one where I went through the devices and
> listed what they are along with and their pci ids so I could try and
> understand what was going on.

I found some boot log of OpenWrt in the OpenWrt forum in this post, it
shows how the PCIe devices are looking without your patch.
https://forum.openwrt.org/viewtopic.php?pid=269905#p269905
I am used to search for some boot logs random people posted on the
Internet. ;-)

> I could try and find that and post it if it would be useful.
> Note that it was just used to understand what was what so it isn't
> pretty but should have quite a bit of info in it.
> 
> There's no question the current patch is wrong so I don't recommend it
> be used.
> 
> I can however post my updated patch now on the understanding that it
> hasn't been tested at all, which might be good for initial review
> anyway.
> 
>>
>> On the hardware side this SoC has 3 PCIe controllers, but one shares a
>> PHY with the USB 3.0 controller. Instead of using the 3rd PCIe
>> controller they used USB 3.0 and split one of the PCIe controllers into
>> 2 PCIE lanes.
> 
> Right, I didn't get that, mmm ...

With kernel 4.1 OpenWrt switched to a different PICe driver, which is
also in the mainline kernel and supported by Broadcom.

Hauke
Ian Kent Aug. 15, 2015, 1:55 a.m. UTC | #14
On Fri, 2015-08-14 at 19:55 +0200, Hauke Mehrtens wrote:
> On 08/14/2015 06:03 AM, Ian Kent wrote:
> > On Wed, 2015-08-12 at 22:01 +0200, Hauke Mehrtens wrote:
> >> On 07/15/2015 12:11 PM, Ian Kent wrote:
> >>> On Tue, 2015-07-14 at 18:19 +0200, Rafał Miłecki wrote:
> >>>> On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
> >>>>> Let me rework this using the bus number as you recommend.
> >>>>> I'll repost my updated patch series once I've done that.
> >>>>
> >>>> Hi Ian,
> >>>>
> >>>> Is there any chance you'll find a moment for it anytime soon? It'd be
> >>>> awesome to get R8000 support for CC release.
> >>>
> >>> I have reworked the patch and a broken package build problem I had is
> >>> gone but I didn't get time to fix build problems with a third patch I
> >>> have.
> >>>
> >>> Just didn't get time last weekend and this week has been quite busy too.
> >>> I'll try and get onto this in the next few days.
> >>>
> >>> Ian
> >>
> >> Hi Ian,
> >>
> >> you patch looks better than the hack Broadcom did in their vendor driver.
> > 
> > I thought so, ;)
> > 
> >>
> >> Could you send me a lspci output or the content of /proc/bus/pci/devices
> >> of the original firmware or of OpenWrt with your patch applied? I would
> >> prefer lspci because it is easier to read but cat from
> >> /proc/bus/pci/devices also works. I do not have such a device and want
> >> to understand how this PCIe switch looks like on the software side, so
> >> we can fix the domain, bus, slot, function mixup.
> > 
> > I haven't been able to build OpenWrt for a while now and that's why I
> > haven't been able to test my changes to the patch.
> 
> I haven't noticed a problem in the OpenWrt build system, do you still
> have this problem? Have you tried to clean and rebuild again?

The problem I have now is with mkimage.

It started after a distclean and reconfigure to ensure I was getting a
fully up to date repo.

> 
> > I really wish we could avoid committing changes that don't build but I
> > know it isn't that simple.
> > 
> > I have got some other lists (around somewhere) based on output, mostly
> > from the Vendor firmware, and one where I went through the devices and
> > listed what they are along with and their pci ids so I could try and
> > understand what was going on.
> 
> I found some boot log of OpenWrt in the OpenWrt forum in this post, it
> shows how the PCIe devices are looking without your patch.
> https://forum.openwrt.org/viewtopic.php?pid=269905#p269905
> I am used to search for some boot logs random people posted on the
> Internet. ;-)

Yes, I'm pretty sure the broken PEX8603 patch was applied to the build I
used that produced that dmesg output.

Is that sufficient?

> 
> > I could try and find that and post it if it would be useful.
> > Note that it was just used to understand what was what so it isn't
> > pretty but should have quite a bit of info in it.
> > 
> > There's no question the current patch is wrong so I don't recommend it
> > be used.
> > 
> > I can however post my updated patch now on the understanding that it
> > hasn't been tested at all, which might be good for initial review
> > anyway.
> > 
> >>
> >> On the hardware side this SoC has 3 PCIe controllers, but one shares a
> >> PHY with the USB 3.0 controller. Instead of using the 3rd PCIe
> >> controller they used USB 3.0 and split one of the PCIe controllers into
> >> 2 PCIE lanes.
> > 
> > Right, I didn't get that, mmm ...
> 
> With kernel 4.1 OpenWrt switched to a different PICe driver, which is
> also in the mainline kernel and supported by Broadcom.
> 
> Hauke
> 
>
Ian Kent Aug. 15, 2015, 2:03 a.m. UTC | #15
On Sat, 2015-08-15 at 09:55 +0800, Ian Kent wrote:
> On Fri, 2015-08-14 at 19:55 +0200, Hauke Mehrtens wrote:
> > On 08/14/2015 06:03 AM, Ian Kent wrote:
> > > On Wed, 2015-08-12 at 22:01 +0200, Hauke Mehrtens wrote:
> > >> On 07/15/2015 12:11 PM, Ian Kent wrote:
> > >>> On Tue, 2015-07-14 at 18:19 +0200, Rafał Miłecki wrote:
> > >>>> On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
> > >>>>> Let me rework this using the bus number as you recommend.
> > >>>>> I'll repost my updated patch series once I've done that.
> > >>>>
> > >>>> Hi Ian,
> > >>>>
> > >>>> Is there any chance you'll find a moment for it anytime soon? It'd be
> > >>>> awesome to get R8000 support for CC release.
> > >>>
> > >>> I have reworked the patch and a broken package build problem I had is
> > >>> gone but I didn't get time to fix build problems with a third patch I
> > >>> have.
> > >>>
> > >>> Just didn't get time last weekend and this week has been quite busy too.
> > >>> I'll try and get onto this in the next few days.
> > >>>
> > >>> Ian
> > >>
> > >> Hi Ian,
> > >>
> > >> you patch looks better than the hack Broadcom did in their vendor driver.
> > > 
> > > I thought so, ;)
> > > 
> > >>
> > >> Could you send me a lspci output or the content of /proc/bus/pci/devices
> > >> of the original firmware or of OpenWrt with your patch applied? I would
> > >> prefer lspci because it is easier to read but cat from
> > >> /proc/bus/pci/devices also works. I do not have such a device and want
> > >> to understand how this PCIe switch looks like on the software side, so
> > >> we can fix the domain, bus, slot, function mixup.
> > > 
> > > I haven't been able to build OpenWrt for a while now and that's why I
> > > haven't been able to test my changes to the patch.
> > 
> > I haven't noticed a problem in the OpenWrt build system, do you still
> > have this problem? Have you tried to clean and rebuild again?
> 
> The problem I have now is with mkimage.
> 
> It started after a distclean and reconfigure to ensure I was getting a
> fully up to date repo.
> 
> > 
> > > I really wish we could avoid committing changes that don't build but I
> > > know it isn't that simple.
> > > 
> > > I have got some other lists (around somewhere) based on output, mostly
> > > from the Vendor firmware, and one where I went through the devices and
> > > listed what they are along with and their pci ids so I could try and
> > > understand what was going on.
> > 
> > I found some boot log of OpenWrt in the OpenWrt forum in this post, it
> > shows how the PCIe devices are looking without your patch.
> > https://forum.openwrt.org/viewtopic.php?pid=269905#p269905
> > I am used to search for some boot logs random people posted on the
> > Internet. ;-)
> 
> Yes, I'm pretty sure the broken PEX8603 patch was applied to the build I
> used that produced that dmesg output.

I looked at that output again and it does must the broken patch applied.
If it didn't you would see a message about a broken device class device,
hence the fixup, and lots of non-existent pci devices during discovery.

Ian
Ian Kent Aug. 15, 2015, 3:05 a.m. UTC | #16
On Sat, 2015-08-15 at 09:55 +0800, Ian Kent wrote:
> On Fri, 2015-08-14 at 19:55 +0200, Hauke Mehrtens wrote:
> > On 08/14/2015 06:03 AM, Ian Kent wrote:
> > > On Wed, 2015-08-12 at 22:01 +0200, Hauke Mehrtens wrote:
> > >> On 07/15/2015 12:11 PM, Ian Kent wrote:
> > >>> On Tue, 2015-07-14 at 18:19 +0200, Rafał Miłecki wrote:
> > >>>> On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
> > >>>>> Let me rework this using the bus number as you recommend.
> > >>>>> I'll repost my updated patch series once I've done that.
> > >>>>
> > >>>> Hi Ian,
> > >>>>
> > >>>> Is there any chance you'll find a moment for it anytime soon? It'd be
> > >>>> awesome to get R8000 support for CC release.
> > >>>
> > >>> I have reworked the patch and a broken package build problem I had is
> > >>> gone but I didn't get time to fix build problems with a third patch I
> > >>> have.
> > >>>
> > >>> Just didn't get time last weekend and this week has been quite busy too.
> > >>> I'll try and get onto this in the next few days.
> > >>>
> > >>> Ian
> > >>
> > >> Hi Ian,
> > >>
> > >> you patch looks better than the hack Broadcom did in their vendor driver.
> > > 
> > > I thought so, ;)
> > > 
> > >>
> > >> Could you send me a lspci output or the content of /proc/bus/pci/devices
> > >> of the original firmware or of OpenWrt with your patch applied? I would
> > >> prefer lspci because it is easier to read but cat from
> > >> /proc/bus/pci/devices also works. I do not have such a device and want
> > >> to understand how this PCIe switch looks like on the software side, so
> > >> we can fix the domain, bus, slot, function mixup.
> > > 
> > > I haven't been able to build OpenWrt for a while now and that's why I
> > > haven't been able to test my changes to the patch.
> > 
> > I haven't noticed a problem in the OpenWrt build system, do you still
> > have this problem? Have you tried to clean and rebuild again?
> 
> The problem I have now is with mkimage.
> 
> It started after a distclean and reconfigure to ensure I was getting a
> fully up to date repo.

OK, I had a quick look around for this problem and, much to my surprise,
I found this (I hadn't found anything previously).

https://dev.openwrt.org/ticket/20134#comment:10

I'll try reverting the commit and see if I can make some progress over
the weekend.

Ian
Hauke Mehrtens Aug. 15, 2015, 3:10 p.m. UTC | #17
On 08/15/2015 05:05 AM, Ian Kent wrote:
> On Sat, 2015-08-15 at 09:55 +0800, Ian Kent wrote:
>> On Fri, 2015-08-14 at 19:55 +0200, Hauke Mehrtens wrote:
>>> On 08/14/2015 06:03 AM, Ian Kent wrote:
>>>> On Wed, 2015-08-12 at 22:01 +0200, Hauke Mehrtens wrote:
>>>>> On 07/15/2015 12:11 PM, Ian Kent wrote:
>>>>>> On Tue, 2015-07-14 at 18:19 +0200, Rafał Miłecki wrote:
>>>>>>> On 28 June 2015 at 05:37, Ian Kent <raven@themaw.net> wrote:
>>>>>>>> Let me rework this using the bus number as you recommend.
>>>>>>>> I'll repost my updated patch series once I've done that.
>>>>>>>
>>>>>>> Hi Ian,
>>>>>>>
>>>>>>> Is there any chance you'll find a moment for it anytime soon? It'd be
>>>>>>> awesome to get R8000 support for CC release.
>>>>>>
>>>>>> I have reworked the patch and a broken package build problem I had is
>>>>>> gone but I didn't get time to fix build problems with a third patch I
>>>>>> have.
>>>>>>
>>>>>> Just didn't get time last weekend and this week has been quite busy too.
>>>>>> I'll try and get onto this in the next few days.
>>>>>>
>>>>>> Ian
>>>>>
>>>>> Hi Ian,
>>>>>
>>>>> you patch looks better than the hack Broadcom did in their vendor driver.
>>>>
>>>> I thought so, ;)
>>>>
>>>>>
>>>>> Could you send me a lspci output or the content of /proc/bus/pci/devices
>>>>> of the original firmware or of OpenWrt with your patch applied? I would
>>>>> prefer lspci because it is easier to read but cat from
>>>>> /proc/bus/pci/devices also works. I do not have such a device and want
>>>>> to understand how this PCIe switch looks like on the software side, so
>>>>> we can fix the domain, bus, slot, function mixup.
>>>>
>>>> I haven't been able to build OpenWrt for a while now and that's why I
>>>> haven't been able to test my changes to the patch.
>>>
>>> I haven't noticed a problem in the OpenWrt build system, do you still
>>> have this problem? Have you tried to clean and rebuild again?
>>
>> The problem I have now is with mkimage.
>>
>> It started after a distclean and reconfigure to ensure I was getting a
>> fully up to date repo.
> 
> OK, I had a quick look around for this problem and, much to my surprise,
> I found this (I hadn't found anything previously).
> 
> https://dev.openwrt.org/ticket/20134#comment:10
> 
> I'll try reverting the commit and see if I can make some progress over
> the weekend.
> 
> Ian
> 

I hopefully fixed the problem reported in that ticket, I am able to
build on CentOS 7 without problems. If the problem still exists for you
could you please send me the error message you get.

Hauke
Ian Kent Aug. 16, 2015, 4:19 a.m. UTC | #18
On Tue, 2015-06-23 at 07:58 +0800, Ian Kent wrote:
> On Mon, 2015-06-22 at 18:42 +0200, Hauke Mehrtens wrote:
> > 
> > On 03/10/2015 04:30 AM, Ian Kent wrote:
> > > The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
> > > it isn't configured during the bus scan the PCI layer goes crazy
> > > trying to configure phantom devices.
> > 
> > Could you provide some diagram how this is connected?
> 
> I could try, when I get a chance, ascii art isn't my strong suit.
> 
> > 
> > My current assumption is that on one of the 3 PCIe ports is this switch,
> > so the scan will find this switch as a PCIe device, bu how does it go
> > from there?
> 
> I can only infer from looking at sysfs, which is what I have done.
> 
> Perhaps I'm not correct but it looks to me that there are is a BCM53012
> connected with two legs, one has one wireless device, and the other has
> a PEX8603 bridge which has two legs, each with a wireless device.
> 
> > From the vendor driver I would assume that that the two devices behind
> > the switch are device function 0x08 and 0x10 on the switch device.
> 
> I'll have to reacquaint myself with the code before I respond to the
> comments below, its been a while.
>  
> > 
> > Can you also post the output of lspci on your device?
> 
> Don't think I have lspci in the build I was using, I'll need to add it
> and rebuild. That probably won't be until the weekend.

OK, I've been able get a build.

My updated patch doesn't yet function so I've used the driver we're
discussing here to get info.

TBH, looking at this, I'm not so sure the patch is wrong now.

lspci gives:
0000:00:00.0 PCI bridge: Broadcom Corporation Device 8012 (rev 01)
0000:01:00.0 Network controller: Broadcom Corporation Device aa52 (rev 01)
0001:00:00.0 PCI bridge: Broadcom Corporation Device 8012 (rev 01)
0001:01:00.0 PCI bridge: PLX Technology, Inc. Device 8603 (rev ab)
0001:02:01.0 PCI bridge: PLX Technology, Inc. Device 8603 (rev ab)
0001:02:02.0 PCI bridge: PLX Technology, Inc. Device 8603 (rev ab)
0001:03:00.0 Network controller: Broadcom Corporation Device aa52 (rev 01)
0001:04:00.0 Network controller: Broadcom Corporation Device aa52 (rev 01)

and a list of /sys/bus/pci/devices on a Vendor firmware install gives:
0000:00:00.0  0000:00:06.0  0000:00:0b.1  0000:00:11.0  0002:01:00.0
0000:00:01.0  0000:00:07.0  0000:00:0c.0  0000:00:12.0  0002:02:01.0
0000:00:02.0  0000:00:08.0  0000:00:0d.0  0000:00:13.0  0002:02:02.0
0000:00:03.0  0000:00:09.0  0000:00:0e.0  0001:00:00.0  0002:03:00.0
0000:00:04.0  0000:00:0a.0  0000:00:0f.0  0001:01:00.0  0002:04:00.0
0000:00:05.0  0000:00:0b.0  0000:00:10.0  0002:00:00.0

which looks like the topology is the same.

So, possibly, my description of how I believe the devices are connected
is accurate.

	    bcm8012
	 ------------
	 |	    |
	aa52	 pex8603
		 -------
		 |     |
		aa52  aa52

> 
> > 
> > > 
> > > Signed-off-by: Ian Kent <raven@themaw.net>
> > > ---
> > >  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
> > >  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
> > >  2 files changed, 450 insertions(+)
> > >  create mode 100644 target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > >  create mode 100644 target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > > 
> > 
> > 
> > ......
> > 
> > 
> > > diff --git a/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > > new file mode 100644
> > > index 0000000..fc606b4
> > > --- /dev/null
> > > +++ b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> > > @@ -0,0 +1,225 @@
> > > +bcm53xx: R8000 handle PEX8603 switch
> > > +
> > > +The Netgear R8000 has a PEX8603 which, if not configured at
> > > +bus probe results in quite a few phantom devices as it doesn't
> > > +respond properly to configuration requests. The device needs
> > > +to be configured when seen.
> > > +
> > > +Signed-off-by: Ian Kent <raven@themaw.net>
> > > +
> > > +--- a/drivers/pci/host/pci-host-bcm5301x.c
> > > ++++ b/drivers/pci/host/pci-host-bcm5301x.c
> > > +@@ -29,6 +29,21 @@
> > > + #define PCI_TARGET_LINK_SPEED_GEN2    0x2
> > > + #define PCI_TARGET_LINK_SPEED_GEN1    0x1
> > > + 
> > > ++#define PCI_MAX_BUS			4
> > > ++#define PLX_PRIM_SEC_BUS_NUM		(0x00000201 | (PCI_MAX_BUS << 16))
> > > ++
> > > ++#ifndef SZ_48M
> > > ++#define SZ_48M	(SZ_32M + SZ_16M)
> > > ++#endif
> > 
> > Please remove the ifndef, it should fail if this gets added.
> > 
> > 
> > > ++
> > > ++struct pex86xx_info {
> > > ++	u8 busno;	/* Upstream bus PEX is on */
> > > ++	u8 slot;	/* Upstream slot PEX is at */
> > > ++	u16 active;	/* Active port count */
> > > ++	u16 ports;	/* Active port bit map */
> > > ++};
> > > ++struct pex86xx_info pex8603;
> > > ++
> > > + static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> > > + {
> > > + 	struct pci_sys_data *sys = pdev->sysdata;
> > > +@@ -115,6 +130,39 @@ static int bcma_pcie2_read_config_pci(st
> > > + 	struct pci_sys_data *sys = bus->sysdata;
> > > + 	struct bcma_device *bdev = sys->private_data;
> > > + 
> > > ++	/* The PEX8603 won't return sensible values to the PCI layer so
> > > ++	 * we have to do that ourselves.
> > > ++	 */
> > > ++	if (pex8603.busno) {
> > > ++		u16 slot = PCI_SLOT(devfn);
> > > ++
> > > ++		/* Not the PEX upstream slot */
> > > ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> > > ++			goto done;
> > > ++
> > > ++		/* Not the PEX downstream bus? */
> > > ++		if (bus->number < pex8603.busno ||
> > > ++		    bus->number > pex8603.busno + 1)
> > > ++			goto done;
> > > ++
> > > ++		switch (bus->number - pex8603.busno) {
> > > ++		case 0:
> > > ++			/* Upstream port */
> > > ++			break;
> > > ++
> > > ++		case 1:
> > > ++			/* PEX8603, not present for slots other than 1 or 2 */
> > > ++			if (!(slot == 1 || slot == 2)) {
> > > ++				*val = 0xffffffff;
> > > ++				return PCIBIOS_SUCCESSFUL;
> > > ++			}
> > > ++			break;
> > > ++
> > > ++		default:
> > > ++			break;
> > > ++		}
> > > ++	}
> > > ++done:
> > > + 	*val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size);
> > > + 
> > > + 	return PCIBIOS_SUCCESSFUL;
> > > +@@ -126,6 +174,37 @@ static int bcma_pcie2_write_config_pci(s
> > > + 	struct pci_sys_data *sys = bus->sysdata;
> > > + 	struct bcma_device *bdev = sys->private_data;
> > > + 
> > > ++	/* Don't try and set anything on the PEX8603 if it isn't
> > > ++	 * valid.
> > > ++	 */
> > > ++	if (pex8603.busno) {
> > > ++		u16 slot = PCI_SLOT(devfn);
> > > ++
> > > ++		/* Not the PEX upstream slot */
> > > ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> > > ++			goto done;
> > > ++
> > > ++		/* Not the PEX downstream bus? */
> > > ++		if (bus->number < pex8603.busno ||
> > > ++		    bus->number > pex8603.busno + 1)
> > > ++			goto done;
> > > ++
> > > ++		switch (bus->number - pex8603.busno) {
> > > ++		case 0:
> > > ++			/* Upstream port */
> > > ++			break;
> > > ++
> > > ++		case 1:
> > > ++			/* PEX8603 slots only slots 1 and 2 present */
> > > ++			if (!(slot == 1 || slot == 2))
> > > ++				return PCIBIOS_SUCCESSFUL;
> > > ++			break;
> > > ++
> > > ++		default:
> > > ++			break;
> > > ++		}
> > > ++	}
> > > ++done:
> > > + 	bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val);
> > > + 
> > > + 	return PCIBIOS_SUCCESSFUL;
> > > +@@ -147,6 +226,113 @@ static void bcma_pcie2_fixup_class(struc
> > > + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class);
> > > + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class);
> > > + 
> > > ++static void bcma_pcie2_pex_switch_setup(struct pci_dev *dev)
> > > ++{
> > > ++	struct pci_sys_data *sys = dev->sysdata;
> > > ++	struct bcma_device *bdev = sys->private_data;
> > > ++	unsigned char busno = dev->bus->number;
> > > ++	unsigned int devfn = dev->devfn;
> > > ++	unsigned int slot = PCI_SLOT(devfn);
> > > ++	u32 addr = bdev->addr_s[0];
> > > ++	u32 tmp32;
> > > ++	u16 tmp16;
> > > ++
> > > ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x100, 4);
> > > ++	if (!tmp32) {
> > > ++		dev_info(&bdev->dev, "failed to read PEX switch\n");
> > > ++		return;
> > > ++	}
> > > ++
> > > ++	/* Debug control register. */
> > > ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x1dc, 4);
> > > ++	tmp32 &= ~(1<<22);
> > > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x1dc, 4, tmp32);
> > > ++
> > > ++	/* Set GPIO enable. */
> > > ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x62c, 4);
> > > ++	tmp32 &= ~((1 << 0) | (1 << 1) | (1 << 3));
> > > ++	tmp32 |= ((1 << 4) | (1 << 5) | (1 << 7));
> > > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> > > ++
> > > ++	mdelay(50);
> > 
> > You should use msleep(50) here.
> > 
> > > ++
> > > ++	tmp32 |= ((1<<0)|(1<<1));
> > > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> > > ++
> > > ++	/* Bus master */
> > > ++	tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x4, 2);
> > > ++	tmp16 |= 0x06;
> > > ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x4, 2, tmp16);
> > > ++
> > > ++	switch (slot) {
> > 
> > Are you sure this is correct?
> > 
> > Why does the vendor driver use the bus number and afterwards the device
> > function for the last two spaces and you are using only the slot number?
> > 
> > > ++	case 0:
> > > ++		/* Upstream port busno and slot */
> > > ++		pex8603.busno = busno;
> > > ++		pex8603.slot = slot;
> > > ++
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, 0x18, 4, PLX_PRIM_SEC_BUS_NUM);
> > > ++
> > > ++		/* TODO: We need to scan all outgoing windows,
> > > ++		 * to look for a base limit pair for this register.
> > > ++		 */
> > > ++		/* MEM_BASE, MEM_LIM require 1MB alignment */
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_BASE, 2,
> > > ++					addr >> 16);
> > > ++		BUG_ON(((addr + SZ_32M) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_LIMIT, 2,
> > > ++					(addr + SZ_32M) >> 16);
> > > ++		break;
> > > ++
> > > ++	case 1:
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, 0x18, 4,
> > > ++					(((busno + slot) << 16) |
> > > ++					 ((busno + slot) << 8) | busno));
> > > ++		BUG_ON(((addr + SZ_48M) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_BASE, 4,
> > > ++					(addr + SZ_48M) >> 16);
> > > ++		BUG_ON(((addr + SZ_48M + SZ_32M) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_LIMIT, 4,
> > > ++					(addr + SZ_48M + SZ_32M) >> 16);
> > > ++
> > > ++		/* Mark port bit number as active if successful */
> > > ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> > > ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> > > ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> > > ++			pex8603.active++;
> > > ++		}
> > > ++		break;
> > > ++
> > > ++	case 2:
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, 0x18, 4,
> > > ++					(((busno + slot) << 16) |
> > > ++					 ((busno + slot) << 8) | busno));
> > > ++		BUG_ON(((addr + (SZ_48M * 2)) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_BASE, 4,
> > > ++					(addr + (SZ_48M * 2)) >> 16);
> > > ++		BUG_ON(((addr + (SZ_48M * 2) + SZ_32M) >> 16) & 0xf);
> > > ++		bcma_pcie2_write_config(bdev, busno,
> > > ++					devfn, PCI_MEMORY_LIMIT, 4,
> > > ++					(addr + (SZ_48M * 2) + SZ_32M) >> 16);
> > > ++
> > > ++		/* Mark port bit number as active if successful */
> > > ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> > > ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> > > ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> > > ++			pex8603.active++;
> > > ++		}
> > > ++		break;
> > > ++	}
> > > ++}
> > > ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8603, bcma_pcie2_pex_switch_setup);
> > > ++
> > > + /*
> > > +  * Check link status, return 0 if link is up in RC mode,
> > > +  * otherwise return non-zero
> > > _______________________________________________
> > > openwrt-devel mailing list
> > > openwrt-devel@lists.openwrt.org
> > > https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
> > > 
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
Hauke Mehrtens Aug. 21, 2015, 6:17 p.m. UTC | #19
On 08/16/2015 06:19 AM, Ian Kent wrote:
> On Tue, 2015-06-23 at 07:58 +0800, Ian Kent wrote:
>> On Mon, 2015-06-22 at 18:42 +0200, Hauke Mehrtens wrote:
>>>
>>> On 03/10/2015 04:30 AM, Ian Kent wrote:
>>>> The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
>>>> it isn't configured during the bus scan the PCI layer goes crazy
>>>> trying to configure phantom devices.
>>>
>>> Could you provide some diagram how this is connected?
>>
>> I could try, when I get a chance, ascii art isn't my strong suit.
>>
>>>
>>> My current assumption is that on one of the 3 PCIe ports is this switch,
>>> so the scan will find this switch as a PCIe device, bu how does it go
>>> from there?
>>
>> I can only infer from looking at sysfs, which is what I have done.
>>
>> Perhaps I'm not correct but it looks to me that there are is a BCM53012
>> connected with two legs, one has one wireless device, and the other has
>> a PEX8603 bridge which has two legs, each with a wireless device.
>>
>>> From the vendor driver I would assume that that the two devices behind
>>> the switch are device function 0x08 and 0x10 on the switch device.
>>
>> I'll have to reacquaint myself with the code before I respond to the
>> comments below, its been a while.
>>  
>>>
>>> Can you also post the output of lspci on your device?
>>
>> Don't think I have lspci in the build I was using, I'll need to add it
>> and rebuild. That probably won't be until the weekend.
> 
> OK, I've been able get a build.

I think we do not get this into OpenWrt CC any more. You should probably
base your work on top of the new PCIe host driver in the trunk used with
kernel 4.1.

Will you send a new Version or should I look into this?

> My updated patch doesn't yet function so I've used the driver we're
> discussing here to get info.
> 
> TBH, looking at this, I'm not so sure the patch is wrong now.
> 
> lspci gives:
> 0000:00:00.0 PCI bridge: Broadcom Corporation Device 8012 (rev 01)
> 0000:01:00.0 Network controller: Broadcom Corporation Device aa52 (rev 01)
> 0001:00:00.0 PCI bridge: Broadcom Corporation Device 8012 (rev 01)
> 0001:01:00.0 PCI bridge: PLX Technology, Inc. Device 8603 (rev ab)
> 0001:02:01.0 PCI bridge: PLX Technology, Inc. Device 8603 (rev ab)
> 0001:02:02.0 PCI bridge: PLX Technology, Inc. Device 8603 (rev ab)
> 0001:03:00.0 Network controller: Broadcom Corporation Device aa52 (rev 01)
> 0001:04:00.0 Network controller: Broadcom Corporation Device aa52 (rev 01)
> 
> and a list of /sys/bus/pci/devices on a Vendor firmware install gives:
> 0000:00:00.0  0000:00:06.0  0000:00:0b.1  0000:00:11.0  0002:01:00.0
> 0000:00:01.0  0000:00:07.0  0000:00:0c.0  0000:00:12.0  0002:02:01.0
> 0000:00:02.0  0000:00:08.0  0000:00:0d.0  0000:00:13.0  0002:02:02.0
> 0000:00:03.0  0000:00:09.0  0000:00:0e.0  0001:00:00.0  0002:03:00.0
> 0000:00:04.0  0000:00:0a.0  0000:00:0f.0  0001:01:00.0  0002:04:00.0
> 0000:00:05.0  0000:00:0b.0  0000:00:10.0  0002:00:00.0

Thanks for these information.
Without your patch the PCI subsystem will find lots of strange devices
and will report broken data and does not only show nothing, is that
correct?

> which looks like the topology is the same.
> 
> So, possibly, my description of how I believe the devices are connected
> is accurate.
> 
> 	    bcm8012
> 	 ------------
> 	 |	    |
> 	aa52	 pex8603
> 		 -------
> 		 |     |
> 		aa52  aa52
>
Ian Kent Aug. 23, 2015, 1:14 a.m. UTC | #20
On Fri, 2015-08-21 at 20:17 +0200, Hauke Mehrtens wrote:
> 
> On 08/16/2015 06:19 AM, Ian Kent wrote:
> > On Tue, 2015-06-23 at 07:58 +0800, Ian Kent wrote:
> >> On Mon, 2015-06-22 at 18:42 +0200, Hauke Mehrtens wrote:
> >>>
> >>> On 03/10/2015 04:30 AM, Ian Kent wrote:
> >>>> The Netgear R8000 has a PEX8603 connected to the BCM53012 and if
> >>>> it isn't configured during the bus scan the PCI layer goes crazy
> >>>> trying to configure phantom devices.
> >>>
> >>> Could you provide some diagram how this is connected?
> >>
> >> I could try, when I get a chance, ascii art isn't my strong suit.
> >>
> >>>
> >>> My current assumption is that on one of the 3 PCIe ports is this switch,
> >>> so the scan will find this switch as a PCIe device, bu how does it go
> >>> from there?
> >>
> >> I can only infer from looking at sysfs, which is what I have done.
> >>
> >> Perhaps I'm not correct but it looks to me that there are is a BCM53012
> >> connected with two legs, one has one wireless device, and the other has
> >> a PEX8603 bridge which has two legs, each with a wireless device.
> >>
> >>> From the vendor driver I would assume that that the two devices behind
> >>> the switch are device function 0x08 and 0x10 on the switch device.
> >>
> >> I'll have to reacquaint myself with the code before I respond to the
> >> comments below, its been a while.
> >>  
> >>>
> >>> Can you also post the output of lspci on your device?
> >>
> >> Don't think I have lspci in the build I was using, I'll need to add it
> >> and rebuild. That probably won't be until the weekend.
> > 
> > OK, I've been able get a build.
> 
> I think we do not get this into OpenWrt CC any more. You should probably
> base your work on top of the new PCIe host driver in the trunk used with
> kernel 4.1.
> 
> Will you send a new Version or should I look into this?

I will, have been and continue to be quite busy so it will need to be
done when I decide to have some "weekend time", ;)

> 
> > My updated patch doesn't yet function so I've used the driver we're
> > discussing here to get info.
> > 
> > TBH, looking at this, I'm not so sure the patch is wrong now.
> > 
> > lspci gives:
> > 0000:00:00.0 PCI bridge: Broadcom Corporation Device 8012 (rev 01)
> > 0000:01:00.0 Network controller: Broadcom Corporation Device aa52 (rev 01)
> > 0001:00:00.0 PCI bridge: Broadcom Corporation Device 8012 (rev 01)
> > 0001:01:00.0 PCI bridge: PLX Technology, Inc. Device 8603 (rev ab)
> > 0001:02:01.0 PCI bridge: PLX Technology, Inc. Device 8603 (rev ab)
> > 0001:02:02.0 PCI bridge: PLX Technology, Inc. Device 8603 (rev ab)
> > 0001:03:00.0 Network controller: Broadcom Corporation Device aa52 (rev 01)
> > 0001:04:00.0 Network controller: Broadcom Corporation Device aa52 (rev 01)
> > 
> > and a list of /sys/bus/pci/devices on a Vendor firmware install gives:
> > 0000:00:00.0  0000:00:06.0  0000:00:0b.1  0000:00:11.0  0002:01:00.0
> > 0000:00:01.0  0000:00:07.0  0000:00:0c.0  0000:00:12.0  0002:02:01.0
> > 0000:00:02.0  0000:00:08.0  0000:00:0d.0  0000:00:13.0  0002:02:02.0
> > 0000:00:03.0  0000:00:09.0  0000:00:0e.0  0001:00:00.0  0002:03:00.0
> > 0000:00:04.0  0000:00:0a.0  0000:00:0f.0  0001:01:00.0  0002:04:00.0
> > 0000:00:05.0  0000:00:0b.0  0000:00:10.0  0002:00:00.0
> 
> Thanks for these information.
> Without your patch the PCI subsystem will find lots of strange devices
> and will report broken data and does not only show nothing, is that
> correct?

That's exactly so.
And the bridge itself isn't recognised properly because of fixup needed
at initial probe.

> 
> > which looks like the topology is the same.
> > 
> > So, possibly, my description of how I believe the devices are connected
> > is accurate.
> > 
> > 	    bcm8012
> > 	 ------------
> > 	 |	    |
> > 	aa52	 pex8603
> > 		 -------
> > 		 |     |
> > 		aa52  aa52
> >
diff mbox

Patch

diff --git a/target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch b/target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch
new file mode 100644
index 0000000..fc606b4
--- /dev/null
+++ b/target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch
@@ -0,0 +1,225 @@ 
+bcm53xx: R8000 handle PEX8603 switch
+
+The Netgear R8000 has a PEX8603 which, if not configured at
+bus probe results in quite a few phantom devices as it doesn't
+respond properly to configuration requests. The device needs
+to be configured when seen.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+
+--- a/drivers/pci/host/pci-host-bcm5301x.c
++++ b/drivers/pci/host/pci-host-bcm5301x.c
+@@ -29,6 +29,21 @@
+ #define PCI_TARGET_LINK_SPEED_GEN2    0x2
+ #define PCI_TARGET_LINK_SPEED_GEN1    0x1
+ 
++#define PCI_MAX_BUS			4
++#define PLX_PRIM_SEC_BUS_NUM		(0x00000201 | (PCI_MAX_BUS << 16))
++
++#ifndef SZ_48M
++#define SZ_48M	(SZ_32M + SZ_16M)
++#endif
++
++struct pex86xx_info {
++	u8 busno;	/* Upstream bus PEX is on */
++	u8 slot;	/* Upstream slot PEX is at */
++	u16 active;	/* Active port count */
++	u16 ports;	/* Active port bit map */
++};
++struct pex86xx_info pex8603;
++
+ static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+ {
+ 	struct pci_sys_data *sys = pdev->sysdata;
+@@ -115,6 +130,39 @@ static int bcma_pcie2_read_config_pci(st
+ 	struct pci_sys_data *sys = bus->sysdata;
+ 	struct bcma_device *bdev = sys->private_data;
+ 
++	/* The PEX8603 won't return sensible values to the PCI layer so
++	 * we have to do that ourselves.
++	 */
++	if (pex8603.busno) {
++		u16 slot = PCI_SLOT(devfn);
++
++		/* Not the PEX upstream slot */
++		if (pex8603.busno == bus->number && pex8603.slot != slot)
++			goto done;
++
++		/* Not the PEX downstream bus? */
++		if (bus->number < pex8603.busno ||
++		    bus->number > pex8603.busno + 1)
++			goto done;
++
++		switch (bus->number - pex8603.busno) {
++		case 0:
++			/* Upstream port */
++			break;
++
++		case 1:
++			/* PEX8603, not present for slots other than 1 or 2 */
++			if (!(slot == 1 || slot == 2)) {
++				*val = 0xffffffff;
++				return PCIBIOS_SUCCESSFUL;
++			}
++			break;
++
++		default:
++			break;
++		}
++	}
++done:
+ 	*val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size);
+ 
+ 	return PCIBIOS_SUCCESSFUL;
+@@ -126,6 +174,37 @@ static int bcma_pcie2_write_config_pci(s
+ 	struct pci_sys_data *sys = bus->sysdata;
+ 	struct bcma_device *bdev = sys->private_data;
+ 
++	/* Don't try and set anything on the PEX8603 if it isn't
++	 * valid.
++	 */
++	if (pex8603.busno) {
++		u16 slot = PCI_SLOT(devfn);
++
++		/* Not the PEX upstream slot */
++		if (pex8603.busno == bus->number && pex8603.slot != slot)
++			goto done;
++
++		/* Not the PEX downstream bus? */
++		if (bus->number < pex8603.busno ||
++		    bus->number > pex8603.busno + 1)
++			goto done;
++
++		switch (bus->number - pex8603.busno) {
++		case 0:
++			/* Upstream port */
++			break;
++
++		case 1:
++			/* PEX8603 slots only slots 1 and 2 present */
++			if (!(slot == 1 || slot == 2))
++				return PCIBIOS_SUCCESSFUL;
++			break;
++
++		default:
++			break;
++		}
++	}
++done:
+ 	bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val);
+ 
+ 	return PCIBIOS_SUCCESSFUL;
+@@ -147,6 +226,113 @@ static void bcma_pcie2_fixup_class(struc
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class);
+ 
++static void bcma_pcie2_pex_switch_setup(struct pci_dev *dev)
++{
++	struct pci_sys_data *sys = dev->sysdata;
++	struct bcma_device *bdev = sys->private_data;
++	unsigned char busno = dev->bus->number;
++	unsigned int devfn = dev->devfn;
++	unsigned int slot = PCI_SLOT(devfn);
++	u32 addr = bdev->addr_s[0];
++	u32 tmp32;
++	u16 tmp16;
++
++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x100, 4);
++	if (!tmp32) {
++		dev_info(&bdev->dev, "failed to read PEX switch\n");
++		return;
++	}
++
++	/* Debug control register. */
++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x1dc, 4);
++	tmp32 &= ~(1<<22);
++	bcma_pcie2_write_config(bdev, busno, devfn, 0x1dc, 4, tmp32);
++
++	/* Set GPIO enable. */
++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x62c, 4);
++	tmp32 &= ~((1 << 0) | (1 << 1) | (1 << 3));
++	tmp32 |= ((1 << 4) | (1 << 5) | (1 << 7));
++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
++
++	mdelay(50);
++
++	tmp32 |= ((1<<0)|(1<<1));
++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
++
++	/* Bus master */
++	tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x4, 2);
++	tmp16 |= 0x06;
++	bcma_pcie2_write_config(bdev, busno, devfn, 0x4, 2, tmp16);
++
++	switch (slot) {
++	case 0:
++		/* Upstream port busno and slot */
++		pex8603.busno = busno;
++		pex8603.slot = slot;
++
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, 0x18, 4, PLX_PRIM_SEC_BUS_NUM);
++
++		/* TODO: We need to scan all outgoing windows,
++		 * to look for a base limit pair for this register.
++		 */
++		/* MEM_BASE, MEM_LIM require 1MB alignment */
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_BASE, 2,
++					addr >> 16);
++		BUG_ON(((addr + SZ_32M) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_LIMIT, 2,
++					(addr + SZ_32M) >> 16);
++		break;
++
++	case 1:
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, 0x18, 4,
++					(((busno + slot) << 16) |
++					 ((busno + slot) << 8) | busno));
++		BUG_ON(((addr + SZ_48M) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_BASE, 4,
++					(addr + SZ_48M) >> 16);
++		BUG_ON(((addr + SZ_48M + SZ_32M) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_LIMIT, 4,
++					(addr + SZ_48M + SZ_32M) >> 16);
++
++		/* Mark port bit number as active if successful */
++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
++			pex8603.active++;
++		}
++		break;
++
++	case 2:
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, 0x18, 4,
++					(((busno + slot) << 16) |
++					 ((busno + slot) << 8) | busno));
++		BUG_ON(((addr + (SZ_48M * 2)) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_BASE, 4,
++					(addr + (SZ_48M * 2)) >> 16);
++		BUG_ON(((addr + (SZ_48M * 2) + SZ_32M) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_LIMIT, 4,
++					(addr + (SZ_48M * 2) + SZ_32M) >> 16);
++
++		/* Mark port bit number as active if successful */
++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
++			pex8603.active++;
++		}
++		break;
++	}
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8603, bcma_pcie2_pex_switch_setup);
++
+ /*
+  * Check link status, return 0 if link is up in RC mode,
+  * otherwise return non-zero
diff --git a/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
new file mode 100644
index 0000000..fc606b4
--- /dev/null
+++ b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
@@ -0,0 +1,225 @@ 
+bcm53xx: R8000 handle PEX8603 switch
+
+The Netgear R8000 has a PEX8603 which, if not configured at
+bus probe results in quite a few phantom devices as it doesn't
+respond properly to configuration requests. The device needs
+to be configured when seen.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+
+--- a/drivers/pci/host/pci-host-bcm5301x.c
++++ b/drivers/pci/host/pci-host-bcm5301x.c
+@@ -29,6 +29,21 @@
+ #define PCI_TARGET_LINK_SPEED_GEN2    0x2
+ #define PCI_TARGET_LINK_SPEED_GEN1    0x1
+ 
++#define PCI_MAX_BUS			4
++#define PLX_PRIM_SEC_BUS_NUM		(0x00000201 | (PCI_MAX_BUS << 16))
++
++#ifndef SZ_48M
++#define SZ_48M	(SZ_32M + SZ_16M)
++#endif
++
++struct pex86xx_info {
++	u8 busno;	/* Upstream bus PEX is on */
++	u8 slot;	/* Upstream slot PEX is at */
++	u16 active;	/* Active port count */
++	u16 ports;	/* Active port bit map */
++};
++struct pex86xx_info pex8603;
++
+ static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+ {
+ 	struct pci_sys_data *sys = pdev->sysdata;
+@@ -115,6 +130,39 @@ static int bcma_pcie2_read_config_pci(st
+ 	struct pci_sys_data *sys = bus->sysdata;
+ 	struct bcma_device *bdev = sys->private_data;
+ 
++	/* The PEX8603 won't return sensible values to the PCI layer so
++	 * we have to do that ourselves.
++	 */
++	if (pex8603.busno) {
++		u16 slot = PCI_SLOT(devfn);
++
++		/* Not the PEX upstream slot */
++		if (pex8603.busno == bus->number && pex8603.slot != slot)
++			goto done;
++
++		/* Not the PEX downstream bus? */
++		if (bus->number < pex8603.busno ||
++		    bus->number > pex8603.busno + 1)
++			goto done;
++
++		switch (bus->number - pex8603.busno) {
++		case 0:
++			/* Upstream port */
++			break;
++
++		case 1:
++			/* PEX8603, not present for slots other than 1 or 2 */
++			if (!(slot == 1 || slot == 2)) {
++				*val = 0xffffffff;
++				return PCIBIOS_SUCCESSFUL;
++			}
++			break;
++
++		default:
++			break;
++		}
++	}
++done:
+ 	*val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size);
+ 
+ 	return PCIBIOS_SUCCESSFUL;
+@@ -126,6 +174,37 @@ static int bcma_pcie2_write_config_pci(s
+ 	struct pci_sys_data *sys = bus->sysdata;
+ 	struct bcma_device *bdev = sys->private_data;
+ 
++	/* Don't try and set anything on the PEX8603 if it isn't
++	 * valid.
++	 */
++	if (pex8603.busno) {
++		u16 slot = PCI_SLOT(devfn);
++
++		/* Not the PEX upstream slot */
++		if (pex8603.busno == bus->number && pex8603.slot != slot)
++			goto done;
++
++		/* Not the PEX downstream bus? */
++		if (bus->number < pex8603.busno ||
++		    bus->number > pex8603.busno + 1)
++			goto done;
++
++		switch (bus->number - pex8603.busno) {
++		case 0:
++			/* Upstream port */
++			break;
++
++		case 1:
++			/* PEX8603 slots only slots 1 and 2 present */
++			if (!(slot == 1 || slot == 2))
++				return PCIBIOS_SUCCESSFUL;
++			break;
++
++		default:
++			break;
++		}
++	}
++done:
+ 	bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val);
+ 
+ 	return PCIBIOS_SUCCESSFUL;
+@@ -147,6 +226,113 @@ static void bcma_pcie2_fixup_class(struc
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class);
+ 
++static void bcma_pcie2_pex_switch_setup(struct pci_dev *dev)
++{
++	struct pci_sys_data *sys = dev->sysdata;
++	struct bcma_device *bdev = sys->private_data;
++	unsigned char busno = dev->bus->number;
++	unsigned int devfn = dev->devfn;
++	unsigned int slot = PCI_SLOT(devfn);
++	u32 addr = bdev->addr_s[0];
++	u32 tmp32;
++	u16 tmp16;
++
++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x100, 4);
++	if (!tmp32) {
++		dev_info(&bdev->dev, "failed to read PEX switch\n");
++		return;
++	}
++
++	/* Debug control register. */
++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x1dc, 4);
++	tmp32 &= ~(1<<22);
++	bcma_pcie2_write_config(bdev, busno, devfn, 0x1dc, 4, tmp32);
++
++	/* Set GPIO enable. */
++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x62c, 4);
++	tmp32 &= ~((1 << 0) | (1 << 1) | (1 << 3));
++	tmp32 |= ((1 << 4) | (1 << 5) | (1 << 7));
++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
++
++	mdelay(50);
++
++	tmp32 |= ((1<<0)|(1<<1));
++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
++
++	/* Bus master */
++	tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x4, 2);
++	tmp16 |= 0x06;
++	bcma_pcie2_write_config(bdev, busno, devfn, 0x4, 2, tmp16);
++
++	switch (slot) {
++	case 0:
++		/* Upstream port busno and slot */
++		pex8603.busno = busno;
++		pex8603.slot = slot;
++
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, 0x18, 4, PLX_PRIM_SEC_BUS_NUM);
++
++		/* TODO: We need to scan all outgoing windows,
++		 * to look for a base limit pair for this register.
++		 */
++		/* MEM_BASE, MEM_LIM require 1MB alignment */
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_BASE, 2,
++					addr >> 16);
++		BUG_ON(((addr + SZ_32M) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_LIMIT, 2,
++					(addr + SZ_32M) >> 16);
++		break;
++
++	case 1:
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, 0x18, 4,
++					(((busno + slot) << 16) |
++					 ((busno + slot) << 8) | busno));
++		BUG_ON(((addr + SZ_48M) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_BASE, 4,
++					(addr + SZ_48M) >> 16);
++		BUG_ON(((addr + SZ_48M + SZ_32M) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_LIMIT, 4,
++					(addr + SZ_48M + SZ_32M) >> 16);
++
++		/* Mark port bit number as active if successful */
++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
++			pex8603.active++;
++		}
++		break;
++
++	case 2:
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, 0x18, 4,
++					(((busno + slot) << 16) |
++					 ((busno + slot) << 8) | busno));
++		BUG_ON(((addr + (SZ_48M * 2)) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_BASE, 4,
++					(addr + (SZ_48M * 2)) >> 16);
++		BUG_ON(((addr + (SZ_48M * 2) + SZ_32M) >> 16) & 0xf);
++		bcma_pcie2_write_config(bdev, busno,
++					devfn, PCI_MEMORY_LIMIT, 4,
++					(addr + (SZ_48M * 2) + SZ_32M) >> 16);
++
++		/* Mark port bit number as active if successful */
++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
++			pex8603.active++;
++		}
++		break;
++	}
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8603, bcma_pcie2_pex_switch_setup);
++
+ /*
+  * Check link status, return 0 if link is up in RC mode,
+  * otherwise return non-zero