aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c8
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c63
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c11
3 files changed, 67 insertions, 15 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 4688904908ec..758c115b556e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -108,9 +108,15 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
108 sdio_release_host(sdfunc); 108 sdio_release_host(sdfunc);
109 } 109 }
110 } else if (regaddr == SDIO_CCCR_ABORT) { 110 } else if (regaddr == SDIO_CCCR_ABORT) {
111 sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
112 GFP_KERNEL);
113 if (!sdfunc)
114 return -ENOMEM;
115 sdfunc->num = 0;
111 sdio_claim_host(sdfunc); 116 sdio_claim_host(sdfunc);
112 sdio_writeb(sdfunc, *byte, regaddr, &err_ret); 117 sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
113 sdio_release_host(sdfunc); 118 sdio_release_host(sdfunc);
119 kfree(sdfunc);
114 } else if (regaddr < 0xF0) { 120 } else if (regaddr < 0xF0) {
115 brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); 121 brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
116 err_ret = -EPERM; 122 err_ret = -EPERM;
@@ -486,7 +492,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
486 kfree(bus_if); 492 kfree(bus_if);
487 return -ENOMEM; 493 return -ENOMEM;
488 } 494 }
489 sdiodev->func[0] = func->card->sdio_func[0]; 495 sdiodev->func[0] = func;
490 sdiodev->func[1] = func; 496 sdiodev->func[1] = func;
491 sdiodev->bus_if = bus_if; 497 sdiodev->bus_if = bus_if;
492 bus_if->bus_priv.sdio = sdiodev; 498 bus_if->bus_priv.sdio = sdiodev;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 2bf5dda29291..eb3829b03cd3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -574,6 +574,8 @@ struct brcmf_sdio {
574 574
575 struct task_struct *dpc_tsk; 575 struct task_struct *dpc_tsk;
576 struct completion dpc_wait; 576 struct completion dpc_wait;
577 struct list_head dpc_tsklst;
578 spinlock_t dpc_tl_lock;
577 579
578 struct semaphore sdsem; 580 struct semaphore sdsem;
579 581
@@ -2594,29 +2596,58 @@ clkwait:
2594 return resched; 2596 return resched;
2595} 2597}
2596 2598
2599static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
2600{
2601 struct list_head *new_hd;
2602 unsigned long flags;
2603
2604 if (in_interrupt())
2605 new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
2606 else
2607 new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL);
2608 if (new_hd == NULL)
2609 return;
2610
2611 spin_lock_irqsave(&bus->dpc_tl_lock, flags);
2612 list_add_tail(new_hd, &bus->dpc_tsklst);
2613 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
2614}
2615
2597static int brcmf_sdbrcm_dpc_thread(void *data) 2616static int brcmf_sdbrcm_dpc_thread(void *data)
2598{ 2617{
2599 struct brcmf_sdio *bus = (struct brcmf_sdio *) data; 2618 struct brcmf_sdio *bus = (struct brcmf_sdio *) data;
2619 struct list_head *cur_hd, *tmp_hd;
2620 unsigned long flags;
2600 2621
2601 allow_signal(SIGTERM); 2622 allow_signal(SIGTERM);
2602 /* Run until signal received */ 2623 /* Run until signal received */
2603 while (1) { 2624 while (1) {
2604 if (kthread_should_stop()) 2625 if (kthread_should_stop())
2605 break; 2626 break;
2606 if (!wait_for_completion_interruptible(&bus->dpc_wait)) { 2627
2607 /* Call bus dpc unless it indicated down 2628 if (list_empty(&bus->dpc_tsklst))
2608 (then clean stop) */ 2629 if (wait_for_completion_interruptible(&bus->dpc_wait))
2609 if (bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN) { 2630 break;
2610 if (brcmf_sdbrcm_dpc(bus)) 2631
2611 complete(&bus->dpc_wait); 2632 spin_lock_irqsave(&bus->dpc_tl_lock, flags);
2612 } else { 2633 list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) {
2634 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
2635
2636 if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
2613 /* after stopping the bus, exit thread */ 2637 /* after stopping the bus, exit thread */
2614 brcmf_sdbrcm_bus_stop(bus->sdiodev->dev); 2638 brcmf_sdbrcm_bus_stop(bus->sdiodev->dev);
2615 bus->dpc_tsk = NULL; 2639 bus->dpc_tsk = NULL;
2616 break; 2640 break;
2617 } 2641 }
2618 } else 2642
2619 break; 2643 if (brcmf_sdbrcm_dpc(bus))
2644 brcmf_sdbrcm_adddpctsk(bus);
2645
2646 spin_lock_irqsave(&bus->dpc_tl_lock, flags);
2647 list_del(cur_hd);
2648 kfree(cur_hd);
2649 }
2650 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
2620 } 2651 }
2621 return 0; 2652 return 0;
2622} 2653}
@@ -2669,8 +2700,10 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
2669 /* Schedule DPC if needed to send queued packet(s) */ 2700 /* Schedule DPC if needed to send queued packet(s) */
2670 if (!bus->dpc_sched) { 2701 if (!bus->dpc_sched) {
2671 bus->dpc_sched = true; 2702 bus->dpc_sched = true;
2672 if (bus->dpc_tsk) 2703 if (bus->dpc_tsk) {
2704 brcmf_sdbrcm_adddpctsk(bus);
2673 complete(&bus->dpc_wait); 2705 complete(&bus->dpc_wait);
2706 }
2674 } 2707 }
2675 2708
2676 return ret; 2709 return ret;
@@ -3514,8 +3547,10 @@ void brcmf_sdbrcm_isr(void *arg)
3514 brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); 3547 brcmf_dbg(ERROR, "isr w/o interrupt configured!\n");
3515 3548
3516 bus->dpc_sched = true; 3549 bus->dpc_sched = true;
3517 if (bus->dpc_tsk) 3550 if (bus->dpc_tsk) {
3551 brcmf_sdbrcm_adddpctsk(bus);
3518 complete(&bus->dpc_wait); 3552 complete(&bus->dpc_wait);
3553 }
3519} 3554}
3520 3555
3521static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) 3556static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
@@ -3559,8 +3594,10 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
3559 bus->ipend = true; 3594 bus->ipend = true;
3560 3595
3561 bus->dpc_sched = true; 3596 bus->dpc_sched = true;
3562 if (bus->dpc_tsk) 3597 if (bus->dpc_tsk) {
3598 brcmf_sdbrcm_adddpctsk(bus);
3563 complete(&bus->dpc_wait); 3599 complete(&bus->dpc_wait);
3600 }
3564 } 3601 }
3565 } 3602 }
3566 3603
@@ -3897,6 +3934,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
3897 } 3934 }
3898 /* Initialize DPC thread */ 3935 /* Initialize DPC thread */
3899 init_completion(&bus->dpc_wait); 3936 init_completion(&bus->dpc_wait);
3937 INIT_LIST_HEAD(&bus->dpc_tsklst);
3938 spin_lock_init(&bus->dpc_tl_lock);
3900 bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread, 3939 bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
3901 bus, "brcmf_dpc"); 3940 bus, "brcmf_dpc");
3902 if (IS_ERR(bus->dpc_tsk)) { 3941 if (IS_ERR(bus->dpc_tsk)) {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 231ddf4a674f..b4d92792c502 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -847,8 +847,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
847 */ 847 */
848 if (!(txs->status & TX_STATUS_AMPDU) 848 if (!(txs->status & TX_STATUS_AMPDU)
849 && (txs->status & TX_STATUS_INTERMEDIATE)) { 849 && (txs->status & TX_STATUS_INTERMEDIATE)) {
850 wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n", 850 BCMMSG(wlc->wiphy, "INTERMEDIATE but not AMPDU\n");
851 __func__);
852 return false; 851 return false;
853 } 852 }
854 853
@@ -7614,6 +7613,7 @@ brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
7614{ 7613{
7615 int len_mpdu; 7614 int len_mpdu;
7616 struct ieee80211_rx_status rx_status; 7615 struct ieee80211_rx_status rx_status;
7616 struct ieee80211_hdr *hdr;
7617 7617
7618 memset(&rx_status, 0, sizeof(rx_status)); 7618 memset(&rx_status, 0, sizeof(rx_status));
7619 prep_mac80211_status(wlc, rxh, p, &rx_status); 7619 prep_mac80211_status(wlc, rxh, p, &rx_status);
@@ -7623,6 +7623,13 @@ brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
7623 skb_pull(p, D11_PHY_HDR_LEN); 7623 skb_pull(p, D11_PHY_HDR_LEN);
7624 __skb_trim(p, len_mpdu); 7624 __skb_trim(p, len_mpdu);
7625 7625
7626 /* unmute transmit */
7627 if (wlc->hw->suspended_fifos) {
7628 hdr = (struct ieee80211_hdr *)p->data;
7629 if (ieee80211_is_beacon(hdr->frame_control))
7630 brcms_b_mute(wlc->hw, false);
7631 }
7632
7626 memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status)); 7633 memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
7627 ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p); 7634 ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
7628} 7635}