[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