aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2013-06-18 07:29:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-18 14:46:50 -0400
commitfccfe93036312f3ad35d37c2ca960f104c6e7f21 (patch)
treef7a089b5fcaeb2324f2dd7e0edcf1eabbc83eeea /drivers/net/wireless/brcm80211/brcmfmac
parent1ab083a3752760ec7751a7fa43db555d2d6f1e6a (diff)
brcmfmac: simplify dpc handling using atomic operations
Instead of allocating an empty list item and queue that for the dpc data worker to dequeue an atomic counter is used. Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c70
1 files changed, 12 insertions, 58 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 6f3d181659ef..d4db0c7cd692 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -495,8 +495,7 @@ struct brcmf_sdio {
495 495
496 struct workqueue_struct *brcmf_wq; 496 struct workqueue_struct *brcmf_wq;
497 struct work_struct datawork; 497 struct work_struct datawork;
498 struct list_head dpc_tsklst; 498 atomic_t dpc_tskcnt;
499 spinlock_t dpc_tl_lock;
500 499
501 const struct firmware *firmware; 500 const struct firmware *firmware;
502 u32 fw_ptr; 501 u32 fw_ptr;
@@ -2061,23 +2060,6 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
2061 } 2060 }
2062} 2061}
2063 2062
2064static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
2065{
2066 struct list_head *new_hd;
2067 unsigned long flags;
2068
2069 if (in_interrupt())
2070 new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
2071 else
2072 new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL);
2073 if (new_hd == NULL)
2074 return;
2075
2076 spin_lock_irqsave(&bus->dpc_tl_lock, flags);
2077 list_add_tail(new_hd, &bus->dpc_tsklst);
2078 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
2079}
2080
2081static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) 2063static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
2082{ 2064{
2083 u8 idx; 2065 u8 idx;
@@ -2312,7 +2294,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
2312 (!atomic_read(&bus->fcstate) && 2294 (!atomic_read(&bus->fcstate) &&
2313 brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && 2295 brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
2314 data_ok(bus)) || PKT_AVAILABLE()) { 2296 data_ok(bus)) || PKT_AVAILABLE()) {
2315 brcmf_sdbrcm_adddpctsk(bus); 2297 atomic_inc(&bus->dpc_tskcnt);
2316 } 2298 }
2317 2299
2318 /* If we're done for now, turn off clock request. */ 2300 /* If we're done for now, turn off clock request. */
@@ -2342,7 +2324,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
2342 struct brcmf_bus *bus_if = dev_get_drvdata(dev); 2324 struct brcmf_bus *bus_if = dev_get_drvdata(dev);
2343 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; 2325 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
2344 struct brcmf_sdio *bus = sdiodev->bus; 2326 struct brcmf_sdio *bus = sdiodev->bus;
2345 unsigned long flags;
2346 2327
2347 brcmf_dbg(TRACE, "Enter\n"); 2328 brcmf_dbg(TRACE, "Enter\n");
2348 2329
@@ -2381,14 +2362,9 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
2381 qcount[prec] = pktq_plen(&bus->txq, prec); 2362 qcount[prec] = pktq_plen(&bus->txq, prec);
2382#endif 2363#endif
2383 2364
2384 spin_lock_irqsave(&bus->dpc_tl_lock, flags); 2365 if (atomic_read(&bus->dpc_tskcnt) == 0) {
2385 if (list_empty(&bus->dpc_tsklst)) { 2366 atomic_inc(&bus->dpc_tskcnt);
2386 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
2387
2388 brcmf_sdbrcm_adddpctsk(bus);
2389 queue_work(bus->brcmf_wq, &bus->datawork); 2367 queue_work(bus->brcmf_wq, &bus->datawork);
2390 } else {
2391 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
2392 } 2368 }
2393 2369
2394 return ret; 2370 return ret;
@@ -2525,7 +2501,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
2525 struct brcmf_bus *bus_if = dev_get_drvdata(dev); 2501 struct brcmf_bus *bus_if = dev_get_drvdata(dev);
2526 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; 2502 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
2527 struct brcmf_sdio *bus = sdiodev->bus; 2503 struct brcmf_sdio *bus = sdiodev->bus;
2528 unsigned long flags;
2529 2504
2530 brcmf_dbg(TRACE, "Enter\n"); 2505 brcmf_dbg(TRACE, "Enter\n");
2531 2506
@@ -2612,18 +2587,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
2612 } while (ret < 0 && retries++ < TXRETRIES); 2587 } while (ret < 0 && retries++ < TXRETRIES);
2613 } 2588 }
2614 2589
2615 spin_lock_irqsave(&bus->dpc_tl_lock, flags);
2616 if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && 2590 if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) &&
2617 list_empty(&bus->dpc_tsklst)) { 2591 atomic_read(&bus->dpc_tskcnt) == 0) {
2618 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
2619
2620 bus->activity = false; 2592 bus->activity = false;
2621 sdio_claim_host(bus->sdiodev->func[1]); 2593 sdio_claim_host(bus->sdiodev->func[1]);
2622 brcmf_dbg(INFO, "idle\n"); 2594 brcmf_dbg(INFO, "idle\n");
2623 brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); 2595 brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
2624 sdio_release_host(bus->sdiodev->func[1]); 2596 sdio_release_host(bus->sdiodev->func[1]);
2625 } else {
2626 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
2627 } 2597 }
2628 2598
2629 if (ret) 2599 if (ret)
@@ -3451,7 +3421,7 @@ void brcmf_sdbrcm_isr(void *arg)
3451 if (!bus->intr) 3421 if (!bus->intr)
3452 brcmf_err("isr w/o interrupt configured!\n"); 3422 brcmf_err("isr w/o interrupt configured!\n");
3453 3423
3454 brcmf_sdbrcm_adddpctsk(bus); 3424 atomic_inc(&bus->dpc_tskcnt);
3455 queue_work(bus->brcmf_wq, &bus->datawork); 3425 queue_work(bus->brcmf_wq, &bus->datawork);
3456} 3426}
3457 3427
@@ -3460,7 +3430,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
3460#ifdef DEBUG 3430#ifdef DEBUG
3461 struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); 3431 struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev);
3462#endif /* DEBUG */ 3432#endif /* DEBUG */
3463 unsigned long flags;
3464 3433
3465 brcmf_dbg(TIMER, "Enter\n"); 3434 brcmf_dbg(TIMER, "Enter\n");
3466 3435
@@ -3476,11 +3445,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
3476 if (!bus->intr || 3445 if (!bus->intr ||
3477 (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { 3446 (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
3478 3447
3479 spin_lock_irqsave(&bus->dpc_tl_lock, flags); 3448 if (atomic_read(&bus->dpc_tskcnt) == 0) {
3480 if (list_empty(&bus->dpc_tsklst)) {
3481 u8 devpend; 3449 u8 devpend;
3482 spin_unlock_irqrestore(&bus->dpc_tl_lock, 3450
3483 flags);
3484 sdio_claim_host(bus->sdiodev->func[1]); 3451 sdio_claim_host(bus->sdiodev->func[1]);
3485 devpend = brcmf_sdio_regrb(bus->sdiodev, 3452 devpend = brcmf_sdio_regrb(bus->sdiodev,
3486 SDIO_CCCR_INTx, 3453 SDIO_CCCR_INTx,
@@ -3489,9 +3456,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
3489 intstatus = 3456 intstatus =
3490 devpend & (INTR_STATUS_FUNC1 | 3457 devpend & (INTR_STATUS_FUNC1 |
3491 INTR_STATUS_FUNC2); 3458 INTR_STATUS_FUNC2);
3492 } else {
3493 spin_unlock_irqrestore(&bus->dpc_tl_lock,
3494 flags);
3495 } 3459 }
3496 3460
3497 /* If there is something, make like the ISR and 3461 /* If there is something, make like the ISR and
@@ -3500,7 +3464,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
3500 bus->sdcnt.pollcnt++; 3464 bus->sdcnt.pollcnt++;
3501 atomic_set(&bus->ipend, 1); 3465 atomic_set(&bus->ipend, 1);
3502 3466
3503 brcmf_sdbrcm_adddpctsk(bus); 3467 atomic_inc(&bus->dpc_tskcnt);
3504 queue_work(bus->brcmf_wq, &bus->datawork); 3468 queue_work(bus->brcmf_wq, &bus->datawork);
3505 } 3469 }
3506 } 3470 }
@@ -3566,20 +3530,11 @@ static void brcmf_sdio_dataworker(struct work_struct *work)
3566{ 3530{
3567 struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, 3531 struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
3568 datawork); 3532 datawork);
3569 struct list_head *cur_hd, *tmp_hd;
3570 unsigned long flags;
3571
3572 spin_lock_irqsave(&bus->dpc_tl_lock, flags);
3573 list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) {
3574 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
3575 3533
3534 while (atomic_read(&bus->dpc_tskcnt)) {
3576 brcmf_sdbrcm_dpc(bus); 3535 brcmf_sdbrcm_dpc(bus);
3577 3536 atomic_dec(&bus->dpc_tskcnt);
3578 spin_lock_irqsave(&bus->dpc_tl_lock, flags);
3579 list_del(cur_hd);
3580 kfree(cur_hd);
3581 } 3537 }
3582 spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
3583} 3538}
3584 3539
3585static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) 3540static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus)
@@ -3927,8 +3882,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
3927 bus->watchdog_tsk = NULL; 3882 bus->watchdog_tsk = NULL;
3928 } 3883 }
3929 /* Initialize DPC thread */ 3884 /* Initialize DPC thread */
3930 INIT_LIST_HEAD(&bus->dpc_tsklst); 3885 atomic_set(&bus->dpc_tskcnt, 0);
3931 spin_lock_init(&bus->dpc_tl_lock);
3932 3886
3933 /* Assign bus interface call back */ 3887 /* Assign bus interface call back */
3934 bus->sdiodev->bus_if->dev = bus->sdiodev->dev; 3888 bus->sdiodev->bus_if->dev = bus->sdiodev->dev;