提交 2a7fc5b1 编写于 作者: R Roland Vossen 提交者: John W. Linville

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: NAlwin Beukers <alwin@broadcom.com>
Reviewed-by: NArend van Spriel <arend@broadcom.com>
Signed-off-by: NArend van Spriel <arend@broadcom.com>
Signed-off-by: NJohn W. Linville <linville@tuxdriver.com>
上级 be69c4ef
...@@ -1409,18 +1409,22 @@ void brcms_down(struct brcms_info *wl) ...@@ -1409,18 +1409,22 @@ void brcms_down(struct brcms_info *wl)
/* /*
* precondition: perimeter lock is not acquired * 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); spin_lock_bh(&t->wl->lock);
if (t->set) { if (t->set) {
if (t->periodic) { if (t->periodic) {
t->timer.expires = jiffies + t->ms * HZ / 1000;
atomic_inc(&t->wl->callbacks); atomic_inc(&t->wl->callbacks);
add_timer(&t->timer); ieee80211_queue_delayed_work(t->wl->pub->ieee_hw,
t->set = true; &t->dly_wrk,
} else msecs_to_jiffies(t->ms));
} else {
t->set = false; t->set = false;
}
t->fn(t->arg); t->fn(t->arg);
} }
...@@ -1430,14 +1434,6 @@ void brcms_timer(struct brcms_timer *t) ...@@ -1430,14 +1434,6 @@ void brcms_timer(struct brcms_timer *t)
spin_unlock_bh(&t->wl->lock); 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. * Adds a timer to the list. Caller supplies a timer function.
* Is called from wlc. * Is called from wlc.
...@@ -1454,9 +1450,7 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl, ...@@ -1454,9 +1450,7 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
if (!t) if (!t)
return NULL; return NULL;
init_timer(&t->timer); INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer);
t->timer.data = (unsigned long) t;
t->timer.function = _brcms_timer;
t->wl = wl; t->wl = wl;
t->fn = fn; t->fn = fn;
t->arg = arg; t->arg = arg;
...@@ -1478,22 +1472,22 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl, ...@@ -1478,22 +1472,22 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
* *
* precondition: perimeter lock has been acquired * precondition: perimeter lock has been acquired
*/ */
void brcms_add_timer(struct brcms_timer *t, uint ms, void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
int periodic)
{ {
struct ieee80211_hw *hw = t->wl->pub->ieee_hw;
#ifdef BCMDBG #ifdef BCMDBG
if (t->set) 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); __func__, t->name, periodic);
#endif #endif
t->ms = ms; t->ms = ms;
t->periodic = (bool) periodic; t->periodic = (bool) periodic;
t->set = true; t->set = true;
t->timer.expires = jiffies + ms * HZ / 1000;
atomic_inc(&t->wl->callbacks); 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) ...@@ -1505,7 +1499,7 @@ bool brcms_del_timer(struct brcms_timer *t)
{ {
if (t->set) { if (t->set) {
t->set = false; t->set = false;
if (!del_timer(&t->timer)) if (!cancel_delayed_work(&t->dly_wrk))
return false; return false;
atomic_dec(&t->wl->callbacks); atomic_dec(&t->wl->callbacks);
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/workqueue.h>
#include "ucode_loader.h" #include "ucode_loader.h"
/* /*
* Starting index for 5G rates in the * Starting index for 5G rates in the
...@@ -30,14 +32,14 @@ ...@@ -30,14 +32,14 @@
#define BRCMS_SET_SHORTSLOT_OVERRIDE 146 #define BRCMS_SET_SHORTSLOT_OVERRIDE 146
struct brcms_timer { struct brcms_timer {
struct timer_list timer; struct delayed_work dly_wrk;
struct brcms_info *wl; struct brcms_info *wl;
void (*fn) (void *); void (*fn) (void *); /* function called upon expiration */
void *arg; /* argument to fn */ void *arg; /* fixed argument provided to called function */
uint ms; uint ms;
bool periodic; bool periodic;
bool set; bool set; /* indicates if timer is active */
struct brcms_timer *next; struct brcms_timer *next; /* for freeing on unload */
#ifdef BCMDBG #ifdef BCMDBG
char *name; /* Description of the timer */ char *name; /* Description of the timer */
#endif #endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册