aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2014-10-08 02:48:40 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-10-09 05:30:09 -0400
commit0f791eb47f8222fd594e6f8a090632344ef23924 (patch)
treeec3771ef78ebd391e7c4e90472b5e8246f083703
parent0c21e6320f6ea7c4bd2fc0a8c1d8577b372f92d2 (diff)
mac80211: allow channel switch with multiple channel contexts
Channel switch with multiple channel contexts should now work fine. Remove check that disallows switches when multiple contexts are in use. Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965.h5
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c1
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c23
-rw-r--r--include/net/mac80211.h1
-rw-r--r--net/mac80211/driver-ops.h7
-rw-r--r--net/mac80211/mlme.c26
-rw-r--r--net/mac80211/trace.h9
8 files changed, 34 insertions, 40 deletions
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 26fec54dcd03..2748fde4b90c 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -6063,7 +6063,7 @@ il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
6063} 6063}
6064 6064
6065void 6065void
6066il4965_mac_channel_switch(struct ieee80211_hw *hw, 6066il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
6067 struct ieee80211_channel_switch *ch_switch) 6067 struct ieee80211_channel_switch *ch_switch)
6068{ 6068{
6069 struct il_priv *il = hw->priv; 6069 struct il_priv *il = hw->priv;
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
index 337dfcf3bbde..3a57f71b8ed5 100644
--- a/drivers/net/wireless/iwlegacy/4965.h
+++ b/drivers/net/wireless/iwlegacy/4965.h
@@ -187,8 +187,9 @@ int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
187 u8 buf_size); 187 u8 buf_size);
188int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 188int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
189 struct ieee80211_sta *sta); 189 struct ieee80211_sta *sta);
190void il4965_mac_channel_switch(struct ieee80211_hw *hw, 190void
191 struct ieee80211_channel_switch *ch_switch); 191il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
192 struct ieee80211_channel_switch *ch_switch);
192 193
193void il4965_led_enable(struct il_priv *il); 194void il4965_led_enable(struct il_priv *il);
194 195
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 2364a3c09b9e..a967bf893a89 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -941,6 +941,7 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
941} 941}
942 942
943static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, 943static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
944 struct ieee80211_vif *vif,
944 struct ieee80211_channel_switch *ch_switch) 945 struct ieee80211_channel_switch *ch_switch)
945{ 946{
946 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); 947 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 575c8f6d4009..6ad3fcedab9b 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5177,10 +5177,11 @@ out:
5177} 5177}
5178 5178
5179static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, 5179static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
5180 struct ieee80211_vif *vif,
5180 struct ieee80211_channel_switch *ch_switch) 5181 struct ieee80211_channel_switch *ch_switch)
5181{ 5182{
5182 struct wl1271 *wl = hw->priv; 5183 struct wl1271 *wl = hw->priv;
5183 struct wl12xx_vif *wlvif; 5184 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
5184 int ret; 5185 int ret;
5185 5186
5186 wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch"); 5187 wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
@@ -5190,14 +5191,8 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
5190 mutex_lock(&wl->mutex); 5191 mutex_lock(&wl->mutex);
5191 5192
5192 if (unlikely(wl->state == WLCORE_STATE_OFF)) { 5193 if (unlikely(wl->state == WLCORE_STATE_OFF)) {
5193 wl12xx_for_each_wlvif_sta(wl, wlvif) { 5194 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
5194 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
5195
5196 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
5197 continue;
5198
5199 ieee80211_chswitch_done(vif, false); 5195 ieee80211_chswitch_done(vif, false);
5200 }
5201 goto out; 5196 goto out;
5202 } else if (unlikely(wl->state != WLCORE_STATE_ON)) { 5197 } else if (unlikely(wl->state != WLCORE_STATE_ON)) {
5203 goto out; 5198 goto out;
@@ -5208,11 +5203,9 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
5208 goto out; 5203 goto out;
5209 5204
5210 /* TODO: change mac80211 to pass vif as param */ 5205 /* TODO: change mac80211 to pass vif as param */
5211 wl12xx_for_each_wlvif_sta(wl, wlvif) {
5212 unsigned long delay_usec;
5213 5206
5214 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) 5207 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
5215 continue; 5208 unsigned long delay_usec;
5216 5209
5217 ret = wl->ops->channel_switch(wl, wlvif, ch_switch); 5210 ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
5218 if (ret) 5211 if (ret)
@@ -5222,10 +5215,10 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
5222 5215
5223 /* indicate failure 5 seconds after channel switch time */ 5216 /* indicate failure 5 seconds after channel switch time */
5224 delay_usec = ieee80211_tu_to_usec(wlvif->beacon_int) * 5217 delay_usec = ieee80211_tu_to_usec(wlvif->beacon_int) *
5225 ch_switch->count; 5218 ch_switch->count;
5226 ieee80211_queue_delayed_work(hw, &wlvif->channel_switch_work, 5219 ieee80211_queue_delayed_work(hw, &wlvif->channel_switch_work,
5227 usecs_to_jiffies(delay_usec) + 5220 usecs_to_jiffies(delay_usec) +
5228 msecs_to_jiffies(5000)); 5221 msecs_to_jiffies(5000));
5229 } 5222 }
5230 5223
5231out_sleep: 5224out_sleep:
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7861ed875c4d..9bb2fc73aeaa 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2969,6 +2969,7 @@ struct ieee80211_ops {
2969 void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 2969 void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2970 u32 queues, bool drop); 2970 u32 queues, bool drop);
2971 void (*channel_switch)(struct ieee80211_hw *hw, 2971 void (*channel_switch)(struct ieee80211_hw *hw,
2972 struct ieee80211_vif *vif,
2972 struct ieee80211_channel_switch *ch_switch); 2973 struct ieee80211_channel_switch *ch_switch);
2973 int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); 2974 int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
2974 int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); 2975 int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 0a6090644769..1bbb0790264f 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -764,12 +764,13 @@ static inline void drv_flush(struct ieee80211_local *local,
764} 764}
765 765
766static inline void drv_channel_switch(struct ieee80211_local *local, 766static inline void drv_channel_switch(struct ieee80211_local *local,
767 struct ieee80211_channel_switch *ch_switch) 767 struct ieee80211_sub_if_data *sdata,
768 struct ieee80211_channel_switch *ch_switch)
768{ 769{
769 might_sleep(); 770 might_sleep();
770 771
771 trace_drv_channel_switch(local, ch_switch); 772 trace_drv_channel_switch(local, sdata, ch_switch);
772 local->ops->channel_switch(&local->hw, ch_switch); 773 local->ops->channel_switch(&local->hw, &sdata->vif, ch_switch);
773 trace_drv_return_void(local); 774 trace_drv_return_void(local);
774} 775}
775 776
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 148253c1bd78..fb6561509caf 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1134,21 +1134,15 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1134 1134
1135 chanctx = container_of(conf, struct ieee80211_chanctx, conf); 1135 chanctx = container_of(conf, struct ieee80211_chanctx, conf);
1136 1136
1137 if (local->use_chanctx) { 1137 if (local->use_chanctx &&
1138 u32 num_chanctx = 0; 1138 !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) {
1139 list_for_each_entry(chanctx, &local->chanctx_list, list) 1139 sdata_info(sdata,
1140 num_chanctx++; 1140 "driver doesn't support chan-switch with channel contexts\n");
1141 1141 ieee80211_queue_work(&local->hw,
1142 if (num_chanctx > 1 || 1142 &ifmgd->csa_connection_drop_work);
1143 !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) { 1143 mutex_unlock(&local->chanctx_mtx);
1144 sdata_info(sdata, 1144 mutex_unlock(&local->mtx);
1145 "not handling chan-switch with channel contexts\n"); 1145 return;
1146 ieee80211_queue_work(&local->hw,
1147 &ifmgd->csa_connection_drop_work);
1148 mutex_unlock(&local->chanctx_mtx);
1149 mutex_unlock(&local->mtx);
1150 return;
1151 }
1152 } 1146 }
1153 1147
1154 ch_switch.timestamp = timestamp; 1148 ch_switch.timestamp = timestamp;
@@ -1192,7 +1186,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1192 1186
1193 if (local->ops->channel_switch) { 1187 if (local->ops->channel_switch) {
1194 /* use driver's channel switch callback */ 1188 /* use driver's channel switch callback */
1195 drv_channel_switch(local, &ch_switch); 1189 drv_channel_switch(local, sdata, &ch_switch);
1196 return; 1190 return;
1197 } 1191 }
1198 1192
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index ca0e12dd23c0..976606aebac9 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -987,12 +987,14 @@ TRACE_EVENT(drv_flush,
987 987
988TRACE_EVENT(drv_channel_switch, 988TRACE_EVENT(drv_channel_switch,
989 TP_PROTO(struct ieee80211_local *local, 989 TP_PROTO(struct ieee80211_local *local,
990 struct ieee80211_sub_if_data *sdata,
990 struct ieee80211_channel_switch *ch_switch), 991 struct ieee80211_channel_switch *ch_switch),
991 992
992 TP_ARGS(local, ch_switch), 993 TP_ARGS(local, sdata, ch_switch),
993 994
994 TP_STRUCT__entry( 995 TP_STRUCT__entry(
995 LOCAL_ENTRY 996 LOCAL_ENTRY
997 VIF_ENTRY
996 CHANDEF_ENTRY 998 CHANDEF_ENTRY
997 __field(u64, timestamp) 999 __field(u64, timestamp)
998 __field(u32, device_timestamp) 1000 __field(u32, device_timestamp)
@@ -1002,6 +1004,7 @@ TRACE_EVENT(drv_channel_switch,
1002 1004
1003 TP_fast_assign( 1005 TP_fast_assign(
1004 LOCAL_ASSIGN; 1006 LOCAL_ASSIGN;
1007 VIF_ASSIGN;
1005 CHANDEF_ASSIGN(&ch_switch->chandef) 1008 CHANDEF_ASSIGN(&ch_switch->chandef)
1006 __entry->timestamp = ch_switch->timestamp; 1009 __entry->timestamp = ch_switch->timestamp;
1007 __entry->device_timestamp = ch_switch->device_timestamp; 1010 __entry->device_timestamp = ch_switch->device_timestamp;
@@ -1010,8 +1013,8 @@ TRACE_EVENT(drv_channel_switch,
1010 ), 1013 ),
1011 1014
1012 TP_printk( 1015 TP_printk(
1013 LOCAL_PR_FMT " new " CHANDEF_PR_FMT " count:%d", 1016 LOCAL_PR_FMT VIF_PR_FMT " new " CHANDEF_PR_FMT " count:%d",
1014 LOCAL_PR_ARG, CHANDEF_PR_ARG, __entry->count 1017 LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG, __entry->count
1015 ) 1018 )
1016); 1019);
1017 1020