Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] ath10k: implement host memory chunks feature
From: Michal Kazior @ 2013-09-18 10:51 UTC (permalink / raw)
  To: Bartosz Markowski; +Cc: ath10k, linux-wireless
In-Reply-To: <1379497651-29933-1-git-send-email-bartosz.markowski@tieto.com>

On 18 September 2013 11:47, Bartosz Markowski
<bartosz.markowski@tieto.com> wrote:
> Firmware can request a memory pool from host to offload
> it's own resources. This is a feature designed especially
> for AP mode where the target has to deal with large number
> of peers.
>
> So we allocate and map a consistent DMA memory which FW can
> use to store e.g. peer rate contol maps.
>
> Signed-off-by: Bartosz Markowski <bartosz.markowski@tieto.com>
> ---
>  drivers/net/wireless/ath/ath10k/core.h |   12 +++
>  drivers/net/wireless/ath/ath10k/hif.h  |   23 ++++++
>  drivers/net/wireless/ath/ath10k/pci.c  |   45 +++++++++++
>  drivers/net/wireless/ath/ath10k/wmi.c  |  129 ++++++++++++++++++++++++++++++--
>  drivers/net/wireless/ath/ath10k/wmi.h  |   12 ++-
>  5 files changed, 209 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
> index fcf94ee..c194f61 100644
> --- a/drivers/net/wireless/ath/ath10k/core.h
> +++ b/drivers/net/wireless/ath/ath10k/core.h
> @@ -278,6 +278,15 @@ enum ath10k_fw_features {
>         ATH10K_FW_FEATURE_COUNT,
>  };
>
> +#define MAX_MEM_CHUNKS 32

I think this should be prefixed with ATH10K_.


> +
> +struct ath10k_mem_chunk {
> +       void *vaddr;
> +       dma_addr_t paddr;
> +       u32 len;
> +       u32 req_id;
> +};
> +
>  struct ath10k {
>         struct ath_common ath_common;
>         struct ieee80211_hw *hw;
> @@ -297,6 +306,9 @@ struct ath10k {
>         u32 vht_cap_info;
>         u32 num_rf_chains;
>
> +       u32 num_mem_chunks;
> +       struct ath10k_mem_chunk mem_chunks[MAX_MEM_CHUNKS];
> +
>         DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
>
>         struct targetdef *targetdef;
> diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
> index dcdea68..4af6a66 100644
> --- a/drivers/net/wireless/ath/ath10k/hif.h
> +++ b/drivers/net/wireless/ath/ath10k/hif.h
> @@ -83,6 +83,12 @@ struct ath10k_hif_ops {
>
>         int (*suspend)(struct ath10k *ar);
>         int (*resume)(struct ath10k *ar);
> +
> +       /* Allocate/Free the host memory for firmware use */
> +       int (*chunk_alloc)(struct ath10k *ar, u32 req_id, u32 index,
> +                          u32 num_units, u32 unit_len);
> +
> +       void (*chunk_free)(struct ath10k *ar, int idx);

Can't we simply use dma_alloc_coherent(ar->dev) and avoid this HIF
abstraction? pci_alloc_consistent is just an alias for
dma_alloc_coherent anyway.


>  };
>
>
> @@ -173,4 +179,21 @@ static inline int ath10k_hif_resume(struct ath10k *ar)
>         return ar->hif.ops->resume(ar);
>  }
>
> +static inline int ath10k_hif_chunk_alloc(struct ath10k *ar,
> +                                        u32 req_id,
> +                                        u32 idx,
> +                                        u32 num_units,
> +                                        u32 unit_len)
> +{
> +       if (!ar->hif.ops->chunk_alloc)
> +               return -EOPNOTSUPP;
> +
> +       return ar->hif.ops->chunk_alloc(ar, req_id, idx, num_units, unit_len);
> +}
> +
> +static inline void ath10k_hif_chunk_free(struct ath10k *ar, int idx)
> +{

Missing check for hif.ops->chunk_free pointer here?


> +       ar->hif.ops->chunk_free(ar, idx);
> +}
> +
>  #endif /* _HIF_H_ */
> diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
> index f1faf46..547d67d 100644
> --- a/drivers/net/wireless/ath/ath10k/pci.c
> +++ b/drivers/net/wireless/ath/ath10k/pci.c
> @@ -1966,6 +1966,49 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
>  }
>  #endif
>
> +static int ath10k_pci_hif_chunk_alloc(struct ath10k *ar,
> +                                     u32 req_id,
> +                                     u32 idx,
> +                                     u32 num_units,
> +                                     u32 unit_len)
> +{
> +       dma_addr_t paddr;
> +       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
> +
> +       if (!num_units  || !unit_len)
> +               return 0;
> +

I'm not seeing any checks against buffer overflow of mem_chunks[req_id].


> diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
> index 6803ead..89de893 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
> @@ -22,6 +22,7 @@
>  #include "debug.h"
>  #include "wmi.h"
>  #include "mac.h"
> +#include "hif.h"
>
>  int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
>  {
> @@ -964,6 +965,46 @@ static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
>         ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n");
>  }
>
> +#define HOST_MEM_SIZE_UNIT 4
> +
> +static void ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
> +                                     u32 num_units, u32 unit_len)
> +{
> +       u32 remaining_units, allocated_units, idx;
> +
> +       /* adjust the length to nearest multiple of unit size */
> +       unit_len = (unit_len + (HOST_MEM_SIZE_UNIT - 1)) &
> +                  (~(HOST_MEM_SIZE_UNIT - 1));

round_up() ?


> @@ -1013,12 +1054,44 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
>                          ar->fw_version_build);
>         }
>
> -       /* FIXME: it probably should be better to support this */
> -       if (__le32_to_cpu(ev->num_mem_reqs) > 0) {
> -               ath10k_warn("target requested %d memory chunks; ignoring\n",
> +       WARN_ON(__le32_to_cpu(ev->num_mem_reqs) > WMI_MAX_MEM_REQS);

This seems wrong.

ath10k_warn() should be used here. Is it really safe to continue and
use the num_mem_reqs while it exceeds the limit?


> +
> +       if (__le32_to_cpu(ev->num_mem_reqs)) {

if (!__le32_to_cpu(ev->num_mem_reqs))
  return;



Michał.

^ permalink raw reply

* [PATCH] ath10k: implement host memory chunks feature
From: Bartosz Markowski @ 2013-09-18  9:47 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Bartosz Markowski

Firmware can request a memory pool from host to offload
it's own resources. This is a feature designed especially
for AP mode where the target has to deal with large number
of peers.

So we allocate and map a consistent DMA memory which FW can
use to store e.g. peer rate contol maps.

Signed-off-by: Bartosz Markowski <bartosz.markowski@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h |   12 +++
 drivers/net/wireless/ath/ath10k/hif.h  |   23 ++++++
 drivers/net/wireless/ath/ath10k/pci.c  |   45 +++++++++++
 drivers/net/wireless/ath/ath10k/wmi.c  |  129 ++++++++++++++++++++++++++++++--
 drivers/net/wireless/ath/ath10k/wmi.h  |   12 ++-
 5 files changed, 209 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index fcf94ee..c194f61 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -278,6 +278,15 @@ enum ath10k_fw_features {
 	ATH10K_FW_FEATURE_COUNT,
 };
 
+#define MAX_MEM_CHUNKS 32
+
+struct ath10k_mem_chunk {
+	void *vaddr;
+	dma_addr_t paddr;
+	u32 len;
+	u32 req_id;
+};
+
 struct ath10k {
 	struct ath_common ath_common;
 	struct ieee80211_hw *hw;
@@ -297,6 +306,9 @@ struct ath10k {
 	u32 vht_cap_info;
 	u32 num_rf_chains;
 
+	u32 num_mem_chunks;
+	struct ath10k_mem_chunk mem_chunks[MAX_MEM_CHUNKS];
+
 	DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
 
 	struct targetdef *targetdef;
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index dcdea68..4af6a66 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -83,6 +83,12 @@ struct ath10k_hif_ops {
 
 	int (*suspend)(struct ath10k *ar);
 	int (*resume)(struct ath10k *ar);
+
+	/* Allocate/Free the host memory for firmware use */
+	int (*chunk_alloc)(struct ath10k *ar, u32 req_id, u32 index,
+			   u32 num_units, u32 unit_len);
+
+	void (*chunk_free)(struct ath10k *ar, int idx);
 };
 
 
@@ -173,4 +179,21 @@ static inline int ath10k_hif_resume(struct ath10k *ar)
 	return ar->hif.ops->resume(ar);
 }
 
+static inline int ath10k_hif_chunk_alloc(struct ath10k *ar,
+					 u32 req_id,
+					 u32 idx,
+					 u32 num_units,
+					 u32 unit_len)
+{
+	if (!ar->hif.ops->chunk_alloc)
+		return -EOPNOTSUPP;
+
+	return ar->hif.ops->chunk_alloc(ar, req_id, idx, num_units, unit_len);
+}
+
+static inline void ath10k_hif_chunk_free(struct ath10k *ar, int idx)
+{
+	ar->hif.ops->chunk_free(ar, idx);
+}
+
 #endif /* _HIF_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index f1faf46..547d67d 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1966,6 +1966,49 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
 }
 #endif
 
+static int ath10k_pci_hif_chunk_alloc(struct ath10k *ar,
+				      u32 req_id,
+				      u32 idx,
+				      u32 num_units,
+				      u32 unit_len)
+{
+	dma_addr_t paddr;
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+	if (!num_units  || !unit_len)
+		return 0;
+
+	/*
+	 * TODO: allocate a chunk of memory at the index indicated and
+	 * if allocation fail allocate smallest size possible and
+	 * return number of units allocated.
+	 */
+	ar->mem_chunks[idx].vaddr = pci_alloc_consistent(ar_pci->pdev,
+							 num_units * unit_len,
+							 &paddr);
+	if(!ar->mem_chunks[idx].vaddr)
+		return 0;
+
+	memset(ar->mem_chunks[idx].vaddr, 0, num_units * unit_len);
+
+	ar->mem_chunks[idx].paddr = paddr;
+	ar->mem_chunks[idx].len = num_units * unit_len;
+	ar->mem_chunks[idx].req_id = req_id;
+
+	return num_units;
+
+}
+
+static void ath10k_pci_hif_chunk_free(struct ath10k *ar, int idx)
+{
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+	pci_free_consistent(ar_pci->pdev,
+			    ar->mem_chunks[idx].len,
+			    ar->mem_chunks[idx].vaddr,
+			    ar->mem_chunks[idx].paddr);
+}
+
 static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
 	.send_head		= ath10k_pci_hif_send_head,
 	.exchange_bmi_msg	= ath10k_pci_hif_exchange_bmi_msg,
@@ -1982,6 +2025,8 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
 	.suspend		= ath10k_pci_hif_suspend,
 	.resume			= ath10k_pci_hif_resume,
 #endif
+	.chunk_alloc		= ath10k_pci_hif_chunk_alloc,
+	.chunk_free		= ath10k_pci_hif_chunk_free,
 };
 
 static void ath10k_pci_ce_tasklet(unsigned long ptr)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6803ead..89de893 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -22,6 +22,7 @@
 #include "debug.h"
 #include "wmi.h"
 #include "mac.h"
+#include "hif.h"
 
 int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
 {
@@ -964,6 +965,46 @@ static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
 	ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n");
 }
 
+#define HOST_MEM_SIZE_UNIT 4
+
+static void ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
+				      u32 num_units, u32 unit_len)
+{
+	u32 remaining_units, allocated_units, idx;
+
+	/* adjust the length to nearest multiple of unit size */
+	unit_len = (unit_len + (HOST_MEM_SIZE_UNIT - 1)) &
+		   (~(HOST_MEM_SIZE_UNIT - 1));
+
+	idx = ar->num_mem_chunks;
+	remaining_units = num_units;
+	while (remaining_units) {
+		allocated_units = ath10k_hif_chunk_alloc(ar, req_id, idx,
+							 remaining_units,
+							 unit_len);
+		if (allocated_units == 0) {
+			ath10k_warn("Memory allocation has failed (unit len %d units requested %d units allocated %d)\n",
+				    unit_len, num_units,
+				    (num_units - remaining_units));
+			ar->num_mem_chunks = idx;
+			break;
+		}
+
+		remaining_units -= allocated_units;
+		++idx;
+		if (idx == MAX_MEM_CHUNKS ) {
+			ath10k_warn("Maximum chunk limit has been reached (for memory units %d unit len %d requested by FW, allocated only %d\n",
+				    num_units,unit_len,
+				    (num_units - remaining_units));
+			ar->num_mem_chunks = idx;
+			break;
+		}
+	}
+	ar->num_mem_chunks = idx;
+
+}
+
+
 static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 					      struct sk_buff *skb)
 {
@@ -1013,12 +1054,44 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 			 ar->fw_version_build);
 	}
 
-	/* FIXME: it probably should be better to support this */
-	if (__le32_to_cpu(ev->num_mem_reqs) > 0) {
-		ath10k_warn("target requested %d memory chunks; ignoring\n",
+	WARN_ON(__le32_to_cpu(ev->num_mem_reqs) > WMI_MAX_MEM_REQS);
+
+	if (__le32_to_cpu(ev->num_mem_reqs)) {
+		u32 num_units, i;
+
+		ath10k_warn("target requested %d memory chunks\n",
 			    __le32_to_cpu(ev->num_mem_reqs));
+
+		for (i = 0; i < __le32_to_cpu(ev->num_mem_reqs); ++i) {
+			num_units = __le32_to_cpu(ev->mem_reqs[i].num_units);
+			if (__le32_to_cpu(ev->mem_reqs[i].n_unit_info)) {
+				if (__le32_to_cpu(ev->mem_reqs[i].n_unit_info)
+				    & NUM_UNITS_IS_NUM_PEERS) {
+					/* number of units to allocate is
+					 * number of peers, 1 extra for self
+					 * peer on target
+					 * this needs to be tied, host and
+					 * target can get out of sync */
+					num_units = TARGET_NUM_PEERS + 1;
+				}
+			}
+
+			ath10k_dbg(ATH10K_DBG_WMI, "i %d req %d  num_units %d n_unit_info %d unit size %d actual units %d \n",
+				   i,
+				   __le32_to_cpu(ev->mem_reqs[i].req_id),
+				   __le32_to_cpu(ev->mem_reqs[i].num_units),
+				   __le32_to_cpu(ev->mem_reqs[i].n_unit_info),
+				   __le32_to_cpu(ev->mem_reqs[i].unit_size),
+				   num_units);
+
+			ath10k_wmi_alloc_host_mem(ar,
+				__le32_to_cpu(ev->mem_reqs[i].req_id),
+				num_units,
+				__le32_to_cpu(ev->mem_reqs[i].unit_size));
+		}
 	}
 
+
 	ath10k_dbg(ATH10K_DBG_WMI,
 		   "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
 		   __le32_to_cpu(ev->sw_version),
@@ -1186,6 +1259,18 @@ int ath10k_wmi_attach(struct ath10k *ar)
 
 void ath10k_wmi_detach(struct ath10k *ar)
 {
+	int i;
+
+	for (i = 0;  i < ar->num_mem_chunks; i++) {
+		ath10k_dbg(ATH10K_DBG_WMI, "free chunk %d len %d vaddr 0x%p paddr 0x%08llx\n",
+			   ar->num_mem_chunks,
+			   ar->mem_chunks[i].len,
+			   ar->mem_chunks[i].vaddr,
+			   ar->mem_chunks[i].paddr);
+
+		ar->hif.ops->chunk_free(ar, i);
+	}
+	ar->num_mem_chunks = 0;
 }
 
 int ath10k_wmi_connect_htc_service(struct ath10k *ar)
@@ -1373,12 +1458,40 @@ int ath10k_wmi_cmd_init(struct ath10k *ar)
 	config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC);
 	config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES);
 
-	buf = ath10k_wmi_alloc_skb(sizeof(*cmd));
-	if (!buf)
-		return -ENOMEM;
+	if (ar->num_mem_chunks) {
+		int i;
+
+		buf = ath10k_wmi_alloc_skb(sizeof(*cmd) +
+			(sizeof(struct host_memory_chunk) * MAX_MEM_CHUNKS));
+		if (!buf)
+			return -ENOMEM;
+
+		cmd = (struct wmi_init_cmd *)buf->data;
+
+		ath10k_dbg(ATH10K_DBG_WMI, "Sending memory chunks info.\n");
+		cmd->num_host_mem_chunks = __cpu_to_le32(ar->num_mem_chunks);
+
+		for (i = 0; i < ar->num_mem_chunks; i++) {
+			cmd->host_mem_chunks[i].ptr =
+				__cpu_to_le32(ar->mem_chunks[i].paddr);
+			cmd->host_mem_chunks[i].size =
+				__cpu_to_le32(ar->mem_chunks[i].len);
+			cmd->host_mem_chunks[i].req_id =
+				__cpu_to_le32(ar->mem_chunks[i].req_id);
+
+			ath10k_dbg(ATH10K_DBG_WMI, "chunk %d len %d requested, addr 0x%x\n",
+				   i,
+				   cmd->host_mem_chunks[i].size,
+				   cmd->host_mem_chunks[i].ptr);
+		}
+	} else {
+		buf = ath10k_wmi_alloc_skb(sizeof(*cmd));
+		if (!buf)
+			return -ENOMEM;
+		cmd = (struct wmi_init_cmd *)buf->data;
+		cmd->num_host_mem_chunks = 0;
+	}
 
-	cmd = (struct wmi_init_cmd *)buf->data;
-	cmd->num_host_mem_chunks = 0;
 	memcpy(&cmd->resource_config, &config, sizeof(config));
 
 	ath10k_dbg(ATH10K_DBG_WMI, "wmi init\n");
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 2c52c23..f586fb6 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -744,13 +744,12 @@ struct wlan_host_mem_req {
 	__le32 req_id;
 	/* size of the  of each unit */
 	__le32 unit_size;
-	/* flags to  indicate that
-	 * the number units is dependent
+	/* flags to  indicate that the number units is dependent
 	 * on number of resources(num vdevs num peers .. etc)
 	 */
-	__le32 num_unit_info;
+	__le32 n_unit_info;
 	/*
-	 * actual number of units to allocate . if flags in the num_unit_info
+	 * actual number of units to allocate . if flags in the n_unit_info
 	 * indicate that number of units is tied to number of a particular
 	 * resource to allocate then  num_units filed is set to 0 and host
 	 * will derive the number units from number of the resources it is
@@ -1012,6 +1011,11 @@ struct wmi_resource_config {
 	__le32 max_frag_entries;
 } __packed;
 
+#define WMI_MAX_MEM_REQS 16
+
+#define NUM_UNITS_IS_NUM_VDEVS   0x1
+#define NUM_UNITS_IS_NUM_PEERS   0x2
+
 /* strucutre describing host memory chunk. */
 struct host_memory_chunk {
 	/* id of the request that is passed up in service ready */
-- 
1.7.10


^ permalink raw reply related

* Re: fyi: scheduling while atomic dmesg output 3.12-rc1
From: Arend van Spriel @ 2013-09-18  9:19 UTC (permalink / raw)
  To: Joe Perches
  Cc: brcm80211-dev-list, linux-wireless, Hauke Mehrtens,
	Rafał Miłecki
In-Reply-To: <1379439942.2012.16.camel@joe-AO722>

[-- Attachment #1: Type: text/plain, Size: 5260 bytes --]

On 09/17/2013 07:45 PM, Joe Perches wrote:
> <3>[   11.206312] BUG: scheduling while atomic: NetworkManager/866/0x00000200

Thanks, Joe

I got a report on this few days ago. It was introduced by bcma API 
change and I already sent email to the committer of that change, ie. 
Hauke Mehrtens. Hope it will be settled soon how to fix this.

Gr. AvS

> <4>[   11.206325] Modules linked in: snd_hda_codec_realtek arc4 brcmsmac cordic brcmutil b43 mac80211 joydev cfg80211 ssb acer_wmi sparse_keymap snd_hda_intel snd_hda_codec snd_hwdep snd_pcm i2c_piix4 psmouse serio_raw k10temp snd_page_alloc snd_seq_midi snd_seq_midi_event snd_rawmidi snd_seq snd_seq_device snd_timer radeon bcma video snd wmi mac_hid parport_pc ppdev ttm rfcomm bnep bluetooth soundcore drm_kms_helper drm i2c_algo_bit binfmt_misc lp parport r8169 mii
> <4>[   11.206419] CPU: 0 PID: 866 Comm: NetworkManager Not tainted 3.12.0-rc1+ #41
> <4>[   11.206424] Hardware name: Acer AO725/ZA10_BZ, BIOS V2.12 04/16/2013
> <4>[   11.206430]  00000000 00000000 f159b828 c15e711b 00000000 f159b840 c15e3ffb c17ab9d0
> <4>[   11.206446]  f6c84320 00000362 00000200 f159b8cc c15eb79c c12de6a0 00000000 f159b8f0
> <4>[   11.206461]  f7bb69b0 f159b86c c106259e 00000000 c19b9940 c19b9940 f159b8bc c106323d
> <4>[   11.206476] Call Trace:
> <4>[   11.206494]  [<c15e711b>] dump_stack+0x41/0x52
> <4>[   11.206503]  [<c15e3ffb>] __schedule_bug+0x4e/0x5c
> <4>[   11.206512]  [<c15eb79c>] __schedule+0x78c/0x7a0
> <4>[   11.206523]  [<c12de6a0>] ? timerqueue_add+0x50/0xb0
> <4>[   11.206534]  [<c106259e>] ? enqueue_hrtimer+0x1e/0x70
> <4>[   11.206544]  [<c106323d>] ? __hrtimer_start_range_ns+0x16d/0x460
> <4>[   11.206552]  [<c15ebf73>] schedule+0x23/0x60
> <4>[   11.206560]  [<c15eab9c>] schedule_hrtimeout_range_clock+0xbc/0x160
> <4>[   11.206569]  [<c10626c0>] ? update_rmtp+0x90/0x90
> <4>[   11.206578]  [<c1063586>] ? hrtimer_start_range_ns+0x26/0x30
> <4>[   11.206586]  [<c15eac57>] schedule_hrtimeout_range+0x17/0x20
> <4>[   11.206594]  [<c104d13d>] usleep_range+0x3d/0x40
> <4>[   11.206612]  [<f88a0e27>] bcma_pcie_mdio_set_phy.isra.3+0x47/0x70 [bcma]
> <4>[   11.206626]  [<f88a0efa>] bcma_pcie_mdio_write.isra.4+0xaa/0xc0 [bcma]
> <4>[   11.206640]  [<f88a10d8>] bcma_pcie_mdio_writeread.isra.6.constprop.13+0x18/0x30 [bcma]
> <4>[   11.206653]  [<f88a1128>] bcma_core_pci_power_save+0x38/0x70 [bcma]
> <4>[   11.206666]  [<f88a126f>] bcma_core_pci_up+0x1f/0x50 [bcma]
> <4>[   11.206693]  [<f8eb523e>] brcms_c_up+0xee/0x3b0 [brcmsmac]
> <4>[   11.206712]  [<f8eab890>] brcms_up+0x20/0x30 [brcmsmac]
> <4>[   11.206731]  [<f8eac1a7>] brcms_ops_start+0x247/0x2e0 [brcmsmac]
> <4>[   11.206740]  [<c15e420a>] ? printk+0x4d/0x4f
> <4>[   11.206750]  [<c15278b0>] ? fib_rules_event+0x20/0x190
> <4>[   11.206798]  [<f941464c>] ieee80211_do_open+0x2fc/0xca0 [mac80211]
> <4>[   11.206807]  [<c1064dae>] ? __raw_notifier_call_chain+0x1e/0x30
> <4>[   11.206815]  [<c1064ddf>] ? raw_notifier_call_chain+0x1f/0x30
> <4>[   11.206856]  [<f941504d>] ieee80211_open+0x5d/0x60 [mac80211]
> <4>[   11.206867]  [<c151225b>] __dev_open+0xab/0x140
> <4>[   11.206875]  [<c15ed044>] ? _raw_spin_unlock_bh+0x14/0x20
> <4>[   11.206884]  [<c1512521>] __dev_change_flags+0x81/0x160
> <4>[   11.206893]  [<c15126b1>] dev_change_flags+0x21/0x60
> <4>[   11.206902]  [<c151d58d>] do_setlink+0x2bd/0x810
> <4>[   11.206913]  [<c12f6b22>] ? nla_parse+0x22/0xa0
> <4>[   11.206921]  [<c151f85e>] rtnl_newlink+0x36e/0x560
> <4>[   11.206932]  [<c1532b00>] ? __netlink_sendskb+0x10/0x120
> <4>[   11.206942]  [<c1268f74>] ? security_sock_rcv_skb+0x14/0x20
> <4>[   11.206951]  [<c1521200>] ? sk_run_filter+0x4a0/0x540
> <4>[   11.206960]  [<c129ee83>] ? apparmor_capable+0x23/0x70
> <4>[   11.206968]  [<c126956c>] ? security_capable+0x1c/0x30
> <4>[   11.206977]  [<c151f356>] rtnetlink_rcv_msg+0x86/0x220
> <4>[   11.206988]  [<c114a41a>] ? __kmalloc_track_caller+0x4a/0x150
> <4>[   11.206997]  [<c1507453>] ? __skb_recv_datagram+0xc3/0x3d0
> <4>[   11.207006]  [<c1504a60>] ? __alloc_skb+0x60/0x250
> <4>[   11.207014]  [<c151f2d0>] ? __rtnl_unlock+0x20/0x20
> <4>[   11.207022]  [<c1535506>] netlink_rcv_skb+0x86/0xa0
> <4>[   11.207030]  [<c151be9c>] rtnetlink_rcv+0x1c/0x30
> <4>[   11.207038]  [<c1534e74>] netlink_unicast+0x134/0x1a0
> <4>[   11.207046]  [<c1535122>] netlink_sendmsg+0x242/0x3e0
> <4>[   11.207055]  [<c14fb9f5>] sock_sendmsg+0x85/0xc0
> <4>[   11.207064]  [<c12e3535>] ? _copy_from_user+0x35/0x50
> <4>[   11.207072]  [<c15069af>] ? verify_iovec+0x3f/0xb0
> <4>[   11.207080]  [<c14fbcc9>] ___sys_sendmsg+0x299/0x2b0
> <4>[   11.207087]  [<c14fbd30>] ? kernel_sendmsg+0x50/0x50
> <4>[   11.207097]  [<c14f9f45>] ? sockfd_lookup_light+0x25/0x70
> <4>[   11.207107]  [<c107500d>] ? update_curr+0x12d/0x1e0
> <4>[   11.207116]  [<c10724a0>] ? __enqueue_entity+0x70/0x80
> <4>[   11.207124]  [<c1072405>] ? __dequeue_entity+0x25/0x40
> <4>[   11.207133]  [<c1073b16>] ? set_next_entity+0xa6/0xc0
> <4>[   11.207141]  [<c14fca2e>] __sys_sendmsg+0x3e/0x70
> <4>[   11.207149]  [<c14fca76>] SyS_sendmsg+0x16/0x20
> <4>[   11.207157]  [<c14fd193>] SyS_socketcall+0x2d3/0x300
> <4>[   11.207166]  [<c15f4c5b>] ? do_IRQ+0x4b/0xc0
> <4>[   11.207238]  [<c15f4681>] sysenter_do_call+0x12/0x22
>
>
>


[-- Attachment #2: Fwd: brcmsmac follow up.eml --]
[-- Type: application/x-extension-eml, Size: 112303 bytes --]

^ permalink raw reply

* [PATCH] rt2x00: Fix rf register for RT3070
From: Kevin Lo @ 2013-09-18  8:22 UTC (permalink / raw)
  To: linux-wireless

Fix RT3070 chip RF initial value to be similar to the latest Ralink vendor
driver.

Tested on Asus N13 usb wifi dongle.

Signed-off-by: Kevin Lo <kevlo@kevlo.org>
---

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c 
b/drivers/net/wireless/rt2x00/rt2800lib.c
index 95e6e61..3ea35d4 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -5985,7 +5985,7 @@ static void rt2800_init_rfcsr_30xx(struct 
rt2x00_dev *rt2x00dev)
         rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
         rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
         rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
-       rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+       rt2800_rfcsr_write(rt2x00dev, 25, 0x03);
         rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);

         if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {


^ permalink raw reply related

* RE: guidance on struct alignment for rtl8192cu driver
From: Jason Andrews @ 2013-09-18  4:59 UTC (permalink / raw)
  To: Larry Finger, Emmanuel Grumbach
  Cc: Seth Forshee, linux-wireless@vger.kernel.org
In-Reply-To: <52375EA3.4090408@lwfinger.net>

> -----Original Message-----
> From: Larry Finger [mailto:larry.finger@gmail.com] On Behalf Of Larry
> Finger
> Sent: Monday, September 16, 2013 9:40 PM
> To: Emmanuel Grumbach
> Cc: Seth Forshee; Jason Andrews; linux-wireless@vger.kernel.org
> Subject: Re: guidance on struct alignment for rtl8192cu driver
> 
> On 09/16/2013 02:29 PM, Emmanuel Grumbach wrote:
> >>>> Index: wireless-testing-save/drivers/net/wireless/rtlwifi/wifi.h
> >>>>
> ===================================================================
> >>>> --- wireless-testing-save.orig/drivers/net/wireless/rtlwifi/wifi.h
> >>>> +++ wireless-testing-save/drivers/net/wireless/rtlwifi/wifi.h
> >>>> @@ -2057,7 +2057,7 @@ struct rtl_priv {
> >>>>            that it points to the data allocated
> >>>>            beyond  this structure like:
> >>>>            rtl_pci_priv or rtl_usb_priv */
> >>>> -       u8 priv[0];
> >>>> +       u8 __aligned(4) priv[0];
> >>>>    };
> >>>
> >>>
> >>> __attribute__((aligned)) might be a safer bet, as this will align
> it to
> >>> the largest alignment that could possibly be needed.
> >
> > Or copy the code from mac80211.h:
> >
> > u8 drv_priv[0] __aligned(sizeof(void *));
> >
> > I did the same in iwlwifi.
> > Note the new way to add the __aligned thing. Joe will tell you that
> is
> > better than __attribute__ blablabla
> 
> Thanks. I had noticed that checkpatch.pl complains about the
> __attribute
> construction.
> 
> Larry
> 

Larry,

I confirmed that my original alignment error is properly solved by:

    u8 drv_priv[0] __aligned(sizeof(void *));

The driver is now working for my ARM system.

Regards,
Jason


^ permalink raw reply

* [PATCH] doc: fix some typos in documentations
From: Xishi Qiu @ 2013-09-18  3:45 UTC (permalink / raw)
  To: rob, johannes, Andrew Morton; +Cc: linux-doc, LKML, linux-wireless, Xishi Qiu

Fix some typos in five documentations, no functional change.

Signed-off-by: Xishi Qiu <qiuxishi@huawei.com>
---
 Documentation/md.txt              |    2 +-
 Documentation/rfkill.txt          |    2 +-
 Documentation/rt-mutex-design.txt |    2 +-
 Documentation/static-keys.txt     |    4 ++--
 Documentation/sysfs-rules.txt     |    2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Documentation/md.txt b/Documentation/md.txt
index fbb2fcb..f925666 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -533,7 +533,7 @@ also have
       found.  The count in 'mismatch_cnt' is the number of sectors
       that were re-written, or (for 'check') would have been
       re-written.  As most raid levels work in units of pages rather
-      than sectors, this my be larger than the number of actual errors
+      than sectors, this may be larger than the number of actual errors
       by a factor of the number of sectors in a page.
 
    bitmap_set_bits
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt
index 03c9d92..f430004 100644
--- a/Documentation/rfkill.txt
+++ b/Documentation/rfkill.txt
@@ -71,7 +71,7 @@ To create an rfkill driver, driver's Kconfig needs to have
 	depends on RFKILL || !RFKILL
 
 to ensure the driver cannot be built-in when rfkill is modular. The !RFKILL
-case allows the driver to be built when rfkill is not configured, which which
+case allows the driver to be built when rfkill is not configured, which
 case all rfkill API can still be used but will be provided by static inlines
 which compile to almost nothing.
 
diff --git a/Documentation/rt-mutex-design.txt b/Documentation/rt-mutex-design.txt
index a5bcd7f..8666070 100644
--- a/Documentation/rt-mutex-design.txt
+++ b/Documentation/rt-mutex-design.txt
@@ -30,7 +30,7 @@ is something called unbounded priority inversion.  That is when the high
 priority process is prevented from running by a lower priority process for
 an undetermined amount of time.
 
-The classic example of unbounded priority inversion is were you have three
+The classic example of unbounded priority inversion is where you have three
 processes, let's call them processes A, B, and C, where A is the highest
 priority process, C is the lowest, and B is in between. A tries to grab a lock
 that C owns and must wait and lets C run to release the lock. But in the
diff --git a/Documentation/static-keys.txt b/Documentation/static-keys.txt
index 9f5263d..c4407a4 100644
--- a/Documentation/static-keys.txt
+++ b/Documentation/static-keys.txt
@@ -116,7 +116,7 @@ The branch(es) can then be switched via:
 	static_key_slow_dec(&key);
 
 Thus, 'static_key_slow_inc()' means 'make the branch true', and
-'static_key_slow_dec()' means 'make the the branch false' with appropriate
+'static_key_slow_dec()' means 'make the branch false' with appropriate
 reference counting. For example, if the key is initialized true, a
 static_key_slow_dec(), will switch the branch to false. And a subsequent
 static_key_slow_inc(), will change the branch back to true. Likewise, if the
@@ -236,7 +236,7 @@ label case adds:
 
 If we then include the padding bytes, the jump label code saves, 16 total bytes
 of instruction memory for this small function. In this case the non-jump label
-function is 80 bytes long. Thus, we have have saved 20% of the instruction
+function is 80 bytes long. Thus, we have saved 20% of the instruction
 footprint. We can in fact improve this even further, since the 5-byte no-op
 really can be a 2-byte no-op since we can reach the branch with a 2-byte jmp.
 However, we have not yet implemented optimal no-op sizes (they are currently
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt
index c1a1fd6..a5f985e 100644
--- a/Documentation/sysfs-rules.txt
+++ b/Documentation/sysfs-rules.txt
@@ -47,7 +47,7 @@ versions of the sysfs interface.
         at device creation and removal
       - the unique key to the device at that point in time
       - the kernel's path to the device directory without the leading
-        /sys, and always starting with with a slash
+        /sys, and always starting with a slash
       - all elements of a devpath must be real directories. Symlinks
         pointing to /sys/devices must always be resolved to their real
         target and the target path must be used to access the device.
-- 
1.7.1



^ permalink raw reply related

* Re: [REGRESSION]: bcma: fix handling of big addrl
From: Tom Gundersen @ 2013-09-17 21:50 UTC (permalink / raw)
  To: Hauke Mehrtens; +Cc: Linux Wireless List, John W. Linville, LKML
In-Reply-To: <5238B55A.5050002@hauke-m.de>

On Tue, Sep 17, 2013 at 10:02 PM, Hauke Mehrtens <hauke@hauke-m.de> wrote:
> On 09/17/2013 09:11 PM, Tom Gundersen wrote:
>> The above commit causes a regression for me.
>>
>> Booting with initcall_debug shows that bcma_modinit never returns:
>>
>> calling  bcma_modinit+0x0/0x33 [bcma] @ 210
>> bcma-pci-bridge 0000:02:00.0: enabling device (0000 -> 0002)
>> bcma: bus0: Found chip with id 0xA8D8, rev 0x01 and package 0x08
>>
>> Which means that (obviously) my wireless nic doesnot work (doe not
>> show up in "ip addr"). Moreover, the kernel hangs during reboot and
>> I'm forced to do a hard-reboot.
>>
>> Reverting the offending commit on top of 3.12-rc1 fixes the problem.
>
> There is already a patch in wireless-testing on its way into linux tree:
>
> https://git.kernel.org/cgit/linux/kernel/git/linville/wireless-testing.git/commit/?id=167fef2a4dce0fa9b9b847bac91cd06c191396d2

Thanks for the reference, hadn't seen that. FWIW, it works for me.

Cheers,

Tom

^ permalink raw reply

* [PATCH] p54usb: fix leak at failure path in p54u_load_firmware()
From: Alexey Khoroshilov @ 2013-09-17 20:57 UTC (permalink / raw)
  To: Christian Lamparter
  Cc: Alexey Khoroshilov, John W. Linville, linux-wireless, netdev,
	linux-kernel, ldv-project

If request_firmware_nowait() fails in p54u_load_firmware(),
p54u_load_firmware_cb is not called and no one decrements usb_dev refcnt.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
---
 drivers/net/wireless/p54/p54usb.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index b9deef6..7fa81d1 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -979,6 +979,7 @@ static int p54u_load_firmware(struct ieee80211_hw *dev,
 	if (err) {
 		dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
 					  "(%d)!\n", p54u_fwlist[i].fw, err);
+		usb_put_dev(udev);
 	}
 
 	return err;
-- 
1.8.1.2


^ permalink raw reply related

* Re: [REGRESSION]: bcma: fix handling of big addrl
From: Hauke Mehrtens @ 2013-09-17 20:02 UTC (permalink / raw)
  To: Tom Gundersen; +Cc: Linux Wireless List, John W. Linville, LKML
In-Reply-To: <CAG-2HqUUbmcEoYqV+qi8SWZXzSLd22WUO88Gry6Mc1GQJy-Ocg@mail.gmail.com>

On 09/17/2013 09:11 PM, Tom Gundersen wrote:
> The above commit causes a regression for me.
> 
> Booting with initcall_debug shows that bcma_modinit never returns:
> 
> calling  bcma_modinit+0x0/0x33 [bcma] @ 210
> bcma-pci-bridge 0000:02:00.0: enabling device (0000 -> 0002)
> bcma: bus0: Found chip with id 0xA8D8, rev 0x01 and package 0x08
> 
> Which means that (obviously) my wireless nic doesnot work (doe not
> show up in "ip addr"). Moreover, the kernel hangs during reboot and
> I'm forced to do a hard-reboot.
> 
> Reverting the offending commit on top of 3.12-rc1 fixes the problem.

Hi,

There is already a patch in wireless-testing on its way into linux tree:

https://git.kernel.org/cgit/linux/kernel/git/linville/wireless-testing.git/commit/?id=167fef2a4dce0fa9b9b847bac91cd06c191396d2

Hauke


^ permalink raw reply

* [PATCH 2/2] nl80211/cfg80211: PMF Requirement communicated to driver with AP SME
From: Chet Lanctot @ 2013-09-17 19:31 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Chet Lanctot
In-Reply-To: <1379446296-22236-1-git-send-email-clanctot@codeaurora.org>

Needed for drivers that have AP SME integrated.  Whether PMF (Protected
Management Frames, 802.11w) should be used for station connections
is communicated from upper layer software through nl80211/cfg80211.

Signed-off-by: Chet Lanctot <clanctot@codeaurora.org>
---
 include/net/cfg80211.h       |  3 +++
 include/uapi/linux/nl80211.h | 14 ++++++++++----
 net/wireless/nl80211.c       |  9 +++++++++
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index aeaf6df..5ac389c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -636,6 +636,8 @@ struct cfg80211_acl_data {
  *	user space)
  * @ssid_len: length of @ssid
  * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames
+ * @mfp: indicate whether management frame protection is used for 
+ *	station connections 
  * @crypto: crypto settings
  * @privacy: the BSS uses privacy
  * @auth_type: Authentication type (algorithm)
@@ -655,6 +657,7 @@ struct cfg80211_ap_settings {
 	const u8 *ssid;
 	size_t ssid_len;
 	enum nl80211_hidden_ssid hidden_ssid;
+	enum nl80211_mfp mfp;
 	struct cfg80211_crypto_settings crypto;
 	bool privacy;
 	enum nl80211_auth_type auth_type;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index aa1d122..f711ab5 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1063,8 +1063,8 @@ enum nl80211_commands {
  *
  * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is
  *	used for the association (&enum nl80211_mfp, represented as a u32);
- *	this attribute can be used
- *	with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests
+ *	this attribute can be used with %NL80211_CMD_ASSOCIATE,
+ *	%NL80211_CMD_CONNECT, and @NL80211_CMD_START_AP requests
  *
  * @NL80211_ATTR_STA_FLAGS2: Attribute containing a
  *	&struct nl80211_sta_flag_update.
@@ -2934,12 +2934,18 @@ enum nl80211_key_type {
 
 /**
  * enum nl80211_mfp - Management frame protection state
- * @NL80211_MFP_NO: Management frame protection not used
- * @NL80211_MFP_REQUIRED: Management frame protection required
+ * @NL80211_MFP_NO: Management frame protection not used on 
+ *	any connection 
+ * @NL80211_MFP_REQUIRED: Management frame protection required 
+ *	on all connections 
+ * @NL80211_MFP_OPTIONAL: For an AP, management frame 
+ *	protection is optional for a station connection depending
+ *	on whether the station supports MFP
  */
 enum nl80211_mfp {
 	NL80211_MFP_NO,
 	NL80211_MFP_REQUIRED,
+	NL80211_MFP_OPTIONAL,
 };
 
 enum nl80211_wpa_versions {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 14a14d4..1702ae9 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3207,6 +3207,15 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 			return PTR_ERR(params.acl);
 	}
 
+	if (info->attrs[NL80211_ATTR_USE_MFP]) {
+		params.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
+		if (params.mfp != NL80211_MFP_REQUIRED &&
+		    params.mfp != NL80211_MFP_OPTIONAL &&
+		    params.mfp != NL80211_MFP_NO)
+			return -EINVAL;
+	} else
+		params.mfp = NL80211_MFP_NO;
+
 	err = rdev_start_ap(rdev, dev, &params);
 	if (!err) {
 		wdev->preset_chandef = params.chandef;
-- 
1.7.12.rc0.22.gcdd159b


^ permalink raw reply related

* [PATCH 1/2] nl80211/cfg80211: Driver with AP SME advertises need for PMF SA Query
From: Chet Lanctot @ 2013-09-17 19:31 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Chet Lanctot
In-Reply-To: <1379446296-22236-1-git-send-email-clanctot@codeaurora.org>

Needed for drivers that have AP SME integrated but do not implement
The SA Query procedure that is part of Protected Management Frames
(PMF, 802.11w).  Instead, the need for upper layer software to do
this procedure is advertised through nl80211/cfg80211.

Signed-off-by: Chet Lanctot <clanctot@codeaurora.org>
---
 include/uapi/linux/nl80211.h | 11 ++++++++---
 net/wireless/nl80211.c       |  3 ++-
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index eb68735..aa1d122 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1891,6 +1891,9 @@ enum nl80211_iftype {
  * @NL80211_STA_FLAG_ASSOCIATED: station is associated; used with drivers
  *	that support %NL80211_FEATURE_FULL_AP_CLIENT_STATE to transition a
  *	previously added station into associated state
+ * @NL80211_STA_FLAG_NO_SA_QUERY_REQUIRED: no SA Query procedure is needed
+ *	when an association request is received from a station with which there
+ *	is already a MFP connection
  * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
  * @__NL80211_STA_FLAG_AFTER_LAST: internal use
  */
@@ -1903,6 +1906,7 @@ enum nl80211_sta_flags {
 	NL80211_STA_FLAG_AUTHENTICATED,
 	NL80211_STA_FLAG_TDLS_PEER,
 	NL80211_STA_FLAG_ASSOCIATED,
+	NL80211_STA_FLAG_NO_SA_QUERY_REQUIRED,
 
 	/* keep last */
 	__NL80211_STA_FLAG_AFTER_LAST,
@@ -3648,11 +3652,12 @@ enum nl80211_tdls_operation {
 
 /*
  * enum nl80211_ap_sme_features - device-integrated AP features
- * Reserved for future use, no bits are defined in
- * NL80211_ATTR_DEVICE_AP_SME yet.
+ * @NL80211_ATTR_AP_SME_NO_SA_QUERY: This device is not able to do
+ *	the MFP SA query procedure and needs hostapd to do this procedure
+ */
 enum nl80211_ap_sme_features {
+	NL80211_AP_SME_FEATURE_NO_SA_QUERY
 };
- */
 
 /**
  * enum nl80211_feature_flags - device/driver features
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 587ff84..14a14d4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3766,7 +3766,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
 				  BIT(NL80211_STA_FLAG_ASSOCIATED) |
 				  BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
 				  BIT(NL80211_STA_FLAG_WME) |
-				  BIT(NL80211_STA_FLAG_MFP)))
+				  BIT(NL80211_STA_FLAG_MFP) |
+				  BIT(NL80211_STA_FLAG_SA_QUERY_REQUIRED)))
 			return -EINVAL;
 
 		/* but authenticated/associated only if driver handles it */
-- 
1.7.12.rc0.22.gcdd159b


^ permalink raw reply related

* [PATCH 0/2] nl80211/cfg80211: Support PMF on drivers with integrated AP SME
From: Chet Lanctot @ 2013-09-17 19:31 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Chet Lanctot

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 2544 bytes --]

These patches represent a small number of changes to the
nl80211/cfg80211 interface to support Protected Management Frames
(PMF, 802.11w) on an AP.  Specifically, these changes are needed for
drivers that have the AP SME integrated.

Support is added for drivers that do not implement the SA Query procedure
that is part of PMF.  Instead, the need for upper layer software to
do this procedure is advertised.  And support is added so that  whether
PMF should be used for station connections is communicated to the driver.

The following changes are made to nl80211/cfg80211.

1.  A new nl80211_ap_sme_feature is defined which is the driver
advertising that it does not support the SA query procedure.  This
means that the upper layer software must register for Re/Association
Request frames from the driver so that these frames can be delivered
by the driver to start an SA Query procedure.  An example of code in
the driver that sets this feature is as follows:
     struct wiphy *wiphy; /* wiphy defined in cfg80211.h */
     .
     .
     .
     wiphy->ap_sme_capa |= BIT(NL80211_AP_SME_FEATURE_NO_SA_QUERY);

2.  A new entry is made in cfg80211_ap_settings that communicates
to the driver whether management frame protection should be used
for station connections.  This entry is passed by upper layer software
using NL80211_CMD_START_AP.  Existing type nl80211_mfp defines the
values that can be used for this entry.  Existing value ^[-Y´no¡ means
that PMF connections cannot be made with stations. Existing value
´required¡ means that all station connections must be PMF protected.
A new value ´optional¡ is defined which means that a connection can
be made if the station supports it, but it is not required.

3.  A new station flag is defined that indicates to the driver that
no SA Query procedure is needed when an Re/Association Request is
received from a station with which there is already a PMF connection.
The upper layer software will set this for a station when an SA Query
procedure for that station has timed out to indicate to the driver
that the next Re/Association Request should be accepted and not passed
to upper layer software.

Chet Lanctot (2):
  nl80211/cfg80211: Driver with AP SME advertises need for PMF SA Query
  nl80211/cfg80211: PMF Requirement communicated to driver with AP SME

 include/net/cfg80211.h       |  3 +++
 include/uapi/linux/nl80211.h | 25 ++++++++++++++++++-------
 net/wireless/nl80211.c       | 12 +++++++++++-
 3 files changed, 32 insertions(+), 8 deletions(-)

-- 
1.7.12.rc0.22.gcdd159b


^ permalink raw reply

* RE: [PATCH 3.12] mwifiex: queue main work from main process when bailing on races
From: Bing Zhao @ 2013-09-17 19:15 UTC (permalink / raw)
  To: Daniel Mack, linux-wireless@vger.kernel.org
  Cc: s.neumann@raumfeld.com, afenkart@gmail.com,
	linville@tuxdriver.com, johannes.berg@intel.com,
	stable@vger.kernel.org
In-Reply-To: <1379442330-18249-1-git-send-email-zonque@gmail.com>

Hi Daniel,

> Queue main_work in case mwifiex_main_process() bails due to an already
> processed transaction. This is particularly necessary because
> mwifiex_main_process() is called from both the SDIO interrupt handler and
> the workqueue. In case an interrupt occurs while the main process is
> currently executed from the workqueue, the interrupt is lost, resulting in a
> command timeout and consequently a card reset.
> 
> I'm marking this for stable kernel in version 3.7+, because on our platform,
> the issue appears since 601216e12c ("mwifiex: process RX packets in SDIO
> IRQ thread directly") went in.
> 
> Signed-off-by: Daniel Mack <zonque@gmail.com>
> Reported-by: Sven Neumann <s.neumann@raumfeld.com>
> Reported-by: Andreas Fenkart <afenkart@gmail.com>
> Cc: Bing Zhao <bzhao@marvell.com>
> Cc: <stable@vger.kernel.org> [v3.7+]

Acked-by: Bing Zhao <bzhao@marvell.com>

Thanks,
Bing

> ---
>  drivers/net/wireless/mwifiex/main.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/net/wireless/mwifiex/main.c
> b/drivers/net/wireless/mwifiex/main.c
> index ff4ed96..0700bc2 100644
> --- a/drivers/net/wireless/mwifiex/main.c
> +++ b/drivers/net/wireless/mwifiex/main.c
> @@ -235,6 +235,7 @@ int mwifiex_main_process(struct mwifiex_adapter
> *adapter)
>  	/* Check if already processing */
>  	if (adapter->mwifiex_processing) {
>  		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
> +		queue_work(adapter->workqueue, &adapter->main_work);
>  		goto exit_main_proc;
>  	} else {
>  		adapter->mwifiex_processing = true;
> --
> 1.8.3.1


^ permalink raw reply

* [REGRESSION]: bcma: fix handling of big addrl
From: Tom Gundersen @ 2013-09-17 19:11 UTC (permalink / raw)
  To: Linux Wireless List; +Cc: Hauke Mehrtens, John W. Linville, LKML

The above commit causes a regression for me.

Booting with initcall_debug shows that bcma_modinit never returns:

calling  bcma_modinit+0x0/0x33 [bcma] @ 210
bcma-pci-bridge 0000:02:00.0: enabling device (0000 -> 0002)
bcma: bus0: Found chip with id 0xA8D8, rev 0x01 and package 0x08

Which means that (obviously) my wireless nic doesnot work (doe not
show up in "ip addr"). Moreover, the kernel hangs during reboot and
I'm forced to do a hard-reboot.

Reverting the offending commit on top of 3.12-rc1 fixes the problem.

Cheers,

Tom

^ permalink raw reply

* [PATCH 2/2] staging: vt6656: rxtx.c s_vGenerateTxParameter replace pTxBufHead void pointer.
From: Malcolm Priestley @ 2013-09-17 18:58 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

with struct vnt_tx_buffer and attach vnt_tx_fifo_head to pTX_Buffer structure.

The the calling pbyTxBufferAddr points to the same address as
vnt_tx_buffer->fifo_head and is still in use.

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/rxtx.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index a733e3b..2a9deb6 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -99,9 +99,9 @@ static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum,
 static void *s_vGetFreeContext(struct vnt_private *pDevice);
 
 static void s_vGenerateTxParameter(struct vnt_private *pDevice,
-	u8 byPktType, u16 wCurrentRate,	void *pTxBufHead, void *pvRrvTime,
-	void *rts_cts, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx,
-	struct ethhdr *psEthHeader, bool need_rts);
+	u8 byPktType, u16 wCurrentRate,	struct vnt_tx_buffer *tx_buffer,
+	void *pvRrvTime, void *rts_cts, u32 cbFrameSize, int bNeedACK,
+	u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts);
 
 static u32 s_uFillDataHead(struct vnt_private *pDevice,
 	u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
@@ -840,12 +840,11 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
 -*/
 
 static void s_vGenerateTxParameter(struct vnt_private *pDevice,
-	u8 byPktType, u16 wCurrentRate,	void *pTxBufHead, void *pvRrvTime,
-	void *rts_cts, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx,
-	struct ethhdr *psEthHeader, bool need_rts)
+	u8 byPktType, u16 wCurrentRate,	struct vnt_tx_buffer *tx_buffer,
+	void *pvRrvTime, void *rts_cts, u32 cbFrameSize, int bNeedACK,
+	u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts)
 {
-	struct vnt_tx_fifo_head *pFifoHead =
-				(struct vnt_tx_fifo_head *)pTxBufHead;
+	struct vnt_tx_fifo_head *pFifoHead = &tx_buffer->fifo_head;
 	union vnt_tx_data_head *head = rts_cts;
 	u32 cbMACHdLen = WLAN_HDR_ADDR3_LEN; /* 24 */
 	u16 wFifoCtl;
@@ -1237,7 +1236,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
 
     //Fill FIFO,RrvTime,RTS,and CTS
     s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
-		(void *)pbyTxBufferAddr, pvRrvTime, rts_cts,
+		tx_buffer, pvRrvTime, rts_cts,
 		cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
     //Fill DataHead
     uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
@@ -1639,7 +1638,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
 
 	/* Fill FIFO,RrvTime,RTS,and CTS */
 	s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
-		pbyTxBufferAddr, pvRrvTime, rts_cts,
+		pTX_Buffer, pvRrvTime, rts_cts,
 		cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
 
     //Fill DataHead
@@ -2053,7 +2052,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 
 	/* Fill FIFO,RrvTime,RTS,and CTS */
 	s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
-		pbyTxBufferAddr, pvRrvTime, rts_cts,
+		pTX_Buffer, pvRrvTime, rts_cts,
 		cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
 
     //Fill DataHead
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 1/2] staging vt6656: desc.h remove typedef struct tagSTxBufHead to rxtx.h
From: Malcolm Priestley @ 2013-09-17 18:54 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

In code it is referred to as fifo to renamed to
typedef struct tagSTxBufHead -> struct vnt_tx_fifo_head

This is only needed by rxtc.c so moved to rxtx.h

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/desc.h |  9 --------
 drivers/staging/vt6656/rxtx.c | 52 ++++++++++++++++++++++++++++---------------
 drivers/staging/vt6656/rxtx.h | 12 ++++++----
 3 files changed, 42 insertions(+), 31 deletions(-)

diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h
index 4675135..afe7074 100644
--- a/drivers/staging/vt6656/desc.h
+++ b/drivers/staging/vt6656/desc.h
@@ -146,15 +146,6 @@
 /*
  * TX FIFO header
  */
-typedef struct tagSTxBufHead {
-	u32 adwTxKey[4];
-    u16    wFIFOCtl;
-    u16    wTimeStamp;
-    u16    wFragCtl;
-    u16    wReserved;
-} __attribute__ ((__packed__))
-STxBufHead, *PSTxBufHead;
-typedef const STxBufHead *PCSTxBufHead;
 
 typedef struct tagSTxShortBufHead {
     u16    wFIFOCtl;
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index fb743a8..a733e3b 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -844,13 +844,14 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
 	void *rts_cts, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx,
 	struct ethhdr *psEthHeader, bool need_rts)
 {
+	struct vnt_tx_fifo_head *pFifoHead =
+				(struct vnt_tx_fifo_head *)pTxBufHead;
 	union vnt_tx_data_head *head = rts_cts;
 	u32 cbMACHdLen = WLAN_HDR_ADDR3_LEN; /* 24 */
 	u16 wFifoCtl;
 	u8 byFBOption = AUTO_FB_NONE;
 
     //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter...\n");
-    PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead;
     pFifoHead->wReserved = wCurrentRate;
     wFifoCtl = pFifoHead->wFIFOCtl;
 
@@ -953,11 +954,12 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
 */
 
 static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
-	struct vnt_tx_buffer *pTxBufHead, int bNeedEncryption,
+	struct vnt_tx_buffer *tx_buffer, int bNeedEncryption,
 	u32 uSkbPacketLen, u32 uDMAIdx,	struct ethhdr *psEthHeader,
 	u8 *pPacket, PSKeyItem pTransmitKey, u32 uNodeIndex, u16 wCurrentRate,
 	u32 *pcbHeaderLen, u32 *pcbTotalLen)
 {
+	struct vnt_tx_fifo_head *pTxBufHead = &tx_buffer->fifo_head;
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	u32 cbFrameSize, cbFrameBodySize;
 	u32 cb802_1_H_len;
@@ -980,7 +982,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
 	u32 dwMICKey0, dwMICKey1, dwMIC_Priority;
 	u32 *pdwMIC_L, *pdwMIC_R;
 	int bSoftWEP = false;
-
 	pvRrvTime = pMICHDR = pvTxDataHd = NULL;
 
 	if (bNeedEncryption && pTransmitKey->pvKeyTable) {
@@ -1103,7 +1104,8 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     }
 
     pbyTxBufferAddr = (u8 *) &(pTxBufHead->adwTxKey[0]);
-    wTxBufSize = sizeof(STxBufHead);
+	wTxBufSize = sizeof(struct vnt_tx_fifo_head);
+
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
         if (byFBOption == AUTO_FB_NONE) {
             if (bRTS == true) {//RTS_need
@@ -1467,8 +1469,8 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	struct vnt_tx_buffer *pTX_Buffer;
-	PSTxBufHead pTxBufHead;
 	struct vnt_usb_send_context *pContext;
+	struct vnt_tx_fifo_head *pTxBufHead;
 	struct ieee80211_hdr *pMACHeader;
 	struct ethhdr sEthHeader;
 	u8 byPktType, *pbyTxBufferAddr;
@@ -1490,10 +1492,10 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
     }
 
 	pTX_Buffer = (struct vnt_tx_buffer *)&pContext->Data[0];
-    pbyTxBufferAddr = (u8 *)&(pTX_Buffer->adwTxKey[0]);
     cbFrameBodySize = pPacket->cbPayloadLen;
-    pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
-    wTxBufSize = sizeof(STxBufHead);
+	pTxBufHead = &pTX_Buffer->fifo_head;
+	pbyTxBufferAddr = (u8 *)&pTxBufHead->adwTxKey[0];
+	wTxBufSize = sizeof(struct vnt_tx_fifo_head);
 
     if (pDevice->byBBType == BB_TYPE_11A) {
         wCurrentRate = RATE_6M;
@@ -1725,10 +1727,14 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
-        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+	s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pMACHeader->addr1[0], (u16)cbFrameSize,
+			pTxBufHead->wFIFOCtl);
     }
     else {
-        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+	s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pMACHeader->addr3[0], (u16)cbFrameSize,
+			pTxBufHead->wFIFOCtl);
     }
 
     PIPEnsSendBulkOut(pDevice,pContext);
@@ -1823,6 +1829,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	struct vnt_tx_buffer *pTX_Buffer;
+	struct vnt_tx_fifo_head *pTxBufHead;
 	u8 byPktType;
 	u8 *pbyTxBufferAddr;
 	void *rts_cts = NULL;
@@ -1831,7 +1838,6 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 	struct ieee80211_hdr *pMACHeader;
 	u32 cbHeaderSize, cbFrameBodySize;
 	int bNeedACK, bIsPSPOLL = false;
-	PSTxBufHead pTxBufHead;
 	u32 cbFrameSize;
 	u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbFCSlen = 4;
 	u32 uPadding = 0;
@@ -1872,9 +1878,9 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
     }
 
 	pTX_Buffer = (struct vnt_tx_buffer *)&pContext->Data[0];
-    pbyTxBufferAddr = (u8 *)(&pTX_Buffer->adwTxKey[0]);
-    pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
-    wTxBufSize = sizeof(STxBufHead);
+	pTxBufHead = &pTX_Buffer->fifo_head;
+	pbyTxBufferAddr = (u8 *)&pTxBufHead->adwTxKey[0];
+	wTxBufSize = sizeof(struct vnt_tx_fifo_head);
 
     if (pDevice->byBBType == BB_TYPE_11A) {
         wCurrentRate = RATE_6M;
@@ -2181,10 +2187,14 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
-        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+	s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pMACHeader->addr1[0], (u16)cbFrameSize,
+			pTxBufHead->wFIFOCtl);
     }
     else {
-        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+	s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pMACHeader->addr3[0], (u16)cbFrameSize,
+			pTxBufHead->wFIFOCtl);
     }
     PIPEnsSendBulkOut(pDevice,pContext);
     return ;
@@ -2566,7 +2576,10 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
     pContext->Type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
-    s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl);
+    s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pContext->sEthHeader.h_dest[0],
+			(u16)(BytesToWrite-uHeaderLen),
+			pTX_Buffer->fifo_head.wFIFOCtl);
 
     status = PIPEnsSendBulkOut(pDevice,pContext);
 
@@ -2717,7 +2730,10 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen,
     pContext->Type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
-    s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl);
+    s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+		&pContext->sEthHeader.h_dest[0],
+		(u16)(BytesToWrite - uHeaderLen),
+		pTX_Buffer->fifo_head.wFIFOCtl);
 
     status = PIPEnsSendBulkOut(pDevice,pContext);
 
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index 4bbee1c..137e62d 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -180,10 +180,7 @@ union vnt_tx_data_head {
 	struct vnt_cts_fb cts_g_fb;
 };
 
-struct vnt_tx_buffer {
-	u8 byType;
-	u8 byPKTNO;
-	u16 wTxByteCount;
+struct vnt_tx_fifo_head {
 	u32 adwTxKey[4];
 	u16 wFIFOCtl;
 	u16 wTimeStamp;
@@ -191,6 +188,13 @@ struct vnt_tx_buffer {
 	u16 wReserved;
 } __packed;
 
+struct vnt_tx_buffer {
+	u8 byType;
+	u8 byPKTNO;
+	u16 wTxByteCount;
+	struct vnt_tx_fifo_head fifo_head;
+} __packed;
+
 struct vnt_beacon_buffer {
 	u8 byType;
 	u8 byPKTNO;
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 3.12] mwifiex: queue main work from main process when bailing on races
From: Daniel Mack @ 2013-09-17 18:25 UTC (permalink / raw)
  To: linux-wireless
  Cc: s.neumann, afenkart, bzhao, linville, johannes.berg, Daniel Mack,
	stable

Queue main_work in case mwifiex_main_process() bails due to an already
processed transaction. This is particularly necessary because
mwifiex_main_process() is called from both the SDIO interrupt handler
and the workqueue. In case an interrupt occurs while the main process
is currently executed from the workqueue, the interrupt is lost,
resulting in a command timeout and consequently a card reset.

I'm marking this for stable kernel in version 3.7+, because on our
platform, the issue appears since 601216e12c ("mwifiex: process RX
packets in SDIO IRQ thread directly") went in.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Reported-by: Sven Neumann <s.neumann@raumfeld.com>
Reported-by: Andreas Fenkart <afenkart@gmail.com>
Cc: Bing Zhao <bzhao@marvell.com>
Cc: <stable@vger.kernel.org> [v3.7+]
---
 drivers/net/wireless/mwifiex/main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index ff4ed96..0700bc2 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -235,6 +235,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
 	/* Check if already processing */
 	if (adapter->mwifiex_processing) {
 		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+		queue_work(adapter->workqueue, &adapter->main_work);
 		goto exit_main_proc;
 	} else {
 		adapter->mwifiex_processing = true;
-- 
1.8.3.1


^ permalink raw reply related

* RE: [PATCH 1/1] mwifiex: queue main work from main process when bailing on races
From: Bing Zhao @ 2013-09-17 18:19 UTC (permalink / raw)
  To: Daniel Mack
  Cc: linux-wireless@vger.kernel.org, s.neumann@raumfeld.com,
	afenkart@gmail.com, linville@tuxdriver.com,
	johannes.berg@intel.com, stable@vger.kernel.org
In-Reply-To: <52378D81.3070707@gmail.com>

Hi Daniel,

> >>  	/* Check if already processing */
> >>  	if (adapter->mwifiex_processing) {
> >>  		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
> >> +		queue_work(adapter->workqueue, &adapter->main_work);
> >
> > This is specific to SDIO interface,
> 
> Is it really? By checking adapter->mwifiex_processing, the driver seems
> to expect mwifiex_main_process() to be called from multiple execution
> paths, and in that case, we will always loose one execution cycle in

You are right. I overlooked it.

> case we bail early. I actually wonder why this didn't hit us earlier,
> but I might miss a detail.

I guess, in your case, the interrupt comes in at line 363 where you have passed the int_status or RX_RCVD checking but the mwifiex_processing flag is still true.

 361         if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter))
 362                 goto process_start;
 363
 364         spin_lock_irqsave(&adapter->main_proc_lock, flags);
 365         adapter->mwifiex_processing = false;
 366         spin_unlock_irqrestore(&adapter->main_proc_lock, flags);

The interrupt thread exits because mwifiex_processing is true.
Therefore the mwifiex_main_process misses this interrupt.

> 
> OTOH, the worst thing that can happen if the function is executed too
> often is that it exits early and does nothing.
> 
> > +               if (adapter->iface_type == MWIFIEX_SDIO)
> > +                       queue_work(adapter->workqueue, &adapter->main_work);
> 
> I can of course add this, but I don't fully understand why the driver
> takes care of concurrently running executing paths and then just bails
> silently in case a race is detected.

No. Your original patch is fine.
Could you resend it as [PATCH 3.12]? I will ACK in that thread.

Thanks,
Bing




^ permalink raw reply

* [PATCH v2 11/11] wlcore: always register dummy hardirq
From: Eliad Peller @ 2013-09-17 15:41 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1379432490-22157-1-git-send-email-eliad@wizery.com>

From: Arik Nemtsov <arik@wizery.com>

This keeps the kernel happy when using edge-irqs and requesting a
threaded irq.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/ti/wlcore/main.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 4b52e5a..1f556b6 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5994,6 +5994,11 @@ static const struct wiphy_wowlan_support wlcore_wowlan_support = {
 };
 #endif
 
+static irqreturn_t wlcore_hardirq(int irq, void *cookie)
+{
+	return IRQ_WAKE_THREAD;
+}
+
 static void wlcore_nvs_cb(const struct firmware *fw, void *context)
 {
 	struct wl1271 *wl = context;
@@ -6002,6 +6007,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
 	struct wl12xx_platform_data *pdata = pdev_data->pdata;
 	unsigned long irqflags;
 	int ret;
+	irq_handler_t hardirq_fn = NULL;
 
 	if (fw) {
 		wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);
@@ -6030,12 +6036,14 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
 	wl->platform_quirks = pdata->platform_quirks;
 	wl->if_ops = pdev_data->if_ops;
 
-	if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
+	if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) {
 		irqflags = IRQF_TRIGGER_RISING;
-	else
+		hardirq_fn = wlcore_hardirq;
+	} else {
 		irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
+	}
 
-	ret = request_threaded_irq(wl->irq, NULL, wlcore_irq,
+	ret = request_threaded_irq(wl->irq, hardirq_fn, wlcore_irq,
 				   irqflags, pdev->name, wl);
 	if (ret < 0) {
 		wl1271_error("request_irq() failed: %d", ret);
-- 
1.8.3.rc1.35.g9b79519


^ permalink raw reply related

* [PATCH v2 10/11] wl18xx: print new RDL versions during boot
From: Eliad Peller @ 2013-09-17 15:41 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1379432490-22157-1-git-send-email-eliad@wizery.com>

From: Victor Goldenshtein <victorg@ti.com>

Extract and print info for the new RDL 5, 6, 7 and 8.
Replace const struct with function which translates
the RDL number to string.

Signed-off-by: Victor Goldenshtein <victorg@ti.com>
Signed-off-by: Barak Bercovitz <barak@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v1->v2: split UNTRIMMED/UNKNOWN

 drivers/net/wireless/ti/wl18xx/main.c | 42 ++++++++++++++++++++++++++++++-----
 drivers/net/wireless/ti/wl18xx/reg.h  | 20 ++++++++---------
 2 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index b47eb62..d0daca1 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1228,16 +1228,48 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
 	}
 }
 
+static const char *wl18xx_rdl_name(enum wl18xx_rdl_num rdl_num)
+{
+	switch (rdl_num) {
+	case RDL_1_HP:
+		return "183xH";
+	case RDL_2_SP:
+		return "183x or 180x";
+	case RDL_3_HP:
+		return "187xH";
+	case RDL_4_SP:
+		return "187x";
+	case RDL_5_SP:
+		return "RDL11 - Not Supported";
+	case RDL_6_SP:
+		return "180xD";
+	case RDL_7_SP:
+		return "RDL13 - Not Supported (1893Q)";
+	case RDL_8_SP:
+		return "18xxQ";
+	case RDL_NONE:
+		return "UNTRIMMED";
+	default:
+		return "UNKNOWN";
+	}
+}
+
 static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
 {
 	u32 fuse;
-	s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0;
+	s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0, package_type = 0;
 	int ret;
 
 	ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
 	if (ret < 0)
 		goto out;
 
+	ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse);
+	if (ret < 0)
+		goto out;
+
+	package_type = (fuse >> WL18XX_PACKAGE_TYPE_OFFSET) & 1;
+
 	ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse);
 	if (ret < 0)
 		goto out;
@@ -1245,7 +1277,7 @@ static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
 	pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
 	rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET;
 
-	if (rom <= 0xE)
+	if ((rom <= 0xE) && (package_type == WL18XX_PACKAGE_TYPE_WSP))
 		metal = (fuse & WL18XX_METAL_VER_MASK) >>
 			WL18XX_METAL_VER_OFFSET;
 	else
@@ -1257,11 +1289,9 @@ static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
 		goto out;
 
 	rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET;
-	if (rdl_ver > RDL_MAX)
-		rdl_ver = RDL_NONE;
 
-	wl1271_info("wl18xx HW: RDL %d, %s, PG %x.%x (ROM %x)",
-		    rdl_ver, rdl_names[rdl_ver], pg_ver, metal, rom);
+	wl1271_info("wl18xx HW: %s, PG %d.%d (ROM 0x%x)",
+		    wl18xx_rdl_name(rdl_ver), pg_ver, metal, rom);
 
 	if (ver)
 		*ver = pg_ver;
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 88de3f2..a433a75 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -147,13 +147,16 @@
 #define WL18XX_REG_FUSE_DATA_1_3	0xA0260C
 #define WL18XX_PG_VER_MASK		0x70
 #define WL18XX_PG_VER_OFFSET		4
-#define WL18XX_ROM_VER_MASK		0x3
-#define WL18XX_ROM_VER_OFFSET		0
+#define WL18XX_ROM_VER_MASK		0x3e00
+#define WL18XX_ROM_VER_OFFSET		9
 #define WL18XX_METAL_VER_MASK		0xC
 #define WL18XX_METAL_VER_OFFSET		2
 #define WL18XX_NEW_METAL_VER_MASK	0x180
 #define WL18XX_NEW_METAL_VER_OFFSET	7
 
+#define WL18XX_PACKAGE_TYPE_OFFSET	13
+#define WL18XX_PACKAGE_TYPE_WSP		0
+
 #define WL18XX_REG_FUSE_DATA_2_3	0xA02614
 #define WL18XX_RDL_VER_MASK		0x1f00
 #define WL18XX_RDL_VER_OFFSET		8
@@ -214,24 +217,21 @@ enum {
 	NUM_BOARD_TYPES,
 };
 
-enum {
+enum wl18xx_rdl_num {
 	RDL_NONE	= 0,
 	RDL_1_HP	= 1,
 	RDL_2_SP	= 2,
 	RDL_3_HP	= 3,
 	RDL_4_SP	= 4,
+	RDL_5_SP	= 0x11,
+	RDL_6_SP	= 0x12,
+	RDL_7_SP	= 0x13,
+	RDL_8_SP	= 0x14,
 
 	_RDL_LAST,
 	RDL_MAX = _RDL_LAST - 1,
 };
 
-static const char * const rdl_names[] = {
-	[RDL_NONE]	= "",
-	[RDL_1_HP]	= "1853 SISO",
-	[RDL_2_SP]	= "1857 MIMO",
-	[RDL_3_HP]	= "1893 SISO",
-	[RDL_4_SP]	= "1897 MIMO",
-};
 
 /* FPGA_SPARE_1 register - used to change the PHY ATPG clock at boot time */
 #define WL18XX_PHY_FPGA_SPARE_1		0x8093CA40
-- 
1.8.3.rc1.35.g9b79519


^ permalink raw reply related

* [PATCH v2 09/11] wl18xx: fix boot process in high temperature environment
From: Eliad Peller @ 2013-09-17 15:41 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1379432490-22157-1-git-send-email-eliad@wizery.com>

From: Victor Goldenshtein <victorg@ti.com>

In addition to existing WCS PLL configuration add and enable
also the coex PLL during init phase. This fixes boot failures
due to silicon latchup in high temperature environment (>85c).

Signed-off-by: Victor Goldenshtein <victorg@ti.com>
Signed-off-by: Nadim Zubidat <nadimz@ti.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/ti/wl18xx/main.c | 53 +++++++++++++++++++++++++++++++++++
 drivers/net/wireless/ti/wl18xx/reg.h  | 13 +++++++++
 2 files changed, 66 insertions(+)

diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 7aa0eb8..b47eb62 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -623,6 +623,18 @@ static const int wl18xx_rtable[REG_TABLE_LEN] = {
 	[REG_RAW_FW_STATUS_ADDR]	= WL18XX_FW_STATUS_ADDR,
 };
 
+static const struct wl18xx_clk_cfg wl18xx_clk_table_coex[NUM_CLOCK_CONFIGS] = {
+	[CLOCK_CONFIG_16_2_M]	= { 8,  121, 0, 0, false },
+	[CLOCK_CONFIG_16_368_M]	= { 8,  120, 0, 0, false },
+	[CLOCK_CONFIG_16_8_M]	= { 8,  117, 0, 0, false },
+	[CLOCK_CONFIG_19_2_M]	= { 10, 128, 0, 0, false },
+	[CLOCK_CONFIG_26_M]	= { 11, 104, 0, 0, false },
+	[CLOCK_CONFIG_32_736_M]	= { 8,  120, 0, 0, false },
+	[CLOCK_CONFIG_33_6_M]	= { 8,  117, 0, 0, false },
+	[CLOCK_CONFIG_38_468_M]	= { 10, 128, 0, 0, false },
+	[CLOCK_CONFIG_52_M]	= { 11, 104, 0, 0, false },
+};
+
 static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = {
 	[CLOCK_CONFIG_16_2_M]	= { 7,  104,  801, 4,  true },
 	[CLOCK_CONFIG_16_368_M]	= { 9,  132, 3751, 4,  true },
@@ -704,6 +716,23 @@ static int wl18xx_set_clk(struct wl1271 *wl)
 		     wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q,
 		     wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit");
 
+	/* coex PLL configuration */
+	ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_N,
+				   wl18xx_clk_table_coex[clk_freq].n);
+	if (ret < 0)
+		goto out;
+
+	ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_M,
+				   wl18xx_clk_table_coex[clk_freq].m);
+	if (ret < 0)
+		goto out;
+
+	/* bypass the swallowing logic */
+	ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_SWALLOW_EN,
+				   PLLSH_COEX_PLL_SWALLOW_EN_VAL1);
+	if (ret < 0)
+		goto out;
+
 	ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N,
 				   wl18xx_clk_table[clk_freq].n);
 	if (ret < 0)
@@ -745,6 +774,30 @@ static int wl18xx_set_clk(struct wl1271 *wl)
 					   PLLSH_WCS_PLL_SWALLOW_EN_VAL2);
 	}
 
+	/* choose WCS PLL */
+	ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_SEL,
+				   PLLSH_WL_PLL_SEL_WCS_PLL);
+	if (ret < 0)
+		goto out;
+
+	/* enable both PLLs */
+	ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_EN, PLLSH_WL_PLL_EN_VAL1);
+	if (ret < 0)
+		goto out;
+
+	udelay(1000);
+
+	/* disable coex PLL */
+	ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_EN, PLLSH_WL_PLL_EN_VAL2);
+	if (ret < 0)
+		goto out;
+
+	/* reset the swallowing logic */
+	ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_SWALLOW_EN,
+				   PLLSH_COEX_PLL_SWALLOW_EN_VAL2);
+	if (ret < 0)
+		goto out;
+
 out:
 	return ret;
 }
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 05dd8ba..88de3f2 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -114,6 +114,11 @@
 #define PLATFORM_DETECTION		0xA0E3E0
 #define OCS_EN				0xA02080
 #define PRIMARY_CLK_DETECT		0xA020A6
+#define PLLSH_COEX_PLL_N		0xA02384
+#define PLLSH_COEX_PLL_M		0xA02382
+#define PLLSH_COEX_PLL_SWALLOW_EN	0xA0238E
+#define PLLSH_WL_PLL_SEL		0xA02398
+
 #define PLLSH_WCS_PLL_N			0xA02362
 #define PLLSH_WCS_PLL_M			0xA02360
 #define PLLSH_WCS_PLL_Q_FACTOR_CFG_1	0xA02364
@@ -128,9 +133,17 @@
 #define PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK	0xFFFF
 #define PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK	0x000F
 
+#define PLLSH_WL_PLL_EN_VAL1		0x7
+#define PLLSH_WL_PLL_EN_VAL2		0x2
+#define PLLSH_COEX_PLL_SWALLOW_EN_VAL1	0x2
+#define PLLSH_COEX_PLL_SWALLOW_EN_VAL2	0x11
+
 #define PLLSH_WCS_PLL_SWALLOW_EN_VAL1	0x1
 #define PLLSH_WCS_PLL_SWALLOW_EN_VAL2	0x12
 
+#define PLLSH_WL_PLL_SEL_WCS_PLL	0x0
+#define PLLSH_WL_PLL_SEL_COEX_PLL	0x1
+
 #define WL18XX_REG_FUSE_DATA_1_3	0xA0260C
 #define WL18XX_PG_VER_MASK		0x70
 #define WL18XX_PG_VER_OFFSET		4
-- 
1.8.3.rc1.35.g9b79519


^ permalink raw reply related

* [PATCH v2 08/11] wlcore: clarify and fix regulatory domain bit translation
From: Eliad Peller @ 2013-09-17 15:41 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1379432490-22157-1-git-send-email-eliad@wizery.com>

Channels 52-64 were mapped incorrectly.

Refactor and document wlcore_get_reg_conf_ch_idx() in
order to make it clear what's going on there.

While on it, fix the return value check to consider
0 as a valid return value as well (indicates channel 1).

Reported-by: Yaniv Machani <yanivma@ti.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Ido Reis <idor@ti.com>
Signed-off-by: Victor Goldenshtein <victorg@ti.com>
---
 drivers/net/wireless/ti/wlcore/cmd.c | 52 +++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index e3ae425..9e5416f8 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1607,33 +1607,43 @@ out:
 
 static int wlcore_get_reg_conf_ch_idx(enum ieee80211_band band, u16 ch)
 {
-	int idx = -1;
-
+	/*
+	 * map the given band/channel to the respective predefined
+	 * bit expected by the fw
+	 */
 	switch (band) {
-	case IEEE80211_BAND_5GHZ:
-		if (ch >= 8 && ch <= 16)
-			idx = ((ch-8)/4 + 18);
-		else if (ch >= 34 && ch <= 64)
-			idx = ((ch-34)/2 + 3 + 18);
-		else if (ch >= 100 && ch <= 140)
-			idx = ((ch-100)/4 + 15 + 18);
-		else if (ch >= 149 && ch <= 165)
-			idx = ((ch-149)/4 + 26 + 18);
-		else
-			idx = -1;
-		break;
 	case IEEE80211_BAND_2GHZ:
+		/* channels 1..14 are mapped to 0..13 */
 		if (ch >= 1 && ch <= 14)
-			idx = ch - 1;
-		else
-			idx = -1;
+			return ch - 1;
+		break;
+	case IEEE80211_BAND_5GHZ:
+		switch (ch) {
+		case 8 ... 16:
+			/* channels 8,12,16 are mapped to 18,19,20 */
+			return 18 + (ch-8)/4;
+		case 34 ... 48:
+			/* channels 34,36..48 are mapped to 21..28 */
+			return 21 + (ch-34)/2;
+		case 52 ... 64:
+			/* channels 52,56..64 are mapped to 29..32 */
+			return 29 + (ch-52)/4;
+		case 100 ... 140:
+			/* channels 100,104..140 are mapped to 33..43 */
+			return 33 + (ch-100)/4;
+		case 149 ... 165:
+			/* channels 149,153..165 are mapped to 44..48 */
+			return 44 + (ch-149)/4;
+		default:
+			break;
+		}
 		break;
 	default:
-		wl1271_error("get reg conf ch idx - unknown band: %d",
-			     (int)band);
+		break;
 	}
 
-	return idx;
+	wl1271_error("%s: unknown band/channel: %d/%d", __func__, band, ch);
+	return -1;
 }
 
 void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel,
@@ -1646,7 +1656,7 @@ void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel,
 
 	ch_bit_idx = wlcore_get_reg_conf_ch_idx(band, channel);
 
-	if (ch_bit_idx > 0 && ch_bit_idx <= WL1271_MAX_CHANNELS)
+	if (ch_bit_idx >= 0 && ch_bit_idx <= WL1271_MAX_CHANNELS)
 		set_bit(ch_bit_idx, (long *)wl->reg_ch_conf_pending);
 }
 
-- 
1.8.3.rc1.35.g9b79519


^ permalink raw reply related

* [PATCH v2 07/11] wlcore: remove unsupported channels
From: Eliad Peller @ 2013-09-17 15:41 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1379432490-22157-1-git-send-email-eliad@wizery.com>

The fw doesn't support channels 7,9,11 in 5ghz band,
so don't advertise supporting them.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/ti/wlcore/main.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index d952593..4b52e5a 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5414,10 +5414,7 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = {
 
 /* 5 GHz band channels for WL1273 */
 static struct ieee80211_channel wl1271_channels_5ghz[] = {
-	{ .hw_value = 7, .center_freq = 5035, .max_power = WLCORE_MAX_TXPWR },
 	{ .hw_value = 8, .center_freq = 5040, .max_power = WLCORE_MAX_TXPWR },
-	{ .hw_value = 9, .center_freq = 5045, .max_power = WLCORE_MAX_TXPWR },
-	{ .hw_value = 11, .center_freq = 5055, .max_power = WLCORE_MAX_TXPWR },
 	{ .hw_value = 12, .center_freq = 5060, .max_power = WLCORE_MAX_TXPWR },
 	{ .hw_value = 16, .center_freq = 5080, .max_power = WLCORE_MAX_TXPWR },
 	{ .hw_value = 34, .center_freq = 5170, .max_power = WLCORE_MAX_TXPWR },
-- 
1.8.3.rc1.35.g9b79519


^ permalink raw reply related

* [PATCH v2 06/11] wlcore: fix unsafe dereference of the wlvif
From: Eliad Peller @ 2013-09-17 15:41 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1379432490-22157-1-git-send-email-eliad@wizery.com>

From: Victor Goldenshtein <victorg@ti.com>

wlvif could be passed as NULL from the wlcore_tx_work_locked()
to the wl1271_prepare_tx_frame() and to wl1271_skb_queue_head()
functions. This may lead to a Kernel panic, fix this by
validating that wlvif != NULL.

Signed-off-by: Victor Goldenshtein <victorg@ti.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/ti/wlcore/tx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 03249da..87cd707 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -401,7 +401,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 		is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) ||
 			 (cipher == WLAN_CIPHER_SUITE_WEP104);
 
-		if (WARN_ON(is_wep && wlvif->default_key != idx)) {
+		if (WARN_ON(is_wep && wlvif && wlvif->default_key != idx)) {
 			ret = wl1271_set_default_wep_key(wl, wlvif, idx);
 			if (ret < 0)
 				return ret;
-- 
1.8.3.rc1.35.g9b79519


^ permalink raw reply related

* [PATCH v2 05/11] wlcore: cleanup scan debug prints
From: Eliad Peller @ 2013-09-17 15:41 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1379432490-22157-1-git-send-email-eliad@wizery.com>

From: Victor Goldenshtein <victorg@ti.com>

Remove scan debug dumps which are rarely used.
Make scan debug prints more clear and short.

Signed-off-by: Victor Goldenshtein <victorg@ti.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v1->v2: fix some formatting issues

 drivers/net/wireless/ti/wlcore/cmd.c  |  6 +++---
 drivers/net/wireless/ti/wlcore/scan.c | 27 +++++++++++++--------------
 2 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index c9e0607..e3ae425 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1126,6 +1126,8 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 	u16 template_id_2_4 = wl->scan_templ_id_2_4;
 	u16 template_id_5 = wl->scan_templ_id_5;
 
+	wl1271_debug(DEBUG_SCAN, "build probe request band %d", band);
+
 	skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
 				     ie_len);
 	if (!skb) {
@@ -1135,8 +1137,6 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 	if (ie_len)
 		memcpy(skb_put(skb, ie_len), ie, ie_len);
 
-	wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
-
 	if (sched_scan &&
 	    (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) {
 		template_id_2_4 = wl->sched_scan_templ_id_2_4;
@@ -1172,7 +1172,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
 	if (!skb)
 		goto out;
 
-	wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len);
+	wl1271_debug(DEBUG_SCAN, "set ap probe request template");
 
 	rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]);
 	if (wlvif->band == IEEE80211_BAND_2GHZ)
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c
index f407101..13e743d 100644
--- a/drivers/net/wireless/ti/wlcore/scan.c
+++ b/drivers/net/wireless/ti/wlcore/scan.c
@@ -174,17 +174,7 @@ wlcore_scan_get_channels(struct wl1271 *wl,
 		    /* if radar is set, we ignore the passive flag */
 		    (radar ||
 		     !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) {
-			wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
-				     req_channels[i]->band,
-				     req_channels[i]->center_freq);
-			wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X",
-				     req_channels[i]->hw_value,
-				     req_channels[i]->flags);
-			wl1271_debug(DEBUG_SCAN, "max_power %d",
-				     req_channels[i]->max_power);
-			wl1271_debug(DEBUG_SCAN, "min_dwell_time %d max dwell time %d",
-				     min_dwell_time_active,
-				     max_dwell_time_active);
+
 
 			if (flags & IEEE80211_CHAN_RADAR) {
 				channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS;
@@ -222,6 +212,17 @@ wlcore_scan_get_channels(struct wl1271 *wl,
 					     *n_pactive_ch);
 			}
 
+			wl1271_debug(DEBUG_SCAN, "freq %d, ch. %d, flags 0x%x, power %d, min/max_dwell %d/%d%s%s",
+				     req_channels[i]->center_freq,
+				     req_channels[i]->hw_value,
+				     req_channels[i]->flags,
+				     req_channels[i]->max_power,
+				     min_dwell_time_active,
+				     max_dwell_time_active,
+				     flags & IEEE80211_CHAN_RADAR ?
+					", DFS" : "",
+				     flags & IEEE80211_CHAN_PASSIVE_SCAN ?
+					", PASSIVE" : "");
 			j++;
 		}
 	}
@@ -364,7 +365,7 @@ wlcore_scan_sched_scan_ssid_list(struct wl1271 *wl,
 	struct cfg80211_ssid *ssids = req->ssids;
 	int ret = 0, type, i, j, n_match_ssids = 0;
 
-	wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");
+	wl1271_debug((DEBUG_CMD | DEBUG_SCAN), "cmd sched scan ssid list");
 
 	/* count the match sets that contain SSIDs */
 	for (i = 0; i < req->n_match_sets; i++)
@@ -442,8 +443,6 @@ wlcore_scan_sched_scan_ssid_list(struct wl1271 *wl,
 		}
 	}
 
-	wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
-
 	ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd,
 			      sizeof(*cmd), 0);
 	if (ret < 0) {
-- 
1.8.3.rc1.35.g9b79519


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox