Hi Nathan,

On 04/11/2012 09:06 AM, Nathan Hintz wrote:
> In the absence of the attached patch, my device (Linksys E3000) does not 
> consistently boot.  Roughly 25% of the time following a power cycle (and
> occasionally on reboot), it will hang just after completion of pre-init.
> There is no stack trace when this occurs.  I'm guessing it is occurring
> when the brcm-wl module is loaded.  At first I thought there may be some
> extended config space access of 1 or 2 bytes (instead of always being 4
> bytes), but when I added logging to detect them, none were ever encountered.
I have never seen this with my bcm4718 based device. Do you also have
these problems when not loading brcm-wl, but b43?

> The existing code (prior to the patch) does an "ioremap_nocache" on a
> subset of a memory region that I think has already been mapped, and then
> un-maps that smaller region when it is finished.  Could the un-mapping of
> the smaller region affect adversely the mapping of the larger region?
Yes I also saw that, but I do not know if it is a biǵ problem, but it
should get fixed.

> Any thoughts on how I might go about isolating the problem further if the
> un-mapping of the smaller region is not the cause?
How far do you exactly get? Have yu tried without loading brcm-wl and
some other modules?
> 
> Thanks,
> 
> Nathan
> 
> --- /dev/null 2012-04-07 22:03:23.120698218 -0700
> +++ target/linux/brcm47xx/patches-3.2/240-bcma-pcie-config-access.patch       
> 2012-03-29 23:03:47.966705769 -0700
> @@ -0,0 +1,104 @@
> +--- a/drivers/bcma/driver_pci_host.c
> ++++ b/drivers/bcma/driver_pci_host.c
> +@@ -98,19 +98,19 @@ static int bcma_extpci_read_config(struc
> +     if (dev == 0) {
> +             /* we support only two functions on device 0 */
> +             if (func > 1)
> +-                    return -EINVAL;
> ++                    goto out;
> + 
> +             /* accesses to config registers with offsets >= 256
> +              * requires indirect access.
> +              */
> +             if (off >= PCI_CONFIG_SPACE_SIZE) {
> +                     addr = (func << 12);
> +-                    addr |= (off & 0x0FFF);
> ++                    addr |= (off & 0x0FFC);
Why do you set this to 0x0FFC ?
> +                     val = bcma_pcie_read_config(pc, addr);
> +             } else {
> +                     addr = BCMA_CORE_PCI_PCICFG0;
> +                     addr |= (func << 8);
> +-                    addr |= (off & 0xfc);
> ++                    addr |= (off & 0xFC);
> +                     val = pcicore_read32(pc, addr);
> +             }
> +     } else {
> +@@ -126,8 +126,6 @@ static int bcma_extpci_read_config(struc
> +                     val = 0xffffffff;
> +                     goto unmap;
> +             }
> +-
> +-            val = readl(mmio);
Does this still work with this readl removed? I think the mmio mem does
not have a problem here as it is from bcma_get_cfgspace_addr() and that
is returning host_cfg_addr which is not ioremap.
> +     }
> +     val >>= (8 * (off & 3));
> + 
> +@@ -155,7 +153,7 @@ static int bcma_extpci_write_config(stru
> +                                const void *buf, int len)
> + {
> +     int err = -EINVAL;
> +-    u32 addr = 0, val = 0;
> ++    u32 addr, val;
> +     void __iomem *mmio = 0;
> +     u16 chipid = pc->core->bus->chipinfo.id;
> + 
> +@@ -163,16 +161,22 @@ static int bcma_extpci_write_config(stru
> +     if (unlikely(len != 1 && len != 2 && len != 4))
> +             goto out;
> +     if (dev == 0) {
> ++            /* we support only two functions on device 0 */
> ++            if (func > 1)
> ++                    goto out;
> ++
> +             /* accesses to config registers with offsets >= 256
> +              * requires indirect access.
> +              */
> +-            if (off < PCI_CONFIG_SPACE_SIZE) {
> +-                    addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
> ++            if (off >= PCI_CONFIG_SPACE_SIZE) {
> ++                    addr = (func << 12);
> ++                    addr |= (off & 0x0FFC);
Why 0x0FFC ?
> ++                    val = bcma_pcie_read_config(pc, addr);
> ++            } else {
> ++                    addr = BCMA_CORE_PCI_PCICFG0;
> +                     addr |= (func << 8);
> +-                    addr |= (off & 0xfc);
> +-                    mmio = ioremap_nocache(addr, sizeof(val));
> +-                    if (!mmio)
> +-                            goto out;
> ++                    addr |= (off & 0xFC);
Why 0xFC ?
> ++                    val = pcicore_read32(pc, addr);
> +             }
> +     } else {
> +             addr = bcma_get_cfgspace_addr(pc, dev, func, off);
This part looks good to me.
> +@@ -191,12 +195,10 @@ static int bcma_extpci_write_config(stru
> + 
> +     switch (len) {
> +     case 1:
> +-            val = readl(mmio);
> +             val &= ~(0xFF << (8 * (off & 3)));
> +             val |= *((const u8 *)buf) << (8 * (off & 3));
> +             break;
> +     case 2:
> +-            val = readl(mmio);
> +             val &= ~(0xFFFF << (8 * (off & 3)));
> +             val |= *((const u16 *)buf) << (8 * (off & 3));
> +             break;
> +@@ -204,13 +206,14 @@ static int bcma_extpci_write_config(stru
> +             val = *((const u32 *)buf);
> +             break;
> +     }
> +-    if (dev == 0 && !addr) {
> ++    if (dev == 0) {
> +             /* accesses to config registers with offsets >= 256
> +              * requires indirect access.
> +              */
> +-            addr = (func << 12);
> +-            addr |= (off & 0x0FFF);
> +-            bcma_pcie_write_config(pc, addr, val);
> ++            if (off >= PCI_CONFIG_SPACE_SIZE)
> ++                    bcma_pcie_write_config(pc, addr, val);
> ++            else
> ++                    pcicore_write32(pc, addr, val);
> +     } else {
> +             writel(val, mmio);
> + 

Hauke
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to