* [RFC 0/7] mac80211: preparations for blocking ampdu_action
@ 2010-05-28 18:53 Johannes Berg
2010-05-28 18:53 ` [RFC 1/7] mac80211: simplify station/aggregation code Johannes Berg
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
To: linux-wireless
Hi all,
These are some preparatory and cleanup patches
for a blocking ampdu_action callback that will
allow simplified locking in drivers and avoid
the race condition I had pointed out and posted
a workaround for around earlier.
Obviously, the interesting patch that actually
does that is still missing, but I wanted to
have people review these patches first anyway
since they can stand on their own and smaller
patch batches are always good :)
johannes
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 1/7] mac80211: simplify station/aggregation code
2010-05-28 18:53 [RFC 0/7] mac80211: preparations for blocking ampdu_action Johannes Berg
@ 2010-05-28 18:53 ` Johannes Berg
2010-05-28 18:53 ` [RFC 2/7] mac80211: use common skb queue Johannes Berg
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
To: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
A number of places use RCU locking for accessing
the station list, even though they do not need
to. Use mutex locking instead to prepare for the
locking changes I want to make.
While doing so, combine places where we loop
over stations twice, and optimise away some of
the loops by checking if the hardware supports
aggregation at all first.
Also fix a more theoretical race condition: right
now we could resume, set up an aggregation session,
and right after tear it down again due to the code
that is needed for hardware reconfiguration here.
Also mark add a comment to that code marking it as
a workaround.
Finally, remove a pointless aggregation disabling
loop when an interface is stopped, directly after
that we remove all stations from it which will also
disable all aggregation sessions that may still be
active, and does so in a race-free way unlike the
current loop that doesn't block new sessions.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/iface.c | 13 -------------
net/mac80211/pm.c | 16 ++++------------
net/mac80211/util.c | 31 ++++++++++++++++---------------
3 files changed, 20 insertions(+), 40 deletions(-)
--- wireless-testing.orig/net/mac80211/pm.c 2010-05-28 20:35:58.000000000 +0200
+++ wireless-testing/net/mac80211/pm.c 2010-05-28 20:36:01.000000000 +0200
@@ -40,22 +40,14 @@ int __ieee80211_suspend(struct ieee80211
list_for_each_entry(sdata, &local->interfaces, list)
ieee80211_disable_keys(sdata);
- /* Tear down aggregation sessions */
-
- rcu_read_lock();
-
- if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
- list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ /* tear down aggregation sessions and remove STAs */
+ mutex_lock(&local->sta_mtx);
+ list_for_each_entry(sta, &local->sta_list, list) {
+ if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
set_sta_flags(sta, WLAN_STA_BLOCK_BA);
ieee80211_sta_tear_down_BA_sessions(sta);
}
- }
- rcu_read_unlock();
-
- /* remove STAs */
- mutex_lock(&local->sta_mtx);
- list_for_each_entry(sta, &local->sta_list, list) {
if (sta->uploaded) {
sdata = sta->sdata;
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
--- wireless-testing.orig/net/mac80211/util.c 2010-05-28 20:35:58.000000000 +0200
+++ wireless-testing/net/mac80211/util.c 2010-05-28 20:36:01.000000000 +0200
@@ -1138,18 +1138,6 @@ int ieee80211_reconfig(struct ieee80211_
}
mutex_unlock(&local->sta_mtx);
- /* Clear Suspend state so that ADDBA requests can be processed */
-
- rcu_read_lock();
-
- if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
- list_for_each_entry_rcu(sta, &local->sta_list, list) {
- clear_sta_flags(sta, WLAN_STA_BLOCK_BA);
- }
- }
-
- rcu_read_unlock();
-
/* setup RTS threshold */
drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
@@ -1202,13 +1190,26 @@ int ieee80211_reconfig(struct ieee80211_
}
}
- rcu_read_lock();
+ /*
+ * Clear the WLAN_STA_BLOCK_BA flag so new aggregation
+ * sessions can be established after a resume.
+ *
+ * Also tear down aggregation sessions since reconfiguring
+ * them in a hardware restart scenario is not easily done
+ * right now, and the hardware will have lost information
+ * about the sessions, but we and the AP still think they
+ * are active. This is really a workaround though.
+ */
if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
- list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ mutex_lock(&local->sta_mtx);
+
+ list_for_each_entry(sta, &local->sta_list, list) {
ieee80211_sta_tear_down_BA_sessions(sta);
+ clear_sta_flags(sta, WLAN_STA_BLOCK_BA);
}
+
+ mutex_unlock(&local->sta_mtx);
}
- rcu_read_unlock();
/* add back keys */
list_for_each_entry(sdata, &local->interfaces, list)
--- wireless-testing.orig/net/mac80211/iface.c 2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c 2010-05-28 20:36:01.000000000 +0200
@@ -340,7 +340,6 @@ static int ieee80211_stop(struct net_dev
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
unsigned long flags;
struct sk_buff *skb, *tmp;
u32 hw_reconf_flags = 0;
@@ -357,18 +356,6 @@ static int ieee80211_stop(struct net_dev
ieee80211_work_purge(sdata);
/*
- * Now delete all active aggregation sessions.
- */
- rcu_read_lock();
-
- list_for_each_entry_rcu(sta, &local->sta_list, list) {
- if (sta->sdata == sdata)
- ieee80211_sta_tear_down_BA_sessions(sta);
- }
-
- rcu_read_unlock();
-
- /*
* Remove all stations associated with this interface.
*
* This must be done before calling ops->remove_interface()
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 2/7] mac80211: use common skb queue
2010-05-28 18:53 [RFC 0/7] mac80211: preparations for blocking ampdu_action Johannes Berg
2010-05-28 18:53 ` [RFC 1/7] mac80211: simplify station/aggregation code Johannes Berg
@ 2010-05-28 18:53 ` Johannes Berg
2010-05-28 18:53 ` [RFC 3/7] mac80211: use common work struct Johannes Berg
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
To: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
IBSS, managed and mesh modes all have an
skb queue, and in the future we want to
also use it in other modes, so make them
all use a common skb queue already.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/ibss.c | 7 +++----
net/mac80211/ieee80211_i.h | 7 ++-----
net/mac80211/iface.c | 21 +++++++++++----------
net/mac80211/mesh.c | 14 ++------------
net/mac80211/mlme.c | 5 ++---
5 files changed, 20 insertions(+), 34 deletions(-)
--- wireless-testing.orig/net/mac80211/ibss.c 2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c 2010-05-28 20:36:59.000000000 +0200
@@ -779,7 +779,7 @@ static void ieee80211_ibss_work(struct w
return;
ifibss = &sdata->u.ibss;
- while ((skb = skb_dequeue(&ifibss->skb_queue)))
+ while ((skb = skb_dequeue(&sdata->skb_queue)))
ieee80211_ibss_rx_queued_mgmt(sdata, skb);
if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request))
@@ -850,7 +850,6 @@ void ieee80211_ibss_setup_sdata(struct i
INIT_WORK(&ifibss->work, ieee80211_ibss_work);
setup_timer(&ifibss->timer, ieee80211_ibss_timer,
(unsigned long) sdata);
- skb_queue_head_init(&ifibss->skb_queue);
}
/* scan finished notification */
@@ -890,7 +889,7 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_
case IEEE80211_STYPE_BEACON:
case IEEE80211_STYPE_PROBE_REQ:
case IEEE80211_STYPE_AUTH:
- skb_queue_tail(&sdata->u.ibss.skb_queue, skb);
+ skb_queue_tail(&sdata->skb_queue, skb);
ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
return RX_QUEUED;
}
@@ -983,7 +982,7 @@ int ieee80211_ibss_leave(struct ieee8021
synchronize_rcu();
kfree_skb(skb);
- skb_queue_purge(&sdata->u.ibss.skb_queue);
+ skb_queue_purge(&sdata->skb_queue);
memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
sdata->u.ibss.ssid_len = 0;
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2010-05-28 20:36:59.000000000 +0200
@@ -340,8 +340,6 @@ struct ieee80211_if_managed {
u16 aid;
- struct sk_buff_head skb_queue;
-
unsigned long timers_running; /* used for quiesce/restart */
bool powersave; /* powersave requested for this iface */
enum ieee80211_smps_mode req_smps, /* requested smps mode */
@@ -388,8 +386,6 @@ struct ieee80211_if_ibss {
struct timer_list timer;
struct work_struct work;
- struct sk_buff_head skb_queue;
-
unsigned long request;
unsigned long last_scan_completed;
@@ -420,7 +416,6 @@ struct ieee80211_if_mesh {
struct timer_list housekeeping_timer;
struct timer_list mesh_path_timer;
struct timer_list mesh_path_root_timer;
- struct sk_buff_head skb_queue;
unsigned long timers_running;
@@ -517,6 +512,8 @@ struct ieee80211_sub_if_data {
u16 sequence_number;
+ struct sk_buff_head skb_queue;
+
/*
* AP this belongs to: self in AP mode and
* corresponding AP in VLAN mode, NULL for
--- wireless-testing.orig/net/mac80211/iface.c 2010-05-28 20:36:01.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c 2010-05-28 20:36:59.000000000 +0200
@@ -466,21 +466,11 @@ static int ieee80211_stop(struct net_dev
cancel_work_sync(&sdata->u.mgd.monitor_work);
cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work);
- /*
- * When we get here, the interface is marked down.
- * Call synchronize_rcu() to wait for the RX path
- * should it be using the interface and enqueuing
- * frames at this very time on another CPU.
- */
- synchronize_rcu();
- skb_queue_purge(&sdata->u.mgd.skb_queue);
/* fall through */
case NL80211_IFTYPE_ADHOC:
if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
del_timer_sync(&sdata->u.ibss.timer);
cancel_work_sync(&sdata->u.ibss.work);
- synchronize_rcu();
- skb_queue_purge(&sdata->u.ibss.skb_queue);
}
/* fall through */
case NL80211_IFTYPE_MESH_POINT:
@@ -496,6 +486,15 @@ static int ieee80211_stop(struct net_dev
}
/* fall through */
default:
+ /*
+ * When we get here, the interface is marked down.
+ * Call synchronize_rcu() to wait for the RX path
+ * should it be using the interface and enqueuing
+ * frames at this very time on another CPU.
+ */
+ synchronize_rcu();
+ skb_queue_purge(&sdata->skb_queue);
+
if (local->scan_sdata == sdata)
ieee80211_scan_cancel(local);
@@ -722,6 +721,8 @@ static void ieee80211_setup_sdata(struct
/* only monitor differs */
sdata->dev->type = ARPHRD_ETHER;
+ skb_queue_head_init(&sdata->skb_queue);
+
switch (type) {
case NL80211_IFTYPE_AP:
skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
--- wireless-testing.orig/net/mac80211/mesh.c 2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c 2010-05-28 20:36:59.000000000 +0200
@@ -537,15 +537,6 @@ void ieee80211_stop_mesh(struct ieee8021
* it no longer is.
*/
cancel_work_sync(&sdata->u.mesh.work);
-
- /*
- * When we get here, the interface is marked down.
- * Call synchronize_rcu() to wait for the RX path
- * should it be using the interface and enqueuing
- * frames at this very time on another CPU.
- */
- rcu_barrier(); /* Wait for RX path and call_rcu()'s */
- skb_queue_purge(&sdata->u.mesh.skb_queue);
}
static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
@@ -650,7 +641,7 @@ static void ieee80211_mesh_work(struct w
if (local->scanning)
return;
- while ((skb = skb_dequeue(&ifmsh->skb_queue)))
+ while ((skb = skb_dequeue(&sdata->skb_queue)))
ieee80211_mesh_rx_queued_mgmt(sdata, skb);
if (ifmsh->preq_queue_len &&
@@ -690,7 +681,6 @@ void ieee80211_mesh_init_sdata(struct ie
setup_timer(&ifmsh->housekeeping_timer,
ieee80211_mesh_housekeeping_timer,
(unsigned long) sdata);
- skb_queue_head_init(&sdata->u.mesh.skb_queue);
ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
@@ -750,7 +740,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_
case IEEE80211_STYPE_ACTION:
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
- skb_queue_tail(&ifmsh->skb_queue, skb);
+ skb_queue_tail(&sdata->skb_queue, skb);
ieee80211_queue_work(&local->hw, &ifmsh->work);
return RX_QUEUED;
}
--- wireless-testing.orig/net/mac80211/mlme.c 2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2010-05-28 20:36:59.000000000 +0200
@@ -1652,7 +1652,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgm
case IEEE80211_STYPE_DEAUTH:
case IEEE80211_STYPE_DISASSOC:
case IEEE80211_STYPE_ACTION:
- skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
+ skb_queue_tail(&sdata->skb_queue, skb);
ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
return RX_QUEUED;
}
@@ -1810,7 +1810,7 @@ static void ieee80211_sta_work(struct wo
ifmgd = &sdata->u.mgd;
/* first process frames to avoid timing out while a frame is pending */
- while ((skb = skb_dequeue(&ifmgd->skb_queue)))
+ while ((skb = skb_dequeue(&sdata->skb_queue)))
ieee80211_sta_rx_queued_mgmt(sdata, skb);
/* then process the rest of the work */
@@ -1967,7 +1967,6 @@ void ieee80211_sta_setup_sdata(struct ie
(unsigned long) sdata);
setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
(unsigned long) sdata);
- skb_queue_head_init(&ifmgd->skb_queue);
ifmgd->flags = 0;
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 3/7] mac80211: use common work struct
2010-05-28 18:53 [RFC 0/7] mac80211: preparations for blocking ampdu_action Johannes Berg
2010-05-28 18:53 ` [RFC 1/7] mac80211: simplify station/aggregation code Johannes Berg
2010-05-28 18:53 ` [RFC 2/7] mac80211: use common skb queue Johannes Berg
@ 2010-05-28 18:53 ` Johannes Berg
2010-05-28 18:53 ` [RFC 4/7] mac80211: use common work function Johannes Berg
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
To: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
IBSS, managed and mesh modes all have their
own work struct, and in the future we want
to also use it in other modes to process
frames from the now common skb queue.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/ibss.c | 14 +++++++-------
net/mac80211/ieee80211_i.h | 4 +---
net/mac80211/iface.c | 4 ++--
net/mac80211/mesh.c | 21 ++++++++++-----------
net/mac80211/mesh_hwmp.c | 4 ++--
net/mac80211/mesh_pathtbl.c | 4 ++--
net/mac80211/mlme.c | 13 ++++++-------
7 files changed, 30 insertions(+), 34 deletions(-)
--- wireless-testing.orig/net/mac80211/ibss.c 2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c 2010-05-28 20:37:06.000000000 +0200
@@ -761,7 +761,7 @@ static void ieee80211_ibss_rx_queued_mgm
static void ieee80211_ibss_work(struct work_struct *work)
{
struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data, u.ibss.work);
+ container_of(work, struct ieee80211_sub_if_data, work);
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_ibss *ifibss;
struct sk_buff *skb;
@@ -804,7 +804,7 @@ static void ieee80211_queue_ibss_work(st
struct ieee80211_local *local = sdata->local;
set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
- ieee80211_queue_work(&local->hw, &ifibss->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
static void ieee80211_ibss_timer(unsigned long data)
@@ -827,7 +827,7 @@ void ieee80211_ibss_quiesce(struct ieee8
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- cancel_work_sync(&ifibss->work);
+ cancel_work_sync(&sdata->work);
if (del_timer_sync(&ifibss->timer))
ifibss->timer_running = true;
}
@@ -847,7 +847,7 @@ void ieee80211_ibss_setup_sdata(struct i
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- INIT_WORK(&ifibss->work, ieee80211_ibss_work);
+ INIT_WORK(&sdata->work, ieee80211_ibss_work);
setup_timer(&ifibss->timer, ieee80211_ibss_timer,
(unsigned long) sdata);
}
@@ -890,7 +890,7 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_
case IEEE80211_STYPE_PROBE_REQ:
case IEEE80211_STYPE_AUTH:
skb_queue_tail(&sdata->skb_queue, skb);
- ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
return RX_QUEUED;
}
@@ -956,7 +956,7 @@ int ieee80211_ibss_join(struct ieee80211
ieee80211_recalc_idle(sdata->local);
set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
- ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->work);
return 0;
}
@@ -967,7 +967,7 @@ int ieee80211_ibss_leave(struct ieee8021
del_timer_sync(&sdata->u.ibss.timer);
clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
- cancel_work_sync(&sdata->u.ibss.work);
+ cancel_work_sync(&sdata->work);
clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
sta_info_flush(sdata->local, sdata);
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2010-05-28 20:37:06.000000000 +0200
@@ -325,7 +325,6 @@ struct ieee80211_if_managed {
struct timer_list conn_mon_timer;
struct timer_list bcn_mon_timer;
struct timer_list chswitch_timer;
- struct work_struct work;
struct work_struct monitor_work;
struct work_struct chswitch_work;
struct work_struct beacon_connection_loss_work;
@@ -384,7 +383,6 @@ enum ieee80211_ibss_request {
struct ieee80211_if_ibss {
struct timer_list timer;
- struct work_struct work;
unsigned long request;
unsigned long last_scan_completed;
@@ -412,7 +410,6 @@ struct ieee80211_if_ibss {
};
struct ieee80211_if_mesh {
- struct work_struct work;
struct timer_list housekeeping_timer;
struct timer_list mesh_path_timer;
struct timer_list mesh_path_root_timer;
@@ -512,6 +509,7 @@ struct ieee80211_sub_if_data {
u16 sequence_number;
+ struct work_struct work;
struct sk_buff_head skb_queue;
/*
--- wireless-testing.orig/net/mac80211/mlme.c 2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2010-05-28 20:37:06.000000000 +0200
@@ -1653,7 +1653,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgm
case IEEE80211_STYPE_DISASSOC:
case IEEE80211_STYPE_ACTION:
skb_queue_tail(&sdata->skb_queue, skb);
- ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
return RX_QUEUED;
}
@@ -1779,13 +1779,13 @@ static void ieee80211_sta_timer(unsigned
return;
}
- ieee80211_queue_work(&local->hw, &ifmgd->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
static void ieee80211_sta_work(struct work_struct *work)
{
struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data, u.mgd.work);
+ container_of(work, struct ieee80211_sub_if_data, work);
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd;
struct sk_buff *skb;
@@ -1906,8 +1906,7 @@ static void ieee80211_restart_sta_timer(
ieee80211_queue_work(&sdata->local->hw,
&sdata->u.mgd.monitor_work);
/* and do all the other regular work too */
- ieee80211_queue_work(&sdata->local->hw,
- &sdata->u.mgd.work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->work);
}
}
@@ -1922,7 +1921,7 @@ void ieee80211_sta_quiesce(struct ieee80
* time -- the code here is properly synchronised.
*/
- cancel_work_sync(&ifmgd->work);
+ cancel_work_sync(&sdata->work);
cancel_work_sync(&ifmgd->beacon_connection_loss_work);
if (del_timer_sync(&ifmgd->timer))
set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
@@ -1954,7 +1953,7 @@ void ieee80211_sta_setup_sdata(struct ie
struct ieee80211_if_managed *ifmgd;
ifmgd = &sdata->u.mgd;
- INIT_WORK(&ifmgd->work, ieee80211_sta_work);
+ INIT_WORK(&sdata->work, ieee80211_sta_work);
INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
INIT_WORK(&ifmgd->beacon_connection_loss_work,
--- wireless-testing.orig/net/mac80211/iface.c 2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c 2010-05-28 20:37:06.000000000 +0200
@@ -461,7 +461,7 @@ static int ieee80211_stop(struct net_dev
* whether the interface is running, which, at this point,
* it no longer is.
*/
- cancel_work_sync(&sdata->u.mgd.work);
+ cancel_work_sync(&sdata->work);
cancel_work_sync(&sdata->u.mgd.chswitch_work);
cancel_work_sync(&sdata->u.mgd.monitor_work);
cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work);
@@ -470,7 +470,7 @@ static int ieee80211_stop(struct net_dev
case NL80211_IFTYPE_ADHOC:
if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
del_timer_sync(&sdata->u.ibss.timer);
- cancel_work_sync(&sdata->u.ibss.work);
+ cancel_work_sync(&sdata->work);
}
/* fall through */
case NL80211_IFTYPE_MESH_POINT:
--- wireless-testing.orig/net/mac80211/mesh.c 2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c 2010-05-28 20:37:06.000000000 +0200
@@ -54,7 +54,7 @@ static void ieee80211_mesh_housekeeping_
return;
}
- ieee80211_queue_work(&local->hw, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
/**
@@ -345,7 +345,7 @@ static void ieee80211_mesh_path_timer(un
return;
}
- ieee80211_queue_work(&local->hw, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
static void ieee80211_mesh_path_root_timer(unsigned long data)
@@ -362,7 +362,7 @@ static void ieee80211_mesh_path_root_tim
return;
}
- ieee80211_queue_work(&local->hw, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
@@ -485,7 +485,7 @@ void ieee80211_mesh_quiesce(struct ieee8
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
/* might restart the timer but that doesn't matter */
- cancel_work_sync(&ifmsh->work);
+ cancel_work_sync(&sdata->work);
/* use atomic bitops in case both timers fire at the same time */
@@ -518,7 +518,7 @@ void ieee80211_start_mesh(struct ieee802
set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
ieee80211_mesh_root_setup(ifmsh);
- ieee80211_queue_work(&local->hw, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED |
@@ -536,7 +536,7 @@ void ieee80211_stop_mesh(struct ieee8021
* whether the interface is running, which, at this point,
* it no longer is.
*/
- cancel_work_sync(&sdata->u.mesh.work);
+ cancel_work_sync(&sdata->work);
}
static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
@@ -630,7 +630,7 @@ static void ieee80211_mesh_rx_queued_mgm
static void ieee80211_mesh_work(struct work_struct *work)
{
struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data, u.mesh.work);
+ container_of(work, struct ieee80211_sub_if_data, work);
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct sk_buff *skb;
@@ -669,7 +669,7 @@ void ieee80211_mesh_notify_scan_complete
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list)
if (ieee80211_vif_is_mesh(&sdata->vif))
- ieee80211_queue_work(&local->hw, &sdata->u.mesh.work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
rcu_read_unlock();
}
@@ -677,7 +677,7 @@ void ieee80211_mesh_init_sdata(struct ie
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- INIT_WORK(&ifmsh->work, ieee80211_mesh_work);
+ INIT_WORK(&sdata->work, ieee80211_mesh_work);
setup_timer(&ifmsh->housekeeping_timer,
ieee80211_mesh_housekeeping_timer,
(unsigned long) sdata);
@@ -726,7 +726,6 @@ ieee80211_rx_result
ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
{
struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_mgmt *mgmt;
u16 fc;
@@ -741,7 +740,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
skb_queue_tail(&sdata->skb_queue, skb);
- ieee80211_queue_work(&local->hw, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
return RX_QUEUED;
}
--- wireless-testing.orig/net/mac80211/mesh_hwmp.c 2010-05-28 20:35:59.000000000 +0200
+++ wireless-testing/net/mac80211/mesh_hwmp.c 2010-05-28 20:37:06.000000000 +0200
@@ -805,14 +805,14 @@ static void mesh_queue_preq(struct mesh_
spin_unlock(&ifmsh->mesh_preq_queue_lock);
if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
- ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->work);
else if (time_before(jiffies, ifmsh->last_preq)) {
/* avoid long wait if did not send preqs for a long time
* and jiffies wrapped around
*/
ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
- ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->work);
} else
mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
min_preq_int_jiff(sdata));
--- wireless-testing.orig/net/mac80211/mesh_pathtbl.c 2010-05-28 20:35:59.000000000 +0200
+++ wireless-testing/net/mac80211/mesh_pathtbl.c 2010-05-28 20:37:06.000000000 +0200
@@ -315,7 +315,7 @@ int mesh_path_add(u8 *dst, struct ieee80
read_unlock(&pathtbl_resize_lock);
if (grow) {
set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
- ieee80211_queue_work(&local->hw, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
return 0;
@@ -425,7 +425,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struc
read_unlock(&pathtbl_resize_lock);
if (grow) {
set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
- ieee80211_queue_work(&local->hw, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
return 0;
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 4/7] mac80211: use common work function
2010-05-28 18:53 [RFC 0/7] mac80211: preparations for blocking ampdu_action Johannes Berg
` (2 preceding siblings ...)
2010-05-28 18:53 ` [RFC 3/7] mac80211: use common work struct Johannes Berg
@ 2010-05-28 18:53 ` Johannes Berg
2010-05-28 18:53 ` [RFC 5/7] mac80211: common work skb freeing Johannes Berg
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
To: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
Even with the previous patch, IBSS, managed
and mesh modes all attach their own work
function to the shared work struct, which
means some duplicated code. Change that to
only have a frame processing function and a
further work function for each of them and
share some common code.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/ibss.c | 29 ++-------------------
net/mac80211/ieee80211_i.h | 11 +++++++
net/mac80211/iface.c | 62 +++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/mesh.c | 20 ++------------
net/mac80211/mlme.c | 35 ++-----------------------
5 files changed, 84 insertions(+), 73 deletions(-)
--- wireless-testing.orig/net/mac80211/ibss.c 2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c 2010-05-28 20:37:08.000000000 +0200
@@ -727,8 +727,8 @@ static void ieee80211_rx_mgmt_beacon(str
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);
}
-static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
+void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
struct ieee80211_rx_status *rx_status;
struct ieee80211_mgmt *mgmt;
@@ -758,29 +758,9 @@ static void ieee80211_ibss_rx_queued_mgm
kfree_skb(skb);
}
-static void ieee80211_ibss_work(struct work_struct *work)
+void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
{
- struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data, work);
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_ibss *ifibss;
- struct sk_buff *skb;
-
- if (WARN_ON(local->suspended))
- return;
-
- if (!ieee80211_sdata_running(sdata))
- return;
-
- if (local->scanning)
- return;
-
- if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_ADHOC))
- return;
- ifibss = &sdata->u.ibss;
-
- while ((skb = skb_dequeue(&sdata->skb_queue)))
- ieee80211_ibss_rx_queued_mgmt(sdata, skb);
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request))
return;
@@ -847,7 +827,6 @@ void ieee80211_ibss_setup_sdata(struct i
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- INIT_WORK(&sdata->work, ieee80211_ibss_work);
setup_timer(&ifibss->timer, ieee80211_ibss_timer,
(unsigned long) sdata);
}
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2010-05-28 20:37:08.000000000 +0200
@@ -998,6 +998,9 @@ void ieee80211_sta_process_chanswitch(st
u64 timestamp);
void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
+void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
+void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb);
/* IBSS code */
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
@@ -1012,6 +1015,14 @@ int ieee80211_ibss_join(struct ieee80211
int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata);
+void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata);
+void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb);
+
+/* mesh code */
+void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata);
+void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb);
/* scan/BSS handling */
void ieee80211_scan_work(struct work_struct *work);
--- wireless-testing.orig/net/mac80211/iface.c 2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c 2010-05-28 20:37:08.000000000 +0200
@@ -704,6 +704,67 @@ static void ieee80211_if_setup(struct ne
dev->destructor = free_netdev;
}
+static void ieee80211_iface_work(struct work_struct *work)
+{
+ struct ieee80211_sub_if_data *sdata =
+ container_of(work, struct ieee80211_sub_if_data, work);
+ struct ieee80211_local *local = sdata->local;
+ struct sk_buff *skb;
+
+ if (!ieee80211_sdata_running(sdata))
+ return;
+
+ if (local->scanning)
+ return;
+
+ /*
+ * ieee80211_queue_work() should have picked up most cases,
+ * here we'll pick the the rest.
+ */
+ if (WARN(local->suspended,
+ "interface work scheduled while going to suspend\n"))
+ return;
+
+ /* first process frames */
+ while ((skb = skb_dequeue(&sdata->skb_queue))) {
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
+ ieee80211_sta_rx_queued_mgmt(sdata, skb);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ ieee80211_ibss_rx_queued_mgmt(sdata, skb);
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ if (!ieee80211_vif_is_mesh(&sdata->vif))
+ break;
+ ieee80211_mesh_rx_queued_mgmt(sdata, skb);
+ break;
+ default:
+ WARN(1, "frame for unexpected interface type");
+ kfree_skb(skb);
+ break;
+ }
+ }
+
+ /* then other type-dependent work */
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
+ ieee80211_sta_work(sdata);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ ieee80211_ibss_work(sdata);
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ if (!ieee80211_vif_is_mesh(&sdata->vif))
+ break;
+ ieee80211_mesh_work(sdata);
+ break;
+ default:
+ break;
+ }
+}
+
+
/*
* Helper function to initialise an interface to a specific type.
*/
@@ -722,6 +783,7 @@ static void ieee80211_setup_sdata(struct
sdata->dev->type = ARPHRD_ETHER;
skb_queue_head_init(&sdata->skb_queue);
+ INIT_WORK(&sdata->work, ieee80211_iface_work);
switch (type) {
case NL80211_IFTYPE_AP:
--- wireless-testing.orig/net/mac80211/mesh.c 2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c 2010-05-28 20:37:08.000000000 +0200
@@ -599,8 +599,8 @@ static void ieee80211_mesh_rx_mgmt_actio
}
}
-static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
+void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
struct ieee80211_rx_status *rx_status;
struct ieee80211_if_mesh *ifmsh;
@@ -627,22 +627,9 @@ static void ieee80211_mesh_rx_queued_mgm
kfree_skb(skb);
}
-static void ieee80211_mesh_work(struct work_struct *work)
+void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
{
- struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data, work);
- struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- struct sk_buff *skb;
-
- if (!ieee80211_sdata_running(sdata))
- return;
-
- if (local->scanning)
- return;
-
- while ((skb = skb_dequeue(&sdata->skb_queue)))
- ieee80211_mesh_rx_queued_mgmt(sdata, skb);
if (ifmsh->preq_queue_len &&
time_after(jiffies,
@@ -677,7 +664,6 @@ void ieee80211_mesh_init_sdata(struct ie
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- INIT_WORK(&sdata->work, ieee80211_mesh_work);
setup_timer(&ifmsh->housekeeping_timer,
ieee80211_mesh_housekeeping_timer,
(unsigned long) sdata);
--- wireless-testing.orig/net/mac80211/mlme.c 2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2010-05-28 20:37:08.000000000 +0200
@@ -1660,8 +1660,8 @@ ieee80211_rx_result ieee80211_sta_rx_mgm
return RX_DROP_MONITOR;
}
-static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
+void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_rx_status *rx_status;
@@ -1782,36 +1782,10 @@ static void ieee80211_sta_timer(unsigned
ieee80211_queue_work(&local->hw, &sdata->work);
}
-static void ieee80211_sta_work(struct work_struct *work)
+void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
{
- struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data, work);
struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_managed *ifmgd;
- struct sk_buff *skb;
-
- if (!ieee80211_sdata_running(sdata))
- return;
-
- if (local->scanning)
- return;
-
- if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
- return;
-
- /*
- * ieee80211_queue_work() should have picked up most cases,
- * here we'll pick the the rest.
- */
- if (WARN(local->suspended, "STA MLME work scheduled while "
- "going to suspend\n"))
- return;
-
- ifmgd = &sdata->u.mgd;
-
- /* first process frames to avoid timing out while a frame is pending */
- while ((skb = skb_dequeue(&sdata->skb_queue)))
- ieee80211_sta_rx_queued_mgmt(sdata, skb);
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
/* then process the rest of the work */
mutex_lock(&ifmgd->mtx);
@@ -1953,7 +1927,6 @@ void ieee80211_sta_setup_sdata(struct ie
struct ieee80211_if_managed *ifmgd;
ifmgd = &sdata->u.mgd;
- INIT_WORK(&sdata->work, ieee80211_sta_work);
INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
INIT_WORK(&ifmgd->beacon_connection_loss_work,
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 5/7] mac80211: common work skb freeing
2010-05-28 18:53 [RFC 0/7] mac80211: preparations for blocking ampdu_action Johannes Berg
` (3 preceding siblings ...)
2010-05-28 18:53 ` [RFC 4/7] mac80211: use common work function Johannes Berg
@ 2010-05-28 18:53 ` Johannes Berg
2010-05-28 18:53 ` [RFC 6/7] mac80211: pull mgmt frame rx into rx handler Johannes Berg
2010-05-28 18:53 ` [RFC 7/7] mac80211: always process blockack action from workqueue Johannes Berg
6 siblings, 0 replies; 8+ messages in thread
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
To: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
All the management processing functions free the
skb after they are done, so this can be done in
the new common code instead.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/ibss.c | 2 --
net/mac80211/iface.c | 3 ++-
net/mac80211/mesh.c | 2 --
net/mac80211/mlme.c | 5 +----
4 files changed, 3 insertions(+), 9 deletions(-)
--- wireless-testing.orig/net/mac80211/ibss.c 2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c 2010-05-28 20:37:10.000000000 +0200
@@ -754,8 +754,6 @@ void ieee80211_ibss_rx_queued_mgmt(struc
ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len);
break;
}
-
- kfree_skb(skb);
}
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
--- wireless-testing.orig/net/mac80211/mesh.c 2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c 2010-05-28 20:37:10.000000000 +0200
@@ -623,8 +623,6 @@ void ieee80211_mesh_rx_queued_mgmt(struc
ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
break;
}
-
- kfree_skb(skb);
}
void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
--- wireless-testing.orig/net/mac80211/mlme.c 2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2010-05-28 20:37:10.000000000 +0200
@@ -1754,7 +1754,7 @@ void ieee80211_sta_rx_queued_mgmt(struct
default:
WARN(1, "unexpected: %d", rma);
}
- goto out;
+ return;
}
mutex_unlock(&ifmgd->mtx);
@@ -1762,9 +1762,6 @@ void ieee80211_sta_rx_queued_mgmt(struct
if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
(fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
-
- out:
- kfree_skb(skb);
}
static void ieee80211_sta_timer(unsigned long data)
--- wireless-testing.orig/net/mac80211/iface.c 2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c 2010-05-28 20:37:10.000000000 +0200
@@ -741,9 +741,10 @@ static void ieee80211_iface_work(struct
break;
default:
WARN(1, "frame for unexpected interface type");
- kfree_skb(skb);
break;
}
+
+ kfree_skb(skb);
}
/* then other type-dependent work */
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 6/7] mac80211: pull mgmt frame rx into rx handler
2010-05-28 18:53 [RFC 0/7] mac80211: preparations for blocking ampdu_action Johannes Berg
` (4 preceding siblings ...)
2010-05-28 18:53 ` [RFC 5/7] mac80211: common work skb freeing Johannes Berg
@ 2010-05-28 18:53 ` Johannes Berg
2010-05-28 18:53 ` [RFC 7/7] mac80211: always process blockack action from workqueue Johannes Berg
6 siblings, 0 replies; 8+ messages in thread
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
To: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
Some code is duplicated between ibss, mesh and
managed mode regarding the queueing of management
frames. Since all modes now use a common skb
queue and a common work function, we can pull
the queueing code into the rx handler directly
and remove the duplicated length checks etc.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/ibss.c | 26 -------------------
net/mac80211/ieee80211_i.h | 4 --
net/mac80211/mesh.c | 25 ------------------
net/mac80211/mesh.h | 2 -
net/mac80211/mlme.c | 27 -------------------
net/mac80211/rx.c | 61 +++++++++++++++++++++++++++++++++++----------
6 files changed, 48 insertions(+), 97 deletions(-)
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2010-05-28 20:37:11.000000000 +0200
@@ -985,8 +985,6 @@ int ieee80211_mgd_action(struct ieee8021
enum nl80211_channel_type channel_type,
bool channel_type_valid,
const u8 *buf, size_t len, u64 *cookie);
-ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb);
void ieee80211_send_pspoll(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency);
@@ -1005,8 +1003,6 @@ void ieee80211_sta_rx_queued_mgmt(struct
/* IBSS code */
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
-ieee80211_rx_result
-ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
u8 *bssid, u8 *addr, u32 supp_rates,
gfp_t gfp);
--- wireless-testing.orig/net/mac80211/mesh.h 2010-05-28 20:35:58.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.h 2010-05-28 20:37:11.000000000 +0200
@@ -237,8 +237,6 @@ void ieee80211s_update_metric(struct iee
struct sta_info *stainfo, struct sk_buff *skb);
void ieee80211s_stop(void);
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
-ieee80211_rx_result
-ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh);
--- wireless-testing.orig/net/mac80211/ibss.c 2010-05-28 20:37:10.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c 2010-05-28 20:37:11.000000000 +0200
@@ -848,32 +848,6 @@ void ieee80211_ibss_notify_scan_complete
mutex_unlock(&local->iflist_mtx);
}
-ieee80211_rx_result
-ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_mgmt *mgmt;
- u16 fc;
-
- if (skb->len < 24)
- return RX_DROP_MONITOR;
-
- mgmt = (struct ieee80211_mgmt *) skb->data;
- fc = le16_to_cpu(mgmt->frame_control);
-
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_PROBE_RESP:
- case IEEE80211_STYPE_BEACON:
- case IEEE80211_STYPE_PROBE_REQ:
- case IEEE80211_STYPE_AUTH:
- skb_queue_tail(&sdata->skb_queue, skb);
- ieee80211_queue_work(&local->hw, &sdata->work);
- return RX_QUEUED;
- }
-
- return RX_DROP_MONITOR;
-}
-
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params)
{
--- wireless-testing.orig/net/mac80211/mesh.c 2010-05-28 20:37:10.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c 2010-05-28 20:37:11.000000000 +0200
@@ -705,28 +705,3 @@ void ieee80211_mesh_init_sdata(struct ie
INIT_LIST_HEAD(&ifmsh->preq_queue.list);
spin_lock_init(&ifmsh->mesh_preq_queue_lock);
}
-
-ieee80211_rx_result
-ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_mgmt *mgmt;
- u16 fc;
-
- if (skb->len < 24)
- return RX_DROP_MONITOR;
-
- mgmt = (struct ieee80211_mgmt *) skb->data;
- fc = le16_to_cpu(mgmt->frame_control);
-
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_ACTION:
- case IEEE80211_STYPE_PROBE_RESP:
- case IEEE80211_STYPE_BEACON:
- skb_queue_tail(&sdata->skb_queue, skb);
- ieee80211_queue_work(&local->hw, &sdata->work);
- return RX_QUEUED;
- }
-
- return RX_CONTINUE;
-}
--- wireless-testing.orig/net/mac80211/mlme.c 2010-05-28 20:37:10.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2010-05-28 20:37:11.000000000 +0200
@@ -1633,33 +1633,6 @@ static void ieee80211_rx_mgmt_beacon(str
ieee80211_bss_info_change_notify(sdata, changed);
}
-ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_mgmt *mgmt;
- u16 fc;
-
- if (skb->len < 24)
- return RX_DROP_MONITOR;
-
- mgmt = (struct ieee80211_mgmt *) skb->data;
- fc = le16_to_cpu(mgmt->frame_control);
-
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_PROBE_RESP:
- case IEEE80211_STYPE_BEACON:
- case IEEE80211_STYPE_DEAUTH:
- case IEEE80211_STYPE_DISASSOC:
- case IEEE80211_STYPE_ACTION:
- skb_queue_tail(&sdata->skb_queue, skb);
- ieee80211_queue_work(&local->hw, &sdata->work);
- return RX_QUEUED;
- }
-
- return RX_DROP_MONITOR;
-}
-
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
--- wireless-testing.orig/net/mac80211/rx.c 2010-05-28 20:35:58.000000000 +0200
+++ wireless-testing/net/mac80211/rx.c 2010-05-28 20:37:11.000000000 +0200
@@ -1936,8 +1936,11 @@ ieee80211_rx_h_action(struct ieee80211_r
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
break;
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ skb_queue_tail(&sdata->skb_queue, rx->skb);
+ ieee80211_queue_work(&local->hw, &sdata->work);
+ return RX_QUEUED;
+ }
switch (mgmt->u.action.u.addba_req.action_code) {
case WLAN_ACTION_ADDBA_REQ:
@@ -1989,7 +1992,9 @@ ieee80211_rx_h_action(struct ieee80211_r
if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
break;
- return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+ skb_queue_tail(&sdata->skb_queue, rx->skb);
+ ieee80211_queue_work(&local->hw, &sdata->work);
+ return RX_QUEUED;
}
break;
case WLAN_CATEGORY_SA_QUERY:
@@ -2007,9 +2012,11 @@ ieee80211_rx_h_action(struct ieee80211_r
break;
case WLAN_CATEGORY_MESH_PLINK:
case WLAN_CATEGORY_MESH_PATH_SEL:
- if (ieee80211_vif_is_mesh(&sdata->vif))
- return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
- break;
+ if (!ieee80211_vif_is_mesh(&sdata->vif))
+ break;
+ skb_queue_tail(&sdata->skb_queue, rx->skb);
+ ieee80211_queue_work(&local->hw, &sdata->work);
+ return RX_QUEUED;
}
/*
@@ -2067,10 +2074,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
ieee80211_rx_result rxs;
+ struct ieee80211_mgmt *mgmt = (void *)rx->skb->data;
+ __le16 stype;
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
return RX_DROP_MONITOR;
+ if (rx->skb->len < 24)
+ return RX_DROP_MONITOR;
+
if (ieee80211_drop_unencrypted_mgmt(rx))
return RX_DROP_UNUSABLE;
@@ -2078,16 +2090,39 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
if (rxs != RX_CONTINUE)
return rxs;
- if (ieee80211_vif_is_mesh(&sdata->vif))
- return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
+ stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE);
+
+ if (!ieee80211_vif_is_mesh(&sdata->vif) &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+ sdata->vif.type != NL80211_IFTYPE_STATION)
+ return RX_DROP_MONITOR;
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
- return ieee80211_ibss_rx_mgmt(sdata, rx->skb);
+ switch (stype) {
+ case cpu_to_le16(IEEE80211_STYPE_BEACON):
+ case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+ /* process for all: mesh, mlme, ibss */
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+ case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+ /* process only for station */
+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
+ return RX_DROP_MONITOR;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
+ case cpu_to_le16(IEEE80211_STYPE_AUTH):
+ /* process only for ibss */
+ if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ return RX_DROP_MONITOR;
+ break;
+ default:
+ return RX_DROP_MONITOR;
+ }
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+ /* queue up frame and kick off work to process it */
+ skb_queue_tail(&sdata->skb_queue, rx->skb);
+ ieee80211_queue_work(&rx->local->hw, &sdata->work);
- return RX_DROP_MONITOR;
+ return RX_QUEUED;
}
static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr,
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 7/7] mac80211: always process blockack action from workqueue
2010-05-28 18:53 [RFC 0/7] mac80211: preparations for blocking ampdu_action Johannes Berg
` (5 preceding siblings ...)
2010-05-28 18:53 ` [RFC 6/7] mac80211: pull mgmt frame rx into rx handler Johannes Berg
@ 2010-05-28 18:53 ` Johannes Berg
6 siblings, 0 replies; 8+ messages in thread
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
To: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
To prepare for making the ampdu_action callback
sleep, make mac80211 always process blockack
action frames from the skb queue. This gets rid
of the current special case for managed mode
interfaces as well.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/iface.c | 35 ++++++++++++++++++++++++++++++++++-
net/mac80211/mlme.c | 38 --------------------------------------
net/mac80211/rx.c | 29 +++++++++++++----------------
3 files changed, 47 insertions(+), 55 deletions(-)
--- wireless-testing.orig/net/mac80211/iface.c 2010-05-28 20:37:10.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c 2010-05-28 20:37:13.000000000 +0200
@@ -727,7 +727,40 @@ static void ieee80211_iface_work(struct
/* first process frames */
while ((skb = skb_dequeue(&sdata->skb_queue))) {
- switch (sdata->vif.type) {
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+
+ if (ieee80211_is_action(mgmt->frame_control) &&
+ mgmt->u.action.category == WLAN_CATEGORY_BACK) {
+ int len = skb->len;
+ struct sta_info *sta;
+
+ rcu_read_lock();
+ sta = sta_info_get(sdata, mgmt->sa);
+ if (sta) {
+ local_bh_disable();
+
+ switch (mgmt->u.action.u.addba_req.action_code) {
+ case WLAN_ACTION_ADDBA_REQ:
+ ieee80211_process_addba_request(
+ local, sta, mgmt, len);
+ break;
+ case WLAN_ACTION_ADDBA_RESP:
+ ieee80211_process_addba_resp(local, sta,
+ mgmt, len);
+ break;
+ case WLAN_ACTION_DELBA:
+ ieee80211_process_delba(sdata, sta,
+ mgmt, len);
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ local_bh_enable();
+ }
+ rcu_read_unlock();
+ } else switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
ieee80211_sta_rx_queued_mgmt(sdata, skb);
break;
--- wireless-testing.orig/net/mac80211/mlme.c 2010-05-28 20:37:11.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2010-05-28 20:37:13.000000000 +0200
@@ -1666,44 +1666,6 @@ void ieee80211_sta_rx_queued_mgmt(struct
break;
case IEEE80211_STYPE_ACTION:
switch (mgmt->u.action.category) {
- case WLAN_CATEGORY_BACK: {
- struct ieee80211_local *local = sdata->local;
- int len = skb->len;
- struct sta_info *sta;
-
- rcu_read_lock();
- sta = sta_info_get(sdata, mgmt->sa);
- if (!sta) {
- rcu_read_unlock();
- break;
- }
-
- local_bh_disable();
-
- switch (mgmt->u.action.u.addba_req.action_code) {
- case WLAN_ACTION_ADDBA_REQ:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.addba_req)))
- break;
- ieee80211_process_addba_request(local, sta, mgmt, len);
- break;
- case WLAN_ACTION_ADDBA_RESP:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.addba_resp)))
- break;
- ieee80211_process_addba_resp(local, sta, mgmt, len);
- break;
- case WLAN_ACTION_DELBA:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.delba)))
- break;
- ieee80211_process_delba(sdata, sta, mgmt, len);
- break;
- }
- local_bh_enable();
- rcu_read_unlock();
- break;
- }
case WLAN_CATEGORY_SPECTRUM_MGMT:
ieee80211_sta_process_chanswitch(sdata,
&mgmt->u.action.u.chan_switch.sw_elem,
--- wireless-testing.orig/net/mac80211/rx.c 2010-05-28 20:37:11.000000000 +0200
+++ wireless-testing/net/mac80211/rx.c 2010-05-28 20:37:13.000000000 +0200
@@ -1936,33 +1936,29 @@ ieee80211_rx_h_action(struct ieee80211_r
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
break;
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- skb_queue_tail(&sdata->skb_queue, rx->skb);
- ieee80211_queue_work(&local->hw, &sdata->work);
- return RX_QUEUED;
- }
-
switch (mgmt->u.action.u.addba_req.action_code) {
case WLAN_ACTION_ADDBA_REQ:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.addba_req)))
- return RX_DROP_MONITOR;
- ieee80211_process_addba_request(local, rx->sta, mgmt, len);
- goto handled;
+ goto invalid;
+ break;
case WLAN_ACTION_ADDBA_RESP:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.addba_resp)))
- break;
- ieee80211_process_addba_resp(local, rx->sta, mgmt, len);
- goto handled;
+ goto invalid;
+ break;
case WLAN_ACTION_DELBA:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.delba)))
- break;
- ieee80211_process_delba(sdata, rx->sta, mgmt, len);
- goto handled;
+ goto invalid;
+ break;
+ default:
+ goto invalid;
}
- break;
+
+ skb_queue_tail(&sdata->skb_queue, rx->skb);
+ ieee80211_queue_work(&local->hw, &sdata->work);
+ return RX_QUEUED;
case WLAN_CATEGORY_SPECTRUM_MGMT:
if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ)
break;
@@ -2019,6 +2015,7 @@ ieee80211_rx_h_action(struct ieee80211_r
return RX_QUEUED;
}
+ invalid:
/*
* For AP mode, hostapd is responsible for handling any action
* frames that we didn't handle, including returning unknown
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-05-28 18:57 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-28 18:53 [RFC 0/7] mac80211: preparations for blocking ampdu_action Johannes Berg
2010-05-28 18:53 ` [RFC 1/7] mac80211: simplify station/aggregation code Johannes Berg
2010-05-28 18:53 ` [RFC 2/7] mac80211: use common skb queue Johannes Berg
2010-05-28 18:53 ` [RFC 3/7] mac80211: use common work struct Johannes Berg
2010-05-28 18:53 ` [RFC 4/7] mac80211: use common work function Johannes Berg
2010-05-28 18:53 ` [RFC 5/7] mac80211: common work skb freeing Johannes Berg
2010-05-28 18:53 ` [RFC 6/7] mac80211: pull mgmt frame rx into rx handler Johannes Berg
2010-05-28 18:53 ` [RFC 7/7] mac80211: always process blockack action from workqueue Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).