Message ID | 20160526121210.GA7006@wunner.de (mailing list archive) |
---|---|
State | Not Applicable |
Delegated to: | Kalle Valo |
Headers | show |
On Thu, 26 May 2016 14:12:10 +0200 Lukas Wunner <lukas@wunner.de> wrote: > + mmio = early_ioremap(addr, BCM4331_MMIO_SIZE); > + if (!mmio) { > + pr_err("Cannot iomap Apple AirPort card\n"); > + return; > + } > + pr_info("Resetting Apple AirPort card\n"); > + iowrite32(BCMA_RESET_CTL_RESET, > + mmio + (1 * BCMA_CORE_SIZE) + BCMA_RESET_CTL); > + early_iounmap(mmio, BCM4331_MMIO_SIZE); Just writing that bit is not the correct reset procedure. So it might cause problems depending on how wl does the core reset later. Please try this: - wait for BCMA_RESET_ST to be 0 - set reset bit - flush - wait 1us - reset reset bit - flush - wait 10us See bcma_core_disable()
On Thu, May 26, 2016 at 02:42:46PM +0200, Michael Büsch wrote: > On Thu, 26 May 2016 14:12:10 +0200 Lukas Wunner <lukas@wunner.de> wrote: > > + mmio = early_ioremap(addr, BCM4331_MMIO_SIZE); > > + if (!mmio) { > > + pr_err("Cannot iomap Apple AirPort card\n"); > > + return; > > + } > > + pr_info("Resetting Apple AirPort card\n"); > > + iowrite32(BCMA_RESET_CTL_RESET, > > + mmio + (1 * BCMA_CORE_SIZE) + BCMA_RESET_CTL); > > + early_iounmap(mmio, BCM4331_MMIO_SIZE); > > Just writing that bit is not the correct reset procedure. > So it might cause problems depending on how wl does the core reset > later. > > Please try this: > - wait for BCMA_RESET_ST to be 0 > - set reset bit > - flush > - wait 1us > - reset reset bit > - flush > - wait 10us > > See bcma_core_disable() It turned out that the lockups are triggered by bec3cfdca36b ("net: skb_segment() provides list head and tail") in Linux 3.18 and that Eric Duzamet has kindly provided a fix for broadcom-sta: https://bugs.gentoo.org/show_bug.cgi?id=523326#c24 https://523326.bugs.gentoo.org/attachment.cgi?id=393374 @Broadcom: Please consider releasing a new driver version which incorporates that patch. The latest version 6.30.223.271 of your driver is still missing it even though the issue has existed for almost 18 months now. Nevertheless I amended my patch to follow the reset procedure you specified above, just to cover all bases. Thanks Michael. Best regards, Lukas -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 29-05-16 13:02, Lukas Wunner wrote: > On Thu, May 26, 2016 at 02:42:46PM +0200, Michael Büsch wrote: >> On Thu, 26 May 2016 14:12:10 +0200 Lukas Wunner <lukas@wunner.de> wrote: >>> + mmio = early_ioremap(addr, BCM4331_MMIO_SIZE); >>> + if (!mmio) { >>> + pr_err("Cannot iomap Apple AirPort card\n"); >>> + return; >>> + } >>> + pr_info("Resetting Apple AirPort card\n"); >>> + iowrite32(BCMA_RESET_CTL_RESET, >>> + mmio + (1 * BCMA_CORE_SIZE) + BCMA_RESET_CTL); >>> + early_iounmap(mmio, BCM4331_MMIO_SIZE); >> >> Just writing that bit is not the correct reset procedure. >> So it might cause problems depending on how wl does the core reset >> later. >> >> Please try this: >> - wait for BCMA_RESET_ST to be 0 >> - set reset bit >> - flush >> - wait 1us >> - reset reset bit >> - flush >> - wait 10us >> >> See bcma_core_disable() > > It turned out that the lockups are triggered by bec3cfdca36b > ("net: skb_segment() provides list head and tail") in Linux 3.18 > and that Eric Duzamet has kindly provided a fix for broadcom-sta: > https://bugs.gentoo.org/show_bug.cgi?id=523326#c24 > https://523326.bugs.gentoo.org/attachment.cgi?id=393374 > > @Broadcom: Please consider releasing a new driver version which > incorporates that patch. The latest version 6.30.223.271 of your > driver is still missing it even though the issue has existed for > almost 18 months now. > > Nevertheless I amended my patch to follow the reset procedure you > specified above, just to cover all bases. Thanks Michael. That reset procedure is a bit superseded. For brcmfmac we decided to talk to some hardware engineers and looking at ai_core_disable (from which bcma_core_disable() is (probably) derived) they shook their head in horror. So better check brcmf_chip_ai_coredisable() in .../brcm80211/brcmfmac/chip.c. The function needs a prereset and reset parameter which are core specific. For the 802.11 core you need preset=D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN and reset=D11_BCMA_IOCTL_PHYCLOCKEN. /* D11 core specific control flag bits */ #define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004 #define D11_BCMA_IOCTL_PHYRESET 0x0008 I still have a patch for bcma lying around for this, but did not complete the work for submission. Regards, Arend > Best regards, > > Lukas > -- > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 29-05-16 13:02, Lukas Wunner wrote: > On Thu, May 26, 2016 at 02:42:46PM +0200, Michael Büsch wrote: >> On Thu, 26 May 2016 14:12:10 +0200 Lukas Wunner <lukas@wunner.de> wrote: >>> + mmio = early_ioremap(addr, BCM4331_MMIO_SIZE); >>> + if (!mmio) { >>> + pr_err("Cannot iomap Apple AirPort card\n"); >>> + return; >>> + } >>> + pr_info("Resetting Apple AirPort card\n"); >>> + iowrite32(BCMA_RESET_CTL_RESET, >>> + mmio + (1 * BCMA_CORE_SIZE) + BCMA_RESET_CTL); >>> + early_iounmap(mmio, BCM4331_MMIO_SIZE); >> >> Just writing that bit is not the correct reset procedure. >> So it might cause problems depending on how wl does the core reset >> later. >> >> Please try this: >> - wait for BCMA_RESET_ST to be 0 >> - set reset bit >> - flush >> - wait 1us >> - reset reset bit >> - flush >> - wait 10us >> >> See bcma_core_disable() > > It turned out that the lockups are triggered by bec3cfdca36b > ("net: skb_segment() provides list head and tail") in Linux 3.18 > and that Eric Duzamet has kindly provided a fix for broadcom-sta: > https://bugs.gentoo.org/show_bug.cgi?id=523326#c24 > https://523326.bugs.gentoo.org/attachment.cgi?id=393374 Looked at the patch and it provides little context. So before diving in the code would you know if the patched broadcom-sta driver works for kernels before 3.18? Regards, Arend -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[cc += Eric Dumazet] On Sun, May 29, 2016 at 08:55:01PM +0200, Arend van Spriel wrote: > On 29-05-16 13:02, Lukas Wunner wrote: > > On Thu, May 26, 2016 at 02:42:46PM +0200, Michael Büsch wrote: > >> On Thu, 26 May 2016 14:12:10 +0200 Lukas Wunner <lukas@wunner.de> wrote: > >>> + mmio = early_ioremap(addr, BCM4331_MMIO_SIZE); > >>> + if (!mmio) { > >>> + pr_err("Cannot iomap Apple AirPort card\n"); > >>> + return; > >>> + } > >>> + pr_info("Resetting Apple AirPort card\n"); > >>> + iowrite32(BCMA_RESET_CTL_RESET, > >>> + mmio + (1 * BCMA_CORE_SIZE) + BCMA_RESET_CTL); > >>> + early_iounmap(mmio, BCM4331_MMIO_SIZE); > >> > >> Just writing that bit is not the correct reset procedure. > >> So it might cause problems depending on how wl does the core reset > >> later. > >> > >> Please try this: > >> - wait for BCMA_RESET_ST to be 0 > >> - set reset bit > >> - flush > >> - wait 1us > >> - reset reset bit > >> - flush > >> - wait 10us > >> > >> See bcma_core_disable() > > > > It turned out that the lockups are triggered by bec3cfdca36b > > ("net: skb_segment() provides list head and tail") in Linux 3.18 > > and that Eric Dumazet has kindly provided a fix for broadcom-sta: > > https://bugs.gentoo.org/show_bug.cgi?id=523326#c24 > > https://523326.bugs.gentoo.org/attachment.cgi?id=393374 > > Looked at the patch and it provides little context. So before diving in > the code would you know if the patched broadcom-sta driver works for > kernels before 3.18? I'm not familiar with the broadcom-sta code but I'm inclined to say yes. The function modified by the patch, wl_start(), contains an if/else statement, the if-branch puts a packet to be transmitted on a work queue and the else-branch transmits it straight away. Apparently skb->prev isn't initialized to NULL for the else-branch which wasn't an issue until bec3cfdca36b. That's my superficial understanding of that code, I'm sure you have access to the full source and revision history and can make more sense of it than I do. Best regards, Lukas -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index bca14c8..514fa84 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -11,7 +11,11 @@ #include <linux/pci.h> #include <linux/acpi.h> +#include <linux/delay.h> +#include <linux/dmi.h> #include <linux/pci_ids.h> +#include <linux/bcma/bcma.h> +#include <linux/bcma/bcma_regs.h> #include <drm/i915_drm.h> #include <asm/pci-direct.h> #include <asm/dma.h> @@ -21,6 +25,7 @@ #include <asm/iommu.h> #include <asm/gart.h> #include <asm/irq_remapping.h> +#include <asm/early_ioremap.h> static void __init fix_hypertransport_config(int num, int slot, int func) { @@ -76,6 +81,13 @@ static void __init nvidia_bugs(int num, int slot, int func) #ifdef CONFIG_ACPI #ifdef CONFIG_X86_IO_APIC /* + * Only applies to Nvidia root ports (bus 0) and not to + * Nvidia graphics cards with PCI ports on secondary buses. + */ + if (num) + return; + + /* * All timer overrides on Nvidia are * wrong unless HPET is enabled. * Unfortunately that's not true on many Asus boards. @@ -590,6 +602,47 @@ static void __init force_disable_hpet(int num, int slot, int func) #endif } +#define BCM4331_MMIO_SIZE 16384 +#define BCM4331_PM_CAP 0x40 + +static void __init apple_airport_reset(int bus, int slot, int func) +{ + void __iomem *mmio; + u16 pmcsr; + u64 addr; + + if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) + return; + + /* Card may have been put into PCI_D3hot by grub quirk */ + pmcsr = read_pci_config_16(bus, slot, func, + BCM4331_PM_CAP + PCI_PM_CTRL); + if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) { + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; + write_pci_config_16(bus, slot, func, + BCM4331_PM_CAP + PCI_PM_CTRL, pmcsr); + mdelay(10); + pmcsr = read_pci_config_16(bus, slot, func, + BCM4331_PM_CAP + PCI_PM_CTRL); + if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) { + pr_err("Cannot power up Apple AirPort card\n"); + return; + } + } + + addr = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0); + addr |= (u64)read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_1) << 32; + addr &= PCI_BASE_ADDRESS_MEM_MASK; + mmio = early_ioremap(addr, BCM4331_MMIO_SIZE); + if (!mmio) { + pr_err("Cannot iomap Apple AirPort card\n"); + return; + } + pr_info("Resetting Apple AirPort card\n"); + iowrite32(BCMA_RESET_CTL_RESET, + mmio + (1 * BCMA_CORE_SIZE) + BCMA_RESET_CTL); + early_iounmap(mmio, BCM4331_MMIO_SIZE); +} #define QFLAG_APPLY_ONCE 0x1 #define QFLAG_APPLIED 0x2 @@ -603,12 +656,6 @@ struct chipset { void (*f)(int num, int slot, int func); }; -/* - * Only works for devices on the root bus. If you add any devices - * not on bus 0 readd another loop level in early_quirks(). But - * be careful because at least the Nvidia quirk here relies on - * only matching on bus 0. - */ static struct chipset early_qrk[] __initdata = { { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, nvidia_bugs }, @@ -638,9 +685,13 @@ static struct chipset early_qrk[] __initdata = { */ { PCI_VENDOR_ID_INTEL, 0x0f00, PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet}, + { PCI_VENDOR_ID_BROADCOM, 0x4331, + PCI_CLASS_NETWORK_OTHER, PCI_ANY_ID, 0, apple_airport_reset}, {} }; +static void __init early_pci_scan_bus(int bus); + /** * check_dev_quirk - apply early quirks to a given PCI device * @num: bus number @@ -649,7 +700,7 @@ static struct chipset early_qrk[] __initdata = { * * Check the vendor & device ID against the early quirks table. * - * If the device is single function, let early_quirks() know so we don't + * If the device is single function, let early_pci_scan_bus() know so we don't * poke at this device again. */ static int __init check_dev_quirk(int num, int slot, int func) @@ -658,6 +709,7 @@ static int __init check_dev_quirk(int num, int slot, int func) u16 vendor; u16 device; u8 type; + u8 sec; int i; class = read_pci_config_16(num, slot, func, PCI_CLASS_DEVICE); @@ -685,25 +737,35 @@ static int __init check_dev_quirk(int num, int slot, int func) type = read_pci_config_byte(num, slot, func, PCI_HEADER_TYPE); + + if ((type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) { + sec = read_pci_config_byte(num, slot, func, PCI_SECONDARY_BUS); + early_pci_scan_bus(sec); + } + if (!(type & 0x80)) return -1; return 0; } -void __init early_quirks(void) +static void __init early_pci_scan_bus(int bus) { int slot, func; - if (!early_pci_allowed()) - return; - /* Poor man's PCI discovery */ - /* Only scan the root bus */ for (slot = 0; slot < 32; slot++) for (func = 0; func < 8; func++) { /* Only probe function 0 on single fn devices */ - if (check_dev_quirk(0, slot, func)) + if (check_dev_quirk(bus, slot, func)) break; } } + +void __init early_quirks(void) +{ + if (!early_pci_allowed()) + return; + + early_pci_scan_bus(0); +} diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index eda0909..f642c42 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -8,8 +8,6 @@ #include <linux/bcma/bcma.h> #include <linux/delay.h> -#define BCMA_CORE_SIZE 0x1000 - #define bcma_err(bus, fmt, ...) \ pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) #define bcma_warn(bus, fmt, ...) \ diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 0367c63..5c37b58 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -158,6 +158,7 @@ struct bcma_host_ops { #define BCMA_CORE_DEFAULT 0xFFF #define BCMA_MAX_NR_CORES 16 +#define BCMA_CORE_SIZE 0x1000 /* Chip IDs of PCIe devices */ #define BCMA_CHIP_ID_BCM4313 0x4313