diff options
author | Luciano Coelho <luciano.coelho@intel.com> | 2014-10-08 02:48:37 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-10-09 05:30:08 -0400 |
commit | 6d027bcc8a4e2518ae825b0ff3dd069ab1abfe96 (patch) | |
tree | 798d3bfaf90f5f653905da6cb3be864f2a7a0443 /net | |
parent | e9a21949b79414dda42a017855b288901c07e613 (diff) |
mac80211: add pre_channel_switch driver operation
Some drivers may need to prepare for a channel switch also when it is
initiated from the remote side (eg. station, P2P client). To make
this possible, add a generic callback that can be called for all
interface types.
Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 11 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 18 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 25 | ||||
-rw-r--r-- | net/mac80211/trace.h | 33 |
4 files changed, 79 insertions, 8 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 3a04f2edd3c3..647a2f6eb7dc 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -3104,6 +3104,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3104 | { | 3104 | { |
3105 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3105 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3106 | struct ieee80211_local *local = sdata->local; | 3106 | struct ieee80211_local *local = sdata->local; |
3107 | struct ieee80211_channel_switch ch_switch; | ||
3107 | struct ieee80211_chanctx_conf *conf; | 3108 | struct ieee80211_chanctx_conf *conf; |
3108 | struct ieee80211_chanctx *chanctx; | 3109 | struct ieee80211_chanctx *chanctx; |
3109 | int err, changed = 0; | 3110 | int err, changed = 0; |
@@ -3139,6 +3140,10 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3139 | goto out; | 3140 | goto out; |
3140 | } | 3141 | } |
3141 | 3142 | ||
3143 | err = drv_pre_channel_switch(sdata, &ch_switch); | ||
3144 | if (err) | ||
3145 | goto out; | ||
3146 | |||
3142 | err = ieee80211_vif_reserve_chanctx(sdata, ¶ms->chandef, | 3147 | err = ieee80211_vif_reserve_chanctx(sdata, ¶ms->chandef, |
3143 | chanctx->mode, | 3148 | chanctx->mode, |
3144 | params->radar_required); | 3149 | params->radar_required); |
@@ -3152,6 +3157,12 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3152 | goto out; | 3157 | goto out; |
3153 | } | 3158 | } |
3154 | 3159 | ||
3160 | ch_switch.timestamp = 0; | ||
3161 | ch_switch.device_timestamp = 0; | ||
3162 | ch_switch.block_tx = params->block_tx; | ||
3163 | ch_switch.chandef = params->chandef; | ||
3164 | ch_switch.count = params->count; | ||
3165 | |||
3155 | err = ieee80211_set_csa_beacon(sdata, params, &changed); | 3166 | err = ieee80211_set_csa_beacon(sdata, params, &changed); |
3156 | if (err) { | 3167 | if (err) { |
3157 | ieee80211_vif_unreserve_chanctx(sdata); | 3168 | ieee80211_vif_unreserve_chanctx(sdata); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 196d48c68134..5522672129ce 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -1196,6 +1196,24 @@ drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata, | |||
1196 | } | 1196 | } |
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | static inline int | ||
1200 | drv_pre_channel_switch(struct ieee80211_sub_if_data *sdata, | ||
1201 | struct ieee80211_channel_switch *ch_switch) | ||
1202 | { | ||
1203 | struct ieee80211_local *local = sdata->local; | ||
1204 | int ret = 0; | ||
1205 | |||
1206 | if (!check_sdata_in_driver(sdata)) | ||
1207 | return -EIO; | ||
1208 | |||
1209 | trace_drv_pre_channel_switch(local, sdata, ch_switch); | ||
1210 | if (local->ops->pre_channel_switch) | ||
1211 | ret = local->ops->pre_channel_switch(&local->hw, &sdata->vif, | ||
1212 | ch_switch); | ||
1213 | trace_drv_return_int(local, ret); | ||
1214 | return ret; | ||
1215 | } | ||
1216 | |||
1199 | static inline int drv_join_ibss(struct ieee80211_local *local, | 1217 | static inline int drv_join_ibss(struct ieee80211_local *local, |
1200 | struct ieee80211_sub_if_data *sdata) | 1218 | struct ieee80211_sub_if_data *sdata) |
1201 | { | 1219 | { |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f2e048fa250c..d23d6d97e453 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1057,6 +1057,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1057 | struct ieee80211_chanctx *chanctx; | 1057 | struct ieee80211_chanctx *chanctx; |
1058 | enum ieee80211_band current_band; | 1058 | enum ieee80211_band current_band; |
1059 | struct ieee80211_csa_ie csa_ie; | 1059 | struct ieee80211_csa_ie csa_ie; |
1060 | struct ieee80211_channel_switch ch_switch; | ||
1060 | int res; | 1061 | int res; |
1061 | 1062 | ||
1062 | sdata_assert_lock(sdata); | 1063 | sdata_assert_lock(sdata); |
@@ -1128,6 +1129,22 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1128 | } | 1129 | } |
1129 | } | 1130 | } |
1130 | 1131 | ||
1132 | ch_switch.timestamp = timestamp; | ||
1133 | ch_switch.device_timestamp = device_timestamp; | ||
1134 | ch_switch.block_tx = csa_ie.mode; | ||
1135 | ch_switch.chandef = csa_ie.chandef; | ||
1136 | ch_switch.count = csa_ie.count; | ||
1137 | |||
1138 | if (drv_pre_channel_switch(sdata, &ch_switch)) { | ||
1139 | sdata_info(sdata, | ||
1140 | "preparing for channel switch failed, disconnecting\n"); | ||
1141 | ieee80211_queue_work(&local->hw, | ||
1142 | &ifmgd->csa_connection_drop_work); | ||
1143 | mutex_unlock(&local->chanctx_mtx); | ||
1144 | mutex_unlock(&local->mtx); | ||
1145 | return; | ||
1146 | } | ||
1147 | |||
1131 | res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef, | 1148 | res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef, |
1132 | chanctx->mode, false); | 1149 | chanctx->mode, false); |
1133 | if (res) { | 1150 | if (res) { |
@@ -1153,14 +1170,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1153 | 1170 | ||
1154 | if (local->ops->channel_switch) { | 1171 | if (local->ops->channel_switch) { |
1155 | /* use driver's channel switch callback */ | 1172 | /* use driver's channel switch callback */ |
1156 | struct ieee80211_channel_switch ch_switch = { | ||
1157 | .timestamp = timestamp, | ||
1158 | .device_timestamp = device_timestamp, | ||
1159 | .block_tx = csa_ie.mode, | ||
1160 | .chandef = csa_ie.chandef, | ||
1161 | .count = csa_ie.count, | ||
1162 | }; | ||
1163 | |||
1164 | drv_channel_switch(local, &ch_switch); | 1173 | drv_channel_switch(local, &ch_switch); |
1165 | return; | 1174 | return; |
1166 | } | 1175 | } |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 853c440218d4..30476d2c7302 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -2108,6 +2108,39 @@ TRACE_EVENT(drv_channel_switch_beacon, | |||
2108 | ) | 2108 | ) |
2109 | ); | 2109 | ); |
2110 | 2110 | ||
2111 | TRACE_EVENT(drv_pre_channel_switch, | ||
2112 | TP_PROTO(struct ieee80211_local *local, | ||
2113 | struct ieee80211_sub_if_data *sdata, | ||
2114 | struct ieee80211_channel_switch *ch_switch), | ||
2115 | |||
2116 | TP_ARGS(local, sdata, ch_switch), | ||
2117 | |||
2118 | TP_STRUCT__entry( | ||
2119 | LOCAL_ENTRY | ||
2120 | VIF_ENTRY | ||
2121 | CHANDEF_ENTRY | ||
2122 | __field(u64, timestamp) | ||
2123 | __field(bool, block_tx) | ||
2124 | __field(u8, count) | ||
2125 | ), | ||
2126 | |||
2127 | TP_fast_assign( | ||
2128 | LOCAL_ASSIGN; | ||
2129 | VIF_ASSIGN; | ||
2130 | CHANDEF_ASSIGN(&ch_switch->chandef) | ||
2131 | __entry->timestamp = ch_switch->timestamp; | ||
2132 | __entry->block_tx = ch_switch->block_tx; | ||
2133 | __entry->count = ch_switch->count; | ||
2134 | ), | ||
2135 | |||
2136 | TP_printk( | ||
2137 | LOCAL_PR_FMT VIF_PR_FMT " prepare channel switch to " | ||
2138 | CHANDEF_PR_FMT " count:%d block_tx:%d timestamp:%llu", | ||
2139 | LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG, __entry->count, | ||
2140 | __entry->block_tx, __entry->timestamp | ||
2141 | ) | ||
2142 | ); | ||
2143 | |||
2111 | 2144 | ||
2112 | #ifdef CONFIG_MAC80211_MESSAGE_TRACING | 2145 | #ifdef CONFIG_MAC80211_MESSAGE_TRACING |
2113 | #undef TRACE_SYSTEM | 2146 | #undef TRACE_SYSTEM |