summaryrefslogtreecommitdiff
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-12-02 23:25:38 +0400
committerJohn W. Linville <linville@tuxdriver.com>2013-12-02 23:25:38 +0400
commit4b074b07625f603d40d4d04937f8874a00415dc4 (patch)
tree2dffdc46e3fea0320524f483cf5ac2c058ab59f2 /net/mac80211/util.c
parent7d68849f40cd9169088249cc889d95c8998c3fb8 (diff)
parentddcc347b70f298f9d624cd0e250581d831d915fb (diff)
downloadlinux-4b074b07625f603d40d4d04937f8874a00415dc4.tar.xz
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c95
1 files changed, 92 insertions, 3 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 592a18171f95..06265d7f8cc3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1804,6 +1804,26 @@ void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)
mutex_unlock(&local->chanctx_mtx);
}
+void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_chanctx *chanctx;
+
+ mutex_lock(&local->chanctx_mtx);
+
+ chanctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+ lockdep_is_held(&local->chanctx_mtx));
+
+ if (WARN_ON_ONCE(!chanctx_conf))
+ goto unlock;
+
+ chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
+ ieee80211_recalc_chanctx_min_def(local, chanctx);
+ unlock:
+ mutex_unlock(&local->chanctx_mtx);
+}
+
static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
{
int i;
@@ -2259,14 +2279,17 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
+ struct cfg80211_chan_def chandef;
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) {
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
if (sdata->wdev.cac_started) {
+ chandef = sdata->vif.bss_conf.chandef;
ieee80211_vif_release_channel(sdata);
cfg80211_cac_event(sdata->dev,
+ &chandef,
NL80211_RADAR_CAC_ABORTED,
GFP_KERNEL);
}
@@ -2447,7 +2470,6 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
if (ieee80211_vif_is_mesh(&sdata->vif)) {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- __le16 pre_value;
skb_put(skb, 8);
*pos++ = WLAN_EID_CHAN_SWITCH_PARAM; /* EID */
@@ -2463,8 +2485,7 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
ifmsh->pre_value = 1;
else
ifmsh->pre_value++;
- pre_value = cpu_to_le16(ifmsh->pre_value);
- memcpy(pos, &pre_value, 2); /* Precedence Value */
+ put_unaligned_le16(ifmsh->pre_value, pos);/* Precedence Value */
pos += 2;
ifmsh->chsw_init = true;
}
@@ -2472,3 +2493,71 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
ieee80211_tx_skb(sdata, skb);
return 0;
}
+
+bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs)
+{
+ return !(cs == NULL || cs->cipher == 0 ||
+ cs->hdr_len < cs->pn_len + cs->pn_off ||
+ cs->hdr_len <= cs->key_idx_off ||
+ cs->key_idx_shift > 7 ||
+ cs->key_idx_mask == 0);
+}
+
+bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n)
+{
+ int i;
+
+ /* Ensure we have enough iftype bitmap space for all iftype values */
+ WARN_ON((NUM_NL80211_IFTYPES / 8 + 1) > sizeof(cs[0].iftype));
+
+ for (i = 0; i < n; i++)
+ if (!ieee80211_cs_valid(&cs[i]))
+ return false;
+
+ return true;
+}
+
+const struct ieee80211_cipher_scheme *
+ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
+ enum nl80211_iftype iftype)
+{
+ const struct ieee80211_cipher_scheme *l = local->hw.cipher_schemes;
+ int n = local->hw.n_cipher_schemes;
+ int i;
+ const struct ieee80211_cipher_scheme *cs = NULL;
+
+ for (i = 0; i < n; i++) {
+ if (l[i].cipher == cipher) {
+ cs = &l[i];
+ break;
+ }
+ }
+
+ if (!cs || !(cs->iftype & BIT(iftype)))
+ return NULL;
+
+ return cs;
+}
+
+int ieee80211_cs_headroom(struct ieee80211_local *local,
+ struct cfg80211_crypto_settings *crypto,
+ enum nl80211_iftype iftype)
+{
+ const struct ieee80211_cipher_scheme *cs;
+ int headroom = IEEE80211_ENCRYPT_HEADROOM;
+ int i;
+
+ for (i = 0; i < crypto->n_ciphers_pairwise; i++) {
+ cs = ieee80211_cs_get(local, crypto->ciphers_pairwise[i],
+ iftype);
+
+ if (cs && headroom < cs->hdr_len)
+ headroom = cs->hdr_len;
+ }
+
+ cs = ieee80211_cs_get(local, crypto->cipher_group, iftype);
+ if (cs && headroom < cs->hdr_len)
+ headroom = cs->hdr_len;
+
+ return headroom;
+}