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>
This commit is contained in:
parent
be69c4ef46
commit
2a7fc5b1c1
2 changed files with 24 additions and 28 deletions
|
@ -1409,18 +1409,22 @@ void brcms_down(struct brcms_info *wl)
|
|||
/*
|
||||
* precondition: perimeter lock is not acquired
|
||||
*/
|
||||
void brcms_timer(struct brcms_timer *t)
|
||||
static void _brcms_timer(struct work_struct *work)
|
||||
{
|
||||
struct brcms_timer *t = container_of(work, struct brcms_timer,
|
||||
dly_wrk.work);
|
||||
|
||||
spin_lock_bh(&t->wl->lock);
|
||||
|
||||
if (t->set) {
|
||||
if (t->periodic) {
|
||||
t->timer.expires = jiffies + t->ms * HZ / 1000;
|
||||
atomic_inc(&t->wl->callbacks);
|
||||
add_timer(&t->timer);
|
||||
t->set = true;
|
||||
} else
|
||||
ieee80211_queue_delayed_work(t->wl->pub->ieee_hw,
|
||||
&t->dly_wrk,
|
||||
msecs_to_jiffies(t->ms));
|
||||
} else {
|
||||
t->set = false;
|
||||
}
|
||||
|
||||
t->fn(t->arg);
|
||||
}
|
||||
|
@ -1430,14 +1434,6 @@ void brcms_timer(struct brcms_timer *t)
|
|||
spin_unlock_bh(&t->wl->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* is called by the kernel from software irq context
|
||||
*/
|
||||
static void _brcms_timer(unsigned long data)
|
||||
{
|
||||
brcms_timer((struct brcms_timer *) data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a timer to the list. Caller supplies a timer function.
|
||||
* Is called from wlc.
|
||||
|
@ -1454,9 +1450,7 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
|
|||
if (!t)
|
||||
return NULL;
|
||||
|
||||
init_timer(&t->timer);
|
||||
t->timer.data = (unsigned long) t;
|
||||
t->timer.function = _brcms_timer;
|
||||
INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer);
|
||||
t->wl = wl;
|
||||
t->fn = fn;
|
||||
t->arg = arg;
|
||||
|
@ -1478,22 +1472,22 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
|
|||
*
|
||||
* precondition: perimeter lock has been acquired
|
||||
*/
|
||||
void brcms_add_timer(struct brcms_timer *t, uint ms,
|
||||
int periodic)
|
||||
void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
|
||||
{
|
||||
struct ieee80211_hw *hw = t->wl->pub->ieee_hw;
|
||||
|
||||
#ifdef BCMDBG
|
||||
if (t->set)
|
||||
wiphy_err(t->wl->wiphy, "%s: Already set. Name: %s, per %d\n",
|
||||
wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n",
|
||||
__func__, t->name, periodic);
|
||||
|
||||
#endif
|
||||
t->ms = ms;
|
||||
t->periodic = (bool) periodic;
|
||||
t->set = true;
|
||||
t->timer.expires = jiffies + ms * HZ / 1000;
|
||||
|
||||
atomic_inc(&t->wl->callbacks);
|
||||
add_timer(&t->timer);
|
||||
|
||||
ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1505,7 +1499,7 @@ bool brcms_del_timer(struct brcms_timer *t)
|
|||
{
|
||||
if (t->set) {
|
||||
t->set = false;
|
||||
if (!del_timer(&t->timer))
|
||||
if (!cancel_delayed_work(&t->dly_wrk))
|
||||
return false;
|
||||
|
||||
atomic_dec(&t->wl->callbacks);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <linux/timer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "ucode_loader.h"
|
||||
/*
|
||||
* Starting index for 5G rates in the
|
||||
|
@ -30,14 +32,14 @@
|
|||
#define BRCMS_SET_SHORTSLOT_OVERRIDE 146
|
||||
|
||||
struct brcms_timer {
|
||||
struct timer_list timer;
|
||||
struct delayed_work dly_wrk;
|
||||
struct brcms_info *wl;
|
||||
void (*fn) (void *);
|
||||
void *arg; /* argument to fn */
|
||||
void (*fn) (void *); /* function called upon expiration */
|
||||
void *arg; /* fixed argument provided to called function */
|
||||
uint ms;
|
||||
bool periodic;
|
||||
bool set;
|
||||
struct brcms_timer *next;
|
||||
bool set; /* indicates if timer is active */
|
||||
struct brcms_timer *next; /* for freeing on unload */
|
||||
#ifdef BCMDBG
|
||||
char *name; /* Description of the timer */
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue