[PATCH v2] iwlwifi: allow memory debug TLV to specify the memory type

2017-01-25 Thread Luca Coelho
From: Johannes Berg 

Due to some new features and changes, the firmware file will now
specify what type of memory to dump, in upper 8 bits of the type
field of the TLV. Parse it (types we don't understand are errors)
and teach the code to dump periphery memory.

Signed-off-by: Johannes Berg 
Signed-off-by: Luca Coelho 
---

In v2:

The prph read should read dwords, but now the offset is incremented
by a byte in each iteration, instead of a dword.
As a result, the prph dump both prints each value multiple times
and not all of the block is read.

Fix this by advancing the read offset in a dword after every
iteration.


drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 12 +
 drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 15 +-
 drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c  | 65 +++-
 3 files changed, 79 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c 
b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 431581229948..a6719d67ac00 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -1020,6 +1020,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
IWL_DEBUG_INFO(drv, "Found debug memory segment: %u\n",
   dbg_mem->data_type);
 
+   switch (type & FW_DBG_MEM_TYPE_MASK) {
+   case FW_DBG_MEM_TYPE_REGULAR:
+   case FW_DBG_MEM_TYPE_PRPH:
+   /* we know how to handle these */
+   break;
+   default:
+   IWL_ERR(drv,
+   "Found debug memory segment with 
invalid type: 0x%x\n",
+   type);
+   return -EINVAL;
+   }
+
size = sizeof(*pieces->dbg_mem_tlv) *
   (pieces->n_dbg_mem_tlv + 1);
n = krealloc(pieces->dbg_mem_tlv, size, GFP_KERNEL);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h 
b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
index 11245b9117c7..c84207576587 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
@@ -489,9 +489,22 @@ enum iwl_fw_dbg_monitor_mode {
 };
 
 /**
+ * enum iwl_fw_mem_seg_type - memory segment type
+ * @FW_DBG_MEM_TYPE_MASK: mask for the type indication
+ * @FW_DBG_MEM_TYPE_REGULAR: regular memory
+ * @FW_DBG_MEM_TYPE_PRPH: periphery memory (requires special reading)
+ */
+enum iwl_fw_mem_seg_type {
+   FW_DBG_MEM_TYPE_MASK= 0xff00,
+   FW_DBG_MEM_TYPE_REGULAR = 0x,
+   FW_DBG_MEM_TYPE_PRPH= 0x0100,
+};
+
+/**
  * struct iwl_fw_dbg_mem_seg_tlv - configures the debug data memory segments
  *
- * @data_type: the memory segment type to record
+ * @data_type: the memory segment type to record, see  iwl_fw_mem_seg_type
+ * for what we care about
  * @ofs: the memory segment offset
  * @len: the memory segment length, in bytes
  *
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
index 7df3c3f4749e..e447cd92deb3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
@@ -406,6 +406,30 @@ static const struct iwl_prph_range 
iwl_prph_dump_addr_9000[] = {
{ .start = 0x00a02400, .end = 0x00a02758 },
 };
 
+static void _iwl_read_prph_block(struct iwl_trans *trans, u32 start,
+u32 len_bytes, __le32 *data)
+{
+   u32 i;
+
+   for (i = 0; i < len_bytes; i += 4)
+   *data++ = cpu_to_le32(iwl_read_prph_no_grab(trans, start + i));
+}
+
+static bool iwl_read_prph_block(struct iwl_trans *trans, u32 start,
+   u32 len_bytes, __le32 *data)
+{
+   unsigned long flags;
+   bool success = false;
+
+   if (iwl_trans_grab_nic_access(trans, )) {
+   success = true;
+   _iwl_read_prph_block(trans, start, len_bytes, data);
+   iwl_trans_release_nic_access(trans, );
+   }
+
+   return success;
+}
+
 static void iwl_dump_prph(struct iwl_trans *trans,
  struct iwl_fw_error_dump_data **data,
  const struct iwl_prph_range *iwl_prph_dump_addr,
@@ -422,21 +446,18 @@ static void iwl_dump_prph(struct iwl_trans *trans,
/* The range includes both boundaries */
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
 iwl_prph_dump_addr[i].start + 4;
-   int reg;
-   __le32 *val;
 
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
(*data)->len = 

[PATCH v2] iwlwifi: mvm: use mvm_disable_queue instead of sharing logic

2017-01-25 Thread Luca Coelho
From: Sara Sharon 

When removing inactive queue - use the central disable queue
function. This is needed due to a000 changes to come, but is
a proper cleanup anyway.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---

In v2:

iwl_mvm_disable_txq() returns early if the hw_ref_count is
zeroed, with the result of the queue not being properly disabled.
Avoid zeroing it and other queue information in remove_sta_marking().
iwl_mvm_disable_txq() which is called later in the flow will zero
it.

drivers/net/wireless/intel/iwlwifi/mvm/mvm.h   |  4 ++--
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c   | 29 +++---
 drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 10 +
 3 files changed, 16 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h 
b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 4a9cb76b7611..a672aa71c656 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1657,8 +1657,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, 
int mac80211_queue,
  * Disable a TXQ.
  * Note that in non-DQA mode the %mac80211_queue and %tid params are ignored.
  */
-void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
-u8 tid, u8 flags);
+int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
+   u8 tid, u8 flags);
 int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq);
 
 /* Return a bitmask with all the hw supported queues, except for the
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index cf8222a8b588..40e7fc5f1f1f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -454,13 +454,6 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm 
*mvm, int queue)
 
rcu_read_unlock();
 
-   spin_lock_bh(>queue_info_lock);
-   /* Unmap MAC queues and TIDs from this queue */
-   mvm->queue_info[queue].hw_queue_to_mac80211 = 0;
-   mvm->queue_info[queue].hw_queue_refcount = 0;
-   mvm->queue_info[queue].tid_bitmap = 0;
-   spin_unlock_bh(>queue_info_lock);
-
return disable_agg_tids;
 }
 
@@ -755,28 +748,22 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
 * first
 */
if (using_inactive_queue) {
-   struct iwl_scd_txq_cfg_cmd cmd = {
-   .scd_queue = queue,
-   .action = SCD_CFG_DISABLE_QUEUE,
-   };
-   u8 txq_curr_ac;
-
-   disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue);
+   u8 txq_curr_ac, sta_id;
 
spin_lock_bh(>queue_info_lock);
txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
-   cmd.sta_id = mvm->queue_info[queue].ra_sta_id;
-   cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[txq_curr_ac];
-   cmd.tid = mvm->queue_info[queue].txq_tid;
+   sta_id = mvm->queue_info[queue].ra_sta_id;
spin_unlock_bh(>queue_info_lock);
 
+   disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue);
/* Disable the queue */
if (disable_agg_tids)
iwl_mvm_invalidate_sta_queue(mvm, queue,
 disable_agg_tids, false);
-   iwl_trans_txq_disable(mvm->trans, queue, false);
-   ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd),
-  );
+
+   ret = iwl_mvm_disable_txq(mvm, queue,
+ mvmsta->vif->hw_queue[txq_curr_ac],
+ tid, 0);
if (ret) {
IWL_ERR(mvm,
"Failed to free inactive queue %d (ret=%d)\n",
@@ -791,7 +778,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
}
 
/* If TXQ is allocated to another STA, update removal in FW */
-   if (cmd.sta_id != mvmsta->sta_id)
+   if (sta_id != mvmsta->sta_id)
iwl_mvm_invalidate_sta_queue(mvm, queue, 0, true);
}
 
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index d04babd99b53..2beea3b98e52 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -706,8 +706,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int 
mac80211_queue,
}
 }
 
-void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
-u8 tid, u8 flags)
+int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int 

[PATCH v2] iwlwifi: mvm: change iwl_mvm_tx_csum to return value

2017-01-25 Thread Luca Coelho
From: Sara Sharon 

Currently the function changes the TX cmd itself.
Make it more generic by returning a value, as preperation
to the new TX cmd.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---

In v2:

   * Fix compilation warning when CONFIG_INET is not set

drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 66957ac12ca4..73a90d4a43eb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -102,14 +102,13 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 
*addr,
 #define OPT_HDR(type, skb, off) \
(type *)(skb_network_header(skb) + (off))
 
-static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
-   struct ieee80211_hdr *hdr,
-   struct ieee80211_tx_info *info,
-   struct iwl_tx_cmd *tx_cmd)
+static u16 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
+  struct ieee80211_hdr *hdr,
+  struct ieee80211_tx_info *info)
 {
+   u16 offload_assist = 0;
 #if IS_ENABLED(CONFIG_INET)
u16 mh_len = ieee80211_hdrlen(hdr->frame_control);
-   u16 offload_assist = le16_to_cpu(tx_cmd->offload_assist);
u8 protocol = 0;
 
/*
@@ -117,7 +116,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct 
sk_buff *skb,
 * compute it
 */
if (skb->ip_summed != CHECKSUM_PARTIAL || IWL_MVM_SW_TX_CSUM_OFFLOAD)
-   return;
+   goto out;
 
/* We do not expect to be requested to csum stuff we do not support */
if (WARN_ONCE(!(mvm->hw->netdev_features & IWL_TX_CSUM_NETIF_FLAGS) ||
@@ -125,7 +124,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct 
sk_buff *skb,
   skb->protocol != htons(ETH_P_IPV6)),
  "No support for requested checksum\n")) {
skb_checksum_help(skb);
-   return;
+   goto out;
}
 
if (skb->protocol == htons(ETH_P_IP)) {
@@ -145,7 +144,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct 
sk_buff *skb,
protocol != NEXTHDR_HOP &&
protocol != NEXTHDR_DEST) {
skb_checksum_help(skb);
-   return;
+   goto out;
}
 
hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
@@ -159,7 +158,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct 
sk_buff *skb,
if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) {
WARN_ON_ONCE(1);
skb_checksum_help(skb);
-   return;
+   goto out;
}
 
/* enable L4 csum */
@@ -191,8 +190,9 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct 
sk_buff *skb,
mh_len /= 2;
offload_assist |= mh_len << TX_CMD_OFFLD_MH_SIZE;
 
-   tx_cmd->offload_assist = cpu_to_le16(offload_assist);
+out:
 #endif
+   return offload_assist;
 }
 
 /*
@@ -295,7 +295,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff 
*skb,
!(tx_cmd->offload_assist & cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU
tx_cmd->offload_assist |= cpu_to_le16(BIT(TX_CMD_OFFLD_PAD));
 
-   iwl_mvm_tx_csum(mvm, skb, hdr, info, tx_cmd);
+   tx_cmd->offload_assist |=
+   cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, hdr, info));
 }
 
 /*
-- 
2.11.0



Re: [PATCH] NFC: remove TI nfcwilink driver

2017-01-25 Thread Marcel Holtmann
Hi Rob,

> It appears that TI WiLink devices including NFC (WL185x/WL189x) never
> shipped. The only information I found were announcements in Feb
> 2012 about the parts. There's been no activity on this driver besided
> common changes since initially added in Jan 2012. There's also no in
> users that instantiate the platform device (nor DT bindings).
> 
> This is a first step in removing TI ST (shared transport) driver in
> favor of extending the BT hci_ll driver to support WL183x chips.

since the firmware files TINfcInit_* also never made it into the linux-firmware 
tree, I have no idea who is using this driver. I am actually fine with removing 
it since it would be easy enough to bring back based on hci_ll driver once 
there is hardware to test this on.

Regards

Marcel



[PATCH] nl80211: Fix mesh HT operation check

2017-01-25 Thread Masashi Honma
commit 9757235f451c27deaa88925399f070ff6fcea832 ('nl80211: correct
checks for NL80211_MESHCONF_HT_OPMODE value') missed to mask a flag
when replacing FILL_IN_MESH_PARAM_IF_SET with checking codes. This
could drop the received HT operation value when called by
nl80211_update_mesh_config().

Signed-off-by: Masashi Honma 
---
 net/wireless/nl80211.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e6ed8dc..006c147 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5924,6 +5924,7 @@ do {  
\
break;
}
cfg->ht_opmode = ht_opmode;
+   mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
}
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
  1, 65535, mask,
-- 
2.7.4



[PATCH] NFC: remove TI nfcwilink driver

2017-01-25 Thread Rob Herring
It appears that TI WiLink devices including NFC (WL185x/WL189x) never
shipped. The only information I found were announcements in Feb
2012 about the parts. There's been no activity on this driver besided
common changes since initially added in Jan 2012. There's also no in
users that instantiate the platform device (nor DT bindings).

This is a first step in removing TI ST (shared transport) driver in
favor of extending the BT hci_ll driver to support WL183x chips.

Cc: Ilan Elias 
Cc: Marcel Holtmann 
Cc: Samuel Ortiz 
Cc: Lauro Ramos Venancio 
Cc: Aloisio Almeida Jr 
Cc: linux-wireless@vger.kernel.org
Signed-off-by: Rob Herring 
---
 drivers/nfc/Kconfig |  11 -
 drivers/nfc/Makefile|   1 -
 drivers/nfc/nfcwilink.c | 578 
 3 files changed, 590 deletions(-)
 delete mode 100644 drivers/nfc/nfcwilink.c

diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 9d2369269abf..c4208487fadc 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -5,17 +5,6 @@
 menu "Near Field Communication (NFC) devices"
depends on NFC
 
-config NFC_WILINK
-   tristate "Texas Instruments NFC WiLink driver"
-   depends on TI_ST && NFC_NCI
-   help
- This enables the NFC driver for Texas Instrument's BT/FM/GPS/NFC
- combo devices. This makes use of shared transport line discipline
- core driver to communicate with the NFC core of the combo chip.
-
- Say Y here to compile support for Texas Instrument's NFC WiLink driver
- into the kernel or say M to compile it as module.
-
 config NFC_TRF7970A
tristate "Texas Instruments TRF7970a NFC driver"
depends on SPI && NFC_DIGITAL
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index bab8ef06ae35..640b7274371c 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -6,7 +6,6 @@ obj-$(CONFIG_NFC_FDP)   += fdp/
 obj-$(CONFIG_NFC_PN544)+= pn544/
 obj-$(CONFIG_NFC_MICROREAD)+= microread/
 obj-$(CONFIG_NFC_PN533)+= pn533/
-obj-$(CONFIG_NFC_WILINK)   += nfcwilink.o
 obj-$(CONFIG_NFC_MEI_PHY)  += mei_phy.o
 obj-$(CONFIG_NFC_SIM)  += nfcsim.o
 obj-$(CONFIG_NFC_PORT100)  += port100.o
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c
deleted file mode 100644
index 3fbd18b8e473..
--- a/drivers/nfc/nfcwilink.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- *  Texas Instrument's NFC Driver For Shared Transport.
- *
- *  NFC Driver acts as interface between NCI core and
- *  TI Shared Transport Layer.
- *
- *  Copyright (C) 2011 Texas Instruments, Inc.
- *
- *  Written by Ilan Elias 
- *
- *  Acknowledgements:
- *  This file is based on btwilink.c, which was written
- *  by Raja Mani and Pavan Savoy.
- *
- *  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
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, see .
- *
- */
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#define NFCWILINK_CHNL 12
-#define NFCWILINK_OPCODE   7
-#define NFCWILINK_MAX_FRAME_SIZE   300
-#define NFCWILINK_HDR_LEN  4
-#define NFCWILINK_OFFSET_LEN_IN_HDR1
-#define NFCWILINK_LEN_SIZE 2
-#define NFCWILINK_REGISTER_TIMEOUT 8000/* 8 sec */
-#define NFCWILINK_CMD_TIMEOUT  5000/* 5 sec */
-
-#define BTS_FILE_NAME_MAX_SIZE 40
-#define BTS_FILE_HDR_MAGIC 0x42535442
-#define BTS_FILE_CMD_MAX_LEN   0xff
-#define BTS_FILE_ACTION_TYPE_SEND_CMD  1
-
-#define NCI_VS_NFCC_INFO_CMD_GID   0x2f
-#define NCI_VS_NFCC_INFO_CMD_OID   0x12
-#define NCI_VS_NFCC_INFO_RSP_GID   0x4f
-#define NCI_VS_NFCC_INFO_RSP_OID   0x12
-
-struct nfcwilink_hdr {
-   __u8 chnl;
-   __u8 opcode;
-   __le16 len;
-} __packed;
-
-struct nci_vs_nfcc_info_cmd {
-   __u8 gid;
-   __u8 oid;
-   __u8 plen;
-} __packed;
-
-struct nci_vs_nfcc_info_rsp {
-   __u8 gid;
-   __u8 oid;
-   __u8 plen;
-   __u8 status;
-   __u8 hw_id;
-   __u8 sw_ver_x;
-   __u8 sw_ver_z;
-   __u8 patch_id;
-} __packed;
-
-struct bts_file_hdr {
-   __le32 magic;
-   __le32 ver;
-   __u8 rfu[24];
-   __u8 actions[0];
-} __packed;
-
-struct bts_file_action {
-   __le16 type;
-   __le16 len;
-   __u8 

RE: [RFC 2/3] cfg80211: Disallow moving out of operating DFS channel in non-ETSI

2017-01-25 Thread Jean-Pierre Tosoni
> -Message d'origine-
> De : linux-wireless-ow...@vger.kernel.org [mailto:linux-wireless-
> ow...@vger.kernel.org] De la part de Vasanthakumar Thiagarajan
> Envoyé : mercredi 25 janvier 2017 12:31
> À : johan...@sipsolutions.net
> Cc : linux-wireless@vger.kernel.org; Vasanthakumar Thiagarajan
> Objet : [RFC 2/3] cfg80211: Disallow moving out of operating DFS channel
> in non-ETSI
> 
> For non-ETSI regulatory domain, CAC result on DFS channel may not be valid
> once moving out of that channel (as done during remain-on-channel,
> scannning and off-channel tx).
> Running CAC on an operating DFS channel after every off-channel operation
> will only add complexity and disturb the current link. Better do not allow
> any off-channel switch from a DFS operating channel in non-ETSI domain.
> 

Moving out should be forbidden only to "master" devices i.e. AP, mesh,
ad-hoc.
"Slave" devices i.e. client stations, are not responsible for detecting
radars, hence, they can do an off-channel scan and go back to a "DFS
operating channel" without waiting for CAC.

It looks like your patch would forbid multichannel scan ?



> Signed-off-by: Vasanthakumar Thiagarajan 
> ---
>  net/wireless/nl80211.c | 38 ++
>  1 file changed, 38 insertions(+)
> 
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index
> 63dfa60..c614af4 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -6506,6 +6506,17 @@ static int nl80211_parse_random_mac(struct nlattr
> **attrs,
>   return 0;
>  }
> 
> +static bool cfg80211_off_channel_oper_allowed(struct wireless_dev
> +*wdev) {
> + if (!cfg80211_beaconing_iface_active(wdev))
> + return true;
> +
> + if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR))
> + return true;
> +
> + return regulatory_pre_cac_allowed(wdev->wiphy);
> +}
> +
>  static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info
> *info)  {
>   struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -
> 6631,6 +6642,21 @@ static int nl80211_trigger_scan(struct sk_buff *skb,
> struct genl_info *info)
> 
>   request->n_channels = i;
> 
> + if (!cfg80211_off_channel_oper_allowed(wdev)) {
> + struct ieee80211_channel *chan;
> +
> + if (request->n_channels != 1) {
> + err = -EBUSY;
> + goto out_free;
> + }
> +
> + chan = request->channels[0];
> + if (chan->center_freq != wdev->chandef.chan->center_freq) {
> + err = -EBUSY;
> + goto out_free;
> + }
> + }
> +
>   i = 0;
>   if (n_ssids) {
>   nla_for_each_nested(attr, info-
> >attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { @@ -9053,6 +9079,7 @@ static int
> nl80211_remain_on_channel(struct sk_buff *skb,
>   struct cfg80211_registered_device *rdev = info->user_ptr[0];
>   struct wireless_dev *wdev = info->user_ptr[1];
>   struct cfg80211_chan_def chandef;
> + const struct cfg80211_chan_def *compat_chandef;
>   struct sk_buff *msg;
>   void *hdr;
>   u64 cookie;
> @@ -9081,6 +9108,14 @@ static int nl80211_remain_on_channel(struct sk_buff
> *skb,
>   if (err)
>   return err;
> 
> + if (!(cfg80211_off_channel_oper_allowed(wdev) ||
> +   cfg80211_chandef_identical(>chandef, ))) {
> + compat_chandef = cfg80211_chandef_compatible(>chandef,
> +  );
> + if (compat_chandef != )
> + return -EBUSY;
> + }
> +
>   msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
>   if (!msg)
>   return -ENOMEM;
> @@ -9256,6 +9291,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb,
> struct genl_info *info)
>   if (!chandef.chan && params.offchan)
>   return -EINVAL;
> 
> + if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev))
> + return -EBUSY;
> +
>   params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
>   params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
> 
> --
> 1.9.1




[PATCH 4/4] ath9k: fix race condition in enabling/disabling IRQs

2017-01-25 Thread Felix Fietkau
The code currently relies on refcounting to disable IRQs from within the
IRQ handler and re-enabling them again after the tasklet has run.

However, due to race conditions sometimes the IRQ handler might be
called twice, or the tasklet may not run at all (if interrupted in the
middle of a reset).

This can cause nasty imbalances in the irq-disable refcount which will
get the driver permanently stuck until the entire radio has been stopped
and started again (ath_reset will not recover from this).

Instead of using this fragile logic, change the code to ensure that
running the irq handler during tasklet processing is safe, and leave the
refcount untouched.

Cc: sta...@vger.kernel.org
Signed-off-by: Felix Fietkau 
---
 drivers/net/wireless/ath/ath9k/ath9k.h |  1 +
 drivers/net/wireless/ath/ath9k/init.c  |  1 +
 drivers/net/wireless/ath/ath9k/mac.c   | 44 ++
 drivers/net/wireless/ath/ath9k/mac.h   |  1 +
 drivers/net/wireless/ath/ath9k/main.c  | 15 
 5 files changed, 48 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h 
b/drivers/net/wireless/ath/ath9k/ath9k.h
index a396c99ee84d..46dfca522be3 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -998,6 +998,7 @@ struct ath_softc {
struct survey_info *cur_survey;
struct survey_info survey[ATH9K_NUM_CHANNELS];
 
+   spinlock_t intr_lock;
struct tasklet_struct intr_tq;
struct tasklet_struct bcon_tasklet;
struct ath_hw *sc_ah;
diff --git a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
index a2f7f48bbb92..fa4b3cc1ba22 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -669,6 +669,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
common->bt_ant_diversity = 1;
 
spin_lock_init(>cc_lock);
+   spin_lock_init(>intr_lock);
spin_lock_init(>sc_serial_rw);
spin_lock_init(>sc_pm_lock);
spin_lock_init(>chan_lock);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c 
b/drivers/net/wireless/ath/ath9k/mac.c
index f79587570af6..c059dfcaca22 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -810,21 +810,12 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
 
-void ath9k_hw_enable_interrupts(struct ath_hw *ah)
+static void __ath9k_hw_enable_interrupts(struct ath_hw *ah)
 {
struct ath_common *common = ath9k_hw_common(ah);
u32 sync_default = AR_INTR_SYNC_DEFAULT;
u32 async_mask;
 
-   if (!(ah->imask & ATH9K_INT_GLOBAL))
-   return;
-
-   if (!atomic_inc_and_test(>intr_ref_cnt)) {
-   ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
-   atomic_read(>intr_ref_cnt));
-   return;
-   }
-
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
AR_SREV_9561(ah))
sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
@@ -846,6 +837,39 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
 }
+
+void ath9k_hw_resume_interrupts(struct ath_hw *ah)
+{
+   struct ath_common *common = ath9k_hw_common(ah);
+
+   if (!(ah->imask & ATH9K_INT_GLOBAL))
+   return;
+
+   if (atomic_read(>intr_ref_cnt) != 0) {
+   ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
+   atomic_read(>intr_ref_cnt));
+   return;
+   }
+
+   __ath9k_hw_enable_interrupts(ah);
+}
+EXPORT_SYMBOL(ath9k_hw_resume_interrupts);
+
+void ath9k_hw_enable_interrupts(struct ath_hw *ah)
+{
+   struct ath_common *common = ath9k_hw_common(ah);
+
+   if (!(ah->imask & ATH9K_INT_GLOBAL))
+   return;
+
+   if (!atomic_inc_and_test(>intr_ref_cnt)) {
+   ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
+   atomic_read(>intr_ref_cnt));
+   return;
+   }
+
+   __ath9k_hw_enable_interrupts(ah);
+}
 EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
 
 void ath9k_hw_set_interrupts(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/mac.h 
b/drivers/net/wireless/ath/ath9k/mac.h
index 3bab01435a86..770fc11b41d1 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -744,6 +744,7 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah);
 void ath9k_hw_enable_interrupts(struct ath_hw *ah);
 void ath9k_hw_disable_interrupts(struct ath_hw *ah);
 void ath9k_hw_kill_interrupts(struct ath_hw *ah);
+void ath9k_hw_resume_interrupts(struct ath_hw *ah);
 
 void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
 
diff --git a/drivers/net/wireless/ath/ath9k/main.c 

[PATCH 1/4] ath9k: rename tx_complete_work to hw_check_work

2017-01-25 Thread Felix Fietkau
Also include common MAC alive check. This should make the hang checks
more reliable for modes where beacons are not sent and is used as a
starting point for further hang check improvements

Signed-off-by: Felix Fietkau 
---
 drivers/net/wireless/ath/ath9k/ath9k.h |  6 ++---
 drivers/net/wireless/ath/ath9k/init.c  |  1 +
 drivers/net/wireless/ath/ath9k/link.c  | 46 ++
 drivers/net/wireless/ath/ath9k/main.c  | 10 +---
 drivers/net/wireless/ath/ath9k/xmit.c  |  2 --
 5 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h 
b/drivers/net/wireless/ath/ath9k/ath9k.h
index 331947b6a667..b2fa44adc60e 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -108,7 +108,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct 
ath_descdma *dd,
 #define ATH_AGGR_MIN_QDEPTH2
 /* minimum h/w qdepth for non-aggregated traffic */
 #define ATH_NON_AGGR_MIN_QDEPTH8
-#define ATH_TX_COMPLETE_POLL_INT   1000
+#define ATH_HW_CHECK_POLL_INT  1000
 #define ATH_TXFIFO_DEPTH   8
 #define ATH_TX_ERROR   0x01
 
@@ -745,7 +745,7 @@ void ath9k_csa_update(struct ath_softc *sc);
 #define ATH_PAPRD_TIMEOUT 100 /* msecs */
 #define ATH_PLL_WORK_INTERVAL 100
 
-void ath_tx_complete_poll_work(struct work_struct *work);
+void ath_hw_check_work(struct work_struct *work);
 void ath_reset_work(struct work_struct *work);
 bool ath_hw_check(struct ath_softc *sc);
 void ath_hw_pll_work(struct work_struct *work);
@@ -1053,7 +1053,7 @@ struct ath_softc {
 #ifdef CONFIG_ATH9K_DEBUGFS
struct ath9k_debug debug;
 #endif
-   struct delayed_work tx_complete_work;
+   struct delayed_work hw_check_work;
struct delayed_work hw_pll_work;
struct timer_list sleep_timer;
 
diff --git a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
index 084ad1bd495f..a2f7f48bbb92 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -681,6 +681,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
INIT_WORK(>hw_reset_work, ath_reset_work);
INIT_WORK(>paprd_work, ath_paprd_calibrate);
INIT_DELAYED_WORK(>hw_pll_work, ath_hw_pll_work);
+   INIT_DELAYED_WORK(>hw_check_work, ath_hw_check_work);
 
ath9k_init_channel_context(sc);
 
diff --git a/drivers/net/wireless/ath/ath9k/link.c 
b/drivers/net/wireless/ath/ath9k/link.c
index 5ad0feeebc86..27c50562dc47 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -20,20 +20,13 @@
  * TX polling - checks if the TX engine is stuck somewhere
  * and issues a chip reset if so.
  */
-void ath_tx_complete_poll_work(struct work_struct *work)
+static bool ath_tx_complete_check(struct ath_softc *sc)
 {
-   struct ath_softc *sc = container_of(work, struct ath_softc,
-   tx_complete_work.work);
struct ath_txq *txq;
int i;
-   bool needreset = false;
-
 
-   if (sc->tx99_state) {
-   ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
-   "skip tx hung detection on tx99\n");
-   return;
-   }
+   if (sc->tx99_state)
+   return true;
 
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
txq = sc->tx.txq_map[i];
@@ -41,25 +34,36 @@ void ath_tx_complete_poll_work(struct work_struct *work)
ath_txq_lock(sc, txq);
if (txq->axq_depth) {
if (txq->axq_tx_inprogress) {
-   needreset = true;
ath_txq_unlock(sc, txq);
-   break;
-   } else {
-   txq->axq_tx_inprogress = true;
+   goto reset;
}
+
+   txq->axq_tx_inprogress = true;
}
ath_txq_unlock(sc, txq);
}
 
-   if (needreset) {
-   ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
-   "tx hung, resetting the chip\n");
-   ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
+   return true;
+
+reset:
+   ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
+   "tx hung, resetting the chip\n");
+   ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
+   return false;
+
+}
+
+void ath_hw_check_work(struct work_struct *work)
+{
+   struct ath_softc *sc = container_of(work, struct ath_softc,
+   hw_check_work.work);
+
+   if (!ath_hw_check(sc) ||
+   !ath_tx_complete_check(sc))
return;
-   }
 
-   ieee80211_queue_delayed_work(sc->hw, >tx_complete_work,
-
msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
+   ieee80211_queue_delayed_work(sc->hw, 

[PATCH 2/4] ath9k_hw: check if the chip failed to wake up

2017-01-25 Thread Felix Fietkau
In an RFC patch, Sven Eckelmann and Simon Wunderlich reported:

"QCA 802.11n chips (especially AR9330/AR9340) sometimes end up in a
state in which a read of AR_CFG always returns 0xdeadbeef.
This should not happen when when the power_mode of the device is
ATH9K_PM_AWAKE."

Include the check for the default register state in the existing MAC
hang check.

Signed-off-by: Felix Fietkau 
---
 drivers/net/wireless/ath/ath9k/hw.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 6989f89b3116..11fd98df2c43 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1623,6 +1623,10 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
int count = 50;
u32 reg, last_val;
 
+   /* Check if chip failed to wake up */
+   if (REG_READ(ah, AR_CFG) == 0xdeadbeef)
+   return false;
+
if (AR_SREV_9300(ah))
return !ath9k_hw_detect_mac_hang(ah);
 
-- 
2.11.0



[PATCH 3/4] ath9k: check for deaf rx path state

2017-01-25 Thread Felix Fietkau
Various chips occasionally run into a state where the tx path still
appears to be working normally, but the rx path is deaf.

There is no known register signature to check for this state explicitly,
so use the lack of rx interrupts as an indicator.

This detection is prone to false positives, since a device could also
simply be in an environment where there are no frames on the air.
However, in this case doing a reset should be harmless since it's
obviously not interrupting any real activity. To avoid confusion, call
the reset counters in this case "Rx path inactive" instead of something
like "Rx path deaf", since it may not be an indication of a real
hardware failure.

Signed-off-by: Felix Fietkau 
---
 drivers/net/wireless/ath/ath9k/ath9k.h |  1 +
 drivers/net/wireless/ath/ath9k/debug.c |  1 +
 drivers/net/wireless/ath/ath9k/debug.h |  1 +
 drivers/net/wireless/ath/ath9k/link.c  | 16 +++-
 drivers/net/wireless/ath/ath9k/main.c  |  2 ++
 5 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h 
b/drivers/net/wireless/ath/ath9k/ath9k.h
index b2fa44adc60e..a396c99ee84d 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -1027,6 +1027,7 @@ struct ath_softc {
 
u8 gtt_cnt;
u32 intrstatus;
+   u32 rx_active;
u16 ps_flags; /* PS_* */
bool ps_enabled;
bool ps_idle;
diff --git a/drivers/net/wireless/ath/ath9k/debug.c 
b/drivers/net/wireless/ath/ath9k/debug.c
index 43930c336987..a42402413659 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -763,6 +763,7 @@ static int read_file_reset(struct seq_file *file, void 
*data)
[RESET_TYPE_BEACON_STUCK] = "Stuck Beacon",
[RESET_TYPE_MCI] = "MCI Reset",
[RESET_TYPE_CALIBRATION] = "Calibration error",
+   [RESET_TYPE_RX_INACTIVE] = "Rx path inactive",
[RESET_TX_DMA_ERROR] = "Tx DMA stop error",
[RESET_RX_DMA_ERROR] = "Rx DMA stop error",
};
diff --git a/drivers/net/wireless/ath/ath9k/debug.h 
b/drivers/net/wireless/ath/ath9k/debug.h
index 249f8141cd00..a40c84e8d0b6 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -50,6 +50,7 @@ enum ath_reset_type {
RESET_TYPE_BEACON_STUCK,
RESET_TYPE_MCI,
RESET_TYPE_CALIBRATION,
+   RESET_TYPE_RX_INACTIVE,
RESET_TX_DMA_ERROR,
RESET_RX_DMA_ERROR,
__RESET_TYPE_MAX
diff --git a/drivers/net/wireless/ath/ath9k/link.c 
b/drivers/net/wireless/ath/ath9k/link.c
index 27c50562dc47..b9d92aae00c2 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -53,13 +53,27 @@ static bool ath_tx_complete_check(struct ath_softc *sc)
 
 }
 
+static bool ath_rx_active_check(struct ath_softc *sc)
+{
+   if (sc->rx_active) {
+   sc->rx_active = 0;
+   return true;
+   }
+
+   ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
+   "rx path inactive, resetting the chip\n");
+   ath9k_queue_reset(sc, RESET_TYPE_RX_INACTIVE);
+   return false;
+}
+
 void ath_hw_check_work(struct work_struct *work)
 {
struct ath_softc *sc = container_of(work, struct ath_softc,
hw_check_work.work);
 
if (!ath_hw_check(sc) ||
-   !ath_tx_complete_check(sc))
+   !ath_tx_complete_check(sc) ||
+   !ath_rx_active_check(sc))
return;
 
ieee80211_queue_delayed_work(sc->hw, >hw_check_work,
diff --git a/drivers/net/wireless/ath/ath9k/main.c 
b/drivers/net/wireless/ath/ath9k/main.c
index 0345d6ec564f..985b1cade4a4 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -269,6 +269,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool 
start)
}
 
sc->gtt_cnt = 0;
+   sc->rx_active = 1;
 
ath9k_hw_set_interrupts(ah);
ath9k_hw_enable_interrupts(ah);
@@ -452,6 +453,7 @@ void ath9k_tasklet(unsigned long data)
ath_rx_tasklet(sc, 0, true);
 
ath_rx_tasklet(sc, 0, false);
+   sc->rx_active = 1;
}
 
if (status & ATH9K_INT_TX) {
-- 
2.11.0



[PATCH] wireless: radiotap: rewrite the radiotap header file

2017-01-25 Thread Johannes Berg
From: Johannes Berg 

The header file has grown a lot of #define's etc, but
they are nicer as enums, so rewrite the file from the
documentation as such.

Signed-off-by: Johannes Berg 
---
 include/net/ieee80211_radiotap.h | 444 +--
 1 file changed, 144 insertions(+), 300 deletions(-)

diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index d0e7e3f8e67a..f4ab5c6b5ed3 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -1,201 +1,39 @@
-/*
- * Copyright (c) 2003, 2004 David Young.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *notice, this list of conditions and the following disclaimer in the
- *documentation and/or other materials provided with the distribution.
- * 3. The name of David Young may not be used to endorse or promote
- *products derived from this software without specific prior
- *written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
- * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- */
-
-/*
- * Modifications to fit into the linux IEEE 802.11 stack,
- * Mike Kershaw (drag...@kismetwireless.net)
- */
-
-#ifndef IEEE80211RADIOTAP_H
-#define IEEE80211RADIOTAP_H
+#ifndef __RADIOTAP_H
+#define __RADIOTAP_H
 
-#include 
 #include 
 #include 
 
-/* Base version of the radiotap packet header data */
-#define PKTHDR_RADIOTAP_VERSION0
-
-/* A generic radio capture format is desirable. There is one for
- * Linux, but it is neither rigidly defined (there were not even
- * units given for some fields) nor easily extensible.
- *
- * I suggest the following extensible radio capture format. It is
- * based on a bitmap indicating which fields are present.
- *
- * I am trying to describe precisely what the application programmer
- * should expect in the following, and for that reason I tell the
- * units and origin of each measurement (where it applies), or else I
- * use sufficiently weaselly language ("is a monotonically nondecreasing
- * function of...") that I cannot set false expectations for lawyerly
- * readers.
- */
-
-/*
- * The radio capture header precedes the 802.11 header.
- * All data in the header is little endian on all platforms.
+/**
+ * struct ieee82011_radiotap_header - base radiotap header
  */
 struct ieee80211_radiotap_header {
-   u8 it_version;  /* Version 0. Only increases
-* for drastic changes,
-* introduction of compatible
-* new fields does not count.
-*/
-   u8 it_pad;
-   __le16 it_len;  /* length of the whole
-* header in bytes, including
-* it_version, it_pad,
-* it_len, and data fields.
-*/
-   __le32 it_present;  /* A bitmap telling which
-* fields are present. Set bit 31
-* (0x8000) to extend the
-* bitmap by another 32 bits.
-* Additional extensions are made
-* by setting bit 31.
-*/
+   /**
+* @it_version: radiotap version, always 0
+*/
+   uint8_t it_version;
+
+   /**
+* @it_pad: padding (or alignment)
+*/
+   uint8_t it_pad;
+
+   /**
+* @it_len: overall radiotap header length
+*/
+   __le16 it_len;
+
+   /**
+* @it_present: (first) present word
+*/
+   __le32 it_present;
 } __packed;
 
-/* Name Data typeUnits
- *  --
- *
- * IEEE80211_RADIOTAP_TSFT  __le64   microseconds
- *
- *  Value in microseconds 

[PATCH v2] wireless: radiotap: rewrite the radiotap header file

2017-01-25 Thread Johannes Berg
From: Johannes Berg 

The header file has grown a lot of #define's etc, but
they are nicer as enums, so rewrite the file from the
documentation as such.

Signed-off-by: Johannes Berg 
---
 include/net/ieee80211_radiotap.h | 455 ++-
 1 file changed, 157 insertions(+), 298 deletions(-)

diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index d0e7e3f8e67a..d91f9e7f4d71 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -1,201 +1,54 @@
 /*
- * Copyright (c) 2003, 2004 David Young.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *notice, this list of conditions and the following disclaimer in the
- *documentation and/or other materials provided with the distribution.
- * 3. The name of David Young may not be used to endorse or promote
- *products derived from this software without specific prior
- *written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
- * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- */
-
-/*
- * Modifications to fit into the linux IEEE 802.11 stack,
- * Mike Kershaw (drag...@kismetwireless.net)
+ * Copyright (c) 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+#ifndef __RADIOTAP_H
+#define __RADIOTAP_H
 
-#ifndef IEEE80211RADIOTAP_H
-#define IEEE80211RADIOTAP_H
-
-#include 
 #include 
 #include 
 
-/* Base version of the radiotap packet header data */
-#define PKTHDR_RADIOTAP_VERSION0
-
-/* A generic radio capture format is desirable. There is one for
- * Linux, but it is neither rigidly defined (there were not even
- * units given for some fields) nor easily extensible.
- *
- * I suggest the following extensible radio capture format. It is
- * based on a bitmap indicating which fields are present.
- *
- * I am trying to describe precisely what the application programmer
- * should expect in the following, and for that reason I tell the
- * units and origin of each measurement (where it applies), or else I
- * use sufficiently weaselly language ("is a monotonically nondecreasing
- * function of...") that I cannot set false expectations for lawyerly
- * readers.
- */
-
-/*
- * The radio capture header precedes the 802.11 header.
- * All data in the header is little endian on all platforms.
+/**
+ * struct ieee82011_radiotap_header - base radiotap header
  */
 struct ieee80211_radiotap_header {
-   u8 it_version;  /* Version 0. Only increases
-* for drastic changes,
-* introduction of compatible
-* new fields does not count.
-*/
-   u8 it_pad;
-   __le16 it_len;  /* length of the whole
-* header in bytes, including
-* it_version, it_pad,
-* it_len, and data fields.
-*/
-   __le32 it_present;  /* A bitmap telling which
-* fields are present. Set bit 31
-* (0x8000) to extend the
-* bitmap by another 32 

Re: [PATCH v3] ath10k: Fix crash during rmmod when probe firmware fails

2017-01-25 Thread Valo, Kalle
Kalle Valo  writes:

> Mohammed Shafi Shajakhan  writes:
>
>> From: Mohammed Shafi Shajakhan 
>>
>> This fixes the below crash when ath10k probe firmware fails,
>> NAPI polling tries to access a rx ring resource which was never
>> allocated, fix this by disabling NAPI right away once the probe
>> firmware fails by calling 'ath10k_hif_stop'. Its good to note
>> that the error is never propogated to 'ath10k_pci_probe' when
>> ath10k_core_register fails, so calling 'ath10k_hif_stop' to cleanup
>> PCI related things seems to be ok
>>
>> BUG: unable to handle kernel NULL pointer dereference at (null)
>> IP:  __ath10k_htt_rx_ring_fill_n+0x19/0x230 [ath10k_core]
>> __ath10k_htt_rx_ring_fill_n+0x19/0x230 [ath10k_core]
>>
>> Call Trace:
>>
>> [] ath10k_htt_rx_msdu_buff_replenish+0x42/0x90
>> [ath10k_core]
>> [] ath10k_htt_txrx_compl_task+0x433/0x17d0
>> [ath10k_core]
>> [] ? __wake_up_common+0x4d/0x80
>> [] ? cpu_load_update+0xdc/0x150
>> [] ? ath10k_pci_read32+0xd/0x10 [ath10k_pci]
>> [] ath10k_pci_napi_poll+0x47/0x110 [ath10k_pci]
>> [] net_rx_action+0x20f/0x370
>>
>> Reported-by: Ben Greear 
>> Fixes: 3c97f5de1f28 ("ath10k: implement NAPI support")
>> Signed-off-by: Mohammed Shafi Shajakhan 
>
> Is there an easy way to reproduce this bug? I don't see it on my x86
> laptop with qca988x and I call rmmod all the time. I would like to test
> this myself.
>
>> --- a/drivers/net/wireless/ath/ath10k/core.c
>> +++ b/drivers/net/wireless/ath/ath10k/core.c
>> @@ -2164,6 +2164,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
>>  ath10k_core_free_firmware_files(ar);
>>  
>>  err_power_down:
>> +ath10k_hif_stop(ar);
>>  ath10k_hif_power_down(ar);
>>  
>>  return ret;
>
> This breaks the symmetry, we should not be calling ath10k_hif_stop() if
> we haven't called ath10k_hif_start() from the same function. This can
> just create a bigger mess later, for example with other bus support like
> sdio or usb. In theory it should enough that we call
> ath10k_hif_power_down() and pci.c does the rest correctly "behind the
> scenes".
>
> I investigated this a bit and I think the real cause is that we call
> napi_enable() from ath10k_pci_hif_power_up() and napi_disable() from
> ath10k_pci_hif_stop(). Does anyone remember why?
>
> I was expecting that we would call napi_enable()/napi_disable() either
> in ath10k_hif_power_up/down() or ath10k_hif_start()/stop(), but not
> mixed like it's currently.

So below is something I was thinking of, now napi_enable() is called
from ath10k_hif_start() and napi_disable() from ath10k_hif_stop(). Would
that work?

--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1648,6 +1648,8 @@ static int ath10k_pci_hif_start(struct ath10k *ar)
 
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n");
 
+   napi_enable(>napi);
+
ath10k_pci_irq_enable(ar);
ath10k_pci_rx_post(ar);
 
@@ -2532,7 +2534,6 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
ath10k_err(ar, "could not wake up target CPU: %d\n", ret);
goto err_ce;
}
-   napi_enable(>napi);
 
return 0;

-- 
Kalle Valo

Re: [PATCH v3] ath10k: Fix crash during rmmod when probe firmware fails

2017-01-25 Thread Valo, Kalle
Mohammed Shafi Shajakhan  writes:

> From: Mohammed Shafi Shajakhan 
>
> This fixes the below crash when ath10k probe firmware fails,
> NAPI polling tries to access a rx ring resource which was never
> allocated, fix this by disabling NAPI right away once the probe
> firmware fails by calling 'ath10k_hif_stop'. Its good to note
> that the error is never propogated to 'ath10k_pci_probe' when
> ath10k_core_register fails, so calling 'ath10k_hif_stop' to cleanup
> PCI related things seems to be ok
>
> BUG: unable to handle kernel NULL pointer dereference at (null)
> IP:  __ath10k_htt_rx_ring_fill_n+0x19/0x230 [ath10k_core]
> __ath10k_htt_rx_ring_fill_n+0x19/0x230 [ath10k_core]
>
> Call Trace:
>
> [] ath10k_htt_rx_msdu_buff_replenish+0x42/0x90
> [ath10k_core]
> [] ath10k_htt_txrx_compl_task+0x433/0x17d0
> [ath10k_core]
> [] ? __wake_up_common+0x4d/0x80
> [] ? cpu_load_update+0xdc/0x150
> [] ? ath10k_pci_read32+0xd/0x10 [ath10k_pci]
> [] ath10k_pci_napi_poll+0x47/0x110 [ath10k_pci]
> [] net_rx_action+0x20f/0x370
>
> Reported-by: Ben Greear 
> Fixes: 3c97f5de1f28 ("ath10k: implement NAPI support")
> Signed-off-by: Mohammed Shafi Shajakhan 

Is there an easy way to reproduce this bug? I don't see it on my x86
laptop with qca988x and I call rmmod all the time. I would like to test
this myself.

> --- a/drivers/net/wireless/ath/ath10k/core.c
> +++ b/drivers/net/wireless/ath/ath10k/core.c
> @@ -2164,6 +2164,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
>   ath10k_core_free_firmware_files(ar);
>  
>  err_power_down:
> + ath10k_hif_stop(ar);
>   ath10k_hif_power_down(ar);
>  
>   return ret;

This breaks the symmetry, we should not be calling ath10k_hif_stop() if
we haven't called ath10k_hif_start() from the same function. This can
just create a bigger mess later, for example with other bus support like
sdio or usb. In theory it should enough that we call
ath10k_hif_power_down() and pci.c does the rest correctly "behind the
scenes".

I investigated this a bit and I think the real cause is that we call
napi_enable() from ath10k_pci_hif_power_up() and napi_disable() from
ath10k_pci_hif_stop(). Does anyone remember why?

I was expecting that we would call napi_enable()/napi_disable() either
in ath10k_hif_power_up/down() or ath10k_hif_start()/stop(), but not
mixed like it's currently.

-- 
Kalle Valo

[PATCH v4 1/5] mac80211: Pass new RSSI level in CQM RSSI notification

2017-01-25 Thread Andrew Zaborowski
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 
---
 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(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 0e60e38..e06a2e3 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 dadaa73..e321647 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 daf06a4..a522248 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 d0593bc..f5acd24 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 4b59f67..f2e90d2 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 

[PATCH v4 4/5] mac80211: Add set_cqm_rssi_range_config

2017-01-25 Thread Andrew Zaborowski
Support .set_cqm_rssi_range_config if the beacons are available for
processing in mac80211.  There's no reason that this couldn't be
offloaded by mac80211-based drivers but there's no driver method for
that added in this patch as I don't have the hardware.

Signed-off-by: Andrew Zaborowski 
---
changes in v3:
 - set NL80211_EXT_FEATURE_CQM_RSSI_LIST automatically in
   ieee80211_register_hw based on the default interface's
   IEEE80211_VIF_BEACON_FILTER flag.
changes in v4:
 - drop the above attempt and set NL80211_EXT_FEATURE_CQM_RSSI_LIST
   in a separate patch in each driver.
---
 include/net/mac80211.h |  6 ++
 net/mac80211/cfg.c | 28 
 net/mac80211/mlme.c| 24 
 3 files changed, 58 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 8810ae7..d3992c4 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -502,6 +502,10 @@ struct ieee80211_mu_group_data {
  * implies disabled. As with the cfg80211 callback, a change here should
  * cause an event to be sent indicating where the current value is in
  * relation to the newly configured threshold.
+ * @cqm_rssi_low: Connection quality monitor RSSI lower threshold, a zero value
+ * implies disabled.  This is an alternative mechanism to the single
+ * threshold event and can't be enabled simultaneously with it.
+ * @cqm_rssi_high: Connection quality monitor RSSI upper threshold.
  * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis
  * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The
  * may filter ARP queries targeted for other addresses than listed here.
@@ -554,6 +558,8 @@ struct ieee80211_bss_conf {
u16 ht_operation_mode;
s32 cqm_rssi_thold;
u32 cqm_rssi_hyst;
+   s32 cqm_rssi_low;
+   s32 cqm_rssi_high;
struct cfg80211_chan_def chandef;
struct ieee80211_mu_group_data mu_group;
__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e91e503..cf02aaa 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2630,6 +2630,33 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy 
*wiphy,
 
bss_conf->cqm_rssi_thold = rssi_thold;
bss_conf->cqm_rssi_hyst = rssi_hyst;
+   bss_conf->cqm_rssi_low = 0;
+   bss_conf->cqm_rssi_high = 0;
+   sdata->u.mgd.last_cqm_event_signal = 0;
+
+   /* tell the driver upon association, unless already associated */
+   if (sdata->u.mgd.associated &&
+   sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
+   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
+
+   return 0;
+}
+
+static int ieee80211_set_cqm_rssi_range_config(struct wiphy *wiphy,
+  struct net_device *dev,
+  s32 rssi_low, s32 rssi_high)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct ieee80211_vif *vif = >vif;
+   struct ieee80211_bss_conf *bss_conf = >bss_conf;
+
+   if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
+   return -EOPNOTSUPP;
+
+   bss_conf->cqm_rssi_low = rssi_low;
+   bss_conf->cqm_rssi_high = rssi_high;
+   bss_conf->cqm_rssi_thold = 0;
+   bss_conf->cqm_rssi_hyst = 0;
sdata->u.mgd.last_cqm_event_signal = 0;
 
/* tell the driver upon association, unless already associated */
@@ -3628,6 +3655,7 @@ const struct cfg80211_ops mac80211_config_ops = {
.mgmt_tx = ieee80211_mgmt_tx,
.mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
+   .set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config,
.mgmt_frame_register = ieee80211_mgmt_frame_register,
.set_antenna = ieee80211_set_antenna,
.get_antenna = ieee80211_get_antenna,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0cfa215..260e20d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3434,6 +3434,30 @@ static void ieee80211_rx_mgmt_beacon(struct 
ieee80211_sub_if_data *sdata,
}
}
 
+   if (bss_conf->cqm_rssi_low &&
+   ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
+   int sig = -ewma_beacon_signal_read(>ave_beacon_signal);
+   int last_event = ifmgd->last_cqm_event_signal;
+   int low = bss_conf->cqm_rssi_low;
+   int high = bss_conf->cqm_rssi_high;
+
+   if (sig < low &&
+   (last_event == 0 || last_event >= low)) {
+   ifmgd->last_cqm_event_signal = sig;
+   ieee80211_cqm_rssi_notify(
+   >vif,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+   sig, 

[PATCH v4 5/5] wireless: Set NL80211_EXT_FEATURE_CQM_RSSI_LIST in multiple drivers

2017-01-25 Thread Andrew Zaborowski
Set the NL80211_EXT_FEATURE_CQM_RSSI_LIST wiphy extended feature
wholesale in all mac80211-based drivers that do not set the
IEEE80211_VIF_BEACON_FILTER flags on their interfaces.  mac80211 will
be processing supplied RSSI values in ieee80211_rx_mgmt_beacon and
will detect when the thresholds set by
ieee80211_set_cqm_rssi_range_config are crossed.  Remaining (few)
drivers need code to enable the firmware to monitor the thresholds.
This is mostly only compile-tested.

Signed-off-by: Andrew Zaborowski 
---
 drivers/net/wireless/admtek/adm8211.c  | 2 ++
 drivers/net/wireless/ath/ar5523/ar5523.c   | 2 ++
 drivers/net/wireless/ath/ath10k/mac.c  | 2 ++
 drivers/net/wireless/ath/ath5k/base.c  | 2 ++
 drivers/net/wireless/ath/ath9k/htc_drv_init.c  | 2 ++
 drivers/net/wireless/ath/ath9k/init.c  | 2 ++
 drivers/net/wireless/ath/carl9170/main.c   | 2 ++
 drivers/net/wireless/ath/wcn36xx/main.c| 3 +++
 drivers/net/wireless/atmel/at76c50x-usb.c  | 2 ++
 drivers/net/wireless/broadcom/b43/main.c   | 2 ++
 drivers/net/wireless/broadcom/b43legacy/main.c | 2 ++
 drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c | 2 ++
 drivers/net/wireless/intel/iwlegacy/3945-mac.c | 2 ++
 drivers/net/wireless/intel/iwlegacy/4965-mac.c | 2 ++
 drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c  | 2 ++
 drivers/net/wireless/mac80211_hwsim.c  | 2 ++
 drivers/net/wireless/marvell/libertas_tf/main.c| 2 ++
 drivers/net/wireless/marvell/mwl8k.c   | 2 ++
 drivers/net/wireless/mediatek/mt7601u/init.c   | 2 ++
 drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 3 +++
 drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 2 ++
 drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c | 2 ++
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c  | 2 ++
 drivers/net/wireless/rsi/rsi_91x_mac80211.c| 2 ++
 drivers/net/wireless/zydas/zd1211rw/zd_mac.c   | 2 ++
 drivers/staging/vt6655/device_main.c   | 2 ++
 drivers/staging/vt6656/main_usb.c  | 2 ++
 27 files changed, 56 insertions(+)

diff --git a/drivers/net/wireless/admtek/adm8211.c 
b/drivers/net/wireless/admtek/adm8211.c
index 70ecd82..96362f0 100644
--- a/drivers/net/wireless/admtek/adm8211.c
+++ b/drivers/net/wireless/admtek/adm8211.c
@@ -1896,6 +1896,8 @@ static int adm8211_probe(struct pci_dev *pdev,
 
dev->wiphy->bands[NL80211_BAND_2GHZ] = >band;
 
+   wiphy_ext_feature_set(dev->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
err = ieee80211_register_hw(dev);
if (err) {
printk(KERN_ERR "%s (adm8211): Cannot register device\n",
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c 
b/drivers/net/wireless/ath/ar5523/ar5523.c
index 7a60d2e..f2f4ccf 100644
--- a/drivers/net/wireless/ath/ar5523/ar5523.c
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -1689,6 +1689,8 @@ static int ar5523_probe(struct usb_interface *intf,
if (error)
goto out_cancel_rx_cmd;
 
+   wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
usb_set_intfdata(intf, hw);
 
error = ieee80211_register_hw(hw);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c 
b/drivers/net/wireless/ath/ath10k/mac.c
index aa545a1..fe7eab3 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -8146,6 +8146,8 @@ int ath10k_mac_register(struct ath10k *ar)
ar->hw->wiphy->cipher_suites = cipher_suites;
ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 
+   wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
ret = ieee80211_register_hw(ar->hw);
if (ret) {
ath10k_err(ar, "failed to register ieee80211: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath5k/base.c 
b/drivers/net/wireless/ath/ath5k/base.c
index d98fd42..92ece64 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2564,6 +2564,8 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct 
ath_bus_ops *bus_ops)
 
hw->extra_tx_headroom = 2;
 
+   wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
/*
 * Mark the device as detached to avoid processing
 * interrupts until setup is complete.
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c 
b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index b65c1b6..defacc6 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -780,6 +780,8 @@ static void 

[PATCH v4 2/5] cfg80211: Pass new RSSI level in CQM RSSI notification

2017-01-25 Thread Andrew Zaborowski
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 
---
 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(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c 
b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index 9df0c4d..5cc3aa7 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 603c904..785334f 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 57383a1..9adff4e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5303,6 +5303,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
@@ -5310,7 +5311,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 455ed9b..5cd7a81 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3918,6 +3918,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
  */
@@ -3931,6 +3933,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 

[RFC 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain

2017-01-25 Thread Vasanthakumar Thiagarajan
Sharing DFS channel state across multiple wiphys (radios) could
be useful with multiple radios on the system. When one radio
completes CAC and marks the channel available another radio
can use this information and start beaconing without really doing
CAC.

Whenever there is a state change in DFS channel associated to
a particular wiphy the the same state change is propagated to
other wiphys having the same DFS reg domain configuration.
Also when a new wiphy is created the DFS channel state of
other existing wiphys of same DFS domain is copied.

Signed-off-by: Vasanthakumar Thiagarajan 
---
 net/wireless/chan.c |  24 +--
 net/wireless/core.c |  37 +
 net/wireless/core.h |   6 +++
 net/wireless/mlme.c |  11 +-
 net/wireless/reg.c  | 112 
 net/wireless/reg.h  |  22 +++
 6 files changed, 207 insertions(+), 5 deletions(-)

diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 090309a..40f1097 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -532,21 +532,37 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev 
*wdev)
return active;
 }
 
+static bool cfg80211_5ghz_is_wiphy_oper_chan(struct wiphy *wiphy,
+struct ieee80211_channel *chan)
+{
+   struct wireless_dev *wdev;
+
+   list_for_each_entry(wdev, >wdev_list, list) {
+   if (!cfg80211_beaconing_iface_active(wdev))
+   continue;
+
+   if (cfg80211_5ghz_sub_chan(>chandef, chan))
+   return true;
+   }
+
+   return false;
+}
+
 bool cfg80211_5ghz_any_wiphy_oper_chan(struct wiphy *wiphy,
   struct ieee80211_channel *chan)
 {
-   struct wireless_dev *wdev;
+   struct cfg80211_registered_device *rdev;
 
ASSERT_RTNL();
 
if (!(chan->flags & IEEE80211_CHAN_RADAR))
return false;
 
-   list_for_each_entry(wdev, >wdev_list, list) {
-   if (!cfg80211_beaconing_iface_active(wdev))
+   list_for_each_entry(rdev, _rdev_list, list) {
+   if (!reg_dfs_domain_same(wiphy, >wiphy))
continue;
 
-   if (cfg80211_5ghz_sub_chan(>chandef, chan))
+   if (cfg80211_5ghz_is_wiphy_oper_chan(>wiphy, chan))
return true;
}
 
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 903fc419..c3fe44b 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -357,6 +357,38 @@ static void cfg80211_sched_scan_stop_wk(struct work_struct 
*work)
rtnl_unlock();
 }
 
+static void cfg80211_propagate_radar_detect_wk(struct work_struct *work)
+{
+   struct cfg80211_registered_device *rdev;
+
+   rdev = container_of(work, struct cfg80211_registered_device,
+   porpagate_radar_detect_wk);
+
+   rtnl_lock();
+
+   regulatory_propagate_dfs_state(>wiphy, >radar_chandef,
+  NL80211_DFS_UNAVAILABLE,
+  NL80211_RADAR_DETECTED);
+
+   rtnl_unlock();
+}
+
+static void cfg80211_propagate_cac_done_wk(struct work_struct *work)
+{
+   struct cfg80211_registered_device *rdev;
+
+   rdev = container_of(work, struct cfg80211_registered_device,
+   propagate_cac_done_wk);
+
+   rtnl_lock();
+
+   regulatory_propagate_dfs_state(>wiphy, >cac_done_chandef,
+  NL80211_DFS_AVAILABLE,
+  NL80211_RADAR_CAC_FINISHED);
+
+   rtnl_unlock();
+}
+
 /* exported functions */
 
 struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
@@ -456,6 +488,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, 
int sizeof_priv,
spin_lock_init(>destroy_list_lock);
INIT_WORK(>destroy_work, cfg80211_destroy_iface_wk);
INIT_WORK(>sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
+   INIT_WORK(>porpagate_radar_detect_wk,
+ cfg80211_propagate_radar_detect_wk);
+   INIT_WORK(>propagate_cac_done_wk, cfg80211_propagate_cac_done_wk);
 
 #ifdef CONFIG_CFG80211_DEFAULT_PS
rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -914,6 +949,8 @@ void wiphy_unregister(struct wiphy *wiphy)
flush_work(>destroy_work);
flush_work(>sched_scan_stop_wk);
flush_work(>mlme_unreg_wk);
+   flush_work(>porpagate_radar_detect_wk);
+   flush_work(>propagate_cac_done_wk);
 
 #ifdef CONFIG_PM
if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 327fe95..607c8be 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -97,6 +97,12 @@ struct cfg80211_registered_device {
 
struct work_struct sched_scan_stop_wk;
 
+   struct cfg80211_chan_def radar_chandef;
+   struct work_struct 

[RFC 2/3] cfg80211: Disallow moving out of operating DFS channel in non-ETSI

2017-01-25 Thread Vasanthakumar Thiagarajan
For non-ETSI regulatory domain, CAC result on DFS channel
may not be valid once moving out of that channel (as done
during remain-on-channel, scannning and off-channel tx).
Running CAC on an operating DFS channel after every off-channel
operation will only add complexity and disturb the current
link. Better do not allow any off-channel switch from a DFS
operating channel in non-ETSI domain.

Signed-off-by: Vasanthakumar Thiagarajan 
---
 net/wireless/nl80211.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 63dfa60..c614af4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6506,6 +6506,17 @@ static int nl80211_parse_random_mac(struct nlattr 
**attrs,
return 0;
 }
 
+static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
+{
+   if (!cfg80211_beaconing_iface_active(wdev))
+   return true;
+
+   if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR))
+   return true;
+
+   return regulatory_pre_cac_allowed(wdev->wiphy);
+}
+
 static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 {
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6631,6 +6642,21 @@ static int nl80211_trigger_scan(struct sk_buff *skb, 
struct genl_info *info)
 
request->n_channels = i;
 
+   if (!cfg80211_off_channel_oper_allowed(wdev)) {
+   struct ieee80211_channel *chan;
+
+   if (request->n_channels != 1) {
+   err = -EBUSY;
+   goto out_free;
+   }
+
+   chan = request->channels[0];
+   if (chan->center_freq != wdev->chandef.chan->center_freq) {
+   err = -EBUSY;
+   goto out_free;
+   }
+   }
+
i = 0;
if (n_ssids) {
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], 
tmp) {
@@ -9053,6 +9079,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct wireless_dev *wdev = info->user_ptr[1];
struct cfg80211_chan_def chandef;
+   const struct cfg80211_chan_def *compat_chandef;
struct sk_buff *msg;
void *hdr;
u64 cookie;
@@ -9081,6 +9108,14 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
if (err)
return err;
 
+   if (!(cfg80211_off_channel_oper_allowed(wdev) ||
+ cfg80211_chandef_identical(>chandef, ))) {
+   compat_chandef = cfg80211_chandef_compatible(>chandef,
+);
+   if (compat_chandef != )
+   return -EBUSY;
+   }
+
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
return -ENOMEM;
@@ -9256,6 +9291,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct 
genl_info *info)
if (!chandef.chan && params.offchan)
return -EINVAL;
 
+   if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev))
+   return -EBUSY;
+
params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
 
-- 
1.9.1



[RFC 1/3] cfg80211: Make pre-CAC results valid only for ETSI domain

2017-01-25 Thread Vasanthakumar Thiagarajan
DFS requirement for ETSI domain (section 4.7.1.4 in
ETSI EN 301 893 V1.8.1) is the only one which explicitly
states that once DFS channel is marked as available afer
the CAC, this channel will remain in available state even
moving to a different operating channel. But the same is
not explicitly stated in FCC DFS requirement. Also, Pre-CAC
requriements are not explicitly mentioned in FCC requirement.
Current implementation in keeping DFS channel in available
state is same as described in ETSI domain.

For ETSI DFS domain, this patch gives a grace period of 2 seconds
since the completion of successful CAC before moving the channel's
DFS state to 'usable' from 'available' state. The same grace period
is checked against the channel's dfs_state_entered timestamp while
deciding if a DFS channel is available for operation. There is a new
radar event, NL80211_RADAR_PRE_CAC_EXPIRED, reported when DFS channel
is moved from available to usable state after the grace period. Also
make sure the DFS channel state is reset to usable once the beaconing
operation on that channel is brought down (like stop_ap, leave_ibss
and leave_mesh) in non-ETSI domain.

Signed-off-by: Vasanthakumar Thiagarajan 
---
 include/uapi/linux/nl80211.h |  5 +++
 net/wireless/ap.c|  5 +++
 net/wireless/chan.c  | 96 
 net/wireless/core.h  |  7 
 net/wireless/ibss.c  |  1 +
 net/wireless/mesh.c  |  1 +
 net/wireless/mlme.c  | 41 ++-
 net/wireless/reg.c   | 47 ++
 net/wireless/reg.h   | 14 +++
 9 files changed, 208 insertions(+), 9 deletions(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index d6c62ee..9d2d2b1 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4893,12 +4893,17 @@ enum nl80211_smps_mode {
  * change to the channel status.
  * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is
  * over, channel becomes usable.
+ * @NL80211_RADAR_PRE_CAC_EXPIRED: Channel Availability Check done on this
+ * non-operating channel is expired and no longer valid. New CAC must
+ * be done on this channel before starting the operation. This is not
+ * applicable for ETSI dfs domain where pre-CAC is valid for ever.
  */
 enum nl80211_radar_event {
NL80211_RADAR_DETECTED,
NL80211_RADAR_CAC_FINISHED,
NL80211_RADAR_CAC_ABORTED,
NL80211_RADAR_NOP_FINISHED,
+   NL80211_RADAR_PRE_CAC_EXPIRED,
 };
 
 /**
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
index bdad1f9..25666d3 100644
--- a/net/wireless/ap.c
+++ b/net/wireless/ap.c
@@ -32,6 +32,11 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device 
*rdev,
rdev_set_qos_map(rdev, dev, NULL);
if (notify)
nl80211_send_ap_stopped(wdev);
+
+   /* Should we apply the grace period during beaconing interface
+* shutdown also?
+*/
+   cfg80211_sched_dfs_chan_update(rdev);
}
 
return err;
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 5497d022..090309a 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -456,6 +456,102 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
return (r1 + r2 > 0);
 }
 
+static bool cfg80211_5ghz_sub_chan(struct cfg80211_chan_def *chandef,
+  struct ieee80211_channel *chan)
+{
+   u32 start_freq_seg0 = 0, end_freq_seg0 = 0;
+   u32 start_freq_seg1 = 0, end_freq_seg1 = 0;
+
+   if (chandef->chan->center_freq == chan->center_freq)
+   return true;
+
+   switch (chandef->width) {
+   case NL80211_CHAN_WIDTH_40:
+   start_freq_seg0 = chandef->center_freq1 - 20;
+   end_freq_seg0 = chandef->center_freq1 + 20;
+   break;
+   case NL80211_CHAN_WIDTH_80P80:
+   start_freq_seg1 = chandef->center_freq2 - 40;
+   end_freq_seg1 = chandef->center_freq2 + 40;
+   /* fall through */
+   case NL80211_CHAN_WIDTH_80:
+   start_freq_seg0 = chandef->center_freq1 - 40;
+   end_freq_seg0 = chandef->center_freq1 + 40;
+   break;
+   case NL80211_CHAN_WIDTH_160:
+   start_freq_seg0 = chandef->center_freq1 - 80;
+   end_freq_seg0 = chandef->center_freq1 + 80;
+   break;
+   case NL80211_CHAN_WIDTH_20_NOHT:
+   case NL80211_CHAN_WIDTH_20:
+   case NL80211_CHAN_WIDTH_5:
+   case NL80211_CHAN_WIDTH_10:
+   break;
+   }
+
+   if (chan->center_freq > start_freq_seg0 &&
+   chan->center_freq < end_freq_seg0)
+   return true;
+
+   return chan->center_freq > start_freq_seg1 &&
+   chan->center_freq < end_freq_seg1;
+}
+
+bool 

[RFC 0/3] Pre-CAC and sharing DFS state across multiple radios

2017-01-25 Thread Vasanthakumar Thiagarajan
Currently irrespective of dfs domain and radar detection activity
pre-CAC results for a wiphy are retained till the wiphy is detroyed.
This may not be preferred in non-ETSI dfs domain where pre-CAC is not
explicitly mentioned in the respective DFS requirement spec. This patch
set modifies the current behaviour of pre-CAC for non-ETSI domain by
giving 2 seconds grace period for dfs master interface to start operating
on the CAC completed channel.

This patch set also adds support to share dfs channel state across
multiple radios of the same regulatory configuration.

Vasanthakumar Thiagarajan (3):
  cfg80211: Make pre-CAC results valid only for ETSI domain
  cfg80211: Disallow moving out of operating DFS channel in non-ETSI
  cfg80211: Share Channel DFS state across wiphys of same DFS domain

 include/uapi/linux/nl80211.h |   5 ++
 net/wireless/ap.c|   5 ++
 net/wireless/chan.c  | 112 ++
 net/wireless/core.c  |  37 ++
 net/wireless/core.h  |  13 
 net/wireless/ibss.c  |   1 +
 net/wireless/mesh.c  |   1 +
 net/wireless/mlme.c  |  52 +++---
 net/wireless/nl80211.c   |  38 +++
 net/wireless/reg.c   | 159 +++
 net/wireless/reg.h   |  36 ++
 11 files changed, 449 insertions(+), 10 deletions(-)

-- 
1.9.1



Re: [PATCH 2/2] mac80211: use accessor functions to set sta->_flags

2017-01-25 Thread Johannes Berg
On Wed, 2017-01-25 at 09:55 +0100, Amadeusz Slawinski wrote:
> And yes I did. Somehow managed to ignore those warnings though, sorry
> about that.

:)
That was intentional so nobody changing mac80211 in the future will
accidentally play with those flags through the normal accessors.

> Rechecked with just first patch and it should still be good. Please
> ignore this one ;)

Yeah, I still have that one pending, no worries :)

johannes


Re: [PATCH 2/2] mac80211: use accessor functions to set sta->_flags

2017-01-25 Thread Amadeusz Slawinski
And yes I did. Somehow managed to ignore those warnings though, sorry
about that.
Rechecked with just first patch and it should still be good. Please
ignore this one ;)

On 24 January 2017 at 16:44, Johannes Berg  wrote:
> On Tue, 2017-01-24 at 16:42 +0100, Amadeusz Sławiński wrote:
>> cleanup patch to make use of set_sta_flag()/clear_sta_flag() in
>> places
>> where we access sta->_flags
>>
>> Signed-off-by: Amadeusz Sławiński 
>> ---
>>  net/mac80211/sta_info.c | 12 ++--
>>  1 file changed, 6 insertions(+), 6 deletions(-)
>>
>> diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
>> index b6cfcf0..6c9cc2f 100644
>> --- a/net/mac80211/sta_info.c
>> +++ b/net/mac80211/sta_info.c
>> @@ -1855,13 +1855,13 @@ int sta_info_move_state(struct sta_info *sta,
>>   switch (new_state) {
>>   case IEEE80211_STA_NONE:
>>   if (sta->sta_state == IEEE80211_STA_AUTH)
>> - clear_bit(WLAN_STA_AUTH, >_flags);
>> + clear_sta_flag(sta, WLAN_STA_AUTH);
>
> You should try to run this patch sometime :)
>
> johannes