Loading drivers/net/wireless/at76c50x-usb.c +2 −2 Original line number Diff line number Diff line Loading @@ -1122,12 +1122,12 @@ exit: static void at76_dump_mib_local(struct at76_priv *priv) { int ret; struct mib_local *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL); struct mib_local *m = kmalloc(sizeof(*m), GFP_KERNEL); if (!m) return; ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local)); ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(*m)); if (ret < 0) { wiphy_err(priv->hw->wiphy, "at76_get_mib (LOCAL) failed: %d\n", ret); Loading drivers/net/wireless/brcm80211/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,15 @@ config BRCMFMAC_SDIO IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to use the driver for a SDIO wireless card. config BRCMFMAC_SDIO_OOB bool "Out of band interrupt support for SDIO interface chipset" depends on BRCMFMAC_SDIO ---help--- This option enables out-of-band interrupt support for Broadcom SDIO Wifi chipset using fullmac in order to gain better performance and deep sleep wake up capability on certain platforms. Say N if you are unsure. config BRCMFMAC_USB bool "USB bus interface support for FullMAC driver" depends on USB Loading drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +87 −10 Original line number Diff line number Diff line Loading @@ -39,37 +39,113 @@ #define SDIOH_API_ACCESS_RETRY_LIMIT 2 static void brcmf_sdioh_irqhandler(struct sdio_func *func) #ifdef CONFIG_BRCMFMAC_SDIO_OOB static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id) { struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(dev_id); brcmf_dbg(TRACE, "***IRQHandler\n"); brcmf_dbg(INTR, "oob intr triggered\n"); sdio_release_host(func); /* * out-of-band interrupt is level-triggered which won't * be cleared until dpc */ if (sdiodev->irq_en) { disable_irq_nosync(irq); sdiodev->irq_en = false; } brcmf_sdbrcm_isr(sdiodev->bus); sdio_claim_host(func); return IRQ_HANDLED; } int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) { int ret = 0; u8 data; unsigned long flags; brcmf_dbg(TRACE, "Entering\n"); brcmf_dbg(ERROR, "requesting irq %d\n", sdiodev->irq); ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler, sdiodev->irq_flags, "brcmf_oob_intr", &sdiodev->func[1]->card->dev); if (ret != 0) return ret; spin_lock_init(&sdiodev->irq_en_lock); spin_lock_irqsave(&sdiodev->irq_en_lock, flags); sdiodev->irq_en = true; spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags); ret = enable_irq_wake(sdiodev->irq); if (ret != 0) return ret; sdiodev->irq_wake = true; /* must configure SDIO_CCCR_IENx to enable irq */ data = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, &ret); data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, data, &ret); /* redirect, configure ane enable io for interrupt signal */ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) data |= SDIO_SEPINT_ACT_HI; brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT, data, &ret); return 0; } int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) { brcmf_dbg(TRACE, "Entering\n"); brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT, 0, NULL); brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, 0, NULL); if (sdiodev->irq_wake) { disable_irq_wake(sdiodev->irq); sdiodev->irq_wake = false; } free_irq(sdiodev->irq, &sdiodev->func[1]->card->dev); sdiodev->irq_en = false; return 0; } #else /* CONFIG_BRCMFMAC_SDIO_OOB */ static void brcmf_sdio_irqhandler(struct sdio_func *func) { struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); brcmf_dbg(INTR, "ib intr triggered\n"); brcmf_sdbrcm_isr(sdiodev->bus); } /* dummy handler for SDIO function 2 interrupt */ static void brcmf_sdioh_dummy_irq_handler(struct sdio_func *func) static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func) { } int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev) int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) { brcmf_dbg(TRACE, "Entering\n"); sdio_claim_host(sdiodev->func[1]); sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler); sdio_claim_irq(sdiodev->func[2], brcmf_sdioh_dummy_irq_handler); sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler); sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler); sdio_release_host(sdiodev->func[1]); return 0; } int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) { brcmf_dbg(TRACE, "Entering\n"); Loading @@ -80,6 +156,7 @@ int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) return 0; } #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, int *err) Loading drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +104 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/errno.h> #include <linux/sched.h> /* request_irq() */ #include <linux/module.h> #include <linux/platform_device.h> #include <net/cfg80211.h> #include <defs.h> Loading Loading @@ -55,6 +56,15 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { }; MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); #ifdef CONFIG_BRCMFMAC_SDIO_OOB static struct list_head oobirq_lh; struct brcmf_sdio_oobirq { unsigned int irq; unsigned long flags; struct list_head list; }; #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ static bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) { Loading Loading @@ -107,7 +117,8 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, } sdio_release_host(sdfunc); } } else if (regaddr == SDIO_CCCR_ABORT) { } else if ((regaddr == SDIO_CCCR_ABORT) || (regaddr == SDIO_CCCR_IENx)) { sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func), GFP_KERNEL); if (!sdfunc) Loading Loading @@ -467,12 +478,40 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) } #ifdef CONFIG_BRCMFMAC_SDIO_OOB static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev) { struct brcmf_sdio_oobirq *oobirq_entry; if (list_empty(&oobirq_lh)) { brcmf_dbg(ERROR, "no valid oob irq resource\n"); return -ENXIO; } oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq, list); sdiodev->irq = oobirq_entry->irq; sdiodev->irq_flags = oobirq_entry->flags; list_del(&oobirq_entry->list); kfree(oobirq_entry); return 0; } #else static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev) { return 0; } #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ static int brcmf_ops_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { int ret = 0; struct brcmf_sdio_dev *sdiodev; struct brcmf_bus *bus_if; brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "func->class=%x\n", func->class); brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor); Loading Loading @@ -511,6 +550,10 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, sdiodev = dev_get_drvdata(&func->card->dev); if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) return -ENODEV; ret = brcmf_sdio_getintrcfg(sdiodev); if (ret) return ret; sdiodev->func[2] = func; bus_if = sdiodev->bus_if; Loading Loading @@ -603,6 +646,65 @@ static struct sdio_driver brcmf_sdmmc_driver = { #endif /* CONFIG_PM_SLEEP */ }; #ifdef CONFIG_BRCMFMAC_SDIO_OOB static int brcmf_sdio_pd_probe(struct platform_device *pdev) { struct resource *res; struct brcmf_sdio_oobirq *oobirq_entry; int i, ret; INIT_LIST_HEAD(&oobirq_lh); for (i = 0; ; i++) { res = platform_get_resource(pdev, IORESOURCE_IRQ, i); if (!res) break; oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq), GFP_KERNEL); oobirq_entry->irq = res->start; oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK; list_add_tail(&oobirq_entry->list, &oobirq_lh); } if (i == 0) return -ENXIO; ret = sdio_register_driver(&brcmf_sdmmc_driver); if (ret) brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret); return ret; } static struct platform_driver brcmf_sdio_pd = { .probe = brcmf_sdio_pd_probe, .driver = { .name = "brcmf_sdio_pd" } }; void brcmf_sdio_exit(void) { brcmf_dbg(TRACE, "Enter\n"); sdio_unregister_driver(&brcmf_sdmmc_driver); platform_driver_unregister(&brcmf_sdio_pd); } void brcmf_sdio_init(void) { int ret; brcmf_dbg(TRACE, "Enter\n"); ret = platform_driver_register(&brcmf_sdio_pd); if (ret) brcmf_dbg(ERROR, "platform_driver_register failed: %d\n", ret); } #else void brcmf_sdio_exit(void) { brcmf_dbg(TRACE, "Enter\n"); Loading @@ -621,3 +723,4 @@ void brcmf_sdio_init(void) if (ret) brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret); } #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +28 −11 Original line number Diff line number Diff line Loading @@ -2352,6 +2352,24 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) up(&bus->sdsem); } #ifdef CONFIG_BRCMFMAC_SDIO_OOB static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) { unsigned long flags; spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); if (!bus->sdiodev->irq_en && !bus->ipend) { enable_irq(bus->sdiodev->irq); bus->sdiodev->irq_en = true; } spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags); } #else static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) { } #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) { u32 intstatus, newstatus = 0; Loading Loading @@ -2509,6 +2527,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) bus->intstatus = intstatus; clkwait: brcmf_sdbrcm_clrintr(bus); if (data_ok(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { int ret, i; Loading Loading @@ -3508,8 +3528,14 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); if (ret == 0) { ret = brcmf_sdio_intr_register(bus->sdiodev); if (ret != 0) brcmf_dbg(ERROR, "intr register failed:%d\n", ret); } /* If we didn't come up, turn off backplane clock */ if (!ret) if (bus_if->state != BRCMF_BUS_DATA) brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); exit: Loading Loading @@ -3867,7 +3893,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) if (bus) { /* De-register interrupt handler */ brcmf_sdcard_intr_dereg(bus->sdiodev); brcmf_sdio_intr_unregister(bus->sdiodev); if (bus->sdiodev->bus_if->drvr) { brcmf_detach(bus->sdiodev->dev); Loading Loading @@ -3968,15 +3994,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) goto fail; } /* Register interrupt callback, but mask it (not operational yet). */ brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n"); ret = brcmf_sdcard_intr_reg(bus->sdiodev); if (ret != 0) { brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret); goto fail; } brcmf_dbg(INTR, "registered SDIO interrupt function ok\n"); brcmf_dbg(INFO, "completed!!\n"); /* if firmware path present try to download and bring up bus */ Loading Loading
drivers/net/wireless/at76c50x-usb.c +2 −2 Original line number Diff line number Diff line Loading @@ -1122,12 +1122,12 @@ exit: static void at76_dump_mib_local(struct at76_priv *priv) { int ret; struct mib_local *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL); struct mib_local *m = kmalloc(sizeof(*m), GFP_KERNEL); if (!m) return; ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local)); ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(*m)); if (ret < 0) { wiphy_err(priv->hw->wiphy, "at76_get_mib (LOCAL) failed: %d\n", ret); Loading
drivers/net/wireless/brcm80211/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,15 @@ config BRCMFMAC_SDIO IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to use the driver for a SDIO wireless card. config BRCMFMAC_SDIO_OOB bool "Out of band interrupt support for SDIO interface chipset" depends on BRCMFMAC_SDIO ---help--- This option enables out-of-band interrupt support for Broadcom SDIO Wifi chipset using fullmac in order to gain better performance and deep sleep wake up capability on certain platforms. Say N if you are unsure. config BRCMFMAC_USB bool "USB bus interface support for FullMAC driver" depends on USB Loading
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +87 −10 Original line number Diff line number Diff line Loading @@ -39,37 +39,113 @@ #define SDIOH_API_ACCESS_RETRY_LIMIT 2 static void brcmf_sdioh_irqhandler(struct sdio_func *func) #ifdef CONFIG_BRCMFMAC_SDIO_OOB static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id) { struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(dev_id); brcmf_dbg(TRACE, "***IRQHandler\n"); brcmf_dbg(INTR, "oob intr triggered\n"); sdio_release_host(func); /* * out-of-band interrupt is level-triggered which won't * be cleared until dpc */ if (sdiodev->irq_en) { disable_irq_nosync(irq); sdiodev->irq_en = false; } brcmf_sdbrcm_isr(sdiodev->bus); sdio_claim_host(func); return IRQ_HANDLED; } int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) { int ret = 0; u8 data; unsigned long flags; brcmf_dbg(TRACE, "Entering\n"); brcmf_dbg(ERROR, "requesting irq %d\n", sdiodev->irq); ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler, sdiodev->irq_flags, "brcmf_oob_intr", &sdiodev->func[1]->card->dev); if (ret != 0) return ret; spin_lock_init(&sdiodev->irq_en_lock); spin_lock_irqsave(&sdiodev->irq_en_lock, flags); sdiodev->irq_en = true; spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags); ret = enable_irq_wake(sdiodev->irq); if (ret != 0) return ret; sdiodev->irq_wake = true; /* must configure SDIO_CCCR_IENx to enable irq */ data = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, &ret); data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, data, &ret); /* redirect, configure ane enable io for interrupt signal */ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) data |= SDIO_SEPINT_ACT_HI; brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT, data, &ret); return 0; } int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) { brcmf_dbg(TRACE, "Entering\n"); brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT, 0, NULL); brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, 0, NULL); if (sdiodev->irq_wake) { disable_irq_wake(sdiodev->irq); sdiodev->irq_wake = false; } free_irq(sdiodev->irq, &sdiodev->func[1]->card->dev); sdiodev->irq_en = false; return 0; } #else /* CONFIG_BRCMFMAC_SDIO_OOB */ static void brcmf_sdio_irqhandler(struct sdio_func *func) { struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); brcmf_dbg(INTR, "ib intr triggered\n"); brcmf_sdbrcm_isr(sdiodev->bus); } /* dummy handler for SDIO function 2 interrupt */ static void brcmf_sdioh_dummy_irq_handler(struct sdio_func *func) static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func) { } int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev) int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) { brcmf_dbg(TRACE, "Entering\n"); sdio_claim_host(sdiodev->func[1]); sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler); sdio_claim_irq(sdiodev->func[2], brcmf_sdioh_dummy_irq_handler); sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler); sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler); sdio_release_host(sdiodev->func[1]); return 0; } int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) { brcmf_dbg(TRACE, "Entering\n"); Loading @@ -80,6 +156,7 @@ int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) return 0; } #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, int *err) Loading
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +104 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/errno.h> #include <linux/sched.h> /* request_irq() */ #include <linux/module.h> #include <linux/platform_device.h> #include <net/cfg80211.h> #include <defs.h> Loading Loading @@ -55,6 +56,15 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { }; MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); #ifdef CONFIG_BRCMFMAC_SDIO_OOB static struct list_head oobirq_lh; struct brcmf_sdio_oobirq { unsigned int irq; unsigned long flags; struct list_head list; }; #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ static bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) { Loading Loading @@ -107,7 +117,8 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, } sdio_release_host(sdfunc); } } else if (regaddr == SDIO_CCCR_ABORT) { } else if ((regaddr == SDIO_CCCR_ABORT) || (regaddr == SDIO_CCCR_IENx)) { sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func), GFP_KERNEL); if (!sdfunc) Loading Loading @@ -467,12 +478,40 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) } #ifdef CONFIG_BRCMFMAC_SDIO_OOB static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev) { struct brcmf_sdio_oobirq *oobirq_entry; if (list_empty(&oobirq_lh)) { brcmf_dbg(ERROR, "no valid oob irq resource\n"); return -ENXIO; } oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq, list); sdiodev->irq = oobirq_entry->irq; sdiodev->irq_flags = oobirq_entry->flags; list_del(&oobirq_entry->list); kfree(oobirq_entry); return 0; } #else static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev) { return 0; } #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ static int brcmf_ops_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { int ret = 0; struct brcmf_sdio_dev *sdiodev; struct brcmf_bus *bus_if; brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "func->class=%x\n", func->class); brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor); Loading Loading @@ -511,6 +550,10 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, sdiodev = dev_get_drvdata(&func->card->dev); if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) return -ENODEV; ret = brcmf_sdio_getintrcfg(sdiodev); if (ret) return ret; sdiodev->func[2] = func; bus_if = sdiodev->bus_if; Loading Loading @@ -603,6 +646,65 @@ static struct sdio_driver brcmf_sdmmc_driver = { #endif /* CONFIG_PM_SLEEP */ }; #ifdef CONFIG_BRCMFMAC_SDIO_OOB static int brcmf_sdio_pd_probe(struct platform_device *pdev) { struct resource *res; struct brcmf_sdio_oobirq *oobirq_entry; int i, ret; INIT_LIST_HEAD(&oobirq_lh); for (i = 0; ; i++) { res = platform_get_resource(pdev, IORESOURCE_IRQ, i); if (!res) break; oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq), GFP_KERNEL); oobirq_entry->irq = res->start; oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK; list_add_tail(&oobirq_entry->list, &oobirq_lh); } if (i == 0) return -ENXIO; ret = sdio_register_driver(&brcmf_sdmmc_driver); if (ret) brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret); return ret; } static struct platform_driver brcmf_sdio_pd = { .probe = brcmf_sdio_pd_probe, .driver = { .name = "brcmf_sdio_pd" } }; void brcmf_sdio_exit(void) { brcmf_dbg(TRACE, "Enter\n"); sdio_unregister_driver(&brcmf_sdmmc_driver); platform_driver_unregister(&brcmf_sdio_pd); } void brcmf_sdio_init(void) { int ret; brcmf_dbg(TRACE, "Enter\n"); ret = platform_driver_register(&brcmf_sdio_pd); if (ret) brcmf_dbg(ERROR, "platform_driver_register failed: %d\n", ret); } #else void brcmf_sdio_exit(void) { brcmf_dbg(TRACE, "Enter\n"); Loading @@ -621,3 +723,4 @@ void brcmf_sdio_init(void) if (ret) brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret); } #endif /* CONFIG_BRCMFMAC_SDIO_OOB */
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +28 −11 Original line number Diff line number Diff line Loading @@ -2352,6 +2352,24 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) up(&bus->sdsem); } #ifdef CONFIG_BRCMFMAC_SDIO_OOB static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) { unsigned long flags; spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); if (!bus->sdiodev->irq_en && !bus->ipend) { enable_irq(bus->sdiodev->irq); bus->sdiodev->irq_en = true; } spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags); } #else static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) { } #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) { u32 intstatus, newstatus = 0; Loading Loading @@ -2509,6 +2527,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) bus->intstatus = intstatus; clkwait: brcmf_sdbrcm_clrintr(bus); if (data_ok(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { int ret, i; Loading Loading @@ -3508,8 +3528,14 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); if (ret == 0) { ret = brcmf_sdio_intr_register(bus->sdiodev); if (ret != 0) brcmf_dbg(ERROR, "intr register failed:%d\n", ret); } /* If we didn't come up, turn off backplane clock */ if (!ret) if (bus_if->state != BRCMF_BUS_DATA) brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); exit: Loading Loading @@ -3867,7 +3893,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) if (bus) { /* De-register interrupt handler */ brcmf_sdcard_intr_dereg(bus->sdiodev); brcmf_sdio_intr_unregister(bus->sdiodev); if (bus->sdiodev->bus_if->drvr) { brcmf_detach(bus->sdiodev->dev); Loading Loading @@ -3968,15 +3994,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) goto fail; } /* Register interrupt callback, but mask it (not operational yet). */ brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n"); ret = brcmf_sdcard_intr_reg(bus->sdiodev); if (ret != 0) { brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret); goto fail; } brcmf_dbg(INTR, "registered SDIO interrupt function ok\n"); brcmf_dbg(INFO, "completed!!\n"); /* if firmware path present try to download and bring up bus */ Loading