[rt2x00-users] [RFC 2/8] rt2x00: Introduce an atomic beacon update method

Helmut Schaa helmut.schaa at googlemail.com
Thu Dec 9 22:52:23 EST 2010


Introduce a new function for updating the beacon from atomic context by
refusing to update the beacon while a beacon update is already happening
in process context.

Signed-off-by: Helmut Schaa <helmut.schaa at googlemail.com>
---
 drivers/net/wireless/rt2x00/rt2x00dev.c   |    4 +-
 drivers/net/wireless/rt2x00/rt2x00lib.h   |   17 ++++++++++--
 drivers/net/wireless/rt2x00/rt2x00mac.c   |    2 +-
 drivers/net/wireless/rt2x00/rt2x00queue.c |   39 +++++++++++++++++++++++------
 4 files changed, 48 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 99e533c..5c0e4f2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -134,7 +134,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
 		return;
 
 	if (delayed_flags & DELAYED_UPDATE_BEACON)
-		rt2x00queue_update_beacon(rt2x00dev, vif, true);
+		rt2x00queue_update_beacon_nonatomic(rt2x00dev, vif);
 }
 
 static void rt2x00lib_intf_scheduled(struct work_struct *work)
@@ -187,7 +187,7 @@ static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac,
 	    vif->type != NL80211_IFTYPE_WDS)
 		return;
 
-	rt2x00queue_update_beacon(rt2x00dev, vif);
+	rt2x00queue_update_beacon_nonatomic(rt2x00dev, vif);
 }
 
 void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 6c6a8f1..d15a771 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -157,12 +157,23 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 			       bool local);
 
 /**
- * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware
+ * rt2x00queue_update_beacon_nonatomic - Send new beacon from mac80211
+ *	to hardware in non atomic context.
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
  * @vif: Interface for which the beacon should be updated.
  */
-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
-			      struct ieee80211_vif *vif);
+int rt2x00queue_update_beacon_nonatomic(struct rt2x00_dev *rt2x00dev,
+					struct ieee80211_vif *vif);
+
+/**
+ * rt2x00queue_update_beacon_atomic - Send new beacon from mac80211
+ *	to hardware in atomic context. If process context is currently
+ *	updating the beacon this beacon update request will get dropped.
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @vif: Interface for which the beacon should be updated.
+ */
+int rt2x00queue_update_beacon_atomic(struct rt2x00_dev *rt2x00dev,
+				     struct ieee80211_vif *vif);
 
 /**
  * rt2x00queue_clear_beacon - Clear beacon in hardware
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 061b7a8..3bb846c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -639,7 +639,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 	 * Update the beacon.
 	 */
 	if (changes & BSS_CHANGED_BEACON)
-		rt2x00queue_update_beacon(rt2x00dev, vif);
+		rt2x00queue_update_beacon_nonatomic(rt2x00dev, vif);
 
 	/*
 	 * Start/stop beaconing.
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index d824584..d02082b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -593,8 +593,8 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
 	return 0;
 }
 
-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
-			      struct ieee80211_vif *vif)
+static int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+				     struct ieee80211_vif *vif)
 {
 	struct rt2x00_intf *intf = vif_to_intf(vif);
 	struct skb_frame_desc *skbdesc;
@@ -603,18 +603,14 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
 	if (unlikely(!intf->beacon))
 		return -ENOBUFS;
 
-	mutex_lock(&intf->beacon_skb_mutex);
-
 	/*
 	 * Clean up the beacon skb.
 	 */
 	rt2x00queue_free_skb(intf->beacon);
 
 	intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
-	if (!intf->beacon->skb) {
-		mutex_unlock(&intf->beacon_skb_mutex);
+	if (!intf->beacon->skb)
 		return -ENOMEM;
-	}
 
 	/*
 	 * Copy all TX descriptor information into txdesc,
@@ -635,9 +631,36 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
 	 */
 	rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc);
 
+	return 0;
+
+}
+
+int rt2x00queue_update_beacon_atomic(struct rt2x00_dev *rt2x00dev,
+				     struct ieee80211_vif *vif)
+{
+	struct rt2x00_intf *intf = vif_to_intf(vif);
+
+	/*
+	 * If a beacon update is happening currently in process context
+	 * just drop this update request.
+	 */
+	if (mutex_is_locked(&intf->beacon_skb_mutex))
+		return 0;
+
+	return rt2x00queue_update_beacon(rt2x00dev, vif);
+}
+
+int rt2x00queue_update_beacon_nonatomic(struct rt2x00_dev *rt2x00dev,
+					struct ieee80211_vif *vif)
+{
+	struct rt2x00_intf *intf = vif_to_intf(vif);
+	int ret;
+
+	mutex_lock(&intf->beacon_skb_mutex);
+	ret = rt2x00queue_update_beacon(rt2x00dev, vif);
 	mutex_unlock(&intf->beacon_skb_mutex);
 
-	return 0;
+	return ret;
 }
 
 void rt2x00queue_for_each_entry(struct data_queue *queue,
-- 
1.7.1




More information about the users mailing list