aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2014-05-23 07:33:12 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-05-26 05:04:41 -0400
commit1a5f0c13d1a8808c2bdd00630818ed491e1719f5 (patch)
tree8fd17631d3377a97be2ccb2181739b4077cf8011 /net
parent67af9811539be83dbdc0739215d29af23c870405 (diff)
mac80211: add a single-transaction driver op to switch contexts
In some cases, when the driver is already using all the channel contexts it can handle at once, we have to do an in-place switch (ie. we cannot afford using an extra context temporarily for the transaction). But some drivers may not support switching the channel context assigned to a vif on the fly (ie. without unassigning and assigning it) while others may only work if the context is changed on the fly, without unassigning it first. To allow these different scenarios, add a new driver operation that let's the driver decide how to handle an in-place switch. 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/driver-ops.h53
-rw-r--r--net/mac80211/trace.h85
2 files changed, 138 insertions, 0 deletions
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,