aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>2014-05-09 07:11:46 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-05-15 09:00:42 -0400
commit9a774c78e2114c7e8605e3a168ccd552cbe3d922 (patch)
treed1ba64609c6fc1b0b7609630635ee66c601e30cc /net/wireless
parent387910cc79da2e529f2fb4ca9428e861b9402975 (diff)
cfg80211: Support multiple CSA counters
Change the type of NL80211_ATTR_CSA_C_OFF_BEACON and NL80211_ATTR_CSA_C_OFF_PRESP to be NLA_BINARY which allows userspace to use beacons and probe responses with multiple CSA counters. This isn't breaking the API since userspace can continue to use nla_put_u16 for this attributes, which is equivalent to a single element u16 array. In addition advertise max number of supported CSA counters. This is needed when using CSA and eCSA IEs together. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c2
-rw-r--r--net/wireless/nl80211.c65
-rw-r--r--net/wireless/trace.h22
3 files changed, 66 insertions, 23 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 39788711ce6e..d03d8bdb29ca 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -402,6 +402,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
402 rdev->wiphy.rts_threshold = (u32) -1; 402 rdev->wiphy.rts_threshold = (u32) -1;
403 rdev->wiphy.coverage_class = 0; 403 rdev->wiphy.coverage_class = 0;
404 404
405 rdev->wiphy.max_num_csa_counters = 1;
406
405 return &rdev->wiphy; 407 return &rdev->wiphy;
406} 408}
407EXPORT_SYMBOL(wiphy_new); 409EXPORT_SYMBOL(wiphy_new);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4c0ca40ef90e..ca19b1520389 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -371,8 +371,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
371 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 }, 371 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
372 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG }, 372 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
373 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, 373 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
374 [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, 374 [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY },
375 [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, 375 [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY },
376 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, 376 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
377 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, 377 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
378 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, 378 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
@@ -1670,6 +1670,13 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
1670 } 1670 }
1671 nla_nest_end(msg, nested); 1671 nla_nest_end(msg, nested);
1672 } 1672 }
1673 state->split_start++;
1674 break;
1675 case 12:
1676 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
1677 nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
1678 rdev->wiphy.max_num_csa_counters))
1679 goto nla_put_failure;
1673 1680
1674 /* done */ 1681 /* done */
1675 state->split_start = 0; 1682 state->split_start = 0;
@@ -5864,6 +5871,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
5864 u8 radar_detect_width = 0; 5871 u8 radar_detect_width = 0;
5865 int err; 5872 int err;
5866 bool need_new_beacon = false; 5873 bool need_new_beacon = false;
5874 int len, i;
5867 5875
5868 if (!rdev->ops->channel_switch || 5876 if (!rdev->ops->channel_switch ||
5869 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) 5877 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
@@ -5922,26 +5930,55 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
5922 if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]) 5930 if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON])
5923 return -EINVAL; 5931 return -EINVAL;
5924 5932
5925 params.counter_offset_beacon = 5933 len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
5926 nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); 5934 if (!len || (len % sizeof(u16)))
5927 if (params.counter_offset_beacon >= params.beacon_csa.tail_len)
5928 return -EINVAL; 5935 return -EINVAL;
5929 5936
5930 /* sanity check - counters should be the same */ 5937 params.n_counter_offsets_beacon = len / sizeof(u16);
5931 if (params.beacon_csa.tail[params.counter_offset_beacon] != 5938 if (rdev->wiphy.max_num_csa_counters &&
5932 params.count) 5939 (params.n_counter_offsets_beacon >
5940 rdev->wiphy.max_num_csa_counters))
5933 return -EINVAL; 5941 return -EINVAL;
5934 5942
5943 params.counter_offsets_beacon =
5944 nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
5945
5946 /* sanity checks - counters should fit and be the same */
5947 for (i = 0; i < params.n_counter_offsets_beacon; i++) {
5948 u16 offset = params.counter_offsets_beacon[i];
5949
5950 if (offset >= params.beacon_csa.tail_len)
5951 return -EINVAL;
5952
5953 if (params.beacon_csa.tail[offset] != params.count)
5954 return -EINVAL;
5955 }
5956
5935 if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) { 5957 if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) {
5936 params.counter_offset_presp = 5958 len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
5937 nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); 5959 if (!len || (len % sizeof(u16)))
5938 if (params.counter_offset_presp >=
5939 params.beacon_csa.probe_resp_len)
5940 return -EINVAL; 5960 return -EINVAL;
5941 5961
5942 if (params.beacon_csa.probe_resp[params.counter_offset_presp] != 5962 params.n_counter_offsets_presp = len / sizeof(u16);
5943 params.count) 5963 if (rdev->wiphy.max_num_csa_counters &&
5964 (params.n_counter_offsets_beacon >
5965 rdev->wiphy.max_num_csa_counters))
5944 return -EINVAL; 5966 return -EINVAL;
5967
5968 params.counter_offsets_presp =
5969 nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
5970
5971 /* sanity checks - counters should fit and be the same */
5972 for (i = 0; i < params.n_counter_offsets_presp; i++) {
5973 u16 offset = params.counter_offsets_presp[i];
5974
5975 if (offset >= params.beacon_csa.probe_resp_len)
5976 return -EINVAL;
5977
5978 if (params.beacon_csa.probe_resp[offset] !=
5979 params.count)
5980 return -EINVAL;
5981 }
5945 } 5982 }
5946 5983
5947skip_beacons: 5984skip_beacons:
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index cdfbb00e1b37..560ed77084e9 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1876,29 +1876,33 @@ TRACE_EVENT(rdev_channel_switch,
1876 WIPHY_ENTRY 1876 WIPHY_ENTRY
1877 NETDEV_ENTRY 1877 NETDEV_ENTRY
1878 CHAN_DEF_ENTRY 1878 CHAN_DEF_ENTRY
1879 __field(u16, counter_offset_beacon)
1880 __field(u16, counter_offset_presp)
1881 __field(bool, radar_required) 1879 __field(bool, radar_required)
1882 __field(bool, block_tx) 1880 __field(bool, block_tx)
1883 __field(u8, count) 1881 __field(u8, count)
1882 __dynamic_array(u16, bcn_ofs, params->n_counter_offsets_beacon)
1883 __dynamic_array(u16, pres_ofs, params->n_counter_offsets_presp)
1884 ), 1884 ),
1885 TP_fast_assign( 1885 TP_fast_assign(
1886 WIPHY_ASSIGN; 1886 WIPHY_ASSIGN;
1887 NETDEV_ASSIGN; 1887 NETDEV_ASSIGN;
1888 CHAN_DEF_ASSIGN(&params->chandef); 1888 CHAN_DEF_ASSIGN(&params->chandef);
1889 __entry->counter_offset_beacon = params->counter_offset_beacon;
1890 __entry->counter_offset_presp = params->counter_offset_presp;
1891 __entry->radar_required = params->radar_required; 1889 __entry->radar_required = params->radar_required;
1892 __entry->block_tx = params->block_tx; 1890 __entry->block_tx = params->block_tx;
1893 __entry->count = params->count; 1891 __entry->count = params->count;
1892 memcpy(__get_dynamic_array(bcn_ofs),
1893 params->counter_offsets_beacon,
1894 params->n_counter_offsets_beacon * sizeof(u16));
1895
1896 /* probe response offsets are optional */
1897 if (params->n_counter_offsets_presp)
1898 memcpy(__get_dynamic_array(pres_ofs),
1899 params->counter_offsets_presp,
1900 params->n_counter_offsets_presp * sizeof(u16));
1894 ), 1901 ),
1895 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT 1902 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
1896 ", block_tx: %d, count: %u, radar_required: %d" 1903 ", block_tx: %d, count: %u, radar_required: %d",
1897 ", counter offsets (beacon/presp): %u/%u",
1898 WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, 1904 WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
1899 __entry->block_tx, __entry->count, __entry->radar_required, 1905 __entry->block_tx, __entry->count, __entry->radar_required)
1900 __entry->counter_offset_beacon,
1901 __entry->counter_offset_presp)
1902); 1906);
1903 1907
1904TRACE_EVENT(rdev_set_qos_map, 1908TRACE_EVENT(rdev_set_qos_map,