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 <ra...@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 <ra...@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