Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a7fc5b1 authored by Roland Vossen's avatar Roland Vossen Committed by John W. Linville
Browse files

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: default avatarAlwin Beukers <alwin@broadcom.com>
Reviewed-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent be69c4ef
Loading
Loading
Loading
Loading
+17 −23
Original line number Diff line number Diff line
@@ -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);
+7 −5
Original line number Diff line number Diff line
@@ -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