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