diff options
author | Roland Vossen <rvossen@broadcom.com> | 2011-10-12 14:51:12 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-10-14 14:48:16 -0400 |
commit | 2a7fc5b1c17a6055fe2753ebacaf43b5780bcf99 (patch) | |
tree | bae75a98fea99de15a4b38b4d6386596a820ecd3 /drivers/net/wireless/brcm80211 | |
parent | be69c4ef462a476523f89c74e7db29f6ad207a1a (diff) |
brcm80211: smac: decreased timer callback irq level
Timer functions were called at soft-irq level, leading to the limitation
that mutexes could not be used. Lifted this limitation by migrating to
work queues.
Reviewed-by: Alwin Beukers <alwin@broadcom.com>
Reviewed-by: Arend van Spriel <arend@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')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 40 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h | 12 |
2 files changed, 24 insertions, 28 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index b665aafe19a..6ce773aee6c 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -1409,18 +1409,22 @@ void brcms_down(struct brcms_info *wl) | |||
1409 | /* | 1409 | /* |
1410 | * precondition: perimeter lock is not acquired | 1410 | * precondition: perimeter lock is not acquired |
1411 | */ | 1411 | */ |
1412 | void brcms_timer(struct brcms_timer *t) | 1412 | static void _brcms_timer(struct work_struct *work) |
1413 | { | 1413 | { |
1414 | struct brcms_timer *t = container_of(work, struct brcms_timer, | ||
1415 | dly_wrk.work); | ||
1416 | |||
1414 | spin_lock_bh(&t->wl->lock); | 1417 | spin_lock_bh(&t->wl->lock); |
1415 | 1418 | ||
1416 | if (t->set) { | 1419 | if (t->set) { |
1417 | if (t->periodic) { | 1420 | if (t->periodic) { |
1418 | t->timer.expires = jiffies + t->ms * HZ / 1000; | ||
1419 | atomic_inc(&t->wl->callbacks); | 1421 | atomic_inc(&t->wl->callbacks); |
1420 | add_timer(&t->timer); | 1422 | ieee80211_queue_delayed_work(t->wl->pub->ieee_hw, |
1421 | t->set = true; | 1423 | &t->dly_wrk, |
1422 | } else | 1424 | msecs_to_jiffies(t->ms)); |
1425 | } else { | ||
1423 | t->set = false; | 1426 | t->set = false; |
1427 | } | ||
1424 | 1428 | ||
1425 | t->fn(t->arg); | 1429 | t->fn(t->arg); |
1426 | } | 1430 | } |
@@ -1431,14 +1435,6 @@ void brcms_timer(struct brcms_timer *t) | |||
1431 | } | 1435 | } |
1432 | 1436 | ||
1433 | /* | 1437 | /* |
1434 | * is called by the kernel from software irq context | ||
1435 | */ | ||
1436 | static void _brcms_timer(unsigned long data) | ||
1437 | { | ||
1438 | brcms_timer((struct brcms_timer *) data); | ||
1439 | } | ||
1440 | |||
1441 | /* | ||
1442 | * Adds a timer to the list. Caller supplies a timer function. | 1438 | * Adds a timer to the list. Caller supplies a timer function. |
1443 | * Is called from wlc. | 1439 | * Is called from wlc. |
1444 | * | 1440 | * |
@@ -1454,9 +1450,7 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl, | |||
1454 | if (!t) | 1450 | if (!t) |
1455 | return NULL; | 1451 | return NULL; |
1456 | 1452 | ||
1457 | init_timer(&t->timer); | 1453 | INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer); |
1458 | t->timer.data = (unsigned long) t; | ||
1459 | t->timer.function = _brcms_timer; | ||
1460 | t->wl = wl; | 1454 | t->wl = wl; |
1461 | t->fn = fn; | 1455 | t->fn = fn; |
1462 | t->arg = arg; | 1456 | t->arg = arg; |
@@ -1478,22 +1472,22 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl, | |||
1478 | * | 1472 | * |
1479 | * precondition: perimeter lock has been acquired | 1473 | * precondition: perimeter lock has been acquired |
1480 | */ | 1474 | */ |
1481 | void brcms_add_timer(struct brcms_timer *t, uint ms, | 1475 | void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) |
1482 | int periodic) | ||
1483 | { | 1476 | { |
1477 | struct ieee80211_hw *hw = t->wl->pub->ieee_hw; | ||
1478 | |||
1484 | #ifdef BCMDBG | 1479 | #ifdef BCMDBG |
1485 | if (t->set) | 1480 | if (t->set) |
1486 | wiphy_err(t->wl->wiphy, "%s: Already set. Name: %s, per %d\n", | 1481 | wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n", |
1487 | __func__, t->name, periodic); | 1482 | __func__, t->name, periodic); |
1488 | |||
1489 | #endif | 1483 | #endif |
1490 | t->ms = ms; | 1484 | t->ms = ms; |
1491 | t->periodic = (bool) periodic; | 1485 | t->periodic = (bool) periodic; |
1492 | t->set = true; | 1486 | t->set = true; |
1493 | t->timer.expires = jiffies + ms * HZ / 1000; | ||
1494 | 1487 | ||
1495 | atomic_inc(&t->wl->callbacks); | 1488 | atomic_inc(&t->wl->callbacks); |
1496 | add_timer(&t->timer); | 1489 | |
1490 | ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); | ||
1497 | } | 1491 | } |
1498 | 1492 | ||
1499 | /* | 1493 | /* |
@@ -1505,7 +1499,7 @@ bool brcms_del_timer(struct brcms_timer *t) | |||
1505 | { | 1499 | { |
1506 | if (t->set) { | 1500 | if (t->set) { |
1507 | t->set = false; | 1501 | t->set = false; |
1508 | if (!del_timer(&t->timer)) | 1502 | if (!cancel_delayed_work(&t->dly_wrk)) |
1509 | return false; | 1503 | return false; |
1510 | 1504 | ||
1511 | atomic_dec(&t->wl->callbacks); | 1505 | atomic_dec(&t->wl->callbacks); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 91e5f2ac56c..177f0e44e4b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h | |||
@@ -19,6 +19,8 @@ | |||
19 | 19 | ||
20 | #include <linux/timer.h> | 20 | #include <linux/timer.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/workqueue.h> | ||
23 | |||
22 | #include "ucode_loader.h" | 24 | #include "ucode_loader.h" |
23 | /* | 25 | /* |
24 | * Starting index for 5G rates in the | 26 | * Starting index for 5G rates in the |
@@ -30,14 +32,14 @@ | |||
30 | #define BRCMS_SET_SHORTSLOT_OVERRIDE 146 | 32 | #define BRCMS_SET_SHORTSLOT_OVERRIDE 146 |
31 | 33 | ||
32 | struct brcms_timer { | 34 | struct brcms_timer { |
33 | struct timer_list timer; | 35 | struct delayed_work dly_wrk; |
34 | struct brcms_info *wl; | 36 | struct brcms_info *wl; |
35 | void (*fn) (void *); | 37 | void (*fn) (void *); /* function called upon expiration */ |
36 | void *arg; /* argument to fn */ | 38 | void *arg; /* fixed argument provided to called function */ |
37 | uint ms; | 39 | uint ms; |
38 | bool periodic; | 40 | bool periodic; |
39 | bool set; | 41 | bool set; /* indicates if timer is active */ |
40 | struct brcms_timer *next; | 42 | struct brcms_timer *next; /* for freeing on unload */ |
41 | #ifdef BCMDBG | 43 | #ifdef BCMDBG |
42 | char *name; /* Description of the timer */ | 44 | char *name; /* Description of the timer */ |
43 | #endif | 45 | #endif |