From 731977e97b3697454a862fec656c2561eabc0b87 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Tue, 24 Jan 2017 16:42:10 +0100 Subject: mac80211: use helper function to access ieee802_1d_to_ac[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cleanup patch to make use of ieee80211_ac_from_tid() to retrieve ac from ieee802_1d_to_ac[] Signed-off-by: Amadeusz Sławiński Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 2 +- net/mac80211/status.c | 2 +- net/mac80211/tx.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b791c4190564..50ca3828b124 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1391,7 +1391,7 @@ EXPORT_SYMBOL(ieee80211_sta_pspoll); void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid) { struct sta_info *sta = container_of(pubsta, struct sta_info, sta); - u8 ac = ieee802_1d_to_ac[tid & 7]; + int ac = ieee80211_ac_from_tid(tid); /* * If this AC is not trigger-enabled do nothing unless the diff --git a/net/mac80211/status.c b/net/mac80211/status.c index d6a1bfaa7a81..a3af6e1bfd98 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -95,7 +95,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, */ if (*p & IEEE80211_QOS_CTL_EOSP) *p &= ~IEEE80211_QOS_CTL_EOSP; - ac = ieee802_1d_to_ac[tid & 7]; + ac = ieee80211_ac_from_tid(tid); } else { ac = IEEE80211_AC_BE; } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 986de098803d..ba8d7db0a071 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1414,7 +1414,7 @@ void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata, txqi->txq.sta = &sta->sta; sta->sta.txq[tid] = &txqi->txq; txqi->txq.tid = tid; - txqi->txq.ac = ieee802_1d_to_ac[tid & 7]; + txqi->txq.ac = ieee80211_ac_from_tid(tid); } else { sdata->vif.txq = &txqi->txq; txqi->txq.tid = 0; @@ -4659,7 +4659,7 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int tid, enum nl80211_band band) { - int ac = ieee802_1d_to_ac[tid & 7]; + int ac = ieee80211_ac_from_tid(tid); skb_reset_mac_header(skb); skb_set_queue_mapping(skb, ac); -- cgit v1.2.3 From bddb2afcb6c52a545f18fb9bcd4829828ebf4a3a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 7 Feb 2017 10:40:50 +0100 Subject: mac80211: add back lost debugfs files Somehow these files were never present or lost, but the code is there and they seem somewhat useful, so add them back. Signed-off-by: Johannes Berg --- net/mac80211/debugfs.c | 1 + net/mac80211/debugfs_sta.c | 1 + 2 files changed, 2 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index f62cd0e13c58..47bea0babe78 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -356,6 +356,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(total_ps_buffered); DEBUGFS_ADD(wep_iv); + DEBUGFS_ADD(rate_ctrl_alg); DEBUGFS_ADD(queues); DEBUGFS_ADD(misc); #ifdef CONFIG_PM diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index f6003b8c2c33..42601820db20 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -522,6 +522,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) return; DEBUGFS_ADD(flags); + DEBUGFS_ADD(aid); DEBUGFS_ADD(num_ps_buf_frames); DEBUGFS_ADD(last_seq_ctrl); DEBUGFS_ADD(agg_status); -- cgit v1.2.3 From fe8de3da13bdbcbe8b583a3bbadf677da0f04f83 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 6 Feb 2017 10:49:27 +0000 Subject: mac80211: fils_aead: Use crypto api CMAC shash rather than bare cipher Switch the FILS AEAD code to use a cmac(aes) shash instantiated by the crypto API rather than reusing the open coded implementation in aes_cmac_vector(). This makes the code more understandable, and allows platforms to implement cmac(aes) in a more secure (*) and efficient way than is typically possible when using the AES cipher directly. So replace the crypto_cipher by a crypto_shash, and update the aes_s2v() routine to call the shash interface directly. * In particular, the generic table based AES implementation is sensitive to known-plaintext timing attacks on the key, to which AES based MAC algorithms are especially vulnerable, given that their plaintext is not usually secret. Time invariant alternatives are available (e.g., based on SIMD algorithms), but may incur a setup cost that is prohibitive when operating on a single block at a time, which is why they don't usually expose the cipher API. Signed-off-by: Ard Biesheuvel Signed-off-by: Johannes Berg --- net/mac80211/Kconfig | 1 + net/mac80211/aes_cmac.h | 4 --- net/mac80211/fils_aead.c | 74 +++++++++++++++++++++--------------------------- 3 files changed, 34 insertions(+), 45 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 3891cbd2adea..76e30f4797fb 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -6,6 +6,7 @@ config MAC80211 select CRYPTO_AES select CRYPTO_CCM select CRYPTO_GCM + select CRYPTO_CMAC select CRC32 ---help--- This option enables the hardware independent IEEE 802.11 diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h index c827e1d5de8b..3702041f44fd 100644 --- a/net/mac80211/aes_cmac.h +++ b/net/mac80211/aes_cmac.h @@ -11,10 +11,6 @@ #include -void gf_mulx(u8 *pad); -void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac, - size_t mac_len); struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], size_t key_len); void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, diff --git a/net/mac80211/fils_aead.c b/net/mac80211/fils_aead.c index ecfdd97758a3..061a9211ecf5 100644 --- a/net/mac80211/fils_aead.c +++ b/net/mac80211/fils_aead.c @@ -9,66 +9,58 @@ #include #include +#include #include #include "ieee80211_i.h" #include "aes_cmac.h" #include "fils_aead.h" -static int aes_s2v(struct crypto_cipher *tfm, +static void gf_mulx(u8 *pad) +{ + u64 a = get_unaligned_be64(pad); + u64 b = get_unaligned_be64(pad + 8); + + put_unaligned_be64((a << 1) | (b >> 63), pad); + put_unaligned_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0), pad + 8); +} + +static int aes_s2v(struct crypto_shash *tfm, size_t num_elem, const u8 *addr[], size_t len[], u8 *v) { - u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; + u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE] = {}; + SHASH_DESC_ON_STACK(desc, tfm); size_t i; - const u8 *data[2]; - size_t data_len[2], data_elems; + + desc->tfm = tfm; /* D = AES-CMAC(K, ) */ - memset(tmp, 0, AES_BLOCK_SIZE); - data[0] = tmp; - data_len[0] = AES_BLOCK_SIZE; - aes_cmac_vector(tfm, 1, data, data_len, d, AES_BLOCK_SIZE); + crypto_shash_digest(desc, tmp, AES_BLOCK_SIZE, d); for (i = 0; i < num_elem - 1; i++) { /* D = dbl(D) xor AES_CMAC(K, Si) */ gf_mulx(d); /* dbl */ - aes_cmac_vector(tfm, 1, &addr[i], &len[i], tmp, - AES_BLOCK_SIZE); + crypto_shash_digest(desc, addr[i], len[i], tmp); crypto_xor(d, tmp, AES_BLOCK_SIZE); } + crypto_shash_init(desc); + if (len[i] >= AES_BLOCK_SIZE) { /* len(Sn) >= 128 */ - size_t j; - const u8 *pos; - /* T = Sn xorend D */ - - /* Use a temporary buffer to perform xorend on Sn (addr[i]) to - * avoid modifying the const input argument. - */ - data[0] = addr[i]; - data_len[0] = len[i] - AES_BLOCK_SIZE; - pos = addr[i] + data_len[0]; - for (j = 0; j < AES_BLOCK_SIZE; j++) - tmp[j] = pos[j] ^ d[j]; - data[1] = tmp; - data_len[1] = AES_BLOCK_SIZE; - data_elems = 2; + crypto_shash_update(desc, addr[i], len[i] - AES_BLOCK_SIZE); + crypto_xor(d, addr[i] + len[i] - AES_BLOCK_SIZE, + AES_BLOCK_SIZE); } else { /* len(Sn) < 128 */ /* T = dbl(D) xor pad(Sn) */ gf_mulx(d); /* dbl */ - memset(tmp, 0, AES_BLOCK_SIZE); - memcpy(tmp, addr[i], len[i]); - tmp[len[i]] = 0x80; - crypto_xor(d, tmp, AES_BLOCK_SIZE); - data[0] = d; - data_len[0] = sizeof(d); - data_elems = 1; + crypto_xor(d, addr[i], len[i]); + d[len[i]] ^= 0x80; } /* V = AES-CMAC(K, T) */ - aes_cmac_vector(tfm, data_elems, data, data_len, v, AES_BLOCK_SIZE); + crypto_shash_finup(desc, d, AES_BLOCK_SIZE, v); return 0; } @@ -80,7 +72,7 @@ static int aes_siv_encrypt(const u8 *key, size_t key_len, size_t len[], u8 *out) { u8 v[AES_BLOCK_SIZE]; - struct crypto_cipher *tfm; + struct crypto_shash *tfm; struct crypto_skcipher *tfm2; struct skcipher_request *req; int res; @@ -95,14 +87,14 @@ static int aes_siv_encrypt(const u8 *key, size_t key_len, /* S2V */ - tfm = crypto_alloc_cipher("aes", 0, 0); + tfm = crypto_alloc_shash("cmac(aes)", 0, 0); if (IS_ERR(tfm)) return PTR_ERR(tfm); /* K1 for S2V */ - res = crypto_cipher_setkey(tfm, key, key_len); + res = crypto_shash_setkey(tfm, key, key_len); if (!res) res = aes_s2v(tfm, num_elem, addr, len, v); - crypto_free_cipher(tfm); + crypto_free_shash(tfm); if (res) return res; @@ -157,7 +149,7 @@ static int aes_siv_decrypt(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], size_t len[], u8 *out) { - struct crypto_cipher *tfm; + struct crypto_shash *tfm; struct crypto_skcipher *tfm2; struct skcipher_request *req; struct scatterlist src[1], dst[1]; @@ -210,14 +202,14 @@ static int aes_siv_decrypt(const u8 *key, size_t key_len, /* S2V */ - tfm = crypto_alloc_cipher("aes", 0, 0); + tfm = crypto_alloc_shash("cmac(aes)", 0, 0); if (IS_ERR(tfm)) return PTR_ERR(tfm); /* K1 for S2V */ - res = crypto_cipher_setkey(tfm, key, key_len); + res = crypto_shash_setkey(tfm, key, key_len); if (!res) res = aes_s2v(tfm, num_elem, addr, len, check); - crypto_free_cipher(tfm); + crypto_free_shash(tfm); if (res) return res; if (memcmp(check, frame_iv, AES_BLOCK_SIZE) != 0) -- cgit v1.2.3 From 26717828b75dd5c46e97f7f4a9b937d038bb2852 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 6 Feb 2017 10:49:28 +0000 Subject: mac80211: aes-cmac: switch to shash CMAC driver Instead of open coding the CMAC algorithm in the mac80211 driver using byte wide xors and calls into the crypto layer for each block of data, instantiate a cmac(aes) synchronous hash and pass all the data into it directly. This does not only simplify the code, it also allows the use of more efficient and more secure implementations, especially on platforms where SIMD ciphers have a considerable setup cost. Signed-off-by: Ard Biesheuvel Signed-off-by: Johannes Berg --- net/mac80211/aes_cmac.c | 126 ++++++++++-------------------------------------- net/mac80211/aes_cmac.h | 11 +++-- net/mac80211/key.h | 2 +- 3 files changed, 32 insertions(+), 107 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index d0bd5fff5f0a..2fb65588490c 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c @@ -22,126 +22,50 @@ #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */ #define AAD_LEN 20 +static const u8 zero[CMAC_TLEN_256]; -void gf_mulx(u8 *pad) -{ - int i, carry; - - carry = pad[0] & 0x80; - for (i = 0; i < AES_BLOCK_SIZE - 1; i++) - pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); - pad[AES_BLOCK_SIZE - 1] <<= 1; - if (carry) - pad[AES_BLOCK_SIZE - 1] ^= 0x87; -} - -void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac, - size_t mac_len) -{ - u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; - const u8 *pos, *end; - size_t i, e, left, total_len; - - memset(cbc, 0, AES_BLOCK_SIZE); - - total_len = 0; - for (e = 0; e < num_elem; e++) - total_len += len[e]; - left = total_len; - - e = 0; - pos = addr[0]; - end = pos + len[0]; - - while (left >= AES_BLOCK_SIZE) { - for (i = 0; i < AES_BLOCK_SIZE; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - if (left > AES_BLOCK_SIZE) - crypto_cipher_encrypt_one(tfm, cbc, cbc); - left -= AES_BLOCK_SIZE; - } - - memset(pad, 0, AES_BLOCK_SIZE); - crypto_cipher_encrypt_one(tfm, pad, pad); - gf_mulx(pad); - - if (left || total_len == 0) { - for (i = 0; i < left; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - cbc[left] ^= 0x80; - gf_mulx(pad); - } - - for (i = 0; i < AES_BLOCK_SIZE; i++) - pad[i] ^= cbc[i]; - crypto_cipher_encrypt_one(tfm, pad, pad); - memcpy(mac, pad, mac_len); -} - - -void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, +void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, const u8 *data, size_t data_len, u8 *mic) { - const u8 *addr[3]; - size_t len[3]; - u8 zero[CMAC_TLEN]; + SHASH_DESC_ON_STACK(desc, tfm); + u8 out[AES_BLOCK_SIZE]; - memset(zero, 0, CMAC_TLEN); - addr[0] = aad; - len[0] = AAD_LEN; - addr[1] = data; - len[1] = data_len - CMAC_TLEN; - addr[2] = zero; - len[2] = CMAC_TLEN; + desc->tfm = tfm; - aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN); + crypto_shash_init(desc); + crypto_shash_update(desc, aad, AAD_LEN); + crypto_shash_update(desc, data, data_len - CMAC_TLEN); + crypto_shash_finup(desc, zero, CMAC_TLEN, out); + + memcpy(mic, out, CMAC_TLEN); } -void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, +void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad, const u8 *data, size_t data_len, u8 *mic) { - const u8 *addr[3]; - size_t len[3]; - u8 zero[CMAC_TLEN_256]; + SHASH_DESC_ON_STACK(desc, tfm); - memset(zero, 0, CMAC_TLEN_256); - addr[0] = aad; - len[0] = AAD_LEN; - addr[1] = data; - len[1] = data_len - CMAC_TLEN_256; - addr[2] = zero; - len[2] = CMAC_TLEN_256; + desc->tfm = tfm; - aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256); + crypto_shash_init(desc); + crypto_shash_update(desc, aad, AAD_LEN); + crypto_shash_update(desc, data, data_len - CMAC_TLEN_256); + crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic); } -struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], - size_t key_len) +struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], + size_t key_len) { - struct crypto_cipher *tfm; + struct crypto_shash *tfm; - tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_shash("cmac(aes)", 0, 0); if (!IS_ERR(tfm)) - crypto_cipher_setkey(tfm, key, key_len); + crypto_shash_setkey(tfm, key, key_len); return tfm; } - -void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm) +void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm) { - crypto_free_cipher(tfm); + crypto_free_shash(tfm); } diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h index 3702041f44fd..fef531f42003 100644 --- a/net/mac80211/aes_cmac.h +++ b/net/mac80211/aes_cmac.h @@ -10,13 +10,14 @@ #define AES_CMAC_H #include +#include -struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], - size_t key_len); -void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, +struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], + size_t key_len); +void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, const u8 *data, size_t data_len, u8 *mic); -void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, +void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad, const u8 *data, size_t data_len, u8 *mic); -void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); +void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm); #endif /* AES_CMAC_H */ diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 4aa20cef0859..ebdb80b85dc3 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -93,7 +93,7 @@ struct ieee80211_key { } ccmp; struct { u8 rx_pn[IEEE80211_CMAC_PN_LEN]; - struct crypto_cipher *tfm; + struct crypto_shash *tfm; u32 replays; /* dot11RSNAStatsCMACReplays */ u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ } aes_cmac; -- cgit v1.2.3 From b2347a322d1f6f93f1a39fe17ed08628fc959351 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 7 Feb 2017 16:20:53 +0300 Subject: mac80211: check for allocation failure in debugfs code kmalloc() can fail. Also let's move the allocation out of the declaration block so it's easier to read. Fixes: 4a5eccaa9350 ("mac80211: Show pending txqlen in debugfs.") Signed-off-by: Dan Carpenter Signed-off-by: Johannes Berg --- net/mac80211/debugfs.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 47bea0babe78..5fae001f286c 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -249,12 +249,19 @@ static ssize_t misc_read(struct file *file, char __user *user_buf, struct ieee80211_local *local = file->private_data; /* Max len of each line is 16 characters, plus 9 for 'pending:\n' */ size_t bufsz = IEEE80211_MAX_QUEUES * 16 + 9; - char *buf = kzalloc(bufsz, GFP_KERNEL); - char *pos = buf, *end = buf + bufsz - 1; + char *buf; + char *pos, *end; ssize_t rv; int i; int ln; + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + pos = buf; + end = buf + bufsz - 1; + pos += scnprintf(pos, end - pos, "pending:\n"); for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { -- cgit v1.2.3 From 769f07d8f0fb6a68a0eda6308bbe890bff894fd7 Mon Sep 17 00:00:00 2001 From: Andrzej Zaborowski Date: Wed, 25 Jan 2017 12:43:40 +0100 Subject: mac80211: Pass new RSSI level in CQM RSSI notification Extend ieee80211_cqm_rssi_notify with a rssi_level parameter so that this information can be passed to netlink clients in the next patch, if available. Most drivers will have this value at hand. wl1251 receives events from the firmware that only tell it whether latest measurement is above or below threshold so we don't pass any value at this time (parameter is 0). Signed-off-by: Andrew Zaborowski Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 2 ++ drivers/net/wireless/rsi/rsi_91x_mac80211.c | 2 +- drivers/net/wireless/st/cw1200/sta.c | 2 +- drivers/net/wireless/ti/wl1251/event.c | 4 ++-- drivers/net/wireless/ti/wlcore/event.c | 3 ++- include/net/mac80211.h | 2 ++ net/mac80211/mlme.c | 7 ++++--- net/mac80211/trace.h | 11 +++++++---- 8 files changed, 21 insertions(+), 12 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 0e60e38b2acf..e06a2e323cc8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -571,6 +571,7 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac, ieee80211_cqm_rssi_notify( vif, NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, + sig, GFP_KERNEL); } else if (sig > thold && (last_event == 0 || sig > last_event + hyst)) { @@ -580,6 +581,7 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac, ieee80211_cqm_rssi_notify( vif, NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, + sig, GFP_KERNEL); } } diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index dadaa73ab49d..e3216473aecb 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -877,7 +877,7 @@ static void rsi_perform_cqm(struct rsi_common *common, common->cqm_info.last_cqm_event_rssi = rssi; rsi_dbg(INFO_ZONE, "CQM: Notifying event: %d\n", event); - ieee80211_cqm_rssi_notify(adapter->vifs[0], event, GFP_KERNEL); + ieee80211_cqm_rssi_notify(adapter->vifs[0], event, rssi, GFP_KERNEL); return; } diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c index daf06a4f842e..a52224836a2b 100644 --- a/drivers/net/wireless/st/cw1200/sta.c +++ b/drivers/net/wireless/st/cw1200/sta.c @@ -1019,7 +1019,7 @@ void cw1200_event_handler(struct work_struct *work) NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW : NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; pr_debug("[CQM] RSSI event: %d.\n", rcpi_rssi); - ieee80211_cqm_rssi_notify(priv->vif, cqm_evt, + ieee80211_cqm_rssi_notify(priv->vif, cqm_evt, rcpi_rssi, GFP_KERNEL); break; } diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c index d0593bc1f1a9..f5acd24d0e2b 100644 --- a/drivers/net/wireless/ti/wl1251/event.c +++ b/drivers/net/wireless/ti/wl1251/event.c @@ -150,7 +150,7 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) "ROAMING_TRIGGER_LOW_RSSI_EVENT"); ieee80211_cqm_rssi_notify(wl->vif, NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, - GFP_KERNEL); + 0, GFP_KERNEL); } if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) { @@ -158,7 +158,7 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) "ROAMING_TRIGGER_REGAINED_RSSI_EVENT"); ieee80211_cqm_rssi_notify(wl->vif, NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, - GFP_KERNEL); + 0, GFP_KERNEL); } } diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 4b59f67724de..f2e90d223d94 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -129,7 +129,8 @@ void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr) vif = wl12xx_wlvif_to_vif(wlvif); if (event != wlvif->last_rssi_event) - ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL); + ieee80211_cqm_rssi_notify(vif, event, metric, + GFP_KERNEL); wlvif->last_rssi_event = event; } } diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 33624ffbd5a5..b9a08cd1d97d 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -5278,6 +5278,7 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif); * * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @rssi_event: the RSSI trigger event type + * @rssi_level: new RSSI level value or 0 if not available * @gfp: context flags * * When the %IEEE80211_VIF_SUPPORTS_CQM_RSSI is set, and a connection quality @@ -5286,6 +5287,7 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif); */ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, enum nl80211_cqm_rssi_threshold_event rssi_event, + s32 rssi_level, gfp_t gfp); /** diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8a6344518674..ee423688c92e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3419,14 +3419,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ieee80211_cqm_rssi_notify( &sdata->vif, NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, - GFP_KERNEL); + sig, GFP_KERNEL); } else if (sig > thold && (last_event == 0 || sig > last_event + hyst)) { ifmgd->last_cqm_event_signal = sig; ieee80211_cqm_rssi_notify( &sdata->vif, NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, - GFP_KERNEL); + sig, GFP_KERNEL); } } @@ -5041,11 +5041,12 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, enum nl80211_cqm_rssi_threshold_event rssi_event, + s32 rssi_level, gfp_t gfp) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - trace_api_cqm_rssi_notify(sdata, rssi_event); + trace_api_cqm_rssi_notify(sdata, rssi_event, rssi_level); cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); } diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 92a47afaa989..f78d9f4f8711 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -1996,23 +1996,26 @@ TRACE_EVENT(api_connection_loss, TRACE_EVENT(api_cqm_rssi_notify, TP_PROTO(struct ieee80211_sub_if_data *sdata, - enum nl80211_cqm_rssi_threshold_event rssi_event), + enum nl80211_cqm_rssi_threshold_event rssi_event, + s32 rssi_level), - TP_ARGS(sdata, rssi_event), + TP_ARGS(sdata, rssi_event, rssi_level), TP_STRUCT__entry( VIF_ENTRY __field(u32, rssi_event) + __field(s32, rssi_level) ), TP_fast_assign( VIF_ASSIGN; __entry->rssi_event = rssi_event; + __entry->rssi_level = rssi_level; ), TP_printk( - VIF_PR_FMT " event:%d", - VIF_PR_ARG, __entry->rssi_event + VIF_PR_FMT " event:%d rssi:%d", + VIF_PR_ARG, __entry->rssi_event, __entry->rssi_level ) ); -- cgit v1.2.3 From bee427b86217b78a0a5fc85575cc155e4c32bbf9 Mon Sep 17 00:00:00 2001 From: Andrzej Zaborowski Date: Wed, 25 Jan 2017 12:43:41 +0100 Subject: cfg80211: Pass new RSSI level in CQM RSSI notification Update the drivers to pass the RSSI level as a cfg80211_cqm_rssi_notify parameter and pass this value to userspace in a new nl80211 attribute. This helps both userspace and also helps in the implementation of the multiple RSSI thresholds CQM mechanism. Note for marvell/mwifiex I pass 0 for the RSSI value because the new RSSI value is not available to the driver at the time of the cfg80211_cqm_rssi_notify call, but the driver queries the new value immediately after that, so it is actually available just a moment later if we wanted to defer caling cfg80211_cqm_rssi_notify until that moment. Without this, the new cfg80211 code (patch 3) will call .get_station which will send a duplicate HostCmd_CMD_RSSI_INFO command to the hardware. Signed-off-by: Andrew Zaborowski Signed-off-by: Johannes Berg --- drivers/net/wireless/marvell/mwifiex/sta_event.c | 4 ++-- drivers/net/wireless/rndis_wlan.c | 2 +- include/net/cfg80211.h | 3 ++- include/uapi/linux/nl80211.h | 3 +++ net/mac80211/mlme.c | 2 +- net/wireless/nl80211.c | 9 +++++++-- net/wireless/trace.h | 11 +++++++---- 7 files changed, 23 insertions(+), 11 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index 9df0c4dc06ed..5cc3aa7c31cd 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -824,7 +824,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_RSSI_LOW: cfg80211_cqm_rssi_notify(priv->netdev, NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, - GFP_KERNEL); + 0, GFP_KERNEL); mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, HostCmd_ACT_GEN_GET, 0, NULL, false); priv->subsc_evt_rssi_state = RSSI_LOW_RECVD; @@ -839,7 +839,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_RSSI_HIGH: cfg80211_cqm_rssi_notify(priv->netdev, NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, - GFP_KERNEL); + 0, GFP_KERNEL); mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, HostCmd_ACT_GEN_GET, 0, NULL, false); priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD; diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 603c90470225..785334f7a538 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -3187,7 +3187,7 @@ static void rndis_do_cqm(struct usbnet *usbdev, s32 rssi) return; priv->last_cqm_event_rssi = rssi; - cfg80211_cqm_rssi_notify(usbdev->net, event, GFP_KERNEL); + cfg80211_cqm_rssi_notify(usbdev->net, event, rssi, GFP_KERNEL); } #define DEVICE_POLLER_JIFFIES (HZ) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5cfd2806a078..a2c18b53e053 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5390,6 +5390,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event * @dev: network device * @rssi_event: the triggered RSSI event + * @rssi_level: new RSSI level value or 0 if not available * @gfp: context flags * * This function is called when a configured connection quality monitoring @@ -5397,7 +5398,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, */ void cfg80211_cqm_rssi_notify(struct net_device *dev, enum nl80211_cqm_rssi_threshold_event rssi_event, - gfp_t gfp); + s32 rssi_level, gfp_t gfp); /** * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index d6c62ee9bd1d..cd547b864595 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3952,6 +3952,8 @@ enum nl80211_ps_state { * %NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting. * @NL80211_ATTR_CQM_BEACON_LOSS_EVENT: flag attribute that's set in a beacon * loss event + * @NL80211_ATTR_CQM_RSSI_LEVEL: the RSSI value in dBm that triggered the + * RSSI threshold event. * @__NL80211_ATTR_CQM_AFTER_LAST: internal * @NL80211_ATTR_CQM_MAX: highest key attribute */ @@ -3965,6 +3967,7 @@ enum nl80211_attr_cqm { NL80211_ATTR_CQM_TXE_PKTS, NL80211_ATTR_CQM_TXE_INTVL, NL80211_ATTR_CQM_BEACON_LOSS_EVENT, + NL80211_ATTR_CQM_RSSI_LEVEL, /* keep last */ __NL80211_ATTR_CQM_AFTER_LAST, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ee423688c92e..6e90301154d5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -5048,7 +5048,7 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, trace_api_cqm_rssi_notify(sdata, rssi_event, rssi_level); - cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); + cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, rssi_level, gfp); } EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b455898df63c..9d738f75bd4e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -9474,6 +9474,7 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 }, [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 }, [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 }, + [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 }, }; static int nl80211_set_cqm_txe(struct genl_info *info, @@ -13959,11 +13960,11 @@ static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp) void cfg80211_cqm_rssi_notify(struct net_device *dev, enum nl80211_cqm_rssi_threshold_event rssi_event, - gfp_t gfp) + s32 rssi_level, gfp_t gfp) { struct sk_buff *msg; - trace_cfg80211_cqm_rssi_notify(dev, rssi_event); + trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level); if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW && rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) @@ -13977,6 +13978,10 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, rssi_event)) goto nla_put_failure; + if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL, + rssi_level)) + goto nla_put_failure; + cfg80211_send_cqm(msg, gfp); return; diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ea1b47e04fa4..2419c390f150 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2490,18 +2490,21 @@ TRACE_EVENT(cfg80211_mgmt_tx_status, TRACE_EVENT(cfg80211_cqm_rssi_notify, TP_PROTO(struct net_device *netdev, - enum nl80211_cqm_rssi_threshold_event rssi_event), - TP_ARGS(netdev, rssi_event), + enum nl80211_cqm_rssi_threshold_event rssi_event, + s32 rssi_level), + TP_ARGS(netdev, rssi_event, rssi_level), TP_STRUCT__entry( NETDEV_ENTRY __field(enum nl80211_cqm_rssi_threshold_event, rssi_event) + __field(s32, rssi_level) ), TP_fast_assign( NETDEV_ASSIGN; __entry->rssi_event = rssi_event; + __entry->rssi_level = rssi_level; ), - TP_printk(NETDEV_PR_FMT ", rssi event: %d", - NETDEV_PR_ARG, __entry->rssi_event) + TP_printk(NETDEV_PR_FMT ", rssi event: %d, level: %d", + NETDEV_PR_ARG, __entry->rssi_event, __entry->rssi_level) ); TRACE_EVENT(cfg80211_reg_can_beacon, -- cgit v1.2.3 From 8585989d146c61dd073d2135c5bb11d0f979d576 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Wed, 8 Feb 2017 15:00:34 +0200 Subject: cfg80211: fix NAN bands definition The nl80211_nan_dual_band_conf enumeration doesn't make much sense. The default value is assigned to a bit, which makes it weird if the default bit and other bits are set at the same time. To improve this, get rid of NL80211_NAN_BAND_DEFAULT and add a wiphy configuration to let the drivers define which bands are supported. This is exposed to the userspace, which then can make a decision on which band(s) to use. Additionally, rename all "dual_band" elements to "bands", to make things clearer. Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 18 ++++++++++---- include/uapi/linux/nl80211.h | 57 ++++++++++++++++++++------------------------ net/mac80211/cfg.c | 4 ++-- net/mac80211/trace.h | 16 ++++++------- net/wireless/core.c | 3 ++- net/wireless/nl80211.c | 35 ++++++++++++++++++++------- net/wireless/trace.h | 16 ++++++------- 7 files changed, 86 insertions(+), 63 deletions(-) (limited to 'net/mac80211') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a2c18b53e053..c92dc03c8528 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5,7 +5,7 @@ * * Copyright 2006-2010 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH - * Copyright 2015-2016 Intel Deutschland GmbH + * Copyright 2015-2017 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -2416,11 +2416,13 @@ struct cfg80211_qos_map { * This struct defines NAN configuration parameters * * @master_pref: master preference (1 - 255) - * @dual: dual band operation mode, see &enum nl80211_nan_dual_band_conf + * @bands: operating bands, a bitmap of &enum nl80211_band values. + * For instance, for NL80211_BAND_2GHZ, bit 0 would be set + * (i.e. BIT(NL80211_BAND_2GHZ)). */ struct cfg80211_nan_conf { u8 master_pref; - u8 dual; + u8 bands; }; /** @@ -2428,11 +2430,11 @@ struct cfg80211_nan_conf { * configuration * * @CFG80211_NAN_CONF_CHANGED_PREF: master preference - * @CFG80211_NAN_CONF_CHANGED_DUAL: dual band operation + * @CFG80211_NAN_CONF_CHANGED_BANDS: operating bands */ enum cfg80211_nan_conf_changes { CFG80211_NAN_CONF_CHANGED_PREF = BIT(0), - CFG80211_NAN_CONF_CHANGED_DUAL = BIT(1), + CFG80211_NAN_CONF_CHANGED_BANDS = BIT(1), }; /** @@ -3596,6 +3598,10 @@ struct wiphy_iftype_ext_capab { * attribute indices defined in &enum nl80211_bss_select_attr. * * @cookie_counter: unique generic cookie counter, used to identify objects. + * @nan_supported_bands: bands supported by the device in NAN mode, a + * bitmap of &enum nl80211_band values. For instance, for + * NL80211_BAND_2GHZ, bit 0 would be set + * (i.e. BIT(NL80211_BAND_2GHZ)). */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -3727,6 +3733,8 @@ struct wiphy { u64 cookie_counter; + u8 nan_supported_bands; + char priv[0] __aligned(NETDEV_ALIGN); }; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index cd547b864595..5ed257c4cd4e 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -10,7 +10,7 @@ * Copyright 2008, 2009 Luis R. Rodriguez * Copyright 2008 Jouni Malinen * Copyright 2008 Colin McCabe - * Copyright 2015 Intel Deutschland GmbH + * Copyright 2015-2017 Intel Deutschland GmbH * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -854,12 +854,15 @@ * cfg80211_scan_done(). * * @NL80211_CMD_START_NAN: Start NAN operation, identified by its - * %NL80211_ATTR_WDEV interface. This interface must have been previously - * created with %NL80211_CMD_NEW_INTERFACE. After it has been started, the - * NAN interface will create or join a cluster. This command must have a - * valid %NL80211_ATTR_NAN_MASTER_PREF attribute and optional - * %NL80211_ATTR_NAN_DUAL attributes. - * After this command NAN functions can be added. + * %NL80211_ATTR_WDEV interface. This interface must have been + * previously created with %NL80211_CMD_NEW_INTERFACE. After it + * has been started, the NAN interface will create or join a + * cluster. This command must have a valid + * %NL80211_ATTR_NAN_MASTER_PREF attribute and optional + * %NL80211_ATTR_BANDS attributes. If %NL80211_ATTR_BANDS is + * omitted or set to 0, it means don't-care and the device will + * decide what to use. After this command NAN functions can be + * added. * @NL80211_CMD_STOP_NAN: Stop the NAN operation, identified by * its %NL80211_ATTR_WDEV interface. * @NL80211_CMD_ADD_NAN_FUNCTION: Add a NAN function. The function is defined @@ -880,10 +883,14 @@ * This command is also used as a notification sent when a NAN function is * terminated. This will contain a %NL80211_ATTR_NAN_FUNC_INST_ID * and %NL80211_ATTR_COOKIE attributes. - * @NL80211_CMD_CHANGE_NAN_CONFIG: Change current NAN configuration. NAN - * must be operational (%NL80211_CMD_START_NAN was executed). - * It must contain at least one of the following attributes: - * %NL80211_ATTR_NAN_MASTER_PREF, %NL80211_ATTR_NAN_DUAL. + * @NL80211_CMD_CHANGE_NAN_CONFIG: Change current NAN + * configuration. NAN must be operational (%NL80211_CMD_START_NAN + * was executed). It must contain at least one of the following + * attributes: %NL80211_ATTR_NAN_MASTER_PREF, + * %NL80211_ATTR_BANDS. If %NL80211_ATTR_BANDS is omitted, the + * current configuration is not changed. If it is present but + * set to zero, the configuration is changed to don't-care + * (i.e. the device can decide what to do). * @NL80211_CMD_NAN_FUNC_MATCH: Notification sent when a match is reported. * This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and * %NL80211_ATTR_COOKIE. @@ -1963,10 +1970,13 @@ enum nl80211_commands { * %NL80211_CMD_CHANGE_NAN_CONFIG. Its type is u8 and it can't be 0. * Also, values 1 and 255 are reserved for certification purposes and * should not be used during a normal device operation. - * @NL80211_ATTR_NAN_DUAL: NAN dual band operation config (see - * &enum nl80211_nan_dual_band_conf). This attribute is used with - * %NL80211_CMD_START_NAN and optionally with - * %NL80211_CMD_CHANGE_NAN_CONFIG. + * @NL80211_ATTR_BANDS: operating bands configuration. This is a u32 + * bitmask of BIT(NL80211_BAND_*) as described in %enum + * nl80211_band. For instance, for NL80211_BAND_2GHZ, bit 0 + * would be set. This attribute is used with + * %NL80211_CMD_START_NAN and %NL80211_CMD_CHANGE_NAN_CONFIG, and + * it is optional. If no bands are set, it means don't-care and + * the device will decide what to use. * @NL80211_ATTR_NAN_FUNC: a function that can be added to NAN. See * &enum nl80211_nan_func_attributes for description of this nested * attribute. @@ -2397,7 +2407,7 @@ enum nl80211_attrs { NL80211_ATTR_MESH_PEER_AID, NL80211_ATTR_NAN_MASTER_PREF, - NL80211_ATTR_NAN_DUAL, + NL80211_ATTR_BANDS, NL80211_ATTR_NAN_FUNC, NL80211_ATTR_NAN_MATCH, @@ -5070,21 +5080,6 @@ enum nl80211_bss_select_attr { NL80211_BSS_SELECT_ATTR_MAX = __NL80211_BSS_SELECT_ATTR_AFTER_LAST - 1 }; -/** - * enum nl80211_nan_dual_band_conf - NAN dual band configuration - * - * Defines the NAN dual band mode of operation - * - * @NL80211_NAN_BAND_DEFAULT: device default mode - * @NL80211_NAN_BAND_2GHZ: 2.4GHz mode - * @NL80211_NAN_BAND_5GHZ: 5GHz mode - */ -enum nl80211_nan_dual_band_conf { - NL80211_NAN_BAND_DEFAULT = 1 << 0, - NL80211_NAN_BAND_2GHZ = 1 << 1, - NL80211_NAN_BAND_5GHZ = 1 << 2, -}; - /** * enum nl80211_nan_function_type - NAN function type * diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a0be2f6cd121..ac879bb17870 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -208,8 +208,8 @@ static int ieee80211_nan_change_conf(struct wiphy *wiphy, if (changes & CFG80211_NAN_CONF_CHANGED_PREF) new_conf.master_pref = conf->master_pref; - if (changes & CFG80211_NAN_CONF_CHANGED_DUAL) - new_conf.dual = conf->dual; + if (changes & CFG80211_NAN_CONF_CHANGED_BANDS) + new_conf.bands = conf->bands; ret = drv_nan_change_conf(sdata->local, sdata, &new_conf, changes); if (!ret) diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index f78d9f4f8711..0d645bc148d0 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -1736,21 +1736,21 @@ TRACE_EVENT(drv_start_nan, LOCAL_ENTRY VIF_ENTRY __field(u8, master_pref) - __field(u8, dual) + __field(u8, bands) ), TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; __entry->master_pref = conf->master_pref; - __entry->dual = conf->dual; + __entry->bands = conf->bands; ), TP_printk( LOCAL_PR_FMT VIF_PR_FMT - ", master preference: %u, dual: %d", + ", master preference: %u, bands: 0x%0x", LOCAL_PR_ARG, VIF_PR_ARG, __entry->master_pref, - __entry->dual + __entry->bands ) ); @@ -1787,7 +1787,7 @@ TRACE_EVENT(drv_nan_change_conf, LOCAL_ENTRY VIF_ENTRY __field(u8, master_pref) - __field(u8, dual) + __field(u8, bands) __field(u32, changes) ), @@ -1795,15 +1795,15 @@ TRACE_EVENT(drv_nan_change_conf, LOCAL_ASSIGN; VIF_ASSIGN; __entry->master_pref = conf->master_pref; - __entry->dual = conf->dual; + __entry->bands = conf->bands; __entry->changes = changes; ), TP_printk( LOCAL_PR_FMT VIF_PR_FMT - ", master preference: %u, dual: %d, changes: 0x%x", + ", master preference: %u, bands: 0x%0x, changes: 0x%x", LOCAL_PR_ARG, VIF_PR_ARG, __entry->master_pref, - __entry->dual, __entry->changes + __entry->bands, __entry->changes ) ); diff --git a/net/wireless/core.c b/net/wireless/core.c index 903fc419217a..e55e05bc4805 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -626,7 +626,8 @@ int wiphy_register(struct wiphy *wiphy) if (WARN_ON((wiphy->interface_modes & BIT(NL80211_IFTYPE_NAN)) && (!rdev->ops->start_nan || !rdev->ops->stop_nan || - !rdev->ops->add_nan_func || !rdev->ops->del_nan_func))) + !rdev->ops->add_nan_func || !rdev->ops->del_nan_func || + !(wiphy->nan_supported_bands & BIT(NL80211_BAND_2GHZ))))) return -EINVAL; #ifndef CONFIG_WIRELESS_WDS diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9d738f75bd4e..b5f755b3ac5d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -398,7 +398,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { }, [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN }, [NL80211_ATTR_NAN_MASTER_PREF] = { .type = NLA_U8 }, - [NL80211_ATTR_NAN_DUAL] = { .type = NLA_U8 }, + [NL80211_ATTR_BANDS] = { .type = NLA_U32 }, [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED }, [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY, .len = FILS_MAX_KEK_LEN }, @@ -1886,6 +1886,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, } } + if (nla_put_u32(msg, NL80211_ATTR_BANDS, + rdev->wiphy.nan_supported_bands)) + goto nla_put_failure; + /* done */ state->split_start = 0; break; @@ -10777,15 +10781,22 @@ static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) return -EINVAL; - if (!info->attrs[NL80211_ATTR_NAN_DUAL]) - return -EINVAL; - conf.master_pref = nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]); if (!conf.master_pref) return -EINVAL; - conf.dual = nla_get_u8(info->attrs[NL80211_ATTR_NAN_DUAL]); + if (info->attrs[NL80211_ATTR_BANDS]) { + u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]); + + if (bands & ~(u32)wdev->wiphy->nan_supported_bands) + return -EOPNOTSUPP; + + if (bands && !(bands & BIT(NL80211_BAND_2GHZ))) + return -EINVAL; + + conf.bands = bands; + } err = rdev_start_nan(rdev, wdev, &conf); if (err) @@ -11150,9 +11161,17 @@ static int nl80211_nan_change_config(struct sk_buff *skb, changed |= CFG80211_NAN_CONF_CHANGED_PREF; } - if (info->attrs[NL80211_ATTR_NAN_DUAL]) { - conf.dual = nla_get_u8(info->attrs[NL80211_ATTR_NAN_DUAL]); - changed |= CFG80211_NAN_CONF_CHANGED_DUAL; + if (info->attrs[NL80211_ATTR_BANDS]) { + u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]); + + if (bands & ~(u32)wdev->wiphy->nan_supported_bands) + return -EOPNOTSUPP; + + if (bands && !(bands & BIT(NL80211_BAND_2GHZ))) + return -EINVAL; + + conf.bands = bands; + changed |= CFG80211_NAN_CONF_CHANGED_BANDS; } if (!changed) diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 2419c390f150..776e80cef9b4 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -1915,18 +1915,18 @@ TRACE_EVENT(rdev_start_nan, WIPHY_ENTRY WDEV_ENTRY __field(u8, master_pref) - __field(u8, dual); + __field(u8, bands); ), TP_fast_assign( WIPHY_ASSIGN; WDEV_ASSIGN; __entry->master_pref = conf->master_pref; - __entry->dual = conf->dual; + __entry->bands = conf->bands; ), TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT - ", master preference: %u, dual: %d", + ", master preference: %u, bands: 0x%0x", WIPHY_PR_ARG, WDEV_PR_ARG, __entry->master_pref, - __entry->dual) + __entry->bands) ); TRACE_EVENT(rdev_nan_change_conf, @@ -1937,20 +1937,20 @@ TRACE_EVENT(rdev_nan_change_conf, WIPHY_ENTRY WDEV_ENTRY __field(u8, master_pref) - __field(u8, dual); + __field(u8, bands); __field(u32, changes); ), TP_fast_assign( WIPHY_ASSIGN; WDEV_ASSIGN; __entry->master_pref = conf->master_pref; - __entry->dual = conf->dual; + __entry->bands = conf->bands; __entry->changes = changes; ), TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT - ", master preference: %u, dual: %d, changes: %x", + ", master preference: %u, bands: 0x%0x, changes: %x", WIPHY_PR_ARG, WDEV_PR_ARG, __entry->master_pref, - __entry->dual, __entry->changes) + __entry->bands, __entry->changes) ); DEFINE_EVENT(wiphy_wdev_evt, rdev_stop_nan, -- cgit v1.2.3 From f181d6a3bcc35633facf5f3925699021c13492c5 Mon Sep 17 00:00:00 2001 From: Koen Vandeputte Date: Wed, 8 Feb 2017 15:32:05 +0100 Subject: mac80211: fix CSA in IBSS mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the missing IBSS capability flag during capability init as it needs to be inserted into the generated beacon in order for CSA to work. Fixes: cd7760e62c2ac ("mac80211: add support for CSA in IBSS mode") Signed-off-by: Piotr Gawlowicz Signed-off-by: Mikołaj Chwalisz Tested-by: Koen Vandeputte Signed-off-by: Johannes Berg --- net/mac80211/ibss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index a31d30713d08..98999d3d5262 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -487,14 +487,14 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, struct beacon_data *presp, *old_presp; struct cfg80211_bss *cbss; const struct cfg80211_bss_ies *ies; - u16 capability = 0; + u16 capability = WLAN_CAPABILITY_IBSS; u64 tsf; int ret = 0; sdata_assert_lock(sdata); if (ifibss->privacy) - capability = WLAN_CAPABILITY_PRIVACY; + capability |= WLAN_CAPABILITY_PRIVACY; cbss = cfg80211_get_bss(sdata->local->hw.wiphy, ifibss->chandef.chan, ifibss->bssid, ifibss->ssid, -- cgit v1.2.3