Skip to contentSkip to conversation

b43: Use a threaded IRQ handler

PATCH In review Michael Buesch 1 participant 1 message Sep 4, 2009 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

PATCH 1/5 b43: Use a threaded IRQ handler

Use a threaded IRQ handler to allow locking the mutex and sleeping while executing an interrupt.
This removes usage of the irq_lock spinlock, but introduces a new hardirq_lock, which is _only_ used for the PCI/SSB lowlevel hard-irq handler. Sleeping busses (SDIO) will use mutex instead.

drivers/net/wireless/b43/b43.h +8 -15
Index: wireless-testing/drivers/net/wireless/b43/b43.h
===================================================================
@@ -616,6 +616,12 @@ struct b43_wl {
 	/* Pointer to the ieee80211 hardware data structure */
 	struct ieee80211_hw *hw;
 
+	/* Global driver mutex. Every operation must run with this mutex locked. */
+	struct mutex mutex;
+	/* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ
+	 * handler, only. This basically is just the IRQ mask register. */
+	spinlock_t hardirq_lock;
+
 	/* The number of queues that were registered with the mac80211 subsystem
 	 * initially. This is a backup copy of hw->queues in case hw->queues has
 	 * to be dynamically lowered at runtime (Firmware does not support QoS).
@@ -623,8 +629,6 @@ struct b43_wl {
 	 * from the mac80211 subsystem. */
 	u16 mac80211_initially_registered_queues;
 
-	struct mutex mutex;
-	spinlock_t irq_lock;
 	/* R/W lock for data transmission.
 	 * Transmissions on 2+ queues can run concurrently, but somebody else
 	 * might sync with TX by write_lock_irqsave()'ing. */
@@ -665,8 +669,7 @@ struct b43_wl {
 	bool radiotap_enabled;
 	bool radio_enabled;
 
-	/* The beacon we are currently using (AP or IBSS mode).
-	 * This beacon stuff is protected by the irq_lock. */
+	/* The beacon we are currently using (AP or IBSS mode). */
 	struct sk_buff *current_beacon;
 	bool beacon0_uploaded;
 	bool beacon1_uploaded;
@@ -754,14 +757,6 @@ enum {
 		smp_wmb();					\
 					} while (0)
 
-/* XXX---   HOW LOCKING WORKS IN B43   ---XXX
- *
- * You should always acquire both, wl->mutex and wl->irq_lock unless:
- * - You don't need to acquire wl->irq_lock, if the interface is stopped.
- * - You don't need to acquire wl->mutex in the IRQ handler, IRQ tasklet
- *   and packet TX path (and _ONLY_ there.)
- */
-
 /* Data structure for one wireless device (802.11 core) */
 struct b43_wldev {
 	struct ssb_device *dev;
@@ -807,14 +802,12 @@ struct b43_wldev {
 	u32 dma_reason[6];
 	/* The currently active generic-interrupt mask. */
 	u32 irq_mask;
+
 	/* Link Quality calculation context. */
 	struct b43_noise_calculation noisecalc;
 	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
 	int mac_suspended;
 
-	/* Interrupt Service Routine tasklet (bottom-half) */
-	struct tasklet_struct isr_tasklet;
-
 	/* Periodic tasks */
 	struct delayed_work periodic_work;
 	unsigned int periodic_state;
drivers/net/wireless/b43/debugfs.c +16 -37

130 lines not on this page · raw message

drivers/net/wireless/b43/main.c +172 -147

639 lines not on this page · raw message

drivers/net/wireless/b43/phy_common.c +0 -1
Index: wireless-testing/drivers/net/wireless/b43/phy_common.c
===================================================================
@@ -347,7 +347,6 @@ void b43_phy_txpower_adjust_work(struct 
 	mutex_unlock(&wl->mutex);
 }
 
-/* Called with wl->irq_lock locked */
 void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
 {
 	struct b43_phy *phy = &dev->phy;
drivers/net/wireless/b43/phy_common.h +1 -2
Index: wireless-testing/drivers/net/wireless/b43/phy_common.h
===================================================================
@@ -131,7 +131,7 @@ enum b43_txpwr_result {
  * 			If the parameter "ignore_tssi" is true, the TSSI values should
  * 			be ignored and a recalculation of the power settings should be
  * 			done even if the TSSI values did not change.
- * 			This callback is called with wl->irq_lock held and must not sleep.
+ * 			This function may sleep, but should not.
  * 			Must not be NULL.
  * @adjust_txpower:	Write the previously calculated TX power settings
  * 			(from @recalc_txpower) to the hardware.
@@ -379,7 +379,6 @@ void b43_software_rfkill(struct b43_wlde
  *
  * Compare the current TX power output to the desired power emission
  * and schedule an adjustment in case it mismatches.
- * Requires wl->irq_lock locked.
  *
  * @flags:	OR'ed enum b43_phy_txpower_check_flags flags.
  * 		See the docs below.
drivers/net/wireless/b43/phy_g.c +0 -7
Index: wireless-testing/drivers/net/wireless/b43/phy_g.c
===================================================================
@@ -2823,8 +2823,6 @@ static void b43_gphy_op_adjust_txpower(s
 
 	b43_mac_suspend(dev);
 
-	spin_lock_irq(&dev->wl->irq_lock);
-
 	/* Calculate the new attenuation values. */
 	bbatt = gphy->bbatt.att;
 	bbatt += gphy->bbatt_delta;
@@ -2864,11 +2862,6 @@ static void b43_gphy_op_adjust_txpower(s
 	gphy->rfatt.att = rfatt;
 	gphy->bbatt.att = bbatt;
 
-	/* We drop the lock early, so we can sleep during hardware
-	 * adjustment. Possible races with op_recalc_txpower are harmless,
-	 * as we will be called once again in case we raced. */
-	spin_unlock_irq(&dev->wl->irq_lock);
-
 	if (b43_debug(dev, B43_DBG_XMITPOWER))
 		b43dbg(dev->wl, "Adjusting TX power\n");
 
drivers/net/wireless/b43/phy_g.h +1 -2
Index: wireless-testing/drivers/net/wireless/b43/phy_g.h
===================================================================
@@ -141,8 +141,7 @@ struct b43_phy_g {
 	int tgt_idle_tssi;
 	/* Current idle TSSI */
 	int cur_idle_tssi;
-	/* The current average TSSI.
-	 * Needs irq_lock, as it's updated in the IRQ path. */
+	/* The current average TSSI. */
 	u8 average_tssi;
 	/* Current TX power level attenuation control values */
 	struct b43_bbatt bbatt;
drivers/net/wireless/b43/sysfs.c +0 -3
Index: wireless-testing/drivers/net/wireless/b43/sysfs.c
===================================================================
@@ -94,7 +94,6 @@ static ssize_t b43_attr_interfmode_store
 					 const char *buf, size_t count)
 {
 	struct b43_wldev *wldev = dev_to_b43_wldev(dev);
-	unsigned long flags;
 	int err;
 	int mode;
 
@@ -120,7 +119,6 @@ static ssize_t b43_attr_interfmode_store
 	}
 
 	mutex_lock(&wldev->wl->mutex);
-	spin_lock_irqsave(&wldev->wl->irq_lock, flags);
 
 	if (wldev->phy.ops->interf_mitigation) {
 		err = wldev->phy.ops->interf_mitigation(wldev, mode);
@@ -132,7 +130,6 @@ static ssize_t b43_attr_interfmode_store
 		err = -ENOSYS;
 
 	mmiowb();
-	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
 	mutex_unlock(&wldev->wl->mutex);
 
 	return err ? err : count;
drivers/net/wireless/b43/dma.c +2 -3
Index: wireless-testing/drivers/net/wireless/b43/dma.c
===================================================================
@@ -1387,7 +1387,6 @@ out_unlock:
 	return err;
 }
 
-/* Called with IRQs disabled. */
 void b43_dma_handle_txstatus(struct b43_wldev *dev,
 			     const struct b43_txstatus *status)
 {
@@ -1402,7 +1401,7 @@ void b43_dma_handle_txstatus(struct b43_
 	if (unlikely(!ring))
 		return;
 
-	spin_lock(&ring->lock); /* IRQs are already disabled. */
+	spin_lock_irq(&ring->lock);
 
 	B43_WARN_ON(!ring->tx);
 	ops = ring->ops;
@@ -1463,7 +1462,7 @@ void b43_dma_handle_txstatus(struct b43_
 		}
 	}
 
-	spin_unlock(&ring->lock);
+	spin_unlock_irq(&ring->lock);
 }
 
 void b43_dma_get_tx_stats(struct b43_wldev *dev,
drivers/net/wireless/b43/pio.c +2 -3
Index: wireless-testing/drivers/net/wireless/b43/pio.c
===================================================================
@@ -570,7 +570,6 @@ out_unlock:
 	return err;
 }
 
-/* Called with IRQs disabled. */
 void b43_pio_handle_txstatus(struct b43_wldev *dev,
 			     const struct b43_txstatus *status)
 {
@@ -584,7 +583,7 @@ void b43_pio_handle_txstatus(struct b43_
 		return;
 	B43_WARN_ON(!pack);
 
-	spin_lock(&q->lock); /* IRQs are already disabled. */
+	spin_lock_irq(&q->lock);
 
 	info = IEEE80211_SKB_CB(pack->skb);
 
@@ -604,7 +603,7 @@ void b43_pio_handle_txstatus(struct b43_
 		q->stopped = 0;
 	}
 
-	spin_unlock(&q->lock);
+	spin_unlock_irq(&q->lock);
 }
 
 void b43_pio_get_tx_stats(struct b43_wldev *dev,
drivers/net/wireless/b43/debugfs.h +2 -1
Index: wireless-testing/drivers/net/wireless/b43/debugfs.h
===================================================================
@@ -23,9 +23,10 @@ struct dentry;
 #define B43_NR_LOGGED_TXSTATUS	100
 
 struct b43_txstatus_log {
+	/* This structure is protected by wl->mutex */
+
 	struct b43_txstatus *log;
 	int end;
-	spinlock_t lock;
 };
 
 struct b43_dfs_file {
Signature · 1 line
Greetings, Michael.