diff options
-rw-r--r-- | include/net/mac80211.h | 46 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 53 | ||||
-rw-r--r-- | net/mac80211/trace.h | 85 |
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 | */ | ||
205 | enum 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 | */ | ||
222 | struct 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 | ||
1051 | static inline int | ||
1052 | drv_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 | |||
1051 | static inline int drv_start_ap(struct ieee80211_local *local, | 1104 | static 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 | ||
1394 | struct trace_vif_entry { | ||
1395 | enum nl80211_iftype vif_type; | ||
1396 | bool p2p; | ||
1397 | char vif_name[IFNAMSIZ]; | ||
1398 | } __packed; | ||
1399 | |||
1400 | struct trace_chandef_entry { | ||
1401 | u32 control_freq; | ||
1402 | u32 chan_width; | ||
1403 | u32 center_freq1; | ||
1404 | u32 center_freq2; | ||
1405 | } __packed; | ||
1406 | |||
1407 | struct 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 | |||
1416 | TRACE_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 | |||
1392 | DECLARE_EVENT_CLASS(local_sdata_chanctx, | 1477 | DECLARE_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, |