aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h46
-rw-r--r--net/mac80211/driver-ops.h53
-rw-r--r--net/mac80211/trace.h85
3 files changed, 184 insertions, 0 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2c78997bc48d..421b6ecb4b2c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -189,6 +189,43 @@ struct ieee80211_chanctx_conf {
189}; 189};
190 190
191/** 191/**
192 * enum ieee80211_chanctx_switch_mode - channel context switch mode
193 * @CHANCTX_SWMODE_REASSIGN_VIF: Both old and new contexts already
194 * exist (and will continue to exist), but the virtual interface
195 * needs to be switched from one to the other.
196 * @CHANCTX_SWMODE_SWAP_CONTEXTS: The old context exists but will stop
197 * to exist with this call, the new context doesn't exist but
198 * will be active after this call, the virtual interface switches
199 * from the old to the new (note that the driver may of course
200 * implement this as an on-the-fly chandef switch of the existing
201 * hardware context, but the mac80211 pointer for the old context
202 * will cease to exist and only the new one will later be used
203 * for changes/removal.)
204 */
205enum ieee80211_chanctx_switch_mode {
206 CHANCTX_SWMODE_REASSIGN_VIF,
207 CHANCTX_SWMODE_SWAP_CONTEXTS,
208};
209
210/**
211 * struct ieee80211_vif_chanctx_switch - vif chanctx switch information
212 *
213 * This is structure is used to pass information about a vif that
214 * needs to switch from one chanctx to another. The
215 * &ieee80211_chanctx_switch_mode defines how the switch should be
216 * done.
217 *
218 * @vif: the vif that should be switched from old_ctx to new_ctx
219 * @old_ctx: the old context to which the vif was assigned
220 * @new_ctx: the new context to which the vif must be assigned
221 */
222struct ieee80211_vif_chanctx_switch {
223 struct ieee80211_vif *vif;
224 struct ieee80211_chanctx_conf *old_ctx;
225 struct ieee80211_chanctx_conf *new_ctx;
226};
227
228/**
192 * enum ieee80211_bss_change - BSS change notification flags 229 * enum ieee80211_bss_change - BSS change notification flags
193 * 230 *
194 * These flags are used with the bss_info_changed() callback 231 * These flags are used with the bss_info_changed() callback
@@ -2736,6 +2773,11 @@ enum ieee80211_roc_type {
2736 * to vif. Possible use is for hw queue remapping. 2773 * to vif. Possible use is for hw queue remapping.
2737 * @unassign_vif_chanctx: Notifies device driver about channel context being 2774 * @unassign_vif_chanctx: Notifies device driver about channel context being
2738 * unbound from vif. 2775 * unbound from vif.
2776 * @switch_vif_chanctx: switch a number of vifs from one chanctx to
2777 * another, as specified in the list of
2778 * @ieee80211_vif_chanctx_switch passed to the driver, according
2779 * to the mode defined in &ieee80211_chanctx_switch_mode.
2780 *
2739 * @start_ap: Start operation on the AP interface, this is called after all the 2781 * @start_ap: Start operation on the AP interface, this is called after all the
2740 * information in bss_conf is set and beacon can be retrieved. A channel 2782 * information in bss_conf is set and beacon can be retrieved. A channel
2741 * context is bound before this is called. Note that if the driver uses 2783 * context is bound before this is called. Note that if the driver uses
@@ -2952,6 +2994,10 @@ struct ieee80211_ops {
2952 void (*unassign_vif_chanctx)(struct ieee80211_hw *hw, 2994 void (*unassign_vif_chanctx)(struct ieee80211_hw *hw,
2953 struct ieee80211_vif *vif, 2995 struct ieee80211_vif *vif,
2954 struct ieee80211_chanctx_conf *ctx); 2996 struct ieee80211_chanctx_conf *ctx);
2997 int (*switch_vif_chanctx)(struct ieee80211_hw *hw,
2998 struct ieee80211_vif_chanctx_switch *vifs,
2999 int n_vifs,
3000 enum ieee80211_chanctx_switch_mode mode);
2955 3001
2956 void (*restart_complete)(struct ieee80211_hw *hw); 3002 void (*restart_complete)(struct ieee80211_hw *hw);
2957 3003
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 696ef78b1fb7..bd782dcffcc7 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1048,6 +1048,59 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
1048 trace_drv_return_void(local); 1048 trace_drv_return_void(local);
1049} 1049}
1050 1050
1051static inline int
1052drv_switch_vif_chanctx(struct ieee80211_local *local,
1053 struct ieee80211_vif_chanctx_switch *vifs,
1054 int n_vifs,
1055 enum ieee80211_chanctx_switch_mode mode)
1056{
1057 int ret = 0;
1058 int i;
1059
1060 if (!local->ops->switch_vif_chanctx)
1061 return -EOPNOTSUPP;
1062
1063 for (i = 0; i < n_vifs; i++) {
1064 struct ieee80211_chanctx *new_ctx =
1065 container_of(vifs[i].new_ctx,
1066 struct ieee80211_chanctx,
1067 conf);
1068 struct ieee80211_chanctx *old_ctx =
1069 container_of(vifs[i].old_ctx,
1070 struct ieee80211_chanctx,
1071 conf);
1072
1073 WARN_ON_ONCE(!old_ctx->driver_present);
1074 WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS &&
1075 new_ctx->driver_present) ||
1076 (mode == CHANCTX_SWMODE_REASSIGN_VIF &&
1077 !new_ctx->driver_present));
1078 }
1079
1080 trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode);
1081 ret = local->ops->switch_vif_chanctx(&local->hw,
1082 vifs, n_vifs, mode);
1083 trace_drv_return_int(local, ret);
1084
1085 if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
1086 for (i = 0; i < n_vifs; i++) {
1087 struct ieee80211_chanctx *new_ctx =
1088 container_of(vifs[i].new_ctx,
1089 struct ieee80211_chanctx,
1090 conf);
1091 struct ieee80211_chanctx *old_ctx =
1092 container_of(vifs[i].old_ctx,
1093 struct ieee80211_chanctx,
1094 conf);
1095
1096 new_ctx->driver_present = true;
1097 old_ctx->driver_present = false;
1098 }
1099 }
1100
1101 return ret;
1102}
1103
1051static inline int drv_start_ap(struct ieee80211_local *local, 1104static inline int drv_start_ap(struct ieee80211_local *local,
1052 struct ieee80211_sub_if_data *sdata) 1105 struct ieee80211_sub_if_data *sdata)
1053{ 1106{
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 942f64b8ce0e..b22d6969cde9 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1389,6 +1389,91 @@ TRACE_EVENT(drv_change_chanctx,
1389 ) 1389 )
1390); 1390);
1391 1391
1392#if !defined(__TRACE_VIF_ENTRY)
1393#define __TRACE_VIF_ENTRY
1394struct trace_vif_entry {
1395 enum nl80211_iftype vif_type;
1396 bool p2p;
1397 char vif_name[IFNAMSIZ];
1398} __packed;
1399
1400struct trace_chandef_entry {
1401 u32 control_freq;
1402 u32 chan_width;
1403 u32 center_freq1;
1404 u32 center_freq2;
1405} __packed;
1406
1407struct trace_switch_entry {
1408 struct trace_vif_entry vif;
1409 struct trace_chandef_entry old_chandef;
1410 struct trace_chandef_entry new_chandef;
1411} __packed;
1412
1413#define SWITCH_ENTRY_ASSIGN(to, from) local_vifs[i].to = vifs[i].from
1414#endif
1415
1416TRACE_EVENT(drv_switch_vif_chanctx,
1417 TP_PROTO(struct ieee80211_local *local,
1418 struct ieee80211_vif_chanctx_switch *vifs,
1419 int n_vifs, enum ieee80211_chanctx_switch_mode mode),
1420 TP_ARGS(local, vifs, n_vifs, mode),
1421
1422 TP_STRUCT__entry(
1423 LOCAL_ENTRY
1424 __field(int, n_vifs)
1425 __field(u32, mode)
1426 __dynamic_array(u8, vifs,
1427 sizeof(struct trace_switch_entry) * n_vifs)
1428 ),
1429
1430 TP_fast_assign(
1431 LOCAL_ASSIGN;
1432 __entry->n_vifs = n_vifs;
1433 __entry->mode = mode;
1434 {
1435 struct trace_switch_entry *local_vifs =
1436 __get_dynamic_array(vifs);
1437 int i;
1438
1439 for (i = 0; i < n_vifs; i++) {
1440 struct ieee80211_sub_if_data *sdata;
1441
1442 sdata = container_of(vifs[i].vif,
1443 struct ieee80211_sub_if_data,
1444 vif);
1445
1446 SWITCH_ENTRY_ASSIGN(vif.vif_type, vif->type);
1447 SWITCH_ENTRY_ASSIGN(vif.p2p, vif->p2p);
1448 strncpy(local_vifs[i].vif.vif_name,
1449 sdata->name,
1450 sizeof(local_vifs[i].vif.vif_name));
1451 SWITCH_ENTRY_ASSIGN(old_chandef.control_freq,
1452 old_ctx->def.chan->center_freq);
1453 SWITCH_ENTRY_ASSIGN(old_chandef.chan_width,
1454 old_ctx->def.width);
1455 SWITCH_ENTRY_ASSIGN(old_chandef.center_freq1,
1456 old_ctx->def.center_freq1);
1457 SWITCH_ENTRY_ASSIGN(old_chandef.center_freq2,
1458 old_ctx->def.center_freq2);
1459 SWITCH_ENTRY_ASSIGN(new_chandef.control_freq,
1460 new_ctx->def.chan->center_freq);
1461 SWITCH_ENTRY_ASSIGN(new_chandef.chan_width,
1462 new_ctx->def.width);
1463 SWITCH_ENTRY_ASSIGN(new_chandef.center_freq1,
1464 new_ctx->def.center_freq1);
1465 SWITCH_ENTRY_ASSIGN(new_chandef.center_freq2,
1466 new_ctx->def.center_freq2);
1467 }
1468 }
1469 ),
1470
1471 TP_printk(
1472 LOCAL_PR_FMT " n_vifs:%d mode:%d",
1473 LOCAL_PR_ARG, __entry->n_vifs, __entry->mode
1474 )
1475);
1476
1392DECLARE_EVENT_CLASS(local_sdata_chanctx, 1477DECLARE_EVENT_CLASS(local_sdata_chanctx,
1393 TP_PROTO(struct ieee80211_local *local, 1478 TP_PROTO(struct ieee80211_local *local,
1394 struct ieee80211_sub_if_data *sdata, 1479 struct ieee80211_sub_if_data *sdata,