From 47846c9b0c10808d9337d2e7d09361f3e0a0a71a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 25 Nov 2009 17:46:19 +0100 Subject: mac80211: reduce reliance on netdev For bluetooth 3, we will most likely not have a netdev for a virtual interface (sdata), so prepare for that by reducing the reliance on having a netdev. This patch moves the name and address fields into the sdata struct and uses them from there all over. Some work is needed to keep them sync'ed, but that's not a lot of work and in slow paths anyway. In doing so, this also reduces the number of pointer dereferences in many places, because of things like sdata->dev->dev_addr becoming sdata->vif.addr. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211/pm.c') diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index e535f1c988fe..05ccaadb6a0e 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -102,7 +102,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) conf.vif = &sdata->vif; conf.type = sdata->vif.type; - conf.mac_addr = sdata->dev->dev_addr; + conf.mac_addr = sdata->vif.addr; drv_remove_interface(local, &conf); } -- cgit v1.2.3 From 12375ef933fa8271396ed0c1e318cb1bd2e2689d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 25 Nov 2009 20:30:31 +0100 Subject: mac80211: trace interface name It's not all that useful to have the vif/sdata pointer, we'd rather refer to the interfaces by their name. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-rx.c | 6 ++---- net/mac80211/agg-tx.c | 7 +++---- net/mac80211/driver-ops.h | 29 +++++++++++++++-------------- net/mac80211/driver-trace.h | 38 ++++++++++++++++++++------------------ net/mac80211/key.c | 4 ++-- net/mac80211/main.c | 3 +-- net/mac80211/pm.c | 2 +- net/mac80211/rx.c | 2 +- net/mac80211/sta_info.c | 6 +++--- net/mac80211/util.c | 2 +- 10 files changed, 49 insertions(+), 50 deletions(-) (limited to 'net/mac80211/pm.c') diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 37ecdeddd5ac..a978e666ed6f 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -41,8 +41,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, sta->sta.addr, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - if (drv_ampdu_action(local, &sta->sdata->vif, - IEEE80211_AMPDU_RX_STOP, + if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, &sta->sta, tid, NULL)) printk(KERN_DEBUG "HW problem - can not stop rx " "aggregation for tid %d\n", tid); @@ -280,8 +279,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, goto end; } - ret = drv_ampdu_action(local, &sta->sdata->vif, - IEEE80211_AMPDU_RX_START, + ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, &sta->sta, tid, &start_seq_num); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 209be60564ce..ceda36618d3c 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -144,7 +144,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, *state = HT_AGG_STATE_REQ_STOP_BA_MSK | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); - ret = drv_ampdu_action(local, &sta->sdata->vif, + ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_TX_STOP, &sta->sta, tid, NULL); @@ -303,8 +303,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) start_seq_num = sta->tid_seq[tid]; - ret = drv_ampdu_action(local, &sdata->vif, - IEEE80211_AMPDU_TX_START, + ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, pubsta, tid, &start_seq_num); if (ret) { @@ -420,7 +419,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, ieee80211_agg_splice_finish(local, sta, tid); spin_unlock(&local->ampdu_lock); - drv_ampdu_action(local, &sta->sdata->vif, + drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_TX_OPERATIONAL, &sta->sta, tid, NULL); } diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index a4002657dac5..727e4cf7b8a6 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -39,7 +39,7 @@ static inline int drv_add_interface(struct ieee80211_local *local, struct ieee80211_if_init_conf *conf) { int ret = local->ops->add_interface(&local->hw, conf); - trace_drv_add_interface(local, conf->vif, ret); + trace_drv_add_interface(local, vif_to_sdata(conf->vif), ret); return ret; } @@ -47,7 +47,7 @@ static inline void drv_remove_interface(struct ieee80211_local *local, struct ieee80211_if_init_conf *conf) { local->ops->remove_interface(&local->hw, conf); - trace_drv_remove_interface(local, conf->vif); + trace_drv_remove_interface(local, vif_to_sdata(conf->vif)); } static inline int drv_config(struct ieee80211_local *local, u32 changed) @@ -58,13 +58,13 @@ static inline int drv_config(struct ieee80211_local *local, u32 changed) } static inline void drv_bss_info_changed(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, struct ieee80211_bss_conf *info, u32 changed) { if (local->ops->bss_info_changed) - local->ops->bss_info_changed(&local->hw, vif, info, changed); - trace_drv_bss_info_changed(local, vif, info, changed); + local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); + trace_drv_bss_info_changed(local, sdata, info, changed); } static inline u64 drv_prepare_multicast(struct ieee80211_local *local, @@ -106,12 +106,13 @@ static inline int drv_set_tim(struct ieee80211_local *local, } static inline int drv_set_key(struct ieee80211_local *local, - enum set_key_cmd cmd, struct ieee80211_vif *vif, + enum set_key_cmd cmd, + struct ieee80211_sub_if_data *sdata, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - int ret = local->ops->set_key(&local->hw, cmd, vif, sta, key); - trace_drv_set_key(local, cmd, vif, sta, key, ret); + int ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); + trace_drv_set_key(local, cmd, sdata, sta, key, ret); return ret; } @@ -179,13 +180,13 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local, } static inline void drv_sta_notify(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, enum sta_notify_cmd cmd, struct ieee80211_sta *sta) { if (local->ops->sta_notify) - local->ops->sta_notify(&local->hw, vif, cmd, sta); - trace_drv_sta_notify(local, vif, cmd, sta); + local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); + trace_drv_sta_notify(local, sdata, cmd, sta); } static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, @@ -239,16 +240,16 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) } static inline int drv_ampdu_action(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { int ret = -EOPNOTSUPP; if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(&local->hw, vif, action, + ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, sta, tid, ssn); - trace_drv_ampdu_action(local, vif, action, sta, tid, ssn, ret); + trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, ret); return ret; } diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 7b155b947209..ee2d19a25ce1 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -25,10 +25,12 @@ static inline void trace_ ## name(proto) {} #define STA_PR_FMT " sta:%pM" #define STA_PR_ARG __entry->sta_addr -#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, vif) -#define VIF_ASSIGN __entry->vif_type = vif ? vif->type : 0; __entry->vif = vif -#define VIF_PR_FMT " vif:%p(%d)" -#define VIF_PR_ARG __entry->vif, __entry->vif_type +#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ + __string(vif_name, sdata->dev ? sdata->dev->name : "") +#define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ + __assign_str(vif_name, sdata->dev ? sdata->dev->name : "") +#define VIF_PR_FMT " vif:%s(%d)" +#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type TRACE_EVENT(drv_start, TP_PROTO(struct ieee80211_local *local, int ret), @@ -70,10 +72,10 @@ TRACE_EVENT(drv_stop, TRACE_EVENT(drv_add_interface, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, int ret), - TP_ARGS(local, vif, ret), + TP_ARGS(local, sdata, ret), TP_STRUCT__entry( LOCAL_ENTRY @@ -85,7 +87,7 @@ TRACE_EVENT(drv_add_interface, TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - memcpy(__entry->addr, vif->addr, 6); + memcpy(__entry->addr, sdata->vif.addr, 6); __entry->ret = ret; ), @@ -96,9 +98,9 @@ TRACE_EVENT(drv_add_interface, ); TRACE_EVENT(drv_remove_interface, - TP_PROTO(struct ieee80211_local *local, struct ieee80211_vif *vif), + TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), - TP_ARGS(local, vif), + TP_ARGS(local, sdata), TP_STRUCT__entry( LOCAL_ENTRY @@ -109,7 +111,7 @@ TRACE_EVENT(drv_remove_interface, TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - memcpy(__entry->addr, vif->addr, 6); + memcpy(__entry->addr, sdata->vif.addr, 6); ), TP_printk( @@ -163,11 +165,11 @@ TRACE_EVENT(drv_config, TRACE_EVENT(drv_bss_info_changed, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, struct ieee80211_bss_conf *info, u32 changed), - TP_ARGS(local, vif, info, changed), + TP_ARGS(local, sdata, info, changed), TP_STRUCT__entry( LOCAL_ENTRY @@ -291,11 +293,11 @@ TRACE_EVENT(drv_set_tim, TRACE_EVENT(drv_set_key, TP_PROTO(struct ieee80211_local *local, - enum set_key_cmd cmd, struct ieee80211_vif *vif, + enum set_key_cmd cmd, struct ieee80211_sub_if_data *sdata, struct ieee80211_sta *sta, struct ieee80211_key_conf *key, int ret), - TP_ARGS(local, cmd, vif, sta, key, ret), + TP_ARGS(local, cmd, sdata, sta, key, ret), TP_STRUCT__entry( LOCAL_ENTRY @@ -489,11 +491,11 @@ TRACE_EVENT(drv_set_rts_threshold, TRACE_EVENT(drv_sta_notify, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, enum sta_notify_cmd cmd, struct ieee80211_sta *sta), - TP_ARGS(local, vif, cmd, sta), + TP_ARGS(local, sdata, cmd, sta), TP_STRUCT__entry( LOCAL_ENTRY @@ -654,12 +656,12 @@ TRACE_EVENT(drv_tx_last_beacon, TRACE_EVENT(drv_ampdu_action, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, int ret), - TP_ARGS(local, vif, action, sta, tid, ssn, ret), + TP_ARGS(local, sdata, action, sta, tid, ssn, ret), TP_STRUCT__entry( LOCAL_ENTRY diff --git a/net/mac80211/key.c b/net/mac80211/key.c index ac1a777674f6..32ee6d0ee34d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -139,7 +139,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) struct ieee80211_sub_if_data, u.ap); - ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); + ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); if (!ret) { spin_lock_bh(&todo_lock); @@ -181,7 +181,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) struct ieee80211_sub_if_data, u.ap); - ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif, + ret = drv_set_key(key->local, DISABLE_KEY, sdata, sta, &key->conf); if (ret) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index dbf05b4dd003..98320a94c270 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -222,8 +222,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, } } - drv_bss_info_changed(local, &sdata->vif, - &sdata->vif.bss_conf, changed); + drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); } u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 05ccaadb6a0e..05e161c3cbc5 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -65,7 +65,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, + drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, &sta->sta); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d0136e3da487..ebab696def5b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1021,7 +1021,7 @@ static void ap_sta_ps_start(struct sta_info *sta) atomic_inc(&sdata->bss->num_sta_ps); set_sta_flags(sta, WLAN_STA_PS_STA); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); + drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", sdata->name, sta->sta.addr, sta->sta.aid); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 294f1b8b1545..d1a77e79d7a9 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -397,7 +397,7 @@ int sta_info_insert(struct sta_info *sta) struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); + drv_sta_notify(local, sdata, STA_NOTIFY_ADD, &sta->sta); sdata = sta->sdata; } @@ -537,7 +537,7 @@ static void __sta_info_unlink(struct sta_info **sta) struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, + drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, &(*sta)->sta); sdata = (*sta)->sdata; } @@ -876,7 +876,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) struct ieee80211_local *local = sdata->local; int sent, buffered; - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); + drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); if (!skb_queue_empty(&sta->ps_tx_buf)) sta_info_clear_tim_bit(sta); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d45760eae6c7..d54dbe8e09ba 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1066,7 +1066,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, + drv_sta_notify(local, sdata, STA_NOTIFY_ADD, &sta->sta); } spin_unlock_irqrestore(&local->sta_lock, flags); -- cgit v1.2.3 From 9607e6b66a0d25ca63b70d54a4283fa13d8f7c9d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:31 +0100 Subject: mac80211: add ieee80211_sdata_running Instead of always using netif_running(sdata->dev) use ieee80211_sdata_running(sdata) now which is just an inline containing netif_running() for now. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 6 ++---- net/mac80211/ibss.c | 4 ++-- net/mac80211/ieee80211_i.h | 5 +++++ net/mac80211/iface.c | 10 +++++----- net/mac80211/key.c | 4 ++-- net/mac80211/main.c | 2 +- net/mac80211/mesh.c | 2 +- net/mac80211/mlme.c | 8 ++++---- net/mac80211/pm.c | 2 +- net/mac80211/rx.c | 6 +++--- net/mac80211/scan.c | 12 ++++++------ net/mac80211/sta_info.c | 2 +- net/mac80211/status.c | 2 +- net/mac80211/tx.c | 2 +- net/mac80211/util.c | 10 +++++----- 15 files changed, 40 insertions(+), 37 deletions(-) (limited to 'net/mac80211/pm.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 63843e3e576a..fdac1bcbfcc0 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -78,17 +78,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int ret; - if (netif_running(dev)) + if (ieee80211_sdata_running(sdata)) return -EBUSY; if (!nl80211_params_check(type, params)) return -EINVAL; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - ret = ieee80211_if_change_type(sdata, type); if (ret) return ret; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index ef6c6b2401d1..3a61f3ba85c9 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -744,7 +744,7 @@ static void ieee80211_ibss_work(struct work_struct *work) if (WARN_ON(local->suspended)) return; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; if (local->scanning) @@ -827,7 +827,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type != NL80211_IFTYPE_ADHOC) continue; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 88b0ba6c7484..adeae03c26a3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -960,6 +960,11 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local); u32 __ieee80211_recalc_idle(struct ieee80211_local *local); void ieee80211_recalc_idle(struct ieee80211_local *local); +static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) +{ + return netif_running(sdata->dev); +} + /* tx handling */ void ieee80211_clear_tx_pending(struct ieee80211_local *local); void ieee80211_tx_pending(unsigned long data); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a6e6da3cab70..1ceca14331d4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -65,7 +65,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int ret; - if (netif_running(dev)) + if (ieee80211_sdata_running(sdata)) return -EBUSY; ret = eth_mac_addr(dev, addr); @@ -111,7 +111,7 @@ static int ieee80211_open(struct net_device *dev) list_for_each_entry(nsdata, &local->interfaces, list) { struct net_device *ndev = nsdata->dev; - if (ndev != dev && netif_running(ndev)) { + if (ndev != dev && ieee80211_sdata_running(nsdata)) { /* * Allow only a single IBSS interface to be up at any * time. This is restricted because beacon distribution @@ -197,7 +197,7 @@ static int ieee80211_open(struct net_device *dev) struct net_device *ndev = nsdata->dev; /* - * No need to check netif_running since we do not allow + * No need to check running since we do not allow * it to start up with this invalid address. */ if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { @@ -756,7 +756,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, * and goes into the requested mode. */ - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) return -EBUSY; /* Purge and reset type-dependent state. */ @@ -930,7 +930,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) return ieee80211_idle_off(local, "scanning"); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* do not count disabled managed interfaces */ if (sdata->vif.type == NL80211_IFTYPE_STATION && diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 32ee6d0ee34d..8160d9c5372e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -443,7 +443,7 @@ void ieee80211_key_link(struct ieee80211_key *key, add_todo(old_key, KEY_FLAG_TODO_DELETE); add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); spin_unlock_irqrestore(&sdata->local->key_lock, flags); @@ -509,7 +509,7 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) { ASSERT_RTNL(); - if (WARN_ON(!netif_running(sdata->dev))) + if (WARN_ON(!ieee80211_sdata_running(sdata))) return; ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d4426748ab10..e93bc558d785 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -212,7 +212,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, } if (changed & BSS_CHANGED_BEACON_ENABLED) { - if (local->quiescing || !netif_running(sdata->dev) || + if (local->quiescing || !ieee80211_sdata_running(sdata) || test_bit(SCAN_SW_SCANNING, &local->scanning)) { sdata->vif.bss_conf.enable_beacon = false; } else { diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e0bd85e3d4b6..61080c5fad50 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -645,7 +645,7 @@ static void ieee80211_mesh_work(struct work_struct *work) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct sk_buff *skb; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; if (local->scanning) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2f9ed8b9c3f0..7f9909340c09 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -604,7 +604,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; mutex_lock(&ifmgd->mtx); @@ -750,7 +750,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) } list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type != NL80211_IFTYPE_STATION) continue; @@ -1263,7 +1263,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; bool already = false; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; if (sdata->local->scanning) @@ -2118,7 +2118,7 @@ static void ieee80211_sta_work(struct work_struct *work) enum rx_mgmt_action rma; bool anybusy = false; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; if (local->scanning) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 05e161c3cbc5..913dc7e3b29e 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -93,7 +93,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) break; } - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* disable beaconing */ diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6cbf1a7b3157..f60dfca52196 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -289,7 +289,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) continue; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (prev_dev) { @@ -2056,7 +2056,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, skb->protocol = htons(ETH_P_802_2); list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type != NL80211_IFTYPE_MONITOR || @@ -2318,7 +2318,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, } if (!found_sta) { list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type == NL80211_IFTYPE_MONITOR || diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 66da0ab1d8fa..ae1830056521 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -346,7 +346,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* Tell AP we're back */ @@ -396,7 +396,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* disable beaconing */ @@ -526,7 +526,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, /* check if at least one STA interface is associated */ mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type == NL80211_IFTYPE_STATION) { @@ -571,7 +571,7 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca */ mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type == NL80211_IFTYPE_STATION) { @@ -603,7 +603,7 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca */ mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* Tell AP we're back */ @@ -727,7 +727,7 @@ void ieee80211_scan_work(struct work_struct *work) /* * Avoid re-scheduling when the sdata is going away. */ - if (!netif_running(sdata->dev)) { + if (!ieee80211_sdata_running(sdata)) { ieee80211_scan_completed(&local->hw, true); return; } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d1a77e79d7a9..f039e761aec1 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -367,7 +367,7 @@ int sta_info_insert(struct sta_info *sta) * something inserts a STA (on one CPU) without holding the RTNL * and another CPU turns off the net device. */ - if (unlikely(!netif_running(sdata->dev))) { + if (unlikely(!ieee80211_sdata_running(sdata))) { err = -ENETDOWN; goto out_free; } diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 0c0850d37dda..0ebcdda24200 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -351,7 +351,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ac48c86ae6b3..1593a2ffd67a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1469,7 +1469,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) { - if (!netif_running(tmp_sdata->dev)) + if (!ieee80211_sdata_running(tmp_sdata)) continue; if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) continue; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b01972579c7c..5ffe9e831b66 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -468,7 +468,7 @@ void ieee80211_iterate_active_interfaces( case NL80211_IFTYPE_MESH_POINT: break; } - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) iterator(data, sdata->vif.addr, &sdata->vif); } @@ -502,7 +502,7 @@ void ieee80211_iterate_active_interfaces_atomic( case NL80211_IFTYPE_MESH_POINT: break; } - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) iterator(data, sdata->vif.addr, &sdata->vif); } @@ -1056,7 +1056,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_MONITOR && - netif_running(sdata->dev)) { + ieee80211_sdata_running(sdata)) { conf.vif = &sdata->vif; conf.type = sdata->vif.type; conf.mac_addr = sdata->vif.addr; @@ -1103,7 +1103,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* Finally also reconfigure all the BSS information */ list_for_each_entry(sdata, &local->interfaces, list) { u32 changed = ~0; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; switch (sdata->vif.type) { case NL80211_IFTYPE_STATION: @@ -1131,7 +1131,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* add back keys */ list_for_each_entry(sdata, &local->interfaces, list) - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) ieee80211_enable_keys(sdata); ieee80211_wake_queues_by_reason(hw, -- cgit v1.2.3 From 1ed32e4fc8cfc9656cc1101e7f9617d485fcbe7b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:45 +0100 Subject: mac80211: remove struct ieee80211_if_init_conf All its members (vif, mac_addr, type) are now available in the vif struct directly, so we can pass that instead of the conf struct. I generated this patch (except the mac80211 and header file changes) with this semantic patch: @@ identifier conf, fn, hw; type tp; @@ tp fn(struct ieee80211_hw *hw, -struct ieee80211_if_init_conf *conf) +struct ieee80211_vif *vif) { <... ( -conf->type +vif->type | -conf->mac_addr +vif->addr | -conf->vif +vif ) ...> } Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 12 +++---- drivers/net/wireless/at76c50x-usb.c | 6 ++-- drivers/net/wireless/ath/ar9170/main.c | 8 ++--- drivers/net/wireless/ath/ath5k/base.c | 18 +++++----- drivers/net/wireless/ath/ath9k/main.c | 28 +++++++-------- drivers/net/wireless/b43/main.c | 26 +++++++------- drivers/net/wireless/b43legacy/main.c | 24 ++++++------- drivers/net/wireless/iwlwifi/iwl-core.c | 20 +++++------ drivers/net/wireless/iwlwifi/iwl-core.h | 4 +-- drivers/net/wireless/libertas_tf/main.c | 10 +++--- drivers/net/wireless/mac80211_hwsim.c | 18 +++++----- drivers/net/wireless/mwl8k.c | 14 ++++---- drivers/net/wireless/p54/main.c | 12 +++---- drivers/net/wireless/rt2x00/rt2x00.h | 4 +-- drivers/net/wireless/rt2x00/rt2x00mac.c | 26 +++++++------- drivers/net/wireless/rtl818x/rtl8180_dev.c | 12 +++---- drivers/net/wireless/rtl818x/rtl8187_dev.c | 10 +++--- drivers/net/wireless/wl12xx/wl1251_main.c | 14 ++++---- drivers/net/wireless/wl12xx/wl1271_main.c | 10 +++--- drivers/net/wireless/zd1211rw/zd_mac.c | 10 +++--- include/net/mac80211.h | 57 ++++++++---------------------- net/mac80211/driver-ops.h | 12 +++---- net/mac80211/iface.c | 14 ++------ net/mac80211/pm.c | 6 +--- net/mac80211/util.c | 9 ++--- 25 files changed, 170 insertions(+), 214 deletions(-) (limited to 'net/mac80211/pm.c') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 39410016b4ff..e1f04bb437e3 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1400,15 +1400,15 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev, } static int adm8211_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct adm8211_priv *priv = dev->priv; if (priv->mode != NL80211_IFTYPE_MONITOR) return -EOPNOTSUPP; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: - priv->mode = conf->type; + priv->mode = vif->type; break; default: return -EOPNOTSUPP; @@ -1416,8 +1416,8 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, ADM8211_IDLE(); - ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr)); - ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); + ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)vif->addr)); + ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(vif->addr + 4))); adm8211_update_mode(dev); @@ -1427,7 +1427,7 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, } static void adm8211_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct adm8211_priv *priv = dev->priv; priv->mode = NL80211_IFTYPE_MONITOR; diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 2517364d3ebe..0fb419936dff 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1789,7 +1789,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw) } static int at76_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct at76_priv *priv = hw->priv; int ret = 0; @@ -1798,7 +1798,7 @@ static int at76_add_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mtx); - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: priv->iw_mode = IW_MODE_INFRA; break; @@ -1814,7 +1814,7 @@ exit: } static void at76_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { at76_dbg(DBG_MAC80211, "%s()", __func__); } diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 20f04ab2b13e..4d27f7f67c76 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -1939,7 +1939,7 @@ err_free: } static int ar9170_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ar9170 *ar = hw->priv; struct ath_common *common = &ar->common; @@ -1952,8 +1952,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, goto unlock; } - ar->vif = conf->vif; - memcpy(common->macaddr, conf->mac_addr, ETH_ALEN); + ar->vif = vif; + memcpy(common->macaddr, vif->addr, ETH_ALEN); if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { ar->rx_software_decryption = true; @@ -1973,7 +1973,7 @@ unlock: } static void ar9170_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ar9170 *ar = hw->priv; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a4c086f069b1..20c7e5b450aa 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -225,9 +225,9 @@ static int ath5k_reset_wake(struct ath5k_softc *sc); static int ath5k_start(struct ieee80211_hw *hw); static void ath5k_stop(struct ieee80211_hw *hw); static int ath5k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); static void ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); static int ath5k_config(struct ieee80211_hw *hw, u32 changed); static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mc_list); @@ -2785,7 +2785,7 @@ static void ath5k_stop(struct ieee80211_hw *hw) } static int ath5k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ath5k_softc *sc = hw->priv; int ret; @@ -2796,22 +2796,22 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, goto end; } - sc->vif = conf->vif; + sc->vif = vif; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_MONITOR: - sc->opmode = conf->type; + sc->opmode = vif->type; break; default: ret = -EOPNOTSUPP; goto end; } - ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); + ath5k_hw_set_lladdr(sc->ah, vif->addr); ath5k_mode_setup(sc); ret = 0; @@ -2822,13 +2822,13 @@ end: static void ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ath5k_softc *sc = hw->priv; u8 mac[ETH_ALEN] = {}; mutex_lock(&sc->lock); - if (sc->vif != conf->vif) + if (sc->vif != vif) goto end; ath5k_hw_set_lladdr(sc->ah, mac); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3f5b887d0fcd..446bd23756e5 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2534,12 +2534,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) } static int ath9k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_vif *avp = (void *)conf->vif->drv_priv; + struct ath_vif *avp = (void *)vif->drv_priv; enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; int ret = 0; @@ -2551,7 +2551,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, goto out; } - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: ic_opmode = NL80211_IFTYPE_STATION; break; @@ -2562,11 +2562,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ret = -ENOBUFS; goto out; } - ic_opmode = conf->type; + ic_opmode = vif->type; break; default: ath_print(common, ATH_DBG_FATAL, - "Interface type %d not yet supported\n", conf->type); + "Interface type %d not yet supported\n", vif->type); ret = -EOPNOTSUPP; goto out; } @@ -2598,18 +2598,18 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, * Enable MIB interrupts when there are hardware phy counters. * Note we only do this (at the moment) for station mode. */ - if ((conf->type == NL80211_IFTYPE_STATION) || - (conf->type == NL80211_IFTYPE_ADHOC) || - (conf->type == NL80211_IFTYPE_MESH_POINT)) { + if ((vif->type == NL80211_IFTYPE_STATION) || + (vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) { sc->imask |= ATH9K_INT_MIB; sc->imask |= ATH9K_INT_TSFOOR; } ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - if (conf->type == NL80211_IFTYPE_AP || - conf->type == NL80211_IFTYPE_ADHOC || - conf->type == NL80211_IFTYPE_MONITOR) + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MONITOR) ath_start_ani(common); out: @@ -2618,12 +2618,12 @@ out: } static void ath9k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_vif *avp = (void *)conf->vif->drv_priv; + struct ath_vif *avp = (void *)vif->drv_priv; int i; ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); @@ -2644,7 +2644,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, sc->sc_flags &= ~SC_OP_BEACONS; for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { - if (sc->beacon.bslot[i] == conf->vif) { + if (sc->beacon.bslot[i] == vif) { printk(KERN_DEBUG "%s: vif had allocated beacon " "slot\n", __func__); sc->beacon.bslot[i] = NULL; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b0b5ce950008..6634a77fc766 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4391,7 +4391,7 @@ err_busdown: } static int b43_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; @@ -4399,24 +4399,24 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, /* TODO: allow WDS/AP devices to coexist */ - if (conf->type != NL80211_IFTYPE_AP && - conf->type != NL80211_IFTYPE_MESH_POINT && - conf->type != NL80211_IFTYPE_STATION && - conf->type != NL80211_IFTYPE_WDS && - conf->type != NL80211_IFTYPE_ADHOC) + if (vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_MESH_POINT && + vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_WDS && + vif->type != NL80211_IFTYPE_ADHOC) return -EOPNOTSUPP; mutex_lock(&wl->mutex); if (wl->operating) goto out_mutex_unlock; - b43dbg(wl, "Adding Interface type %d\n", conf->type); + b43dbg(wl, "Adding Interface type %d\n", vif->type); dev = wl->current_dev; wl->operating = 1; - wl->vif = conf->vif; - wl->if_type = conf->type; - memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); + wl->vif = vif; + wl->if_type = vif->type; + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); b43_adjust_opmode(dev); b43_set_pretbtt(dev); @@ -4431,17 +4431,17 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, } static void b43_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; - b43dbg(wl, "Removing Interface type %d\n", conf->type); + b43dbg(wl, "Removing Interface type %d\n", vif->type); mutex_lock(&wl->mutex); B43_WARN_ON(!wl->operating); - B43_WARN_ON(wl->vif != conf->vif); + B43_WARN_ON(wl->vif != vif); wl->vif = NULL; wl->operating = 0; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index ab6a18c2e9d9..494017e4fcc9 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3361,7 +3361,7 @@ err_kfree_lo_control: } static int b43legacy_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wldev *dev; @@ -3370,23 +3370,23 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, /* TODO: allow WDS/AP devices to coexist */ - if (conf->type != NL80211_IFTYPE_AP && - conf->type != NL80211_IFTYPE_STATION && - conf->type != NL80211_IFTYPE_WDS && - conf->type != NL80211_IFTYPE_ADHOC) + if (vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_WDS && + vif->type != NL80211_IFTYPE_ADHOC) return -EOPNOTSUPP; mutex_lock(&wl->mutex); if (wl->operating) goto out_mutex_unlock; - b43legacydbg(wl, "Adding Interface type %d\n", conf->type); + b43legacydbg(wl, "Adding Interface type %d\n", vif->type); dev = wl->current_dev; wl->operating = 1; - wl->vif = conf->vif; - wl->if_type = conf->type; - memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); + wl->vif = vif; + wl->if_type = vif->type; + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); spin_lock_irqsave(&wl->irq_lock, flags); b43legacy_adjust_opmode(dev); @@ -3403,18 +3403,18 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, } static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wldev *dev = wl->current_dev; unsigned long flags; - b43legacydbg(wl, "Removing Interface type %d\n", conf->type); + b43legacydbg(wl, "Removing Interface type %d\n", vif->type); mutex_lock(&wl->mutex); B43legacy_WARN_ON(!wl->operating); - B43legacy_WARN_ON(wl->vif != conf->vif); + B43legacy_WARN_ON(wl->vif != vif); wl->vif = NULL; wl->operating = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e3b96b48b7fe..14f482960d7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2584,12 +2584,12 @@ int iwl_set_mode(struct iwl_priv *priv, int mode) EXPORT_SYMBOL(iwl_set_mode); int iwl_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; unsigned long flags; - IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); + IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); if (priv->vif) { IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); @@ -2597,19 +2597,19 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, } spin_lock_irqsave(&priv->lock, flags); - priv->vif = conf->vif; - priv->iw_mode = conf->type; + priv->vif = vif; + priv->iw_mode = vif->type; spin_unlock_irqrestore(&priv->lock, flags); mutex_lock(&priv->mutex); - if (conf->mac_addr) { - IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + if (vif->addr) { + IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); + memcpy(priv->mac_addr, vif->addr, ETH_ALEN); } - if (iwl_set_mode(priv, conf->type) == -EAGAIN) + if (iwl_set_mode(priv, vif->type) == -EAGAIN) /* we are not ready, will run again when ready */ set_bit(STATUS_MODE_PENDING, &priv->status); @@ -2621,7 +2621,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, EXPORT_SYMBOL(iwl_mac_add_interface); void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; @@ -2634,7 +2634,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); } - if (priv->vif == conf->vif) { + if (priv->vif == vif) { priv->vif = NULL; memset(priv->bssid, 0, ETH_ALEN); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f7acbb32900a..1728f961dcba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -332,9 +332,9 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); int iwl_commit_rxon(struct iwl_priv *priv); int iwl_set_mode(struct iwl_priv *priv, int mode); int iwl_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); void iwl_config_ap(struct iwl_priv *priv); int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 019431d2f8a9..15a367680f59 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -318,14 +318,14 @@ static void lbtf_op_stop(struct ieee80211_hw *hw) } static int lbtf_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct lbtf_private *priv = hw->priv; if (priv->vif != NULL) return -EOPNOTSUPP; - priv->vif = conf->vif; - switch (conf->type) { + priv->vif = vif; + switch (vif->type) { case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: lbtf_set_mode(priv, LBTF_AP_MODE); @@ -337,12 +337,12 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw, priv->vif = NULL; return -EOPNOTSUPP; } - lbtf_set_mac_address(priv, (u8 *) conf->mac_addr); + lbtf_set_mac_address(priv, (u8 *) vif->addr); return 0; } static void lbtf_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct lbtf_private *priv = hw->priv; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 4dee69a38c1d..84df3fcf37b3 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -584,24 +584,24 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", - wiphy_name(hw->wiphy), __func__, conf->type, - conf->mac_addr); - hwsim_set_magic(conf->vif); + wiphy_name(hw->wiphy), __func__, vif->type, + vif->addr); + hwsim_set_magic(vif); return 0; } static void mac80211_hwsim_remove_interface( - struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) + struct ieee80211_hw *hw, struct ieee80211_vif *vif) { printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", - wiphy_name(hw->wiphy), __func__, conf->type, - conf->mac_addr); - hwsim_check_magic(conf->vif); - hwsim_clear_magic(conf->vif); + wiphy_name(hw->wiphy), __func__, vif->type, + vif->addr); + hwsim_check_magic(vif); + hwsim_clear_magic(vif); } diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 97a95decf9a8..c1c6ecd0c5b3 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2835,7 +2835,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) } static int mwl8k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_vif *mwl8k_vif; @@ -2849,7 +2849,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, /* * We only support managed interfaces for now. */ - if (conf->type != NL80211_IFTYPE_STATION) + if (vif->type != NL80211_IFTYPE_STATION) return -EINVAL; /* @@ -2865,24 +2865,24 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, } /* Clean out driver private area */ - mwl8k_vif = MWL8K_VIF(conf->vif); + mwl8k_vif = MWL8K_VIF(vif); memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); /* Set and save the mac address */ - mwl8k_cmd_set_mac_addr(hw, conf->mac_addr); - memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); + mwl8k_cmd_set_mac_addr(hw, vif->addr); + memcpy(mwl8k_vif->mac_addr, vif->addr, ETH_ALEN); /* Set Initial sequence number to zero */ mwl8k_vif->seqno = 0; - priv->vif = conf->vif; + priv->vif = vif; priv->current_channel = NULL; return 0; } static void mwl8k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 18012dbfb45d..26428e4c9c60 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -216,7 +216,7 @@ static void p54_stop(struct ieee80211_hw *dev) } static int p54_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct p54_common *priv = dev->priv; @@ -226,28 +226,28 @@ static int p54_add_interface(struct ieee80211_hw *dev, return -EOPNOTSUPP; } - priv->vif = conf->vif; + priv->vif = vif; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: - priv->mode = conf->type; + priv->mode = vif->type; break; default: mutex_unlock(&priv->conf_mutex); return -EOPNOTSUPP; } - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + memcpy(priv->mac_addr, vif->addr, ETH_ALEN); p54_setup_mac(priv); mutex_unlock(&priv->conf_mutex); return 0; } static void p54_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct p54_common *priv = dev->priv; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index a664a999b2b0..b4c6e0a6d7e0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1019,9 +1019,9 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); int rt2x00mac_start(struct ieee80211_hw *hw); void rt2x00mac_stop(struct ieee80211_hw *hw); int rt2x00mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); void rt2x00mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); void rt2x00mac_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index de549c244ed8..00f1f939f1bb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -187,10 +187,10 @@ void rt2x00mac_stop(struct ieee80211_hw *hw) EXPORT_SYMBOL_GPL(rt2x00mac_stop); int rt2x00mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(conf->vif); + struct rt2x00_intf *intf = vif_to_intf(vif); struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); struct queue_entry *entry = NULL; unsigned int i; @@ -203,7 +203,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) return -ENODEV; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_AP: /* * We don't support mixed combinations of @@ -263,7 +263,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, * increase interface count and start initialization. */ - if (conf->type == NL80211_IFTYPE_AP) + if (vif->type == NL80211_IFTYPE_AP) rt2x00dev->intf_ap_count++; else rt2x00dev->intf_sta_count++; @@ -273,16 +273,16 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; - if (conf->type == NL80211_IFTYPE_AP) - memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); - memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); + if (vif->type == NL80211_IFTYPE_AP) + memcpy(&intf->bssid, vif->addr, ETH_ALEN); + memcpy(&intf->mac, vif->addr, ETH_ALEN); /* * The MAC adddress must be configured after the device * has been initialized. Otherwise the device can reset * the MAC registers. */ - rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL); /* * Some filters depend on the current working mode. We can force @@ -296,10 +296,10 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); void rt2x00mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(conf->vif); + struct rt2x00_intf *intf = vif_to_intf(vif); /* * Don't allow interfaces to be remove while @@ -307,11 +307,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, * no interface is present. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || - (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || - (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) + (vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || + (vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) return; - if (conf->type == NL80211_IFTYPE_AP) + if (vif->type == NL80211_IFTYPE_AP) rt2x00dev->intf_ap_count--; else rt2x00dev->intf_sta_count--; diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index f01f1ef9e3be..5a2b7199f5d5 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -652,7 +652,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev) } static int rtl8180_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rtl8180_priv *priv = dev->priv; @@ -662,27 +662,27 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, if (priv->vif) return -EBUSY; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: break; default: return -EOPNOTSUPP; } - priv->vif = conf->vif; + priv->vif = vif; rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], - le32_to_cpu(*(__le32 *)conf->mac_addr)); + le32_to_cpu(*(__le32 *)vif->addr)); rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], - le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); + le16_to_cpu(*(__le16 *)(vif->addr + 4))); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); return 0; } static void rtl8180_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rtl8180_priv *priv = dev->priv; priv->vif = NULL; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 1cb0eff46223..f336c63053c1 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1018,7 +1018,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev) } static int rtl8187_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rtl8187_priv *priv = dev->priv; int i; @@ -1028,7 +1028,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, if (priv->vif) goto exit; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: break; default: @@ -1036,12 +1036,12 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, } ret = 0; - priv->vif = conf->vif; + priv->vif = vif; rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); for (i = 0; i < ETH_ALEN; i++) rtl818x_iowrite8(priv, &priv->map->MAC[i], - ((u8 *)conf->mac_addr)[i]); + ((u8 *)vif->addr)[i]); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); exit: @@ -1050,7 +1050,7 @@ exit: } static void rtl8187_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rtl8187_priv *priv = dev->priv; mutex_lock(&priv->conf_mutex); diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 6aeffbe9e401..4e373f3dbc43 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -511,13 +511,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) } static int wl1251_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1251 *wl = hw->priv; int ret = 0; wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - conf->type, conf->mac_addr); + vif->type, vif->addr); mutex_lock(&wl->mutex); if (wl->vif) { @@ -525,9 +525,9 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, goto out; } - wl->vif = conf->vif; + wl->vif = vif; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; break; @@ -539,8 +539,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, goto out; } - if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) { - memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); + if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) { + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); ret = wl1251_acx_station_id(wl); if (ret < 0) @@ -553,7 +553,7 @@ out: } static void wl1251_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1251 *wl = hw->priv; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4a997381a8d0..e4867b895c43 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1039,13 +1039,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) } static int wl1271_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; int ret = 0; wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - conf->type, conf->mac_addr); + vif->type, vif->addr); mutex_lock(&wl->mutex); if (wl->vif) { @@ -1053,9 +1053,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } - wl->vif = conf->vif; + wl->vif = vif; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; break; @@ -1075,7 +1075,7 @@ out: } static void wl1271_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 8a243732c519..c4f41d0016c5 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -872,7 +872,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) } static int zd_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct zd_mac *mac = zd_hw_mac(hw); @@ -880,22 +880,22 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, if (mac->type != NL80211_IFTYPE_UNSPECIFIED) return -EOPNOTSUPP; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: - mac->type = conf->type; + mac->type = vif->type; break; default: return -EOPNOTSUPP; } - return zd_write_mac_addr(&mac->chip, conf->mac_addr); + return zd_write_mac_addr(&mac->chip, vif->addr); } static void zd_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct zd_mac *mac = zd_hw_mac(hw); mac->type = NL80211_IFTYPE_UNSPECIFIED; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 77ea34b03285..08d41357dcbe 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -701,33 +701,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) return false; } -/** - * struct ieee80211_if_init_conf - initial configuration of an interface - * - * @vif: pointer to a driver-use per-interface structure. The pointer - * itself is also used for various functions including - * ieee80211_beacon_get() and ieee80211_get_buffered_bc(). - * @type: one of &enum nl80211_iftype constants. Determines the type of - * added/removed interface. - * @mac_addr: pointer to MAC address of the interface. This pointer is valid - * until the interface is removed (i.e. it cannot be used after - * remove_interface() callback was called for this interface). - * - * This structure is used in add_interface() and remove_interface() - * callbacks of &struct ieee80211_hw. - * - * When you allow multiple interfaces to be added to your PHY, take care - * that the hardware can actually handle multiple MAC addresses. However, - * also take care that when there's no interface left with mac_addr != %NULL - * you remove the MAC address from the device to avoid acknowledging packets - * in pure monitor mode. - */ -struct ieee80211_if_init_conf { - enum nl80211_iftype type; - struct ieee80211_vif *vif; - void *mac_addr; -}; - /** * enum ieee80211_key_alg - key algorithm * @ALG_WEP: WEP40 or WEP104 @@ -1555,9 +1528,9 @@ struct ieee80211_ops { int (*start)(struct ieee80211_hw *hw); void (*stop)(struct ieee80211_hw *hw); int (*add_interface)(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); void (*remove_interface)(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); int (*config)(struct ieee80211_hw *hw, u32 changed); void (*bss_info_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -1845,7 +1818,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, /** * ieee80211_beacon_get_tim - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @tim_offset: pointer to variable that will receive the TIM IE offset. * Set to 0 if invalid (in non-AP modes). * @tim_length: pointer to variable that will receive the TIM IE length, @@ -1873,7 +1846,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, /** * ieee80211_beacon_get - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * * See ieee80211_beacon_get_tim(). */ @@ -1886,7 +1859,7 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, /** * ieee80211_rts_get - RTS frame generation function * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame: pointer to the frame that is going to be protected by the RTS. * @frame_len: the frame length (in octets). * @frame_txctl: &struct ieee80211_tx_info of the frame. @@ -1905,7 +1878,7 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /** * ieee80211_rts_duration - Get the duration field for an RTS frame * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame_len: the length of the frame that is going to be protected by the RTS. * @frame_txctl: &struct ieee80211_tx_info of the frame. * @@ -1920,7 +1893,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, /** * ieee80211_ctstoself_get - CTS-to-self frame generation function * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame: pointer to the frame that is going to be protected by the CTS-to-self. * @frame_len: the frame length (in octets). * @frame_txctl: &struct ieee80211_tx_info of the frame. @@ -1940,7 +1913,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw, /** * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame_len: the length of the frame that is going to be protected by the CTS-to-self. * @frame_txctl: &struct ieee80211_tx_info of the frame. * @@ -1956,7 +1929,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, /** * ieee80211_generic_frame_duration - Calculate the duration field for a frame * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame_len: the length of the frame. * @rate: the rate at which the frame is going to be transmitted. * @@ -1971,7 +1944,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, /** * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames * @hw: pointer as obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * * Function for accessing buffered broadcast and multicast frames. If * hardware/firmware does not implement buffering of broadcast/multicast @@ -2139,7 +2112,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid); /** * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf + * @vif: &struct ieee80211_vif pointer from the add_interface callback * @ra: receiver address of the BA session recipient. * @tid: the TID to BA on. * @@ -2150,7 +2123,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); /** * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf + * @vif: &struct ieee80211_vif pointer from the add_interface callback * @ra: receiver address of the BA session recipient. * @tid: the TID to BA on. * @@ -2178,7 +2151,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid, /** * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf + * @vif: &struct ieee80211_vif pointer from the add_interface callback * @ra: receiver address of the BA session recipient. * @tid: the desired TID to BA on. * @@ -2189,7 +2162,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); /** * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf + * @vif: &struct ieee80211_vif pointer from the add_interface callback * @ra: receiver address of the BA session recipient. * @tid: the desired TID to BA on. * @@ -2268,7 +2241,7 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, /** * ieee80211_beacon_loss - inform hardware does not receive beacons * - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and * IEEE80211_CONF_PS is set, the driver needs to inform whenever the diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index cbe133bcdf34..bc7c8f55487a 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -36,18 +36,18 @@ static inline void drv_stop(struct ieee80211_local *local) } static inline int drv_add_interface(struct ieee80211_local *local, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { - int ret = local->ops->add_interface(&local->hw, conf); - trace_drv_add_interface(local, vif_to_sdata(conf->vif), ret); + int ret = local->ops->add_interface(&local->hw, vif); + trace_drv_add_interface(local, vif_to_sdata(vif), ret); return ret; } static inline void drv_remove_interface(struct ieee80211_local *local, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { - local->ops->remove_interface(&local->hw, conf); - trace_drv_remove_interface(local, vif_to_sdata(conf->vif)); + local->ops->remove_interface(&local->hw, vif); + trace_drv_remove_interface(local, vif_to_sdata(vif)); } static inline int drv_config(struct ieee80211_local *local, u32 changed) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 7d410f15281a..00a1f4ccdaf1 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -96,7 +96,6 @@ static int ieee80211_open(struct net_device *dev) struct ieee80211_sub_if_data *nsdata; struct ieee80211_local *local = sdata->local; struct sta_info *sta; - struct ieee80211_if_init_conf conf; u32 changed = 0; int res; u32 hw_reconf_flags = 0; @@ -248,10 +247,7 @@ static int ieee80211_open(struct net_device *dev) ieee80211_configure_filter(local); break; default: - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->vif.addr; - res = drv_add_interface(local, &conf); + res = drv_add_interface(local, &sdata->vif); if (res) goto err_stop; @@ -334,7 +330,7 @@ static int ieee80211_open(struct net_device *dev) return 0; err_del_interface: - drv_remove_interface(local, &conf); + drv_remove_interface(local, &sdata->vif); err_stop: if (!local->open_count) drv_stop(local); @@ -349,7 +345,6 @@ static int ieee80211_stop(struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; - struct ieee80211_if_init_conf conf; struct sta_info *sta; unsigned long flags; struct sk_buff *skb, *tmp; @@ -533,12 +528,9 @@ static int ieee80211_stop(struct net_device *dev) BSS_CHANGED_BEACON_ENABLED); } - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->vif.addr; /* disable all keys for as long as this netdev is down */ ieee80211_disable_keys(sdata); - drv_remove_interface(local, &conf); + drv_remove_interface(local, &sdata->vif); } sdata->bss = NULL; diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 913dc7e3b29e..47f818959ad7 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -10,7 +10,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_init_conf conf; struct sta_info *sta; unsigned long flags; @@ -100,10 +99,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->vif.addr; - drv_remove_interface(local, &conf); + drv_remove_interface(local, &sdata->vif); } /* stop hardware - this must stop RX */ diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1fdb80ff9241..4b930308b1fb 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1075,7 +1075,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) { struct ieee80211_hw *hw = &local->hw; struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_init_conf conf; struct sta_info *sta; unsigned long flags; int res; @@ -1094,12 +1093,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_MONITOR && - ieee80211_sdata_running(sdata)) { - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->vif.addr; - res = drv_add_interface(local, &conf); - } + ieee80211_sdata_running(sdata)) + res = drv_add_interface(local, &sdata->vif); } /* add STAs back */ -- cgit v1.2.3 From 34e895075e21be3e21e71d6317440d1ee7969ad0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 3 Feb 2010 13:59:58 +0100 Subject: mac80211: allow station add/remove to sleep Many drivers would like to sleep during station addition and removal, and currently have a high complexity there from not being able to. This introduces two new callbacks sta_add() and sta_remove() that drivers can implement instead of using sta_notify() and that can sleep, and the new sta_add() callback is also allowed to fail. The reason we didn't do this previously is that the IBSS code wants to insert stations from the RX path, which is a tasklet, so cannot sleep. This patch will keep the station allocation in that path, but moves adding the station to the driver out of line. Since the addition can now fail, we can have IBSS peer structs the driver rejected -- in that case we still talk to the station but never tell the driver about it in the control.sta pointer. If there will ever be a driver that has a low limit on the number of stations and that cannot talk to any stations that are not known to it, we need to do come up with a new strategy of handling larger IBSSs, maybe quicker expiry or rejecting peers. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 21 +- net/mac80211/cfg.c | 23 +- net/mac80211/driver-ops.h | 34 +++ net/mac80211/driver-trace.h | 52 ++++ net/mac80211/ibss.c | 22 +- net/mac80211/ieee80211_i.h | 18 +- net/mac80211/mesh_plink.c | 17 +- net/mac80211/mlme.c | 14 +- net/mac80211/pm.c | 10 +- net/mac80211/rx.c | 4 +- net/mac80211/sta_info.c | 731 ++++++++++++++++++++++---------------------- net/mac80211/sta_info.h | 32 +- net/mac80211/tx.c | 2 +- net/mac80211/util.c | 16 +- 14 files changed, 526 insertions(+), 470 deletions(-) (limited to 'net/mac80211/pm.c') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 74ccf30fdf8e..a19fac35259a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -814,7 +814,7 @@ enum set_key_cmd { * mac80211, any ieee80211_sta pointer you get access to must * either be protected by rcu_read_lock() explicitly or implicitly, * or you must take good care to not use such a pointer after a - * call to your sta_notify callback that removed it. + * call to your sta_remove callback that removed it. * * @addr: MAC address * @aid: AID we assigned to the station if we're an AP @@ -840,8 +840,8 @@ struct ieee80211_sta { * indicates addition and removal of a station to station table, * or if a associated station made a power state transition. * - * @STA_NOTIFY_ADD: a station was added to the station table - * @STA_NOTIFY_REMOVE: a station being removed from the station table + * @STA_NOTIFY_ADD: (DEPRECATED) a station was added to the station table + * @STA_NOTIFY_REMOVE: (DEPRECATED) a station being removed from the station table * @STA_NOTIFY_SLEEP: a station is now sleeping * @STA_NOTIFY_AWAKE: a sleeping station woke up */ @@ -1534,9 +1534,14 @@ enum ieee80211_ampdu_mlme_action { * @set_rts_threshold: Configuration of RTS threshold (if device needs it) * The callback can sleep. * - * @sta_notify: Notifies low level driver about addition, removal or power - * state transition of an associated station, AP, IBSS/WDS/mesh peer etc. - * Must be atomic. + * @sta_add: Notifies low level driver about addition of an associated station, + * AP, IBSS/WDS/mesh peer etc. This callback can sleep. + * + * @sta_remove: Notifies low level driver about removal of an associated + * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep. + * + * @sta_notify: Notifies low level driver about power state transition of an + * associated station, AP, IBSS/WDS/mesh peer etc. Must be atomic. * * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), * bursting) for a hardware TX queue. @@ -1635,6 +1640,10 @@ struct ieee80211_ops { void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, u16 *iv16); int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); + int (*sta_add)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd, struct ieee80211_sta *sta); int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index facf233843e0..a362523d8eb7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -747,9 +747,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || sdata->vif.type == NL80211_IFTYPE_AP; - rcu_read_lock(); - - err = sta_info_insert(sta); + err = sta_info_insert_rcu(sta); if (err) { rcu_read_unlock(); return err; @@ -768,26 +766,13 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, { struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; - struct sta_info *sta; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (mac) { - rcu_read_lock(); - - sta = sta_info_get_bss(sdata, mac); - if (!sta) { - rcu_read_unlock(); - return -ENOENT; - } - - sta_info_unlink(&sta); - rcu_read_unlock(); - - sta_info_destroy(sta); - } else - sta_info_flush(local, sdata); + if (mac) + return sta_info_destroy_addr_bss(sdata, mac); + sta_info_flush(local, sdata); return 0; } diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 6c31f38ac7f5..855e85b55061 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -243,6 +243,40 @@ static inline void drv_sta_notify(struct ieee80211_local *local, trace_drv_sta_notify(local, sdata, cmd, sta); } +static inline int drv_sta_add(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta) +{ + int ret = 0; + + might_sleep(); + + if (local->ops->sta_add) + ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); + else if (local->ops->sta_notify) + local->ops->sta_notify(&local->hw, &sdata->vif, + STA_NOTIFY_ADD, sta); + + trace_drv_sta_add(local, sdata, sta, ret); + + return ret; +} + +static inline void drv_sta_remove(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta) +{ + might_sleep(); + + if (local->ops->sta_remove) + local->ops->sta_remove(&local->hw, &sdata->vif, sta); + else if (local->ops->sta_notify) + local->ops->sta_notify(&local->hw, &sdata->vif, + STA_NOTIFY_REMOVE, sta); + + trace_drv_sta_remove(local, sdata, sta); +} + static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, const struct ieee80211_tx_queue_params *params) { diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 502424b2538a..c984910bf275 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -545,6 +545,58 @@ TRACE_EVENT(drv_sta_notify, ) ); +TRACE_EVENT(drv_sta_add, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta, int ret), + + TP_ARGS(local, sdata, sta, ret), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + STA_ENTRY + __field(int, ret) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + STA_ASSIGN; + __entry->ret = ret; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d", + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret + ) +); + +TRACE_EVENT(drv_sta_remove, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta), + + TP_ARGS(local, sdata, sta), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + STA_ENTRY + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + STA_ASSIGN; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT, + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG + ) +); + TRACE_EVENT(drv_conf_tx, TP_PROTO(struct ieee80211_local *local, u16 queue, const struct ieee80211_tx_queue_params *params, diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 85c4ba14c77d..f3e942486749 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -275,10 +275,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, (unsigned long long) supp_rates, (unsigned long long) sta->sta.supp_rates[band]); #endif - } else - ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); - - rcu_read_unlock(); + rcu_read_unlock(); + } else { + rcu_read_unlock(); + ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, + supp_rates, GFP_KERNEL); + } } bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, @@ -368,7 +370,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->bssid); #endif ieee80211_sta_join_ibss(sdata, bss); - ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); + ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, + supp_rates, GFP_KERNEL); } put_bss: @@ -381,7 +384,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, * must be callable in atomic context. */ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, - u8 *bssid,u8 *addr, u32 supp_rates) + u8 *bssid,u8 *addr, u32 supp_rates, + gfp_t gfp) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; @@ -410,7 +414,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, wiphy_name(local->hw.wiphy), addr, sdata->name); #endif - sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); + sta = sta_info_alloc(sdata, addr, gfp); if (!sta) return NULL; @@ -422,9 +426,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, rate_control_rate_init(sta); + /* If it fails, maybe we raced another insertion? */ if (sta_info_insert(sta)) - return NULL; - + return sta_info_get(sdata, addr); return sta; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3067fbd69d63..a5911191f224 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -688,15 +688,18 @@ struct ieee80211_local { /* Station data */ /* - * The lock only protects the list, hash, timer and counter - * against manipulation, reads are done in RCU. Additionally, - * the lock protects each BSS's TIM bitmap. + * The mutex only protects the list and counter, + * reads are done in RCU. + * Additionally, the lock protects the hash table, + * the pending list and each BSS's TIM bitmap. */ + struct mutex sta_mtx; spinlock_t sta_lock; unsigned long num_sta; - struct list_head sta_list; + struct list_head sta_list, sta_pending_list; struct sta_info *sta_hash[STA_HASH_SIZE]; struct timer_list sta_cleanup; + struct work_struct sta_finish_work; int sta_generation; struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; @@ -770,10 +773,6 @@ struct ieee80211_local { assoc_led_name[32], radio_led_name[32]; #endif -#ifdef CONFIG_MAC80211_DEBUGFS - struct work_struct sta_debugfs_add; -#endif - #ifdef CONFIG_MAC80211_DEBUG_COUNTERS /* TX/RX handler statistics */ unsigned int tx_handlers_drop; @@ -985,7 +984,8 @@ 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); + u8 *bssid, u8 *addr, u32 supp_rates, + gfp_t gfp); int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, struct cfg80211_ibss_params *params); int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7985e5150898..bc4e20e57ff5 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -102,7 +102,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, if (local->num_sta >= MESH_MAX_PLINKS) return NULL; - sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC); + sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); if (!sta) return NULL; @@ -236,12 +236,12 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data sta = sta_info_get(sdata, hw_addr); if (!sta) { + rcu_read_unlock(); + sta = mesh_plink_alloc(sdata, hw_addr, rates); - if (!sta) { - rcu_read_unlock(); + if (!sta) return; - } - if (sta_info_insert(sta)) { + if (sta_info_insert_rcu(sta)) { rcu_read_unlock(); return; } @@ -485,9 +485,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m } else if (!sta) { /* ftype == PLINK_OPEN */ u32 rates; + + rcu_read_unlock(); + if (!mesh_plink_free_count(sdata)) { mpl_dbg("Mesh plink error: no more free plinks\n"); - rcu_read_unlock(); return; } @@ -495,10 +497,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta = mesh_plink_alloc(sdata, mgmt->sa, rates); if (!sta) { mpl_dbg("Mesh plink error: plink table full\n"); - rcu_read_unlock(); return; } - if (sta_info_insert(sta)) { + if (sta_info_insert_rcu(sta)) { rcu_read_unlock(); return; } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f437284830ef..ac9429e8d72b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -822,19 +822,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) changed |= BSS_CHANGED_BSSID; ieee80211_bss_info_change_notify(sdata, changed); - rcu_read_lock(); - - sta = sta_info_get(sdata, bssid); - if (!sta) { - rcu_read_unlock(); - return; - } - - sta_info_unlink(&sta); - - rcu_read_unlock(); - - sta_info_destroy(sta); + sta_info_destroy_addr(sdata, bssid); } void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 47f818959ad7..0e64484e861c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -11,7 +11,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; struct sta_info *sta; - unsigned long flags; ieee80211_scan_cancel(local); @@ -55,22 +54,21 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) rcu_read_unlock(); /* remove STAs */ - spin_lock_irqsave(&local->sta_lock, flags); + mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { - if (local->ops->sta_notify) { + if (sta->uploaded) { sdata = sta->sdata; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, - &sta->sta); + drv_sta_remove(local, sdata, &sta->sta); } mesh_plink_quiesce(sta); } - spin_unlock_irqrestore(&local->sta_lock, flags); + mutex_unlock(&local->sta_mtx); /* remove all interfaces */ list_for_each_entry(sdata, &local->interfaces, list) { diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5709307fcb9b..01dba7618397 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2244,8 +2244,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, rate_idx = 0; /* TODO: HT rates */ else rate_idx = status->rate_idx; - rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, - BIT(rate_idx)); + rx->sta = ieee80211_ibss_add_sta(sdata, bssid, + hdr->addr2, BIT(rate_idx), GFP_ATOMIC); } break; case NL80211_IFTYPE_MESH_POINT: diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f735826f055c..211c475f73c6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -32,49 +32,33 @@ * for faster lookup and a list for iteration. They are managed using * RCU, i.e. access to the list and hash table is protected by RCU. * - * Upon allocating a STA info structure with sta_info_alloc(), the caller owns - * that structure. It must then either destroy it using sta_info_destroy() - * (which is pretty useless) or insert it into the hash table using - * sta_info_insert() which demotes the reference from ownership to a regular - * RCU-protected reference; if the function is called without protection by an - * RCU critical section the reference is instantly invalidated. Note that the - * caller may not do much with the STA info before inserting it, in particular, - * it may not start any mesh peer link management or add encryption keys. + * Upon allocating a STA info structure with sta_info_alloc(), the caller + * owns that structure. It must then insert it into the hash table using + * either sta_info_insert() or sta_info_insert_rcu(); only in the latter + * case (which acquires an rcu read section but must not be called from + * within one) will the pointer still be valid after the call. Note that + * the caller may not do much with the STA info before inserting it, in + * particular, it may not start any mesh peer link management or add + * encryption keys. * * When the insertion fails (sta_info_insert()) returns non-zero), the * structure will have been freed by sta_info_insert()! * - * sta entries are added by mac80211 when you establish a link with a + * Station entries are added by mac80211 when you establish a link with a * peer. This means different things for the different type of interfaces * we support. For a regular station this mean we add the AP sta when we * receive an assocation response from the AP. For IBSS this occurs when - * we receive a probe response or a beacon from target IBSS network. For - * WDS we add the sta for the peer imediately upon device open. When using - * AP mode we add stations for each respective station upon request from - * userspace through nl80211. + * get to know about a peer on the same IBSS. For WDS we add the sta for + * the peer imediately upon device open. When using AP mode we add stations + * for each respective station upon request from userspace through nl80211. * - * Because there are debugfs entries for each station, and adding those - * must be able to sleep, it is also possible to "pin" a station entry, - * that means it can be removed from the hash table but not be freed. - * See the comment in __sta_info_unlink() for more information, this is - * an internal capability only. + * In order to remove a STA info structure, various sta_info_destroy_*() + * calls are available. * - * In order to remove a STA info structure, the caller needs to first - * unlink it (sta_info_unlink()) from the list and hash tables and - * then destroy it; sta_info_destroy() will wait for an RCU grace period - * to elapse before actually freeing it. Due to the pinning and the - * possibility of multiple callers trying to remove the same STA info at - * the same time, sta_info_unlink() can clear the STA info pointer it is - * passed to indicate that the STA info is owned by somebody else now. - * - * If sta_info_unlink() did not clear the pointer then the caller owns - * the STA info structure now and is responsible of destroying it with - * a call to sta_info_destroy(). - * - * In all other cases, there is no concept of ownership on a STA entry, - * each structure is owned by the global hash table/list until it is - * removed. All users of the structure need to be RCU protected so that - * the structure won't be freed before they are done using it. + * There is no concept of ownership on a STA entry, each structure is + * owned by the global hash table/list until it is removed. All users of + * the structure need to be RCU protected so that the structure won't be + * freed before they are done using it. */ /* Caller must hold local->sta_lock */ @@ -185,101 +169,6 @@ static void __sta_info_free(struct ieee80211_local *local, kfree(sta); } -void sta_info_destroy(struct sta_info *sta) -{ - struct ieee80211_local *local; - struct sk_buff *skb; - int i; - - might_sleep(); - - if (!sta) - return; - - local = sta->local; - - cancel_work_sync(&sta->drv_unblock_wk); - - rate_control_remove_sta_debugfs(sta); - ieee80211_sta_debugfs_remove(sta); - -#ifdef CONFIG_MAC80211_MESH - if (ieee80211_vif_is_mesh(&sta->sdata->vif)) - mesh_plink_deactivate(sta); -#endif - - /* - * We have only unlinked the key, and actually destroying it - * may mean it is removed from hardware which requires that - * the key->sta pointer is still valid, so flush the key todo - * list here. - * - * ieee80211_key_todo() will synchronize_rcu() so after this - * nothing can reference this sta struct any more. - */ - ieee80211_key_todo(); - -#ifdef CONFIG_MAC80211_MESH - if (ieee80211_vif_is_mesh(&sta->sdata->vif)) - del_timer_sync(&sta->plink_timer); -#endif - - while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { - local->total_ps_buffered--; - dev_kfree_skb_any(skb); - } - - while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) - dev_kfree_skb_any(skb); - - for (i = 0; i < STA_TID_NUM; i++) { - struct tid_ampdu_rx *tid_rx; - struct tid_ampdu_tx *tid_tx; - - spin_lock_bh(&sta->lock); - tid_rx = sta->ampdu_mlme.tid_rx[i]; - /* Make sure timer won't free the tid_rx struct, see below */ - if (tid_rx) - tid_rx->shutdown = true; - - spin_unlock_bh(&sta->lock); - - /* - * Outside spinlock - shutdown is true now so that the timer - * won't free tid_rx, we have to do that now. Can't let the - * timer do it because we have to sync the timer outside the - * lock that it takes itself. - */ - if (tid_rx) { - del_timer_sync(&tid_rx->session_timer); - kfree(tid_rx); - } - - /* - * No need to do such complications for TX agg sessions, the - * path leading to freeing the tid_tx struct goes via a call - * from the driver, and thus needs to look up the sta struct - * again, which cannot be found when we get here. Hence, we - * just need to delete the timer and free the aggregation - * info; we won't be telling the peer about it then but that - * doesn't matter if we're not talking to it again anyway. - */ - tid_tx = sta->ampdu_mlme.tid_tx[i]; - if (tid_tx) { - del_timer_sync(&tid_tx->addba_resp_timer); - /* - * STA removed while aggregation session being - * started? Bit odd, but purge frames anyway. - */ - skb_queue_purge(&tid_tx->pending); - kfree(tid_tx); - } - } - - __sta_info_free(local, sta); -} - - /* Caller must hold local->sta_lock */ static void sta_info_hash_add(struct ieee80211_local *local, struct sta_info *sta) @@ -376,7 +265,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, return sta; } -int sta_info_insert(struct sta_info *sta) +static int sta_info_finish_insert(struct sta_info *sta, bool async) { struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -384,6 +273,91 @@ int sta_info_insert(struct sta_info *sta) unsigned long flags; int err = 0; + WARN_ON(!mutex_is_locked(&local->sta_mtx)); + + /* notify driver */ + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + err = drv_sta_add(local, sdata, &sta->sta); + if (err) { + if (!async) + return err; + printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" + " - keeping it anyway.\n", + sdata->name, sta->sta.addr, err); + } else { + sta->uploaded = true; +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + if (async) + printk(KERN_DEBUG "%s: Finished adding IBSS STA %pM\n", + wiphy_name(local->hw.wiphy), sta->sta.addr); +#endif + } + + sdata = sta->sdata; + + if (!async) { + local->num_sta++; + local->sta_generation++; + smp_mb(); + + /* make the station visible */ + spin_lock_irqsave(&local->sta_lock, flags); + sta_info_hash_add(local, sta); + spin_unlock_irqrestore(&local->sta_lock, flags); + } + + list_add(&sta->list, &local->sta_list); + + ieee80211_sta_debugfs_add(sta); + rate_control_add_sta_debugfs(sta); + + sinfo.filled = 0; + sinfo.generation = local->sta_generation; + cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); + + + return 0; +} + +static void sta_info_finish_pending(struct ieee80211_local *local) +{ + struct sta_info *sta; + unsigned long flags; + + spin_lock_irqsave(&local->sta_lock, flags); + while (!list_empty(&local->sta_pending_list)) { + sta = list_first_entry(&local->sta_pending_list, + struct sta_info, list); + list_del(&sta->list); + spin_unlock_irqrestore(&local->sta_lock, flags); + + sta_info_finish_insert(sta, true); + + spin_lock_irqsave(&local->sta_lock, flags); + } + spin_unlock_irqrestore(&local->sta_lock, flags); +} + +static void sta_info_finish_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, sta_finish_work); + + mutex_lock(&local->sta_mtx); + sta_info_finish_pending(local); + mutex_unlock(&local->sta_mtx); +} + +int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) +{ + struct ieee80211_local *local = sta->local; + struct ieee80211_sub_if_data *sdata = sta->sdata; + unsigned long flags; + int err = 0; + /* * Can't be a WARN_ON because it can be triggered through a race: * something inserts a STA (on one CPU) without holding the RTNL @@ -391,36 +365,87 @@ int sta_info_insert(struct sta_info *sta) */ if (unlikely(!ieee80211_sdata_running(sdata))) { err = -ENETDOWN; + rcu_read_lock(); goto out_free; } if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || is_multicast_ether_addr(sta->sta.addr))) { err = -EINVAL; + rcu_read_lock(); goto out_free; } + /* + * In ad-hoc mode, we sometimes need to insert stations + * from tasklet context from the RX path. To avoid races, + * always do so in that case -- see the comment below. + */ + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + spin_lock_irqsave(&local->sta_lock, flags); + /* check if STA exists already */ + if (sta_info_get_bss(sdata, sta->sta.addr)) { + spin_unlock_irqrestore(&local->sta_lock, flags); + rcu_read_lock(); + err = -EEXIST; + goto out_free; + } + + local->num_sta++; + local->sta_generation++; + smp_mb(); + sta_info_hash_add(local, sta); + + list_add_tail(&sta->list, &local->sta_pending_list); + + rcu_read_lock(); + spin_unlock_irqrestore(&local->sta_lock, flags); + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: Added IBSS STA %pM\n", + wiphy_name(local->hw.wiphy), sta->sta.addr); +#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ + + ieee80211_queue_work(&local->hw, &local->sta_finish_work); + + return 0; + } + + /* + * On first glance, this will look racy, because the code + * below this point, which inserts a station with sleeping, + * unlocks the sta_lock between checking existence in the + * hash table and inserting into it. + * + * However, it is not racy against itself because it keeps + * the mutex locked. It still seems to race against the + * above code that atomically inserts the station... That, + * however, is not true because the above code can only + * be invoked for IBSS interfaces, and the below code will + * not be -- and the two do not race against each other as + * the hash table also keys off the interface. + */ + + might_sleep(); + + mutex_lock(&local->sta_mtx); + spin_lock_irqsave(&local->sta_lock, flags); /* check if STA exists already */ - if (sta_info_get(sdata, sta->sta.addr)) { + if (sta_info_get_bss(sdata, sta->sta.addr)) { spin_unlock_irqrestore(&local->sta_lock, flags); + rcu_read_lock(); err = -EEXIST; goto out_free; } - list_add(&sta->list, &local->sta_list); - local->sta_generation++; - local->num_sta++; - sta_info_hash_add(local, sta); - /* notify driver */ - if (local->ops->sta_notify) { - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); + spin_unlock_irqrestore(&local->sta_lock, flags); - drv_sta_notify(local, sdata, STA_NOTIFY_ADD, &sta->sta); - sdata = sta->sdata; + err = sta_info_finish_insert(sta, false); + if (err) { + mutex_unlock(&local->sta_mtx); + rcu_read_lock(); + goto out_free; } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -428,22 +453,9 @@ int sta_info_insert(struct sta_info *sta) wiphy_name(local->hw.wiphy), sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - spin_unlock_irqrestore(&local->sta_lock, flags); - - sinfo.filled = 0; - sinfo.generation = local->sta_generation; - cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_ATOMIC); - -#ifdef CONFIG_MAC80211_DEBUGFS - /* - * Debugfs entry adding might sleep, so schedule process - * context task for adding entry for STAs that do not yet - * have one. - * NOTE: due to auto-freeing semantics this may only be done - * if the insertion is successful! - */ - schedule_work(&local->sta_debugfs_add); -#endif + /* move reference to rcu-protected */ + rcu_read_lock(); + mutex_unlock(&local->sta_mtx); if (ieee80211_vif_is_mesh(&sdata->vif)) mesh_accept_plinks_update(sdata); @@ -455,6 +467,15 @@ int sta_info_insert(struct sta_info *sta) return err; } +int sta_info_insert(struct sta_info *sta) +{ + int err = sta_info_insert_rcu(sta); + + rcu_read_unlock(); + + return err; +} + static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) { /* @@ -523,108 +544,6 @@ void sta_info_clear_tim_bit(struct sta_info *sta) spin_unlock_irqrestore(&sta->local->sta_lock, flags); } -static void __sta_info_unlink(struct sta_info **sta) -{ - struct ieee80211_local *local = (*sta)->local; - struct ieee80211_sub_if_data *sdata = (*sta)->sdata; - /* - * pull caller's reference if we're already gone. - */ - if (sta_info_hash_del(local, *sta)) { - *sta = NULL; - return; - } - - if ((*sta)->key) { - ieee80211_key_free((*sta)->key); - WARN_ON((*sta)->key); - } - - list_del(&(*sta)->list); - (*sta)->dead = true; - - if (test_and_clear_sta_flags(*sta, - WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { - BUG_ON(!sdata->bss); - - atomic_dec(&sdata->bss->num_sta_ps); - __sta_info_clear_tim_bit(sdata->bss, *sta); - } - - local->num_sta--; - local->sta_generation++; - - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - rcu_assign_pointer(sdata->u.vlan.sta, NULL); - - if (local->ops->sta_notify) { - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - - drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, - &(*sta)->sta); - sdata = (*sta)->sdata; - } - - if (ieee80211_vif_is_mesh(&sdata->vif)) { - mesh_accept_plinks_update(sdata); -#ifdef CONFIG_MAC80211_MESH - del_timer(&(*sta)->plink_timer); -#endif - } - -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Removed STA %pM\n", - wiphy_name(local->hw.wiphy), (*sta)->sta.addr); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - - /* - * Finally, pull caller's reference if the STA is pinned by the - * task that is adding the debugfs entries. In that case, we - * leave the STA "to be freed". - * - * The rules are not trivial, but not too complex either: - * (1) pin_status is only modified under the sta_lock - * (2) STAs may only be pinned under the RTNL so that - * sta_info_flush() is guaranteed to actually destroy - * all STAs that are active for a given interface, this - * is required for correctness because otherwise we - * could notify a driver that an interface is going - * away and only after that (!) notify it about a STA - * on that interface going away. - * (3) sta_info_debugfs_add_work() will set the status - * to PINNED when it found an item that needs a new - * debugfs directory created. In that case, that item - * must not be freed although all *RCU* users are done - * with it. Hence, we tell the caller of _unlink() - * that the item is already gone (as can happen when - * two tasks try to unlink/destroy at the same time) - * (4) We set the pin_status to DESTROY here when we - * find such an item. - * (5) sta_info_debugfs_add_work() will reset the pin_status - * from PINNED to NORMAL when it is done with the item, - * but will check for DESTROY before resetting it in - * which case it will free the item. - */ - if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) { - (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY; - *sta = NULL; - return; - } -} - -void sta_info_unlink(struct sta_info **sta) -{ - struct ieee80211_local *local = (*sta)->local; - unsigned long flags; - - spin_lock_irqsave(&local->sta_lock, flags); - __sta_info_unlink(sta); - spin_unlock_irqrestore(&local->sta_lock, flags); -} - static int sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) { @@ -681,109 +600,209 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, } } - -static void sta_info_cleanup(unsigned long data) +static int __must_check __sta_info_destroy(struct sta_info *sta) { - struct ieee80211_local *local = (struct ieee80211_local *) data; - struct sta_info *sta; + struct ieee80211_local *local; + struct ieee80211_sub_if_data *sdata; + struct sk_buff *skb; + unsigned long flags; + int ret, i; - rcu_read_lock(); - list_for_each_entry_rcu(sta, &local->sta_list, list) - sta_info_cleanup_expire_buffered(local, sta); - rcu_read_unlock(); + might_sleep(); - if (local->quiescing) - return; + if (!sta) + return -ENOENT; - local->sta_cleanup.expires = - round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); - add_timer(&local->sta_cleanup); -} + local = sta->local; + sdata = sta->sdata; -#ifdef CONFIG_MAC80211_DEBUGFS -/* - * See comment in __sta_info_unlink, - * caller must hold local->sta_lock. - */ -static void __sta_info_pin(struct sta_info *sta) -{ - WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL); - sta->pin_status = STA_INFO_PIN_STAT_PINNED; + spin_lock_irqsave(&local->sta_lock, flags); + ret = sta_info_hash_del(local, sta); + /* this might still be the pending list ... which is fine */ + if (!ret) + list_del(&sta->list); + spin_unlock_irqrestore(&local->sta_lock, flags); + if (ret) + return ret; + + if (sta->key) { + ieee80211_key_free(sta->key); + /* + * We have only unlinked the key, and actually destroying it + * may mean it is removed from hardware which requires that + * the key->sta pointer is still valid, so flush the key todo + * list here. + * + * ieee80211_key_todo() will synchronize_rcu() so after this + * nothing can reference this sta struct any more. + */ + ieee80211_key_todo(); + + WARN_ON(sta->key); + } + + sta->dead = true; + + if (test_and_clear_sta_flags(sta, + WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { + BUG_ON(!sdata->bss); + + atomic_dec(&sdata->bss->num_sta_ps); + __sta_info_clear_tim_bit(sdata->bss, sta); + } + + local->num_sta--; + local->sta_generation++; + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + rcu_assign_pointer(sdata->u.vlan.sta, NULL); + + if (sta->uploaded) { + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + drv_sta_remove(local, sdata, &sta->sta); + sdata = sta->sdata; + } + +#ifdef CONFIG_MAC80211_MESH + if (ieee80211_vif_is_mesh(&sdata->vif)) { + mesh_accept_plinks_update(sdata); + del_timer(&sta->plink_timer); + } +#endif + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: Removed STA %pM\n", + wiphy_name(local->hw.wiphy), sta->sta.addr); +#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ + cancel_work_sync(&sta->drv_unblock_wk); + + rate_control_remove_sta_debugfs(sta); + ieee80211_sta_debugfs_remove(sta); + +#ifdef CONFIG_MAC80211_MESH + if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { + mesh_plink_deactivate(sta); + del_timer_sync(&sta->plink_timer); + } +#endif + + while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { + local->total_ps_buffered--; + dev_kfree_skb_any(skb); + } + + while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) + dev_kfree_skb_any(skb); + + for (i = 0; i < STA_TID_NUM; i++) { + struct tid_ampdu_rx *tid_rx; + struct tid_ampdu_tx *tid_tx; + + spin_lock_bh(&sta->lock); + tid_rx = sta->ampdu_mlme.tid_rx[i]; + /* Make sure timer won't free the tid_rx struct, see below */ + if (tid_rx) + tid_rx->shutdown = true; + + spin_unlock_bh(&sta->lock); + + /* + * Outside spinlock - shutdown is true now so that the timer + * won't free tid_rx, we have to do that now. Can't let the + * timer do it because we have to sync the timer outside the + * lock that it takes itself. + */ + if (tid_rx) { + del_timer_sync(&tid_rx->session_timer); + kfree(tid_rx); + } + + /* + * No need to do such complications for TX agg sessions, the + * path leading to freeing the tid_tx struct goes via a call + * from the driver, and thus needs to look up the sta struct + * again, which cannot be found when we get here. Hence, we + * just need to delete the timer and free the aggregation + * info; we won't be telling the peer about it then but that + * doesn't matter if we're not talking to it again anyway. + */ + tid_tx = sta->ampdu_mlme.tid_tx[i]; + if (tid_tx) { + del_timer_sync(&tid_tx->addba_resp_timer); + /* + * STA removed while aggregation session being + * started? Bit odd, but purge frames anyway. + */ + skb_queue_purge(&tid_tx->pending); + kfree(tid_tx); + } + } + + __sta_info_free(local, sta); + + return 0; } -/* - * See comment in __sta_info_unlink, returns sta if it - * needs to be destroyed. - */ -static struct sta_info *__sta_info_unpin(struct sta_info *sta) +int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) { - struct sta_info *ret = NULL; - unsigned long flags; + struct sta_info *sta; + int ret; - spin_lock_irqsave(&sta->local->sta_lock, flags); - WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY && - sta->pin_status != STA_INFO_PIN_STAT_PINNED); - if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY) - ret = sta; - sta->pin_status = STA_INFO_PIN_STAT_NORMAL; - spin_unlock_irqrestore(&sta->local->sta_lock, flags); + mutex_lock(&sdata->local->sta_mtx); + sta = sta_info_get(sdata, addr); + ret = __sta_info_destroy(sta); + mutex_unlock(&sdata->local->sta_mtx); return ret; } -static void sta_info_debugfs_add_work(struct work_struct *work) +int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, + const u8 *addr) { - struct ieee80211_local *local = - container_of(work, struct ieee80211_local, sta_debugfs_add); - struct sta_info *sta, *tmp; - unsigned long flags; + struct sta_info *sta; + int ret; - /* We need to keep the RTNL across the whole pinned status. */ - rtnl_lock(); - while (1) { - sta = NULL; + mutex_lock(&sdata->local->sta_mtx); + sta = sta_info_get_bss(sdata, addr); + ret = __sta_info_destroy(sta); + mutex_unlock(&sdata->local->sta_mtx); - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry(tmp, &local->sta_list, list) { - /* - * debugfs.add_has_run will be set by - * ieee80211_sta_debugfs_add regardless - * of what else it does. - */ - if (!tmp->debugfs.add_has_run) { - sta = tmp; - __sta_info_pin(sta); - break; - } - } - spin_unlock_irqrestore(&local->sta_lock, flags); + return ret; +} - if (!sta) - break; +static void sta_info_cleanup(unsigned long data) +{ + struct ieee80211_local *local = (struct ieee80211_local *) data; + struct sta_info *sta; + + rcu_read_lock(); + list_for_each_entry_rcu(sta, &local->sta_list, list) + sta_info_cleanup_expire_buffered(local, sta); + rcu_read_unlock(); - ieee80211_sta_debugfs_add(sta); - rate_control_add_sta_debugfs(sta); + if (local->quiescing) + return; - sta = __sta_info_unpin(sta); - sta_info_destroy(sta); - } - rtnl_unlock(); + local->sta_cleanup.expires = + round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); + add_timer(&local->sta_cleanup); } -#endif void sta_info_init(struct ieee80211_local *local) { spin_lock_init(&local->sta_lock); + mutex_init(&local->sta_mtx); INIT_LIST_HEAD(&local->sta_list); + INIT_LIST_HEAD(&local->sta_pending_list); + INIT_WORK(&local->sta_finish_work, sta_info_finish_work); setup_timer(&local->sta_cleanup, sta_info_cleanup, (unsigned long)local); local->sta_cleanup.expires = round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); - -#ifdef CONFIG_MAC80211_DEBUGFS - INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work); -#endif } int sta_info_start(struct ieee80211_local *local) @@ -795,16 +814,6 @@ int sta_info_start(struct ieee80211_local *local) void sta_info_stop(struct ieee80211_local *local) { del_timer(&local->sta_cleanup); -#ifdef CONFIG_MAC80211_DEBUGFS - /* - * Make sure the debugfs adding work isn't pending after this - * because we're about to be destroyed. It doesn't matter - * whether it ran or not since we're going to flush all STAs - * anyway. - */ - cancel_work_sync(&local->sta_debugfs_add); -#endif - sta_info_flush(local, NULL); } @@ -820,26 +829,19 @@ int sta_info_flush(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata) { struct sta_info *sta, *tmp; - LIST_HEAD(tmp_list); int ret = 0; - unsigned long flags; might_sleep(); - spin_lock_irqsave(&local->sta_lock, flags); + mutex_lock(&local->sta_mtx); + + sta_info_finish_pending(local); + list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { - if (!sdata || sdata == sta->sdata) { - __sta_info_unlink(&sta); - if (sta) { - list_add_tail(&sta->list, &tmp_list); - ret++; - } - } + if (!sdata || sdata == sta->sdata) + WARN_ON(__sta_info_destroy(sta)); } - spin_unlock_irqrestore(&local->sta_lock, flags); - - list_for_each_entry_safe(sta, tmp, &tmp_list, list) - sta_info_destroy(sta); + mutex_unlock(&local->sta_mtx); return ret; } @@ -849,24 +851,17 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct sta_info *sta, *tmp; - LIST_HEAD(tmp_list); - unsigned long flags; - spin_lock_irqsave(&local->sta_lock, flags); + mutex_lock(&local->sta_mtx); list_for_each_entry_safe(sta, tmp, &local->sta_list, list) if (time_after(jiffies, sta->last_rx + exp_time)) { #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", sdata->name, sta->sta.addr); #endif - __sta_info_unlink(&sta); - if (sta) - list_add(&sta->list, &tmp_list); + WARN_ON(__sta_info_destroy(sta)); } - spin_unlock_irqrestore(&local->sta_lock, flags); - - list_for_each_entry_safe(sta, tmp, &tmp_list, list) - sta_info_destroy(sta); + mutex_unlock(&local->sta_mtx); } struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 6f79bba5706e..5ff611a35979 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -162,11 +162,6 @@ struct sta_ampdu_mlme { }; -/* see __sta_info_unlink */ -#define STA_INFO_PIN_STAT_NORMAL 0 -#define STA_INFO_PIN_STAT_PINNED 1 -#define STA_INFO_PIN_STAT_DESTROY 2 - /** * struct sta_info - STA information * @@ -187,7 +182,6 @@ struct sta_ampdu_mlme { * @flaglock: spinlock for flags accesses * @drv_unblock_wk: used for driver PS unblocking * @listen_interval: listen interval of this station, when we're acting as AP - * @pin_status: used internally for pinning a STA struct into memory * @flags: STA flags, see &enum ieee80211_sta_info_flags * @ps_tx_buf: buffer of frames to transmit to this station * when it leaves power saving state @@ -226,6 +220,7 @@ struct sta_ampdu_mlme { * @debugfs: debug filesystem info * @sta: station information we share with the driver * @dead: set to true when sta is unlinked + * @uploaded: set to true when sta is uploaded to the driver */ struct sta_info { /* General information, mostly static */ @@ -245,11 +240,7 @@ struct sta_info { bool dead; - /* - * for use by the internal lifetime management, - * see __sta_info_unlink - */ - u8 pin_status; + bool uploaded; /* * frequently updated, locked with own spinlock (flaglock), @@ -449,18 +440,19 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, * Insert STA info into hash table/list, returns zero or a * -EEXIST if (if the same MAC address is already present). * - * Calling this without RCU protection makes the caller - * relinquish its reference to @sta. + * Calling the non-rcu version makes the caller relinquish, + * the _rcu version calls read_lock_rcu() and must be called + * without it held. */ int sta_info_insert(struct sta_info *sta); -/* - * Unlink a STA info from the hash table/list. - * This can NULL the STA pointer if somebody else - * has already unlinked it. - */ -void sta_info_unlink(struct sta_info **sta); +int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); +int sta_info_insert_atomic(struct sta_info *sta); + +int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, + const u8 *addr); +int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, + const u8 *addr); -void sta_info_destroy(struct sta_info *sta); void sta_info_set_tim_bit(struct sta_info *sta); void sta_info_clear_tim_bit(struct sta_info *sta); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e392820a4c33..cbe53ed4fb0b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -571,7 +571,7 @@ ieee80211_tx_h_sta(struct ieee80211_tx_data *tx) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - if (tx->sta) + if (tx->sta && tx->sta->uploaded) info->control.sta = &tx->sta->sta; return TX_CONTINUE; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ca170b417da6..3af439a85b33 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1082,7 +1082,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) struct ieee80211_hw *hw = &local->hw; struct ieee80211_sub_if_data *sdata; struct sta_info *sta; - unsigned long flags; int res; if (local->suspended) @@ -1116,20 +1115,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) } /* add STAs back */ - if (local->ops->sta_notify) { - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry(sta, &local->sta_list, list) { + 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) sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, sdata, STA_NOTIFY_ADD, - &sta->sta); + WARN_ON(drv_sta_add(local, sdata, &sta->sta)); } - spin_unlock_irqrestore(&local->sta_lock, flags); } + mutex_unlock(&local->sta_mtx); /* Clear Suspend state so that ADDBA requests can be processed */ @@ -1219,10 +1217,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) add_timer(&local->sta_cleanup); - spin_lock_irqsave(&local->sta_lock, flags); + mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) mesh_plink_restart(sta); - spin_unlock_irqrestore(&local->sta_lock, flags); + mutex_unlock(&local->sta_mtx); #else WARN_ON(1); #endif -- cgit v1.2.3