bcm43xx-d80211: opencoded locking
Subsystems (3)
PATCH 1/1 bcm43xx-d80211: opencoded locking
Hi John,
please apply to wireless-dev.
--
Port of the "opencoded locking" patch from bcm43xx-softmac to bcm43xx-d80211.
Signed-off-by Michael Buesch <[email protected]>
drivers/net/wireless/d80211/bcm43xx/bcm43xx.h +14 -50
@@ -660,6 +660,19 @@#define bcm43xx_status (bcm) atomic_read(&(bcm)->init_status)#define bcm43xx_set_status (bcm, stat) atomic_set(&(bcm)->init_status, (stat)) +/* *** THEORY OF LOCKING *** +* +* We have two different locks in the bcm43xx driver. +* => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private +* and the device registers. This mutex does _not_ protect +* against concurrency from the IRQ handler. +* => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. +* +* Please note that, if you only take the irq_lock, you are not protected +* against concurrency from the periodic work handlers. +* Most times you want to take _both_ locks. +*/ +struct bcm43xx_private {struct ieee80211_hw *ieee;struct ieee80211_low_level_stats ieee_stats;
@@ -670,7 +683,6 @@void __iomem *mmio_addr; -/* Locking, see "theory of locking" text below. */ spinlock_t irq_lock;struct mutex mutex;
@@ -710,6 +722,7 @@struct bcm43xx_sprominfo sprom;#define BCM43xx_NR_LEDS 4struct bcm43xx_led leds[BCM43xx_NR_LEDS]; +spinlock_t leds_lock;/* The currently active core. */ struct bcm43xx_coreinfo *current_core;
@@ -779,55 +792,6 @@ }; -/* *** THEORY OF LOCKING *** -* -* We have two different locks in the bcm43xx driver. -* => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private -* and the device registers. -* => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. -* -* We have three types of helper function pairs to utilize these locks. -* (Always use the helper functions.) -* 1) bcm43xx_{un}lock_noirq(): -* Takes bcm->mutex. Does _not_ protect against IRQ concurrency, -* so it is almost always unsafe, if device IRQs are enabled. -* So only use this, if device IRQs are masked. -* Locking may sleep. -* You can sleep within the critical section. -* 2) bcm43xx_{un}lock_irqonly(): -* Takes bcm->irq_lock. Does _not_ protect against -* bcm43xx_lock_noirq() critical sections. -* Does only protect against the IRQ handler path and other -* irqonly() critical sections. -* Locking does not sleep. -* You must not sleep within the critical section. -* 3) bcm43xx_{un}lock_irqsafe(): -* This is the cummulative lock and takes both, mutex and irq_lock. -* Protects against noirq() and irqonly() critical sections (and -* the IRQ handler path). -* Locking may sleep. -* You must not sleep within the critical section. -*/ - -/* Lock type 1 */ -#define bcm43xx_lock_noirq (bcm) mutex_lock(&(bcm)->mutex) -#define bcm43xx_unlock_noirq (bcm) mutex_unlock(&(bcm)->mutex) -/* Lock type 2 */ -#define bcm43xx_lock_irqonly (bcm, flags) \ - spin_lock_irqsave(&(bcm)->irq_lock, flags) -#define bcm43xx_unlock_irqonly (bcm, flags) \ - spin_unlock_irqrestore(&(bcm)->irq_lock, flags) -/* Lock type 3 */ -#define bcm43xx_lock_irqsafe (bcm, flags) do { \ - bcm43xx_lock_noirq(bcm); \ - bcm43xx_lock_irqonly(bcm, flags); \ - } while (0) -#define bcm43xx_unlock_irqsafe (bcm, flags) do { \ - bcm43xx_unlock_irqonly(bcm, flags); \ - bcm43xx_unlock_noirq(bcm); \ - } while (0) - -static inline struct bcm43xx_private *bcm43xx_priv (struct net_device *dev) {
drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c +22 -12
@@ -77,7 +77,8 @@down (&big_buffer_sem); -bcm43xx_lock_irqsafe (bcm, flags); +mutex_lock (&bcm->mutex); +spin_lock_irqsave (&bcm->irq_lock, flags);if (bcm43xx_status (bcm) != BCM43xx_STAT_INITIALIZED) {fappend ("Board not initialized.\n" ); goto out;
@@ -121,7 +122,8 @@fappend ("\n" ); out: -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); +mutex_unlock (&bcm->mutex); res =simple_read_from_buffer (userbuf, count, ppos, buf, pos);up (&big_buffer_sem);return res;
@@ -159,7 +161,8 @@unsigned long flags;down (&big_buffer_sem); -bcm43xx_lock_irqsafe (bcm, flags); +mutex_lock (&bcm->mutex); +spin_lock_irqsave (&bcm->irq_lock, flags);if (bcm43xx_status (bcm) != BCM43xx_STAT_INITIALIZED) {fappend ("Board not initialized.\n" ); goto out;
@@ -169,7 +172,8 @@fappend ("boardflags: 0x%04x\n" , bcm->sprom.boardflags); out: -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); +mutex_unlock (&bcm->mutex); res =simple_read_from_buffer (userbuf, count, ppos, buf, pos);up (&big_buffer_sem);return res;
@@ -188,7 +192,8 @@u64 tsf;down (&big_buffer_sem); -bcm43xx_lock_irqsafe (bcm, flags); +mutex_lock (&bcm->mutex); +spin_lock_irqsave (&bcm->irq_lock, flags);if (bcm43xx_status (bcm) != BCM43xx_STAT_INITIALIZED) {fappend ("Board not initialized.\n" ); goto out;
@@ -199,7 +204,8 @@ (unsigned int)(tsf & 0xFFFFFFFFULL)); out: -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); +mutex_unlock (&bcm->mutex); res =simple_read_from_buffer (userbuf, count, ppos, buf, pos);up (&big_buffer_sem);return res;
@@ -221,7 +227,8 @@ res = -EFAULT ; goto out_up; } -bcm43xx_lock_irqsafe (bcm, flags); +mutex_lock (&bcm->mutex); +spin_lock_irqsave (&bcm->irq_lock, flags);if (bcm43xx_status (bcm) != BCM43xx_STAT_INITIALIZED) { printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); res = -EFAULT ;
@@ -237,7 +244,8 @@ res = buf_size; out_unlock: -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); +mutex_unlock (&bcm->mutex); out_up:up (&big_buffer_sem);return res;
@@ -258,7 +266,8 @@int i, cnt, j =0 ;down (&big_buffer_sem); -bcm43xx_lock_irqsafe (bcm, flags); +mutex_lock (&bcm->mutex); +spin_lock_irqsave (&bcm->irq_lock, flags);fappend ("Last %d logged xmitstatus blobs (Latest first):\n\n" , BCM43xx_NR_LOGGED_XMITSTATUS);
@@ -294,14 +303,15 @@ i = BCM43xx_NR_LOGGED_XMITSTATUS -1 ; } -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); res =simple_read_from_buffer (userbuf, count, ppos, buf, pos); -bcm43xx_lock_irqsafe (bcm, flags); +spin_lock_irqsave (&bcm->irq_lock, flags);if (*ppos == pos) {/* Done. Drop the copied data. */ e->xmitstatus_printing =0 ; } -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); +mutex_unlock (&bcm->mutex);up (&big_buffer_sem);return res; }
drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c +8 -2
@@ -51,12 +51,12 @@struct bcm43xx_private *bcm = led->bcm;unsigned long flags; -bcm43xx_lock_irqonly (bcm, flags); +spin_lock_irqsave (&bcm->leds_lock, flags);if (led->blink_interval) {bcm43xx_led_changestate (led);mod_timer (&led->blink_timer, jiffies + led->blink_interval); } -bcm43xx_unlock_irqonly (bcm, flags); +spin_unlock_irqrestore (&bcm->leds_lock, flags); } static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
@@ -177,7 +177,9 @@int i, turn_on;unsigned long interval =0 ;u16 ledctl; +unsigned long flags; +spin_lock_irqsave (&bcm->leds_lock, flags); ledctl =bcm43xx_read16 (bcm, BCM43xx_MMIO_GPIO_CONTROL);for (i =0 ; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]);
@@ -266,6 +268,7 @@ ledctl &= ~(1 << i); }bcm43xx_write16 (bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +spin_unlock_irqrestore (&bcm->leds_lock, flags); }void bcm43xx_leds_switch_all (struct bcm43xx_private *bcm,int on)
@@ -274,7 +277,9 @@u16 ledctl;int i;int bit_on; +unsigned long flags; +spin_lock_irqsave (&bcm->leds_lock, flags); ledctl =bcm43xx_read16 (bcm, BCM43xx_MMIO_GPIO_CONTROL);for (i =0 ; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]);
@@ -290,4 +295,5 @@ ledctl &= ~(1 << i); }bcm43xx_write16 (bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +spin_unlock_irqrestore (&bcm->leds_lock, flags); }
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c +54 -50
323 lines not on this page · raw message
drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c +2 -2
@@ -263,7 +263,7 @@int err;u16 txctl; -bcm43xx_lock_irqonly (bcm, flags); +spin_lock_irqsave (&bcm->irq_lock, flags);if (queue->tx_frozen) goto out_unlock; txctl =bcm43xx_pio_read (queue, BCM43xx_PIO_TXCTL);
@@ -283,7 +283,7 @@break ; } out_unlock: -bcm43xx_unlock_irqonly (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); }static void setup_txqueues (struct bcm43xx_pioqueue *queue)
drivers/net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c +22 -12
@@ -120,12 +120,14 @@ GFP_KERNEL);if (!sprom)return -ENOMEM ; -bcm43xx_lock_irqsafe (bcm, flags); +mutex_lock (&bcm->mutex); +spin_lock_irqsave (&bcm->irq_lock, flags); err =bcm43xx_sprom_read (bcm, sprom);if (!err) err =sprom2hex (sprom, buf,PAGE_SIZE );mmiowb (); -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); +mutex_unlock (&bcm->mutex);kfree (sprom);return err;
@@ -150,10 +152,14 @@ err =hex2sprom (sprom, buf, count);if (err) goto out_kfree; -bcm43xx_lock_irqsafe (bcm, flags); +mutex_lock (&bcm->mutex); +spin_lock_irqsave (&bcm->irq_lock, flags); +spin_lock (&bcm->leds_lock); err =bcm43xx_sprom_write (bcm, sprom);mmiowb (); -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock (&bcm->leds_lock); +spin_unlock_irqrestore (&bcm->irq_lock, flags); +mutex_unlock (&bcm->mutex); out_kfree:kfree (sprom);
@@ -176,7 +182,7 @@if (!capable (CAP_NET_ADMIN ))return -EPERM ; -bcm43xx_lock_noirq (bcm); +mutex_lock (&bcm->mutex);switch (bcm43xx_current_radio (bcm)->interfmode) {case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -193,7 +199,7 @@ } err =0 ; -bcm43xx_unlock_noirq (bcm); +mutex_unlock (&bcm->mutex);return err ? err : count;
@@ -229,7 +235,8 @@return -EINVAL ; } -bcm43xx_lock_irqsafe (bcm, flags); +mutex_lock (&bcm->mutex); +spin_lock_irqsave (&bcm->irq_lock, flags); err =bcm43xx_radio_set_interference_mitigation (bcm, mode);if (err) {
@@ -237,7 +244,8 @@ "supported by device\n"); }mmiowb (); -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); +mutex_unlock (&bcm->mutex);return err ? err : count; }
@@ -257,7 +265,7 @@if (!capable (CAP_NET_ADMIN ))return -EPERM ; -bcm43xx_lock_noirq (bcm); +mutex_lock (&bcm->mutex);if (bcm->short_preamble) count =snprintf (buf,PAGE_SIZE ,"1 (Short Preamble enabled)\n" );
@@ -265,7 +273,7 @@ count =snprintf (buf,PAGE_SIZE ,"0 (Short Preamble disabled)\n" ); err =0 ; -bcm43xx_unlock_noirq (bcm); +mutex_unlock (&bcm->mutex);return err ? err : count; }
@@ -285,12 +293,14 @@ value =get_boolean (buf, count);if (value <0 )return value; -bcm43xx_lock_irqsafe (bcm, flags); +mutex_lock (&bcm->mutex); +spin_lock_irqsave (&bcm->irq_lock, flags); bcm->short_preamble = !!value; err =0 ; -bcm43xx_unlock_irqsafe (bcm, flags); +spin_unlock_irqrestore (&bcm->irq_lock, flags); +mutex_unlock (&bcm->mutex);return err ? err : count; }
Signature · 1 line
Greetings Michael.