Linux wireless drivers development
 help / color / mirror / Atom feed
* [RFC v4 19/21] ath10k: add QCA9377 usb hw_param item
From: Erik Stromdahl @ 2017-02-21 16:15 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1487693741-10042-1-git-send-email-erik.stromdahl@gmail.com>

Hardware parameters for QCA9377 usb devices.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/core.c | 23 +++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h   |  1 +
 2 files changed, 24 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 2e2d3d3..96b278b 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -288,6 +288,29 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 		.decap_align_bytes = 4,
 	},
 	{
+		.id = QCA9377_HW_1_1_DEV_VERSION,
+		.dev_id = QCA9377_1_0_DEVICE_ID,
+		.name = "qca9377 hw1.1 usb",
+		.patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
+		.uart_pin = 6,
+		.otp_exe_param = 0,
+		.channel_counters_freq_hz = 88000,
+		.max_probe_resp_desc_thres = 0,
+		.cal_data_len = 8124,
+		.fw = {
+			.dir = QCA9377_HW_1_0_FW_DIR,
+			.board = QCA9377_HW_1_0_BOARD_DATA_FILE_USB,
+			.board_size = QCA9377_BOARD_DATA_SZ,
+			.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
+		},
+		.hw_ops = &qca988x_ops,
+		.decap_align_bytes = 4,
+		.max_num_peers = TARGET_QCA9377_HL_NUM_PEERS,
+		.is_high_latency = true,
+		.bus = ATH10K_BUS_USB,
+		.start_once = true,
+	},
+	{
 		.id = QCA4019_HW_1_0_DEV_VERSION,
 		.dev_id = 0,
 		.name = "qca4019 hw1.0",
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index cf88aba..5408ebc 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -127,6 +127,7 @@ enum qca9377_chip_id_rev {
 /* QCA9377 1.0 definitions */
 #define QCA9377_HW_1_0_FW_DIR          ATH10K_FW_DIR "/QCA9377/hw1.0"
 #define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
+#define QCA9377_HW_1_0_BOARD_DATA_FILE_USB "board-usb.bin"
 #define QCA9377_HW_1_0_PATCH_LOAD_ADDR	0x1234
 
 /* QCA4019 1.0 definitions */
-- 
2.7.4

^ permalink raw reply related

* [RFC v4 20/21] ath10k: add QCA9377 sdio hw_param item
From: Erik Stromdahl @ 2017-02-21 16:15 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1487693741-10042-1-git-send-email-erik.stromdahl@gmail.com>

Hardware parameters for QCA9377 sdio devices.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/core.c | 25 +++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h   |  1 +
 2 files changed, 26 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 96b278b..a884e34 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -311,6 +311,31 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 		.start_once = true,
 	},
 	{
+		.id = QCA9377_HW_1_1_DEV_VERSION,
+		.dev_id = QCA9377_1_0_DEVICE_ID,
+		.name = "qca9377 hw1.1 sdio",
+		.patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
+		.uart_pin = 19,
+		.otp_exe_param = 0,
+		.channel_counters_freq_hz = 88000,
+		.max_probe_resp_desc_thres = 0,
+		.cal_data_len = 8124,
+		.fw = {
+			.dir = QCA9377_HW_1_0_FW_DIR,
+			.board = QCA9377_HW_1_0_BOARD_DATA_FILE_SDIO,
+			.board_size = QCA9377_BOARD_DATA_SZ,
+			.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
+		},
+		.hw_ops = &qca6174_ops,
+		.hw_clk = qca6174_clk,
+		.target_cpu_freq = 176000000,
+		.decap_align_bytes = 4,
+		.max_num_peers = TARGET_QCA9377_HL_NUM_PEERS,
+		.is_high_latency = true,
+		.bus = ATH10K_BUS_SDIO,
+		.start_once = true,
+	},
+	{
 		.id = QCA4019_HW_1_0_DEV_VERSION,
 		.dev_id = 0,
 		.name = "qca4019 hw1.0",
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 5408ebc..d76b206 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -128,6 +128,7 @@ enum qca9377_chip_id_rev {
 #define QCA9377_HW_1_0_FW_DIR          ATH10K_FW_DIR "/QCA9377/hw1.0"
 #define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
 #define QCA9377_HW_1_0_BOARD_DATA_FILE_USB "board-usb.bin"
+#define QCA9377_HW_1_0_BOARD_DATA_FILE_SDIO "board-sdio.bin"
 #define QCA9377_HW_1_0_PATCH_LOAD_ADDR	0x1234
 
 /* QCA4019 1.0 definitions */
-- 
2.7.4

^ permalink raw reply related

* [RFC v4 11/21] ath10k: usb support
From: Erik Stromdahl @ 2017-02-21 16:15 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1487693741-10042-1-git-send-email-erik.stromdahl@gmail.com>

usb HIF implementation

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/Kconfig  |    6 +
 drivers/net/wireless/ath/ath10k/Makefile |    3 +
 drivers/net/wireless/ath/ath10k/usb.c    | 1125 ++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/usb.h    |  128 ++++
 4 files changed, 1262 insertions(+)
 create mode 100644 drivers/net/wireless/ath/ath10k/usb.c
 create mode 100644 drivers/net/wireless/ath/ath10k/usb.h

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index f2f6321..9a2f8cd 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -28,6 +28,12 @@ config ATH10K_SDIO
 	---help---
 	  This module adds support for SDIO/MMC bus
 
+config ATH10K_USB
+	tristate "Atheros ath10k USB support (EXPERIMENTAL)"
+	depends on ATH10K && USB
+	---help---
+	  This module adds support for USB bus
+
 config ATH10K_DEBUG
 	bool "Atheros ath10k debugging"
 	depends on ATH10K
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index b0b19a7..899b9b7 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -30,5 +30,8 @@ ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o
 obj-$(CONFIG_ATH10K_SDIO) += ath10k_sdio.o
 ath10k_sdio-y += sdio.o
 
+obj-$(CONFIG_ATH10K_USB) += ath10k_usb.o
+ath10k_usb-y += usb.o
+
 # for tracing framework to find trace.h
 CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c
new file mode 100644
index 0000000..525706c
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/usb.c
@@ -0,0 +1,1125 @@
+/*
+ * Copyright (c) 2007-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
+ * Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "debug.h"
+#include "core.h"
+#include "bmi.h"
+#include "hif.h"
+#include "htc.h"
+#include "usb.h"
+
+static void ath10k_usb_post_recv_transfers(struct ath10k *ar,
+					   struct ath10k_usb_pipe *recv_pipe);
+
+/* inlined helper functions */
+
+static inline enum ath10k_htc_ep_id
+eid_from_htc_hdr(struct ath10k_htc_hdr *htc_hdr)
+{
+	return (enum ath10k_htc_ep_id)htc_hdr->eid;
+}
+
+static inline bool is_trailer_only_msg(struct ath10k_htc_hdr *htc_hdr)
+{
+	bool trailer_only = false;
+	u16 len = __le16_to_cpu(htc_hdr->len);
+
+	if (len == htc_hdr->trailer_len)
+		trailer_only = true;
+
+	return trailer_only;
+}
+
+/* pipe/urb operations */
+static struct ath10k_urb_context *
+ath10k_usb_alloc_urb_from_pipe(struct ath10k_usb_pipe *pipe)
+{
+	struct ath10k_urb_context *urb_context = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
+	if (!list_empty(&pipe->urb_list_head)) {
+		urb_context =
+		    list_first_entry(&pipe->urb_list_head,
+				     struct ath10k_urb_context, link);
+		list_del(&urb_context->link);
+		pipe->urb_cnt--;
+	}
+	spin_unlock_irqrestore(&pipe->ar_usb->cs_lock, flags);
+
+	return urb_context;
+}
+
+static void ath10k_usb_free_urb_to_pipe(struct ath10k_usb_pipe *pipe,
+					struct ath10k_urb_context *urb_context)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
+	pipe->urb_cnt++;
+
+	list_add(&urb_context->link, &pipe->urb_list_head);
+	spin_unlock_irqrestore(&pipe->ar_usb->cs_lock, flags);
+}
+
+static void ath10k_usb_cleanup_recv_urb(struct ath10k_urb_context *urb_context)
+{
+	dev_kfree_skb(urb_context->skb);
+	urb_context->skb = NULL;
+
+	ath10k_usb_free_urb_to_pipe(urb_context->pipe, urb_context);
+}
+
+static void ath10k_usb_free_pipe_resources(struct ath10k *ar,
+					   struct ath10k_usb_pipe *pipe)
+{
+	if (!pipe->ar_usb) {
+		/* nothing allocated for this pipe */
+		return;
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_USB,
+		   "free resources lpipe:%d hpipe:0x%X urbs:%d avail:%d\n",
+		   pipe->logical_pipe_num, pipe->usb_pipe_handle,
+		   pipe->urb_alloc, pipe->urb_cnt);
+
+	if (pipe->urb_alloc != pipe->urb_cnt) {
+		ath10k_dbg(ar, ATH10K_DBG_USB,
+			   "urb leak! lpipe:%d hpipe:0x%X urbs:%d avail:%d\n",
+			   pipe->logical_pipe_num, pipe->usb_pipe_handle,
+			   pipe->urb_alloc, pipe->urb_cnt);
+	}
+
+	while (true) {
+		struct ath10k_urb_context *urb_context;
+
+		urb_context = ath10k_usb_alloc_urb_from_pipe(pipe);
+		if (!urb_context)
+			break;
+		kfree(urb_context);
+	}
+}
+
+static void ath10k_usb_cleanup_pipe_resources(struct ath10k *ar)
+{
+	int i;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+
+	for (i = 0; i < ATH10K_USB_PIPE_MAX; i++)
+		ath10k_usb_free_pipe_resources(ar, &ar_usb->pipes[i]);
+}
+
+/* hif usb rx/tx completion functions */
+
+static void ath10k_usb_recv_complete(struct urb *urb)
+{
+	struct ath10k_urb_context *urb_context = urb->context;
+	struct ath10k_usb_pipe *pipe = urb_context->pipe;
+	struct ath10k *ar = pipe->ar_usb->ar;
+	struct sk_buff *skb = NULL;
+	int status = 0;
+
+	ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
+		   "%s: recv pipe: %d, stat:%d, len:%d urb:0x%p\n", __func__,
+		   pipe->logical_pipe_num, urb->status, urb->actual_length,
+		   urb);
+
+	if (urb->status != 0) {
+		status = -EIO;
+		switch (urb->status) {
+		case -ECONNRESET:
+		case -ENOENT:
+		case -ESHUTDOWN:
+			/* no need to spew these errors when device
+			 * removed or urb killed due to driver shutdown
+			 */
+			status = -ECANCELED;
+			break;
+		default:
+			ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
+				   "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n",
+				   __func__, pipe->logical_pipe_num,
+				   pipe->ep_address, urb->status);
+			break;
+		}
+		goto cleanup_recv_urb;
+	}
+
+	if (urb->actual_length == 0)
+		goto cleanup_recv_urb;
+
+	skb = urb_context->skb;
+
+	/* we are going to pass it up */
+	urb_context->skb = NULL;
+	skb_put(skb, urb->actual_length);
+
+	/* note: queue implements a lock */
+	skb_queue_tail(&pipe->io_comp_queue, skb);
+	schedule_work(&pipe->io_complete_work);
+
+cleanup_recv_urb:
+	ath10k_usb_cleanup_recv_urb(urb_context);
+
+	if (status == 0 &&
+	    pipe->urb_cnt >= pipe->urb_cnt_thresh) {
+		/* our free urbs are piling up, post more transfers */
+		ath10k_usb_post_recv_transfers(ar, pipe);
+	}
+}
+
+static void ath10k_usb_transmit_complete(struct urb *urb)
+{
+	struct ath10k_urb_context *urb_context = urb->context;
+	struct ath10k_usb_pipe *pipe = urb_context->pipe;
+	struct ath10k *ar = pipe->ar_usb->ar;
+	struct sk_buff *skb;
+
+	if (urb->status != 0) {
+		ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
+			   "pipe: %d, failed:%d\n",
+			   pipe->logical_pipe_num, urb->status);
+	}
+
+	skb = urb_context->skb;
+	urb_context->skb = NULL;
+	ath10k_usb_free_urb_to_pipe(urb_context->pipe, urb_context);
+
+	/* note: queue implements a lock */
+	skb_queue_tail(&pipe->io_comp_queue, skb);
+	schedule_work(&pipe->io_complete_work);
+}
+
+/* pipe operations */
+static void ath10k_usb_post_recv_transfers(struct ath10k *ar,
+					   struct ath10k_usb_pipe *recv_pipe)
+{
+	struct ath10k_urb_context *urb_context;
+	struct urb *urb;
+	int usb_status;
+
+	while (true) {
+		urb_context = ath10k_usb_alloc_urb_from_pipe(recv_pipe);
+		if (!urb_context)
+			break;
+
+		urb_context->skb = dev_alloc_skb(ATH10K_USB_RX_BUFFER_SIZE);
+		if (!urb_context->skb)
+			goto err;
+
+		urb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!urb)
+			goto err;
+
+		usb_fill_bulk_urb(urb,
+				  recv_pipe->ar_usb->udev,
+				  recv_pipe->usb_pipe_handle,
+				  urb_context->skb->data,
+				  ATH10K_USB_RX_BUFFER_SIZE,
+				  ath10k_usb_recv_complete, urb_context);
+
+		ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
+			   "bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes buf:0x%p\n",
+			   recv_pipe->logical_pipe_num,
+			   recv_pipe->usb_pipe_handle, recv_pipe->ep_address,
+			   ATH10K_USB_RX_BUFFER_SIZE, urb_context->skb);
+
+		usb_anchor_urb(urb, &recv_pipe->urb_submitted);
+		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
+
+		if (usb_status) {
+			ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
+				   "usb bulk recv failed %d\n",
+				   usb_status);
+			usb_unanchor_urb(urb);
+			usb_free_urb(urb);
+			goto err;
+		}
+		usb_free_urb(urb);
+	}
+
+	return;
+
+err:
+	ath10k_usb_cleanup_recv_urb(urb_context);
+}
+
+static void ath10k_usb_flush_all(struct ath10k *ar)
+{
+	int i;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+
+	for (i = 0; i < ATH10K_USB_PIPE_MAX; i++) {
+		if (ar_usb->pipes[i].ar_usb) {
+			usb_kill_anchored_urbs(&ar_usb->pipes[i].urb_submitted);
+			cancel_work_sync(&ar_usb->pipes[i].io_complete_work);
+		}
+	}
+}
+
+static void ath10k_usb_start_recv_pipes(struct ath10k *ar)
+{
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+
+	ar_usb->pipes[ATH10K_USB_PIPE_RX_DATA].urb_cnt_thresh = 1;
+
+	ath10k_usb_post_recv_transfers(ar,
+				       &ar_usb->pipes[ATH10K_USB_PIPE_RX_DATA]);
+}
+
+static void ath10k_usb_tx_complete(struct ath10k *ar, struct sk_buff *skb)
+{
+	struct ath10k_htc_ep *ep;
+	struct ath10k_htc_hdr *htc_hdr;
+
+	htc_hdr = (struct ath10k_htc_hdr *)skb->data;
+	ep = &ar->htc.endpoint[htc_hdr->eid];
+	ath10k_htc_notify_tx_completion(ep, skb);
+	/* The TX complete handler now owns the skb... */
+}
+
+static void ath10k_usb_rx_complete(struct ath10k *ar, struct sk_buff *skb)
+{
+	int ret;
+	struct ath10k_htc_ep *ep;
+	struct ath10k_htc_hdr *htc_hdr;
+	struct ath10k_htc *htc = &ar->htc;
+	u16 payload_len;
+	enum ath10k_htc_ep_id eid;
+
+	htc_hdr = (struct ath10k_htc_hdr *)skb->data;
+	eid = eid_from_htc_hdr(htc_hdr);
+	ep = &ar->htc.endpoint[eid];
+
+	if (ep->service_id == 0) {
+		ath10k_warn(ar, "ep %d is not connected !\n", eid);
+		goto out_free_skb;
+	}
+
+	payload_len = le16_to_cpu(htc_hdr->len);
+	if (!payload_len) {
+		ath10k_warn(ar, "Zero length frame received! Possible fw crash?\n");
+		goto out_free_skb;
+	}
+
+	if (payload_len < htc_hdr->trailer_len) {
+		ath10k_warn(ar, "Malformed frame received! Possible fw crash?\n");
+		goto out_free_skb;
+	}
+
+	if (htc_hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT) {
+		u8 *trailer;
+
+		trailer = skb->data + sizeof(*htc_hdr) + payload_len -
+			  htc_hdr->trailer_len;
+
+		ret = ath10k_htc_process_trailer(htc,
+						 trailer,
+						 htc_hdr->trailer_len,
+						 eid,
+						 NULL,
+						 NULL);
+		if (ret)
+			goto out_free_skb;
+
+		if (is_trailer_only_msg(htc_hdr))
+			goto out_free_skb;
+
+		/* strip off the trailer from the skb since it should not
+		 * be passed on to upper layers
+		 */
+		skb_trim(skb, skb->len - htc_hdr->trailer_len);
+	}
+
+	skb_pull(skb, sizeof(*htc_hdr));
+	ep->ep_ops.ep_rx_complete(ar, skb);
+	/* The RX complete handler now owns the skb... */
+
+	return;
+
+out_free_skb:
+	dev_kfree_skb(skb);
+}
+
+static void ath10k_usb_io_comp_work(struct work_struct *work)
+{
+	struct ath10k_usb_pipe *pipe = container_of(work,
+						    struct ath10k_usb_pipe,
+						    io_complete_work);
+	struct ath10k *ar = pipe->ar_usb->ar;
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&pipe->io_comp_queue))) {
+		if (pipe->flags & ATH10K_USB_PIPE_FLAG_TX)
+			ath10k_usb_tx_complete(ar, skb);
+		else
+			ath10k_usb_rx_complete(ar, skb);
+	}
+}
+
+#define ATH10K_USB_MAX_DIAG_CMD (sizeof(struct ath10k_usb_ctrl_diag_cmd_write))
+#define ATH10K_USB_MAX_DIAG_RESP (sizeof(struct ath10k_usb_ctrl_diag_resp_read))
+
+static void ath10k_usb_destroy(struct ath10k *ar)
+{
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+
+	ath10k_usb_flush_all(ar);
+	ath10k_usb_cleanup_pipe_resources(ar);
+	usb_set_intfdata(ar_usb->interface, NULL);
+
+	kfree(ar_usb->diag_cmd_buffer);
+	kfree(ar_usb->diag_resp_buffer);
+}
+
+static int ath10k_usb_hif_start(struct ath10k *ar)
+{
+	int i;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+
+	ath10k_usb_start_recv_pipes(ar);
+
+	/* set the TX resource avail threshold for each TX pipe */
+	for (i = ATH10K_USB_PIPE_TX_CTRL;
+	     i <= ATH10K_USB_PIPE_TX_DATA_HP; i++) {
+		ar_usb->pipes[i].urb_cnt_thresh =
+		    ar_usb->pipes[i].urb_alloc / 2;
+	}
+
+	return 0;
+}
+
+static int ath10k_usb_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
+				struct ath10k_hif_sg_item *items, int n_items)
+{
+	int ret, i;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+	struct ath10k_usb_pipe *pipe = &ar_usb->pipes[pipe_id];
+	struct ath10k_urb_context *urb_context;
+	struct urb *urb;
+
+	for (i = 0; i < n_items; i++) {
+		struct sk_buff *skb;
+
+		urb_context = ath10k_usb_alloc_urb_from_pipe(pipe);
+		if (!urb_context) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		skb = items[i].transfer_context;
+		urb_context->skb = skb;
+
+		urb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!urb) {
+			ret = -ENOMEM;
+			goto err_free_urb_to_pipe;
+		}
+
+		usb_fill_bulk_urb(urb,
+				  ar_usb->udev,
+				  pipe->usb_pipe_handle,
+				  skb->data,
+				  skb->len,
+				  ath10k_usb_transmit_complete, urb_context);
+
+		if (!(skb->len % pipe->max_packet_size)) {
+			/* hit a max packet boundary on this pipe */
+			urb->transfer_flags |= URB_ZERO_PACKET;
+		}
+
+		usb_anchor_urb(urb, &pipe->urb_submitted);
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+		if (ret) {
+			ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
+				   "usb bulk transmit failed %d\n", ret);
+			usb_unanchor_urb(urb);
+			ret = -EINVAL;
+			goto err_free_urb_to_pipe;
+		}
+
+		usb_free_urb(urb);
+	}
+
+	return 0;
+
+err_free_urb_to_pipe:
+	ath10k_usb_free_urb_to_pipe(urb_context->pipe, urb_context);
+err:
+	return ret;
+}
+
+static void ath10k_usb_hif_stop(struct ath10k *ar)
+{
+	ath10k_usb_flush_all(ar);
+}
+
+static u16 ath10k_usb_hif_get_free_queue_number(struct ath10k *ar, u8 pipe_id)
+{
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+
+	return ar_usb->pipes[pipe_id].urb_cnt;
+}
+
+static int ath10k_usb_submit_ctrl_out(struct ath10k *ar,
+				      u8 req, u16 value, u16 index, void *data,
+				      u32 size)
+{
+	int ret;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+	u8 *buf = NULL;
+
+	if (size > 0) {
+		buf = kmemdup(data, size, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+	}
+
+	/* note: if successful returns number of bytes transferred */
+	ret = usb_control_msg(ar_usb->udev,
+			      usb_sndctrlpipe(ar_usb->udev, 0),
+			      req,
+			      USB_DIR_OUT | USB_TYPE_VENDOR |
+			      USB_RECIP_DEVICE, value, index, buf,
+			      size, 1000);
+
+	if (ret < 0) {
+		ath10k_warn(ar, "Failed to submit usb control message: %d\n",
+			    ret);
+		kfree(buf);
+		return ret;
+	}
+
+	kfree(buf);
+
+	return 0;
+}
+
+static int ath10k_usb_submit_ctrl_in(struct ath10k *ar,
+				     u8 req, u16 value, u16 index, void *data,
+				     u32 size)
+{
+	int ret;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+	u8 *buf = NULL;
+
+	if (size > 0) {
+		buf = kmalloc(size, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+	}
+
+	/* note: if successful returns number of bytes transferred */
+	ret = usb_control_msg(ar_usb->udev,
+			      usb_rcvctrlpipe(ar_usb->udev, 0),
+			      req,
+			      USB_DIR_IN | USB_TYPE_VENDOR |
+			      USB_RECIP_DEVICE, value, index, buf,
+			      size, 2 * HZ);
+
+	if (ret < 0) {
+		ath10k_warn(ar, "Failed to read usb control message: %d\n",
+			    ret);
+		kfree(buf);
+		return ret;
+	}
+
+	memcpy((u8 *)data, buf, size);
+
+	kfree(buf);
+
+	return 0;
+}
+
+static int ath10k_usb_ctrl_msg_exchange(struct ath10k *ar,
+					u8 req_val, u8 *req_buf, u32 req_len,
+					u8 resp_val, u8 *resp_buf,
+					u32 *resp_len)
+{
+	int ret;
+
+	/* send command */
+	ret = ath10k_usb_submit_ctrl_out(ar, req_val, 0, 0,
+					 req_buf, req_len);
+	if (ret)
+		goto err;
+
+	/* get response */
+	if (resp_buf) {
+		ret = ath10k_usb_submit_ctrl_in(ar, resp_val, 0, 0,
+						resp_buf, *resp_len);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+err:
+	return ret;
+}
+
+static int ath10k_usb_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
+				    size_t buf_len)
+{
+	int ret;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+	struct ath10k_usb_ctrl_diag_cmd_read *cmd;
+	u32 resp_len;
+
+	if (buf_len < sizeof(struct ath10k_usb_ctrl_diag_resp_read)) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	cmd = (struct ath10k_usb_ctrl_diag_cmd_read *)ar_usb->diag_cmd_buffer;
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->cmd = ATH10K_USB_CTRL_DIAG_CC_READ;
+	cmd->address = cpu_to_le32(address);
+	resp_len = sizeof(struct ath10k_usb_ctrl_diag_resp_read);
+
+	ret = ath10k_usb_ctrl_msg_exchange(ar,
+					   ATH10K_USB_CONTROL_REQ_DIAG_CMD,
+					   (u8 *)cmd,
+					   sizeof(*cmd),
+					   ATH10K_USB_CONTROL_REQ_DIAG_RESP,
+					   ar_usb->diag_resp_buffer, &resp_len);
+	if (ret)
+		goto err;
+
+	if (resp_len != sizeof(struct ath10k_usb_ctrl_diag_resp_read)) {
+		ret = -EMSGSIZE;
+		goto err;
+	}
+
+	memcpy(buf, ar_usb->diag_resp_buffer,
+	       sizeof(struct ath10k_usb_ctrl_diag_resp_read));
+	return 0;
+err:
+	return ret;
+}
+
+static int ath10k_usb_hif_diag_write(struct ath10k *ar, u32 address,
+				     const void *data, int nbytes)
+{
+	int ret;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+	struct ath10k_usb_ctrl_diag_cmd_write *cmd;
+
+	if (nbytes != sizeof(cmd->value)) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	cmd = (struct ath10k_usb_ctrl_diag_cmd_write *)ar_usb->diag_cmd_buffer;
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->cmd = cpu_to_le32(ATH10K_USB_CTRL_DIAG_CC_WRITE);
+	cmd->address = cpu_to_le32(address);
+	memcpy(&cmd->value, data, nbytes);
+
+	ret = ath10k_usb_ctrl_msg_exchange(ar,
+					   ATH10K_USB_CONTROL_REQ_DIAG_CMD,
+					   (u8 *)cmd,
+					   sizeof(*cmd),
+					   0, NULL, NULL);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	return ret;
+}
+
+static int ath10k_usb_bmi_exchange_msg(struct ath10k *ar,
+				       void *req, u32 req_len,
+				       void *resp, u32 *resp_len)
+{
+	int ret;
+
+	if (req) {
+		ret = ath10k_usb_submit_ctrl_out(ar,
+						 ATH10K_USB_CONTROL_REQ_SEND_BMI_CMD,
+						 0, 0, req, req_len);
+		if (ret) {
+			ath10k_warn(ar,
+				    "unable to send the bmi data to the device: %d\n",
+				    ret);
+			goto err;
+		}
+	}
+
+	if (resp) {
+		ret = ath10k_usb_submit_ctrl_in(ar,
+						ATH10K_USB_CONTROL_REQ_RECV_BMI_RESP,
+						0, 0, resp, *resp_len);
+		if (ret) {
+			ath10k_warn(ar,
+				    "Unable to read the bmi data from the device: %d\n",
+				    ret);
+			goto err;
+		}
+	}
+
+	return 0;
+err:
+	return ret;
+}
+
+static void ath10k_usb_hif_get_default_pipe(struct ath10k *ar,
+					    u8 *ul_pipe, u8 *dl_pipe)
+{
+	*ul_pipe = ATH10K_USB_PIPE_TX_CTRL;
+	*dl_pipe = ATH10K_USB_PIPE_RX_CTRL;
+}
+
+static int ath10k_usb_hif_map_service_to_pipe(struct ath10k *ar, u16 svc_id,
+					      u8 *ul_pipe, u8 *dl_pipe)
+{
+	int ret = 0;
+
+	switch (svc_id) {
+	case ATH10K_HTC_SVC_ID_RSVD_CTRL:
+	case ATH10K_HTC_SVC_ID_WMI_CONTROL:
+		*ul_pipe = ATH10K_USB_PIPE_TX_CTRL;
+		/* due to large control packets, shift to data pipe */
+		*dl_pipe = ATH10K_USB_PIPE_RX_DATA;
+		break;
+	case ATH10K_HTC_SVC_ID_HTT_DATA_MSG:
+		*ul_pipe = ATH10K_USB_PIPE_TX_DATA_LP;
+		/* Disable rxdata2 directly, it will be enabled
+		 * if FW enable rxdata2
+		 */
+		*dl_pipe = ATH10K_USB_PIPE_RX_DATA;
+		break;
+	default:
+		ret = -EPERM;
+		break;
+	}
+
+	return ret;
+}
+
+/* This op is currently only used by htc_wait_target if the HTC ready
+ * message times out. It is not applicable for USB since there is nothing
+ * we can do if the HTC ready message does not arrive in time.
+ * TODO: Make this op non mandatory by introducing a NULL check in the
+ * hif op wrapper.
+ */
+static void ath10k_usb_hif_send_complete_check(struct ath10k *ar,
+					       u8 pipe, int force)
+{
+}
+
+static int ath10k_usb_hif_power_up(struct ath10k *ar)
+{
+	return 0;
+}
+
+static void ath10k_usb_hif_power_down(struct ath10k *ar)
+{
+	ath10k_usb_flush_all(ar);
+}
+
+#ifdef CONFIG_PM
+
+static int ath10k_usb_hif_suspend(struct ath10k *ar)
+{
+	return -EOPNOTSUPP;
+}
+
+static int ath10k_usb_hif_resume(struct ath10k *ar)
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
+static const struct ath10k_hif_ops ath10k_usb_hif_ops = {
+	.tx_sg			= ath10k_usb_hif_tx_sg,
+	.diag_read		= ath10k_usb_hif_diag_read,
+	.diag_write		= ath10k_usb_hif_diag_write,
+	.exchange_bmi_msg	= ath10k_usb_bmi_exchange_msg,
+	.start			= ath10k_usb_hif_start,
+	.stop			= ath10k_usb_hif_stop,
+	.map_service_to_pipe	= ath10k_usb_hif_map_service_to_pipe,
+	.get_default_pipe	= ath10k_usb_hif_get_default_pipe,
+	.send_complete_check	= ath10k_usb_hif_send_complete_check,
+	.get_free_queue_number	= ath10k_usb_hif_get_free_queue_number,
+	.power_up		= ath10k_usb_hif_power_up,
+	.power_down		= ath10k_usb_hif_power_down,
+#ifdef CONFIG_PM
+	.suspend		= ath10k_usb_hif_suspend,
+	.resume			= ath10k_usb_hif_resume,
+#endif
+};
+
+static u8 ath10k_usb_get_logical_pipe_num(u8 ep_address, int *urb_count)
+{
+	u8 pipe_num = ATH10K_USB_PIPE_INVALID;
+
+	switch (ep_address) {
+	case ATH10K_USB_EP_ADDR_APP_CTRL_IN:
+		pipe_num = ATH10K_USB_PIPE_RX_CTRL;
+		*urb_count = RX_URB_COUNT;
+		break;
+	case ATH10K_USB_EP_ADDR_APP_DATA_IN:
+		pipe_num = ATH10K_USB_PIPE_RX_DATA;
+		*urb_count = RX_URB_COUNT;
+		break;
+	case ATH10K_USB_EP_ADDR_APP_INT_IN:
+		pipe_num = ATH10K_USB_PIPE_RX_INT;
+		*urb_count = RX_URB_COUNT;
+		break;
+	case ATH10K_USB_EP_ADDR_APP_DATA2_IN:
+		pipe_num = ATH10K_USB_PIPE_RX_DATA2;
+		*urb_count = RX_URB_COUNT;
+		break;
+	case ATH10K_USB_EP_ADDR_APP_CTRL_OUT:
+		pipe_num = ATH10K_USB_PIPE_TX_CTRL;
+		*urb_count = TX_URB_COUNT;
+		break;
+	case ATH10K_USB_EP_ADDR_APP_DATA_LP_OUT:
+		pipe_num = ATH10K_USB_PIPE_TX_DATA_LP;
+		*urb_count = TX_URB_COUNT;
+		break;
+	case ATH10K_USB_EP_ADDR_APP_DATA_MP_OUT:
+		pipe_num = ATH10K_USB_PIPE_TX_DATA_MP;
+		*urb_count = TX_URB_COUNT;
+		break;
+	case ATH10K_USB_EP_ADDR_APP_DATA_HP_OUT:
+		pipe_num = ATH10K_USB_PIPE_TX_DATA_HP;
+		*urb_count = TX_URB_COUNT;
+		break;
+	default:
+		/* note: there may be endpoints not currently used */
+		break;
+	}
+
+	return pipe_num;
+}
+
+static int ath10k_usb_alloc_pipe_resources(struct ath10k *ar,
+					   struct ath10k_usb_pipe *pipe,
+					   int urb_cnt)
+{
+	int ret, i;
+	struct ath10k_urb_context *urb_context;
+
+	INIT_LIST_HEAD(&pipe->urb_list_head);
+	init_usb_anchor(&pipe->urb_submitted);
+
+	for (i = 0; i < urb_cnt; i++) {
+		urb_context = kzalloc(sizeof(*urb_context), GFP_KERNEL);
+		if (!urb_context) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		urb_context->pipe = pipe;
+
+		/* we are only allocate the urb contexts here, the actual URB
+		 * is allocated from the kernel as needed to do a transaction
+		 */
+		pipe->urb_alloc++;
+		ath10k_usb_free_urb_to_pipe(pipe, urb_context);
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_USB,
+		   "alloc resources lpipe:%d hpipe:0x%X urbs:%d\n",
+		   pipe->logical_pipe_num, pipe->usb_pipe_handle,
+		   pipe->urb_alloc);
+
+	return 0;
+err:
+	return ret;
+}
+
+static int ath10k_usb_setup_pipe_resources(struct ath10k *ar,
+					   struct usb_interface *interface)
+{
+	int ret = 0, i, urbcount;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+	struct usb_host_interface *iface_desc = interface->cur_altsetting;
+	struct usb_endpoint_descriptor *endpoint;
+	struct ath10k_usb_pipe *pipe;
+	u8 pipe_num;
+
+	ath10k_dbg(ar, ATH10K_DBG_USB, "setting up USB Pipes using interface\n");
+
+	/* walk decriptors and setup pipes */
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (ATH10K_USB_IS_BULK_EP(endpoint->bmAttributes)) {
+			ath10k_dbg(ar, ATH10K_DBG_USB,
+				   "%s Bulk Ep:0x%2.2X maxpktsz:%d\n",
+				   ATH10K_USB_IS_DIR_IN
+				   (endpoint->bEndpointAddress) ?
+				   "RX" : "TX", endpoint->bEndpointAddress,
+				   le16_to_cpu(endpoint->wMaxPacketSize));
+		} else if (ATH10K_USB_IS_INT_EP(endpoint->bmAttributes)) {
+			ath10k_dbg(ar, ATH10K_DBG_USB,
+				   "%s Int Ep:0x%2.2X maxpktsz:%d interval:%d\n",
+				   ATH10K_USB_IS_DIR_IN
+				   (endpoint->bEndpointAddress) ?
+				   "RX" : "TX", endpoint->bEndpointAddress,
+				   le16_to_cpu(endpoint->wMaxPacketSize),
+				   endpoint->bInterval);
+		} else if (ATH10K_USB_IS_ISOC_EP(endpoint->bmAttributes)) {
+			/* TODO for ISO */
+			ath10k_dbg(ar, ATH10K_DBG_USB,
+				   "%s ISOC Ep:0x%2.2X maxpktsz:%d interval:%d\n",
+				   ATH10K_USB_IS_DIR_IN
+				   (endpoint->bEndpointAddress) ?
+				   "RX" : "TX", endpoint->bEndpointAddress,
+				   le16_to_cpu(endpoint->wMaxPacketSize),
+				   endpoint->bInterval);
+		}
+		urbcount = 0;
+
+		pipe_num =
+		    ath10k_usb_get_logical_pipe_num(endpoint->bEndpointAddress,
+						    &urbcount);
+		if (pipe_num == ATH10K_USB_PIPE_INVALID)
+			continue;
+
+		pipe = &ar_usb->pipes[pipe_num];
+		if (pipe->ar_usb) {
+			/* hmmm..pipe was already setup */
+			continue;
+		}
+
+		pipe->ar_usb = ar_usb;
+		pipe->logical_pipe_num = pipe_num;
+		pipe->ep_address = endpoint->bEndpointAddress;
+		pipe->max_packet_size = le16_to_cpu(endpoint->wMaxPacketSize);
+
+		if (ATH10K_USB_IS_BULK_EP(endpoint->bmAttributes)) {
+			if (ATH10K_USB_IS_DIR_IN(pipe->ep_address)) {
+				pipe->usb_pipe_handle =
+				    usb_rcvbulkpipe(ar_usb->udev,
+						    pipe->ep_address);
+			} else {
+				pipe->usb_pipe_handle =
+				    usb_sndbulkpipe(ar_usb->udev,
+						    pipe->ep_address);
+			}
+		} else if (ATH10K_USB_IS_INT_EP(endpoint->bmAttributes)) {
+			if (ATH10K_USB_IS_DIR_IN(pipe->ep_address)) {
+				pipe->usb_pipe_handle =
+				    usb_rcvintpipe(ar_usb->udev,
+						   pipe->ep_address);
+			} else {
+				pipe->usb_pipe_handle =
+				    usb_sndintpipe(ar_usb->udev,
+						   pipe->ep_address);
+			}
+		} else if (ATH10K_USB_IS_ISOC_EP(endpoint->bmAttributes)) {
+			/* TODO for ISO */
+			if (ATH10K_USB_IS_DIR_IN(pipe->ep_address)) {
+				pipe->usb_pipe_handle =
+				    usb_rcvisocpipe(ar_usb->udev,
+						    pipe->ep_address);
+			} else {
+				pipe->usb_pipe_handle =
+				    usb_sndisocpipe(ar_usb->udev,
+						    pipe->ep_address);
+			}
+		}
+
+		pipe->ep_desc = endpoint;
+
+		if (!ATH10K_USB_IS_DIR_IN(pipe->ep_address))
+			pipe->flags |= ATH10K_USB_PIPE_FLAG_TX;
+
+		ret = ath10k_usb_alloc_pipe_resources(ar, pipe, urbcount);
+		if (ret != 0)
+			break;
+	}
+
+	return ret;
+}
+
+static int ath10k_usb_create(struct ath10k *ar,
+			     struct usb_interface *interface)
+{
+	int ret = 0, i;
+	struct ath10k_usb *ar_usb = ath10k_usb_priv(ar);
+	struct usb_device *dev = interface_to_usbdev(interface);
+	struct ath10k_usb_pipe *pipe;
+
+	usb_set_intfdata(interface, ar_usb);
+	spin_lock_init(&ar_usb->cs_lock);
+	ar_usb->udev = dev;
+	ar_usb->interface = interface;
+
+	for (i = 0; i < ATH10K_USB_PIPE_MAX; i++) {
+		pipe = &ar_usb->pipes[i];
+		INIT_WORK(&pipe->io_complete_work,
+			  ath10k_usb_io_comp_work);
+		skb_queue_head_init(&pipe->io_comp_queue);
+	}
+
+	ar_usb->diag_cmd_buffer = kzalloc(ATH10K_USB_MAX_DIAG_CMD, GFP_KERNEL);
+	if (!ar_usb->diag_cmd_buffer) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ar_usb->diag_resp_buffer = kzalloc(ATH10K_USB_MAX_DIAG_RESP,
+					   GFP_KERNEL);
+	if (!ar_usb->diag_resp_buffer) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = ath10k_usb_setup_pipe_resources(ar, interface);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	ath10k_usb_destroy(ar);
+	return ret;
+}
+
+/* ath10k usb driver registered functions */
+static int ath10k_usb_probe(struct usb_interface *interface,
+			    const struct usb_device_id *id)
+{
+	int ret, vendor_id, product_id;
+	struct ath10k_usb *ar_usb;
+	struct ath10k *ar;
+	struct usb_device *dev = interface_to_usbdev(interface);
+	u32 chip_id;
+	enum ath10k_hw_rev hw_rev;
+
+	/* Assumption: All USB based chipsets (so far) are QCA9377 based.
+	 * If there will be newer chipsets that does not use the hw reg
+	 * setup as defined in qca6174_regs and qca6174_values, this
+	 * assumption is no longer valid and hw_rev must be setup differently
+	 * depending on chipset.
+	 */
+	hw_rev = ATH10K_HW_QCA9377;
+
+	ar = ath10k_core_create(sizeof(*ar_usb), &dev->dev, ATH10K_BUS_USB,
+				hw_rev, &ath10k_usb_hif_ops);
+	if (!ar) {
+		dev_err(&dev->dev, "failed to allocate core\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	usb_get_dev(dev);
+	vendor_id = le16_to_cpu(dev->descriptor.idVendor);
+	product_id = le16_to_cpu(dev->descriptor.idProduct);
+
+	ath10k_dbg(ar, ATH10K_DBG_BOOT,
+		   "usb new func: vendor 0x%04x, product 0x%04x\n",
+		   vendor_id, product_id);
+
+	ar_usb = ath10k_usb_priv(ar);
+	ret = ath10k_usb_create(ar, interface);
+	ar_usb->ar = ar;
+
+	ar->dev_id = product_id;
+	ar->id.vendor = vendor_id;
+	ar->id.device = product_id;
+
+	/* TODO: don't know yet how to get chip_id with USB */
+	chip_id = 0;
+	ret = ath10k_core_register(ar, chip_id);
+	if (ret) {
+		ath10k_warn(ar, "failed to register driver core: %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	usb_put_dev(dev);
+	return ret;
+}
+
+static void ath10k_usb_remove(struct usb_interface *interface)
+{
+	struct ath10k_usb *ar_usb;
+
+	ar_usb = usb_get_intfdata(interface);
+	if (!ar_usb)
+		return;
+
+	ath10k_core_unregister(ar_usb->ar);
+	ath10k_usb_destroy(ar_usb->ar);
+	usb_put_dev(interface_to_usbdev(interface));
+	ath10k_core_destroy(ar_usb->ar);
+}
+
+#ifdef CONFIG_PM
+
+static int ath10k_usb_pm_suspend(struct usb_interface *interface,
+				 pm_message_t message)
+{
+	struct ath10k_usb *ar_usb = usb_get_intfdata(interface);
+
+	ath10k_usb_flush_all(ar_usb->ar);
+	return 0;
+}
+
+static int ath10k_usb_pm_resume(struct usb_interface *interface)
+{
+	struct ath10k_usb *ar_usb = usb_get_intfdata(interface);
+	struct ath10k *ar = ar_usb->ar;
+
+	ath10k_usb_post_recv_transfers(ar,
+				       &ar_usb->pipes[ATH10K_USB_PIPE_RX_DATA]);
+
+	return 0;
+}
+
+#else
+
+#define ath10k_usb_pm_suspend NULL
+#define ath10k_usb_pm_resume NULL
+
+#endif
+
+/* table of devices that work with this driver */
+static struct usb_device_id ath10k_usb_ids[] = {
+	{USB_DEVICE(0x13b1, 0x0042)}, /* Linksys WUSB6100M */
+	{ /* Terminating entry */ },
+};
+
+MODULE_DEVICE_TABLE(usb, ath10k_usb_ids);
+
+static struct usb_driver ath10k_usb_driver = {
+	.name = "ath10k_usb",
+	.probe = ath10k_usb_probe,
+	.suspend = ath10k_usb_pm_suspend,
+	.resume = ath10k_usb_pm_resume,
+	.disconnect = ath10k_usb_remove,
+	.id_table = ath10k_usb_ids,
+	.supports_autosuspend = true,
+	.disable_hub_initiated_lpm = 1,
+};
+
+module_usb_driver(ath10k_usb_driver);
+
+MODULE_AUTHOR("Atheros Communications, Inc.");
+MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath10k/usb.h b/drivers/net/wireless/ath/ath10k/usb.h
new file mode 100644
index 0000000..f60a3cc
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/usb.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
+ * Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
+ *
+ * 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 _USB_H_
+#define _USB_H_
+
+/* constants */
+#define TX_URB_COUNT               32
+#define RX_URB_COUNT               32
+#define ATH10K_USB_RX_BUFFER_SIZE  4096
+
+#define ATH10K_USB_PIPE_INVALID ATH10K_USB_PIPE_MAX
+
+/* USB endpoint definitions */
+#define ATH10K_USB_EP_ADDR_APP_CTRL_IN          0x81
+#define ATH10K_USB_EP_ADDR_APP_DATA_IN          0x82
+#define ATH10K_USB_EP_ADDR_APP_DATA2_IN         0x83
+#define ATH10K_USB_EP_ADDR_APP_INT_IN           0x84
+
+#define ATH10K_USB_EP_ADDR_APP_CTRL_OUT         0x01
+#define ATH10K_USB_EP_ADDR_APP_DATA_LP_OUT      0x02
+#define ATH10K_USB_EP_ADDR_APP_DATA_MP_OUT      0x03
+#define ATH10K_USB_EP_ADDR_APP_DATA_HP_OUT      0x04
+
+/* diagnostic command defnitions */
+#define ATH10K_USB_CONTROL_REQ_SEND_BMI_CMD        1
+#define ATH10K_USB_CONTROL_REQ_RECV_BMI_RESP       2
+#define ATH10K_USB_CONTROL_REQ_DIAG_CMD            3
+#define ATH10K_USB_CONTROL_REQ_DIAG_RESP           4
+
+#define ATH10K_USB_CTRL_DIAG_CC_READ               0
+#define ATH10K_USB_CTRL_DIAG_CC_WRITE              1
+
+#define ATH10K_USB_IS_BULK_EP(attr) (((attr) & 3) == 0x02)
+#define ATH10K_USB_IS_INT_EP(attr)  (((attr) & 3) == 0x03)
+#define ATH10K_USB_IS_ISOC_EP(attr) (((attr) & 3) == 0x01)
+#define ATH10K_USB_IS_DIR_IN(addr)  ((addr) & 0x80)
+
+struct ath10k_usb_ctrl_diag_cmd_write {
+	__le32 cmd;
+	__le32 address;
+	__le32 value;
+	__le32 padding;
+} __packed;
+
+struct ath10k_usb_ctrl_diag_cmd_read {
+	__le32 cmd;
+	__le32 address;
+} __packed;
+
+struct ath10k_usb_ctrl_diag_resp_read {
+	u8 value[4];
+} __packed;
+
+/* tx/rx pipes for usb */
+enum ath10k_usb_pipe_id {
+	ATH10K_USB_PIPE_TX_CTRL = 0,
+	ATH10K_USB_PIPE_TX_DATA_LP,
+	ATH10K_USB_PIPE_TX_DATA_MP,
+	ATH10K_USB_PIPE_TX_DATA_HP,
+	ATH10K_USB_PIPE_RX_CTRL,
+	ATH10K_USB_PIPE_RX_DATA,
+	ATH10K_USB_PIPE_RX_DATA2,
+	ATH10K_USB_PIPE_RX_INT,
+	ATH10K_USB_PIPE_MAX
+};
+
+struct ath10k_usb_pipe {
+	struct list_head urb_list_head;
+	struct usb_anchor urb_submitted;
+	u32 urb_alloc;
+	u32 urb_cnt;
+	u32 urb_cnt_thresh;
+	unsigned int usb_pipe_handle;
+	u32 flags;
+	u8 ep_address;
+	u8 logical_pipe_num;
+	struct ath10k_usb *ar_usb;
+	u16 max_packet_size;
+	struct work_struct io_complete_work;
+	struct sk_buff_head io_comp_queue;
+	struct usb_endpoint_descriptor *ep_desc;
+};
+
+#define ATH10K_USB_PIPE_FLAG_TX BIT(0)
+
+/* usb device object */
+struct ath10k_usb {
+	/* protects pipe->urb_list_head and  pipe->urb_cnt */
+	spinlock_t cs_lock;
+
+	struct usb_device *udev;
+	struct usb_interface *interface;
+	struct ath10k_usb_pipe pipes[ATH10K_USB_PIPE_MAX];
+	u8 *diag_cmd_buffer;
+	u8 *diag_resp_buffer;
+	struct ath10k *ar;
+};
+
+/* usb urb object */
+struct ath10k_urb_context {
+	struct list_head link;
+	struct ath10k_usb_pipe *pipe;
+	struct sk_buff *skb;
+	struct ath10k *ar;
+};
+
+static inline struct ath10k_usb *ath10k_usb_priv(struct ath10k *ar)
+{
+	return (struct ath10k_usb *)ar->drv_priv;
+}
+
+#endif
-- 
2.7.4

^ permalink raw reply related

* [RFC v4 21/21] ath10k: dma fixes for high latency devices
From: Erik Stromdahl @ 2017-02-21 16:15 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1487693741-10042-1-git-send-email-erik.stromdahl@gmail.com>

Several DMA related functions (such as the dma_map_xxx functions)
are not used with high latency devices and don't need to be invoked
in this case.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/htc.c    | 13 ++++++++-----
 drivers/net/wireless/ath/ath10k/htt_rx.c |  3 ++-
 drivers/net/wireless/ath/ath10k/htt_tx.c |  3 +++
 drivers/net/wireless/ath/ath10k/txrx.c   |  5 +++--
 4 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 3eaa9a8..b5fddd7 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -134,11 +134,14 @@ int ath10k_htc_send(struct ath10k_htc *htc,
 	ath10k_htc_prepare_tx_skb(ep, skb);
 
 	skb_cb->eid = eid;
-	skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
-	ret = dma_mapping_error(dev, skb_cb->paddr);
-	if (ret) {
-		ret = -EIO;
-		goto err_credits;
+	if (!ar->is_high_latency) {
+		skb_cb->paddr = dma_map_single(dev, skb->data, skb->len,
+					       DMA_TO_DEVICE);
+		ret = dma_mapping_error(dev, skb_cb->paddr);
+		if (ret) {
+			ret = -EIO;
+			goto err_credits;
+		}
 	}
 
 	sg_item.transfer_id = ep->eid;
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index c90570f..96e73b4 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2485,7 +2485,8 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 		break;
 	}
 	case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
-		ath10k_htt_rx_tx_compl_ind(htt->ar, skb);
+		if (!ar->is_high_latency)
+			ath10k_htt_rx_tx_compl_ind(htt->ar, skb);
 		break;
 	case HTT_T2H_MSG_TYPE_SEC_IND: {
 		struct ath10k *ar = htt->ar;
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index a714aa8..190d002 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -409,6 +409,9 @@ int ath10k_htt_tx_start(struct ath10k_htt *htt)
 	if (htt->tx_mem_allocated)
 		return 0;
 
+	if (ar->is_high_latency)
+		return 0;
+
 	ret = ath10k_htt_tx_alloc_buf(htt);
 	if (ret)
 		goto free_idr_pending_tx;
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 9852c5d..5e27f6da 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -89,11 +89,12 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
 
 	ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
 	ath10k_htt_tx_dec_pending(htt);
-	if (htt->num_pending_tx == 0)
+	if (!ar->is_high_latency && (htt->num_pending_tx == 0))
 		wake_up(&htt->empty_tx_wq);
 	spin_unlock_bh(&htt->tx_lock);
 
-	dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
+	if (!ar->is_high_latency)
+		dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
 
 	ath10k_report_offchan_tx(htt->ar, msdu);
 
-- 
2.7.4

^ permalink raw reply related

* [RFC v4 08/21] ath10k: sdio get target info
From: Erik Stromdahl @ 2017-02-21 16:15 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1487693741-10042-1-git-send-email-erik.stromdahl@gmail.com>

Special BMI get target info function for SDIO.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/bmi.c  | 70 ++++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/bmi.h  |  2 +
 drivers/net/wireless/ath/ath10k/core.c |  5 ++-
 3 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c
index abeee20..54aaa1c0 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.c
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
@@ -97,6 +97,76 @@ int ath10k_bmi_get_target_info(struct ath10k *ar,
 	return 0;
 }
 
+#define TARGET_VERSION_SENTINAL 0xffffffffu
+
+int ath10k_bmi_get_target_info_sdio(struct ath10k *ar,
+				    struct bmi_target_info *target_info)
+{
+	struct bmi_cmd cmd;
+	union bmi_resp resp;
+	u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.get_target_info);
+	u32 resplen, tmp, ver_len;
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi get target info SDIO\n");
+
+	if (ar->bmi.done_sent) {
+		ath10k_warn(ar, "BMI Get Target Info Command disallowed\n");
+		return -EBUSY;
+	}
+
+	cmd.id = __cpu_to_le32(BMI_GET_TARGET_INFO);
+
+	/* Step 1: Read 4 bytes of the target info and check if it is
+	 * the special sentinal version word or the first word in the
+	 * version response.
+	 */
+	resplen = sizeof(u32);
+	ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &tmp, &resplen);
+	if (ret) {
+		ath10k_warn(ar, "unable to read from device\n");
+		return ret;
+	}
+
+	/* Some SDIO boards have a special sentinal byte before the real
+	 * version response.
+	 */
+	if (tmp == TARGET_VERSION_SENTINAL) {
+		/* Step 1b: Read the version length */
+		resplen = sizeof(u32);
+		ret = ath10k_hif_exchange_bmi_msg(ar, NULL, 0, &tmp,
+						  &resplen);
+		if (ret) {
+			ath10k_warn(ar, "unable to read from device\n");
+			return ret;
+		}
+	}
+
+	ver_len = __le32_to_cpu(tmp);
+
+	/* Step 2: Check the target info length */
+	if (ver_len != sizeof(resp.get_target_info)) {
+		ath10k_warn(ar, "Unexpected target info len: %u. Expected: %zu\n",
+			    ver_len, sizeof(resp.get_target_info));
+		return -EINVAL;
+	}
+
+	/* Step 3: Read the rest of the version response */
+	resplen = sizeof(resp.get_target_info) - sizeof(u32);
+	ret = ath10k_hif_exchange_bmi_msg(ar, NULL, 0,
+					  &resp.get_target_info.version,
+					  &resplen);
+	if (ret) {
+		ath10k_warn(ar, "unable to read from device\n");
+		return ret;
+	}
+
+	target_info->version = __le32_to_cpu(resp.get_target_info.version);
+	target_info->type    = __le32_to_cpu(resp.get_target_info.type);
+
+	return 0;
+}
+
 int ath10k_bmi_read_memory(struct ath10k *ar,
 			   u32 address, void *buffer, u32 length)
 {
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index a65f262..2043d00 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -197,6 +197,8 @@ void ath10k_bmi_start(struct ath10k *ar);
 int ath10k_bmi_done(struct ath10k *ar);
 int ath10k_bmi_get_target_info(struct ath10k *ar,
 			       struct bmi_target_info *target_info);
+int ath10k_bmi_get_target_info_sdio(struct ath10k *ar,
+				    struct bmi_target_info *target_info);
 int ath10k_bmi_read_memory(struct ath10k *ar, u32 address,
 			   void *buffer, u32 length);
 int ath10k_bmi_write_memory(struct ath10k *ar, u32 address,
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index eae502e..a0b331d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2186,7 +2186,10 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 	}
 
 	memset(&target_info, 0, sizeof(target_info));
-	ret = ath10k_bmi_get_target_info(ar, &target_info);
+	if (ar->hif.bus == ATH10K_BUS_SDIO)
+		ret = ath10k_bmi_get_target_info_sdio(ar, &target_info);
+	else
+		ret = ath10k_bmi_get_target_info(ar, &target_info);
 	if (ret) {
 		ath10k_err(ar, "could not get target info (%d)\n", ret);
 		goto err_power_down;
-- 
2.7.4

^ permalink raw reply related

* [RFC v4 17/21] ath10k: htt: High latency TX support
From: Erik Stromdahl @ 2017-02-21 16:15 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1487693741-10042-1-git-send-email-erik.stromdahl@gmail.com>

Add HTT TX function for HL interfaces.
Intended for SDIO and USB.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/htt.h    |  9 ++--
 drivers/net/wireless/ath/ath10k/htt_tx.c | 72 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/mac.c    |  5 ++-
 3 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index bdee2e7..85ad46c 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1822,9 +1822,12 @@ int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
 int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
 void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
 int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu);
-int ath10k_htt_tx(struct ath10k_htt *htt,
-		  enum ath10k_hw_txrx_mode txmode,
-		  struct sk_buff *msdu);
+int ath10k_htt_tx_ll(struct ath10k_htt *htt,
+		     enum ath10k_hw_txrx_mode txmode,
+		     struct sk_buff *msdu);
+int ath10k_htt_tx_hl(struct ath10k_htt *htt,
+		     enum ath10k_hw_txrx_mode txmode,
+		     struct sk_buff *msdu);
 void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
 					     struct sk_buff *skb);
 int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index ca899e1..a714aa8 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -945,8 +945,76 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 	return res;
 }
 
-int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
-		  struct sk_buff *msdu)
+#define HTT_TX_HL_NEEDED_HEADROOM \
+	(unsigned int)(sizeof(struct htt_cmd_hdr) + \
+	sizeof(struct htt_data_tx_desc) + \
+	sizeof(struct ath10k_htc_hdr))
+
+int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
+		     struct sk_buff *msdu)
+{
+	struct ath10k *ar = htt->ar;
+	int res, data_len;
+	struct htt_cmd_hdr *cmd_hdr;
+	struct htt_data_tx_desc *tx_desc;
+	struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
+	u8 flags0;
+	u16 flags1 = 0;
+
+	data_len = msdu->len;
+	flags0 = SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+
+	if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
+		flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
+
+	if (msdu->ip_summed == CHECKSUM_PARTIAL &&
+	    !test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+		flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
+		flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
+	}
+
+	/* Prepend the HTT header and TX desc struct to the data message
+	 * and realloc the skb if it does not have enough headroom.
+	 */
+	if (skb_headroom(msdu) < HTT_TX_HL_NEEDED_HEADROOM) {
+		struct sk_buff *tmp_skb = msdu;
+
+		ath10k_dbg(htt->ar, ATH10K_DBG_HTT,
+			   "Not enough headroom in skb. Current headroom: %u, needed: %u. Reallocating...\n",
+			   skb_headroom(msdu), HTT_TX_HL_NEEDED_HEADROOM);
+		msdu = skb_realloc_headroom(msdu, HTT_TX_HL_NEEDED_HEADROOM);
+		kfree_skb(tmp_skb);
+		if (!msdu) {
+			ath10k_warn(htt->ar, "htt hl tx: Unable to realloc skb!\n");
+			res = -ENOMEM;
+			goto out;
+		}
+	}
+
+	skb_push(msdu, sizeof(*cmd_hdr));
+	skb_push(msdu, sizeof(*tx_desc));
+	cmd_hdr = (struct htt_cmd_hdr *)msdu->data;
+	tx_desc = (struct htt_data_tx_desc *)(msdu->data + sizeof(*cmd_hdr));
+
+	cmd_hdr->msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
+	tx_desc->flags0 = flags0;
+	tx_desc->flags1 = __cpu_to_le16(flags1);
+	tx_desc->len = __cpu_to_le16(data_len);
+	tx_desc->id = 0;
+	tx_desc->frags_paddr = 0; /* always zero */
+	/* Initialize peer_id to INVALID_PEER because this is NOT
+	 * Reinjection path
+	 */
+	tx_desc->peerid = __cpu_to_le32(HTT_INVALID_PEERID);
+
+	res = ath10k_htc_send(&htt->ar->htc, htt->eid, msdu);
+
+out:
+	return res;
+}
+
+int ath10k_htt_tx_ll(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
+		     struct sk_buff *msdu)
 {
 	struct ath10k *ar = htt->ar;
 	struct device *dev = ar->dev;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 3029f25..6d2da19 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3531,7 +3531,10 @@ static int ath10k_mac_tx_submit(struct ath10k *ar,
 
 	switch (txpath) {
 	case ATH10K_MAC_TX_HTT:
-		ret = ath10k_htt_tx(htt, txmode, skb);
+		if (ar->is_high_latency)
+			ret = ath10k_htt_tx_hl(htt, txmode, skb);
+		else
+			ret = ath10k_htt_tx_ll(htt, txmode, skb);
 		break;
 	case ATH10K_MAC_TX_HTT_MGMT:
 		ret = ath10k_htt_mgmt_tx(htt, skb);
-- 
2.7.4

^ permalink raw reply related

* [RFC v4 18/21] ath10k: htt: High latency RX support
From: Erik Stromdahl @ 2017-02-21 16:15 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1487693741-10042-1-git-send-email-erik.stromdahl@gmail.com>

Special HTT RX handling for high latency interfaces.

Since no DMA physical addresses are used in the RX ring
config message (this is not supported by the high latency
devices), no RX ring is allocated.
All RX skb's are allocated by the driver and passed directly
to mac80211 in the HTT RX indication handler.

A nice side effect of this is that no huge buffer will be
allocated with dma_alloc_coherent. On embedded systems with
limited memory resources, the allocation of the RX ring is
prone to fail.

Some tweaks made to "make it work":

Removal of protected bit in 802.11 header frame control field.
The chipset seems to do hw decryption but the frame_control
protected bit is still set.

This is necessary for mac80211 not to drop the frame.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/core.c    | 38 ++++++++-----
 drivers/net/wireless/ath/ath10k/htt.h     | 47 +++++++++++++++
 drivers/net/wireless/ath/ath10k/htt_rx.c  | 95 ++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/rx_desc.h | 15 +++++
 4 files changed, 177 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 0a177bf..2e2d3d3 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1997,10 +1997,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
 		goto err_wmi_detach;
 	}
 
-	status = ath10k_htt_rx_alloc(&ar->htt);
-	if (status) {
-		ath10k_err(ar, "failed to alloc htt rx: %d\n", status);
-		goto err_htt_tx_detach;
+	if (!ar->is_high_latency) {
+		status = ath10k_htt_rx_alloc(&ar->htt);
+		if (status) {
+			ath10k_err(ar, "failed to alloc htt rx: %d\n", status);
+			goto err_htt_tx_detach;
+		}
 	}
 
 	status = ath10k_hif_start(ar);
@@ -2109,16 +2111,20 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
 		}
 	}
 
-	/* If firmware indicates Full Rx Reorder support it must be used in a
-	 * slightly different manner. Let HTT code know.
-	 */
-	ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
-						ar->wmi.svc_map));
+	if (!ar->is_high_latency) {
+		/* If firmware indicates Full Rx Reorder support it must be
+		 * used in a slightly different manner. Let HTT code know.
+		 */
+		ar->htt.rx_ring.in_ord_rx =
+			!!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
+				    ar->wmi.svc_map));
 
-	status = ath10k_htt_rx_ring_refill(ar);
-	if (status) {
-		ath10k_err(ar, "failed to refill htt rx ring: %d\n", status);
-		goto err_hif_stop;
+		status = ath10k_htt_rx_ring_refill(ar);
+		if (status) {
+			ath10k_err(ar, "failed to refill htt rx ring: %d\n",
+				   status);
+			goto err_hif_stop;
+		}
 	}
 
 	if (ar->max_num_vdevs >= 64)
@@ -2147,7 +2153,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
 err_hif_stop:
 	ath10k_hif_stop(ar);
 err_htt_rx_detach:
-	ath10k_htt_rx_free(&ar->htt);
+	if (!ar->is_high_latency)
+		ath10k_htt_rx_free(&ar->htt);
 err_htt_tx_detach:
 	ath10k_htt_tx_free(&ar->htt);
 err_wmi_detach:
@@ -2192,7 +2199,8 @@ void ath10k_core_stop(struct ath10k *ar)
 
 	ath10k_hif_stop(ar);
 	ath10k_htt_tx_stop(&ar->htt);
-	ath10k_htt_rx_free(&ar->htt);
+	if (!ar->is_high_latency)
+		ath10k_htt_rx_free(&ar->htt);
 	ath10k_wmi_detach(ar);
 	ar->is_started = false;
 }
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 85ad46c..554636d 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -645,6 +645,15 @@ struct htt_rx_indication {
 	struct htt_rx_indication_mpdu_range mpdu_ranges[0];
 } __packed;
 
+/* High latency version of the RX indication */
+struct htt_rx_indication_hl {
+	struct htt_rx_indication_hdr hdr;
+	struct htt_rx_indication_ppdu ppdu;
+	struct htt_rx_indication_prefix prefix;
+	struct fw_rx_desc_hl fw_desc;
+	struct htt_rx_indication_mpdu_range mpdu_ranges[0];
+} __packed;
+
 static inline struct htt_rx_indication_mpdu_range *
 		htt_rx_ind_get_mpdu_ranges(struct htt_rx_indication *rx_ind)
 {
@@ -657,6 +666,18 @@ static inline struct htt_rx_indication_mpdu_range *
 	return ptr;
 }
 
+static inline struct htt_rx_indication_mpdu_range *
+	htt_rx_ind_get_mpdu_ranges_hl(struct htt_rx_indication_hl *rx_ind)
+{
+	void *ptr = rx_ind;
+
+	ptr += sizeof(rx_ind->hdr)
+	     + sizeof(rx_ind->ppdu)
+	     + sizeof(rx_ind->prefix)
+	     + sizeof(rx_ind->fw_desc);
+	return ptr;
+}
+
 enum htt_rx_flush_mpdu_status {
 	HTT_RX_FLUSH_MPDU_DISCARD = 0,
 	HTT_RX_FLUSH_MPDU_REORDER = 1,
@@ -1527,6 +1548,7 @@ struct htt_resp {
 		struct htt_mgmt_tx_completion mgmt_tx_completion;
 		struct htt_data_tx_completion data_tx_completion;
 		struct htt_rx_indication rx_ind;
+		struct htt_rx_indication_hl rx_ind_hl;
 		struct htt_rx_fragment_indication rx_frag_ind;
 		struct htt_rx_peer_map peer_map;
 		struct htt_rx_peer_unmap peer_unmap;
@@ -1747,6 +1769,31 @@ struct htt_rx_desc {
 	u8 msdu_payload[0];
 };
 
+#define HTT_RX_DESC_HL_INFO_SEQ_NUM_MASK           0x00000fff
+#define HTT_RX_DESC_HL_INFO_SEQ_NUM_LSB            0
+#define HTT_RX_DESC_HL_INFO_ENCRYPTED_MASK         0x00001000
+#define HTT_RX_DESC_HL_INFO_ENCRYPTED_LSB          12
+#define HTT_RX_DESC_HL_INFO_CHAN_INFO_PRESENT_MASK 0x00002000
+#define HTT_RX_DESC_HL_INFO_CHAN_INFO_PRESENT_LSB  13
+#define HTT_RX_DESC_HL_INFO_MCAST_BCAST_MASK       0x00008000
+#define HTT_RX_DESC_HL_INFO_MCAST_BCAST_LSB        15
+#define HTT_RX_DESC_HL_INFO_FRAGMENT_MASK          0x00010000
+#define HTT_RX_DESC_HL_INFO_FRAGMENT_LSB           16
+#define HTT_RX_DESC_HL_INFO_KEY_ID_OCT_MASK        0x01fe0000
+#define HTT_RX_DESC_HL_INFO_KEY_ID_OCT_LSB         17
+
+struct htt_rx_desc_base_hl {
+	__le32 info; /* HTT_RX_DESC_HL_INFO_ */
+};
+
+struct htt_rx_chan_info {
+	__le16 primary_chan_center_freq_mhz;
+	__le16 contig_chan1_center_freq_mhz;
+	__le16 contig_chan2_center_freq_mhz;
+	u8 phy_mode;
+	u8 reserved;
+} __packed;
+
 #define HTT_RX_DESC_ALIGN 8
 
 #define HTT_MAC_ADDR_LEN 6
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 02a3fc8..c90570f 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1568,8 +1568,92 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
 	return num_msdus;
 }
 
-static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
-				      struct htt_rx_indication *rx)
+static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
+					 struct htt_rx_indication_hl *rx,
+					 struct sk_buff *skb)
+{
+	struct ath10k *ar = htt->ar;
+	struct ath10k_peer *peer;
+	struct htt_rx_indication_mpdu_range *mpdu_ranges;
+	struct fw_rx_desc_hl *fw_desc;
+	struct ieee80211_hdr *hdr;
+	struct ieee80211_rx_status *rx_status;
+	u16 peer_id;
+	u8 rx_desc_len;
+	int num_mpdu_ranges;
+	size_t tot_hdr_len;
+
+	peer_id = __le16_to_cpu(rx->hdr.peer_id);
+
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer)
+		ath10k_warn(ar, "Got RX ind from invalid peer: %u\n", peer_id);
+
+	num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1),
+			     HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);
+	mpdu_ranges = htt_rx_ind_get_mpdu_ranges_hl(rx);
+	fw_desc = &rx->fw_desc;
+	rx_desc_len = fw_desc->len;
+
+	/* I have not yet seen any case where num_mpdu_ranges > 1.
+	 * qcacld does not seem handle that case either, so we introduce the
+	 * same limitiation here as well.
+	 */
+	if (num_mpdu_ranges > 1)
+		ath10k_warn(ar,
+			    "Unsupported number of MPDU ranges: %d, ignoring all but the first\n",
+			    num_mpdu_ranges);
+
+	if (mpdu_ranges->mpdu_range_status !=
+	    HTT_RX_IND_MPDU_STATUS_OK) {
+		ath10k_warn(ar, "MPDU range status: %d\n",
+			    mpdu_ranges->mpdu_range_status);
+		goto err;
+	}
+
+	/* Strip off all headers before the MAC header before delivery to
+	 * mac80211
+	 */
+	tot_hdr_len = sizeof(struct htt_resp_hdr) + sizeof(rx->hdr) +
+		      sizeof(rx->ppdu) + sizeof(rx->prefix) +
+		      sizeof(rx->fw_desc) + sizeof(*mpdu_ranges) + rx_desc_len;
+	skb_pull(skb, tot_hdr_len);
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	rx_status = IEEE80211_SKB_RXCB(skb);
+	rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
+			    rx->ppdu.combined_rssi;
+	rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
+
+	/* Not entirely sure about this, but all frames from the chipset has
+	 * the protected flag set even though they have already been decrypted.
+	 * Unmasking this flag is necessary in order for mac80211 not to drop
+	 * the frame.
+	 * TODO: Verify this is always the case or find out a way to check
+	 * if there has been hw decryption.
+	 */
+	if (ieee80211_has_protected(hdr->frame_control)) {
+		hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+		rx_status->flag |= RX_FLAG_DECRYPTED |
+				   RX_FLAG_IV_STRIPPED |
+				   RX_FLAG_MMIC_STRIPPED;
+	}
+
+	ieee80211_rx(ar->hw, skb);
+
+	/* We have delivered the skb to the upper layers (mac80211) so we
+	 * must not free it.
+	 */
+	return false;
+err:
+	/* Tell the caller that it must free the skb since we have not
+	 * consumed it
+	 */
+	return true;
+}
+
+static void ath10k_htt_rx_proc_rx_ind_ll(struct ath10k_htt *htt,
+					 struct htt_rx_indication *rx)
 {
 	struct ath10k *ar = htt->ar;
 	struct htt_rx_indication_mpdu_range *mpdu_ranges;
@@ -2351,7 +2435,12 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 		break;
 	}
 	case HTT_T2H_MSG_TYPE_RX_IND:
-		ath10k_htt_rx_proc_rx_ind(htt, &resp->rx_ind);
+		if (ar->is_high_latency)
+			return ath10k_htt_rx_proc_rx_ind_hl(htt,
+							    &resp->rx_ind_hl,
+							    skb);
+		else
+			ath10k_htt_rx_proc_rx_ind_ll(htt, &resp->rx_ind);
 		break;
 	case HTT_T2H_MSG_TYPE_PEER_MAP: {
 		struct htt_peer_map_event ev = {
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
index 034e7a5..0e625cf 100644
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -1219,4 +1219,19 @@ struct fw_rx_desc_base {
 	u8 info0;
 } __packed;
 
+#define FW_RX_DESC_FLAGS_FIRST_MSDU (1 << 0)
+#define FW_RX_DESC_FLAGS_LAST_MSDU  (1 << 1)
+#define FW_RX_DESC_C3_FAILED        (1 << 2)
+#define FW_RX_DESC_C4_FAILED        (1 << 3)
+#define FW_RX_DESC_IPV6             (1 << 4)
+#define FW_RX_DESC_TCP              (1 << 5)
+#define FW_RX_DESC_UDP              (1 << 6)
+
+struct fw_rx_desc_hl {
+	u8 info0;
+	u8 version;
+	u8 len;
+	u8 flags;
+} __packed;
+
 #endif /* _RX_DESC_H_ */
-- 
2.7.4

^ permalink raw reply related

* RE: [OpenWrt-Devel] ATH10K VLAN firmware issue
From: voncken @ 2017-02-21 12:59 UTC (permalink / raw)
  To: 'Valo, Kalle'
  Cc: 'OpenWrt Development List', 'linux-wireless',
	ath10k
In-Reply-To: <87polwq2nq.fsf@kamboji.qca.qualcomm.com>

	Kalle, 

Do you know if the firmware team planned to fix the VLAN issue on ath10k
firmware?

Thanks for your help.

Cedric.
> -----Message d'origine-----
> De : linux-wireless-owner@vger.kernel.org [mailto:linux-wireless-
> owner@vger.kernel.org] De la part de Valo, Kalle
> Envoyé : mardi 15 novembre 2016 14:44
> À : Bruno Antunes
> Cc : OpenWrt Development List; linux-wireless; voncken;
> ath10k@lists.infradead.org
> Objet : Re: [OpenWrt-Devel] ATH10K VLAN firmware issue
> 
> Bruno Antunes <baantunes@gmail.com> writes:
> 
> > On 7 November 2016 at 18:06, Valo, Kalle <kvalo@qca.qualcomm.com>
> wrote:
> >> Bruno Antunes <baantunes@gmail.com> writes:
> >>
> >>> On 4 November 2016 at 21:17, Valo, Kalle <kvalo@qca.qualcomm.com>
> wrote:
> >>>
> >>>> Can someone file a bug to bugzilla about this so that all the info
> >>>> is properly stored? The more comprehensive the report is the
> better.
> >>>>
> >>>> https://bugzilla.kernel.org/
> >>>
> >>> I will file a bug report.
> >>
> >> Thanks, it's good to store all in one place so that it's easier to
> >> find the relevant info.
> >
> > Just file the bug with the ID 187241 - VLAN support in ATH10k Feel
> > free to ask for adicional info. I did not mention any names in the
> bug
> > report fell free to take credit if wanted.
> 
> Thanks. I'll report it to the firmware team, let's see what happens. If
> there's more information which might help to fix this feel free to
> update that to the bug report.
> 
> https://bugzilla.kernel.org/show_bug.cgi?id=187241
> 
> --
> Kalle Valo

^ permalink raw reply

* Re: [PATCH] Make EN2 pin optional in the TRF7970A driver
From: Rob Herring @ 2017-02-21 16:43 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: netdev, Guan Ben, Mark Jonas, devicetree@vger.kernel.org,
	linux-wireless, linux-kernel@vger.kernel.org, Samuel Ortiz,
	Lauro Ramos Venancio, Aloisio Almeida Jr, Mark Rutland
In-Reply-To: <58AA7C5D.60801@denx.de>

On Sun, Feb 19, 2017 at 11:19 PM, Heiko Schocher <hs@denx.de> wrote:
> Hello all,
>
> Am 13.02.2017 um 22:31 schrieb Rob Herring:
>>
>> On Mon, Feb 13, 2017 at 12:38 AM, Heiko Schocher <hs@denx.de> wrote:
>>>
>>> Hello Rob,
>>>
>>>
>>> Am 10.02.2017 um 16:51 schrieb Rob Herring:
>>>>
>>>>
>>>> On Tue, Feb 07, 2017 at 06:22:04AM +0100, Heiko Schocher wrote:
>>>>>
>>>>>
>>>>> From: Guan Ben <ben.guan@cn.bosch.com>
>>>>>
>>>>> Make the EN2 pin optional. This is useful for boards,
>>>>> which have this pin fix wired, for example to ground.
>>>>>
>>>>> Signed-off-by: Guan Ben <ben.guan@cn.bosch.com>
>>>>> Signed-off-by: Mark Jonas <mark.jonas@de.bosch.com>
>>>>> Signed-off-by: Heiko Schocher <hs@denx.de>
>>>>>
>>>>> ---
>>>>>
>>>>>    .../devicetree/bindings/net/nfc/trf7970a.txt       |  4 ++--
>>>>>    drivers/nfc/trf7970a.c                             | 26
>>>>> ++++++++++++----------
>>>>>    2 files changed, 16 insertions(+), 14 deletions(-)
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
>>>>> b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
>>>>> index 32b35a0..5889a3d 100644
>>>>> --- a/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
>>>>> +++ b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
>>>>> @@ -5,8 +5,8 @@ Required properties:
>>>>>    - spi-max-frequency: Maximum SPI frequency (<= 2000000).
>>>>>    - interrupt-parent: phandle of parent interrupt handler.
>>>>>    - interrupts: A single interrupt specifier.
>>>>> -- ti,enable-gpios: Two GPIO entries used for 'EN' and 'EN2' pins on
>>>>> the
>>>>> -  TRF7970A.
>>>>> +- ti,enable-gpios: One or two GPIO entries used for 'EN' and 'EN2'
>>>>> pins
>>>>> on the
>>>>> +  TRF7970A. EN2 is optional.
>>>>
>>>>
>>>>
>>>> Could EN ever be optional/fixed? If so, perhaps deprecate this property
>>>> and do 2 properties, one for each pin.
>>>
>>>
>>>
>>> The hardware I have has the EN2 pin fix connected to ground. Looking
>>> into http://www.ti.com/lit/ds/slos743k/slos743k.pdf page 19 table 6-3
>>> and 6-4 the EN2 pin is a don;t core if EN = 1. If EN = 0 EN2 pin
>>> selects between Power Down and Sleep Mode ... I see no reason why
>>> this is not possible/allowed ...
>>>
>>> Hmm.. I do not like the idea of deprecating the "ti,enable-gpios"
>>> property into 2 seperate properties ... but if this would be a reason
>>> for not accepting this patch, I can do this ... How should I name
>>> the 2 new properties?
>>
>>
>> I guess if this ever happens, then we just add "ti,enable2-gpios" and
>> ti,enable-gpios continues to point to EN. We don't need to deprecate
>> anything (or maybe just deprecate having both GPIOs on single
>> property).
>>
>> In that case,
>>
>> Acked-by: Rob Herring <robh@kernel.org>
>
>
> gentle ping.
>
> Are there any more comments to this patch? Is it acceptable as it
> is?

I acked it, so yes, it is fine.

Rob

^ permalink raw reply

* Re: [OpenWrt-Devel] ATH10K VLAN firmware issue
From: Bruno Antunes @ 2017-02-21 16:47 UTC (permalink / raw)
  To: Tom Psyborg
  Cc: Valo, Kalle, OpenWrt Development List, linux-wireless,
	ath10k@lists.infradead.org, voncken
In-Reply-To: <CAKR_QVLpSWab-kF-f8=xqw+oWAfA966GDm7CtXrWfzmJz8gP-w@mail.gmail.com>

On 21 February 2017 at 13:42, Tom Psyborg <pozega.tomislav@gmail.com> wrote:
> have you tried this one
> https://forum.lede-project.org/t/new-qca988x-firmware-with-mesh-support/1587

>From my testing it does not work.

>
> On 21 February 2017 at 14:19, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
>>
>> voncken <cedric.voncken@acksys.fr> writes:
>>
>> > Do you know if the firmware team planned to fix the VLAN issue on ath10k
>> > firmware?
>>
>> I reported it forward only this week.
>>
>> --
>> Kalle Valo
>> _______________________________________________
>> openwrt-devel mailing list
>> openwrt-devel@lists.openwrt.org
>> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
>
>
>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
>

^ permalink raw reply

* ANNOUNCE: Netdev 2.1 CFP extended
From: Jamal Hadi Salim @ 2017-02-21 17:57 UTC (permalink / raw)
  To: netdev@vger.kernel.org
  Cc: netfilter-devel, netfilter, info, linux-wireless, tech-committee,
	David Miller, Stephen Jaworski, lwn, people, Brenda Butler



The tech committee has graciously extended the CFP to February 27th.
Hurry o thee procastinators and submit early to avoid the hazards of
last minute traffic. Refer to:
https://netdevconf.org/2.1/submit-proposal.html

Some reminders, again:
-Registration is open. Register early so we can plan better.
https://onlineregistrations.ca/netdev21/

- hotel (If you can get the hotel cheaper online than conference
rates please send us email, dont book ):
https://www.netdevconf.org/2.1/hotel.html

cheers,
jamal

^ permalink raw reply

* Re: [PATCH 1/2] firmware: add more flexible request_firmware_async function
From: Luis R. Rodriguez @ 2017-02-21 17:59 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Ming Lei, Luis R . Rodriguez, Greg KH, Linux Kernel Mailing List,
	Kalle Valo, Arend van Spriel, linux-wireless,
	brcm80211-dev-list.pdl, Rafał Miłecki
In-Reply-To: <20170215222948.21030-1-zajec5@gmail.com>

On Wed, Feb 15, 2017 at 11:29:47PM +0100, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
> 
> So far we got only one function for loading firmware asynchronously:
> request_firmware_nowait. It didn't allow much customization of firmware
> loading process - there is only one bool uevent argument. Moreover this
> bool also controls user helper in an unclear way.
> 
> Resolve this problem by adding a one flexible function 

You've just taken under-the-hood flags and exposed them without considering and
enabling easy testing of any possible conflicts here.  Take for instance the
FW_OPT_NOCACHE feature -- not using caching functionality has implications for
driver developers -- they *must* resolve their own suspend/resume mishaps.
Another example, when we get firmware signing having just flags won't cut it
for optional parameters, we want a struct with the ability to specify custom
signing requirements. Exposing just flags will not cut it for us long term and
we'd have to then either add new export symbol or modify this one.

This is not as flexible nor as well documented as I want for future
functionality. Nor is there any series of battery of tests of all possible
options to ensure we do not regress. I've addressed this in the driver data
series.

> and making old
> request_firmware_nowait a simple inline using new solution. 

This I had not addressed in the driver data series but I will fold similar
strategy onto it.

> This
> implementation:
> 1) Modifies only single bits on existing code
> 2) Doesn't require adjusting / rewriting current drivers
> 3) Adds new function for drivers that need more control over loading a
>    firmware. Thanks to using flags more features can be added later.

As I noted in the driver data series -- we're passed using the firmware API for
non-firmware specific stuff, and as recent history shows regressions are are
easy, specially with the fallback mechanism. A new API which just gives us
2 calls: sync/async calls and shares a common set of optional parameters is
what we need, we need proper testing to ensure we also don't regress should
new features be introduced.

What I'll do is I'll integrate the feature you are asking for here and fold
this into the driver data series as what we need now is actual users of new
functionality, not just a test driver.

  Luis

^ permalink raw reply

* Re: [PATCH V2 1/2] firmware: add more flexible request_firmware_async function
From: Luis R. Rodriguez @ 2017-02-21 18:02 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Ming Lei, Luis R . Rodriguez, Greg KH, Linux Kernel Mailing List,
	Kalle Valo, Arend van Spriel, linux-wireless,
	brcm80211-dev-list.pdl, Rafał Miłecki
In-Reply-To: <20170216072636.7128-1-zajec5@gmail.com>

On Thu, Feb 16, 2017 at 08:26:35AM +0100, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
> 
> So far we got only one function for loading firmware asynchronously:
> request_firmware_nowait. It didn't allow much customization of firmware
> loading process - there is only one bool uevent argument. Moreover this
> bool also controls user helper in an unclear way.
> 
> Resolve this problem by adding a one flexible function and making old
> request_firmware_nowait a simple inline using new solution. This
> implementation:
> 1) Modifies only single bits on existing code
> 2) Doesn't require adjusting / rewriting current drivers
> 3) Adds new function for drivers that need more control over loading a
>    firmware. Thanks to using flags more features can be added later.
> 
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> ---
> This patch is based on top of
> [PATCH V2 RESEND] firmware: simplify defining and handling FW_OPT_FALLBACK
> applied on top of Linux 4.10-rc8.
> 
> Ming/Luis/Greg: assuming this gets a positive review, could someone of you pick
> this patchset? Second patch modifies brcmfmac, I'll try to get a proper Ack for
> that one.
> Unless you want this to go through wireless tree, then let me know please.

As I noted in the v1 post, just exposing all the flags under the hood is not
enough to ensure sanity here. Additionally just flags won't cut it to make this
as flexible as we need. I've addressed this in the driver data series, so I'll
take this feature request and fold it in there.

  Luis

^ permalink raw reply

* Re: [PATCH V3 1/2] firmware: add more flexible request_firmware_async function
From: Luis R. Rodriguez @ 2017-02-21 18:04 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Ming Lei, Luis R . Rodriguez, Greg KH, Linux Kernel Mailing List,
	Kalle Valo, Arend van Spriel, linux-wireless,
	brcm80211-dev-list.pdl, Rafał Miłecki
In-Reply-To: <20170221094754.15406-1-zajec5@gmail.com>

On Tue, Feb 21, 2017 at 10:47:53AM +0100, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
> 
> So far we got only one function for loading firmware asynchronously:
> request_firmware_nowait. It didn't allow much customization of firmware
> loading process - there is only one bool uevent argument. Moreover this
> bool also controls user helper in an unclear way.
> 
> Resolve this problem by adding a one flexible function and making old
> request_firmware_nowait a simple inline using new solution. This
> implementation:
> 1) Modifies only single bits on existing code
> 2) Doesn't require adjusting / rewriting current drivers
> 3) Adds new function for drivers that need more control over loading a
>    firmware. Thanks to using flags more features can be added later.
> 
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> ---
> This patch is based on top of
> [PATCH V2 RESEND] firmware: simplify defining and handling FW_OPT_FALLBACK
> applied on top of Linux 4.10-rc8.
> 
> Ming/Luis/Greg: assuming this gets a positive review, could someone of you pick
> this patchset? Second patch modifies brcmfmac, I'll try to get a proper Ack for
> that one.
> Unless you want this to go through wireless tree, then let me know please.

As noted in the v1 and v2 series:

This is not as flexible as we need. I'll fold this functionality in to the
driver data series as it provides more flexibility and enables more testing to
be done in userspace.

  Luis

^ permalink raw reply

* Re: [RFC 2/5] iwlwifi: fix request_module() use
From: Luis R. Rodriguez @ 2017-02-21 18:15 UTC (permalink / raw)
  To: Grumbach, Emmanuel
  Cc: Luis R. Rodriguez, Berg, Johannes, Coelho, Luciano, tj@kernel.org,
	arjan@linux.intel.com, ming.lei@canonical.com, zajec5@gmail.com,
	jeyu@redhat.com, rusty@rustcorp.com.au, pmladek@suse.com,
	gregkh@linuxfoundation.org, linuxwifi,
	linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <0BA3FCBA62E2DC44AF3030971E174FB3A8F4DEAB@hasmsx107.ger.corp.intel.com>

On Tue, Feb 21, 2017 at 07:16:16AM +0000, Grumbach, Emmanuel wrote:
> > 
> > a) just remove the print and use instead request_module_nowait() (this is
> > more in alignment of what your code actually does today; or
> > 
> > b) fix the request_module() use so that the error print matches the
> > expected and proper recommended use of request_module() (what this patch
> > does)
> > 
> > I prefer a) actually but I had to show what b) looked like first :)
>
> Me too. Let's do the simple thing. After all, it's been working for 5 years
> now (maybe more?) and I don't see a huge need to verify that the opmode
> module has been loaded.  It is very unlikely to fail anyway, and in the case
> it did fail, it's not that we can do much from iwlwifi point of view. 

I tend to agree with you on this, retries would be the only sensible thing to
do, but why do that -- the error should be logged right and addressed by any
upper layers. Its one reason to consider in the future adding verifiers
as built-in optional part of module loading.

> iwlwifi will stay loaded and sit idle since no opmode will be there to start
> using the hardware. We will keep having the device claimed, and will keep the
> interrupt registered and all that. No WiFi for you, but no harm caused
> either.

Fine by me. Will send follow up simple patches.

  Luis

^ permalink raw reply

* Re: ath10k regression on XPS13
From: David Miller @ 2017-02-21 18:18 UTC (permalink / raw)
  To: kvalo; +Cc: torvalds, jikos, linux-kernel, ath10k, linux-wireless
In-Reply-To: <87d1eb99dq.fsf_-_@purkki.adurom.net>

From: Kalle Valo <kvalo@codeaurora.org>
Date: Tue, 21 Feb 2017 11:32:49 +0200

> We are working on a fix so that ath10k continues to work with older
> board-2.bin, but that might take a day or two still.

Kalle I really wanted to send my net-next pull request to Linus later
today.  But I guess I have to wait for this ath10k first.

Please get this to me as soon as possible, thanks.

^ permalink raw reply

* Re: ath10k regression on XPS13
From: Kalle Valo @ 2017-02-21 18:38 UTC (permalink / raw)
  To: David Miller; +Cc: torvalds, jikos, linux-kernel, ath10k, linux-wireless
In-Reply-To: <20170221.131858.949421414784612398.davem@davemloft.net>

David Miller <davem@davemloft.net> writes:

> From: Kalle Valo <kvalo@codeaurora.org>
> Date: Tue, 21 Feb 2017 11:32:49 +0200
>
>> We are working on a fix so that ath10k continues to work with older
>> board-2.bin, but that might take a day or two still.
>
> Kalle I really wanted to send my net-next pull request to Linus later
> today.  But I guess I have to wait for this ath10k first.
>
> Please get this to me as soon as possible, thanks.

We have a fix now but it's not really tested that well so I'm reluctant
to submit it yet. As I don't want to make you wait I think I'll submit
you a patch reverting f2593cb1b291 in an hour or two. And later in the
week I send you a properly fixed (and tested) version of f2593cb1b291.

Does that sound ok to you?

-- 
Kalle Valo

^ permalink raw reply

* Re: TL-WN823N
From: Jes Sorensen @ 2017-02-21 18:44 UTC (permalink / raw)
  To: madmaxxx, linux-wireless
In-Reply-To: <58A5C340.3060201@email.it>

On 02/16/2017 10:20 AM, madmaxxx wrote:
> Hi,
>
> I have a problem with rtl8xxxu driver, which seems to not work with a
> dongle tp-link TL-WN823N model. I just filled out a 4.9.10 kernel and the
> device is not fully recognized .. I can only scan network and not link.
>
> Thank you

There is nothing in this output that looks unusual, you need to provide 
more data.

Jes


> lsusb:
> Bus 002 Device 002: ID 2357:0109
>
> dmesg:
> [gio feb 16 16:08:33 2017] usb 2-1: Vendor: Realtek
> [gio feb 16 16:08:33 2017] usb 2-1: Product: \x03802.11n NI
> [gio feb 16 16:08:33 2017] usb 2-1: Serial:
> [gio feb 16 16:08:33 2017] usb 2-1: rtl8192eu_parse_efuse: dumping efuse
> (0x200 bytes):
> [gio feb 16 16:08:33 2017] usb 2-1: 00: 29 81 00 7c 01 40 03 00
> [gio feb 16 16:08:33 2017] usb 2-1: 08: 40 74 04 50 14 00 00 00
> [gio feb 16 16:08:33 2017] usb 2-1: 10: 28 28 28 29 29 29 2a 2a
> [gio feb 16 16:08:33 2017] usb 2-1: 18: 2b 2b 2b f2 ef ef ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 20: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 28: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 30: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 38: ff ff 28 28 28 28 28 28
> [gio feb 16 16:08:33 2017] usb 2-1: 40: 2a 2a 29 2a 2a f2 ef ef
> [gio feb 16 16:08:33 2017] usb 2-1: 48: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 50: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 58: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 60: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 68: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 70: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 78: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 80: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 88: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 90: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 98: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: a0: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: a8: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: b0: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: b8: a1 22 21 00 00 00 ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: c0: ff 01 00 10 00 00 00 ff
> [gio feb 16 16:08:33 2017] usb 2-1: c8: 00 00 ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: d0: 57 23 09 01 e7 47 02 98
> [gio feb 16 16:08:33 2017] usb 2-1: d8: de d0 1e a4 d7 0a 03 52
> [gio feb 16 16:08:33 2017] usb 2-1: e0: 65 61 6c 74 65 6b 20 0e
> [gio feb 16 16:08:33 2017] usb 2-1: e8: 03 38 30 32 2e 31 31 6e
> [gio feb 16 16:08:33 2017] usb 2-1: f0: 20 4e 49 43 20 00 00 ff
> [gio feb 16 16:08:33 2017] usb 2-1: f8: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 100: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 108: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 110: ff ff ff ff ff ff ff 0d
> [gio feb 16 16:08:33 2017] usb 2-1: 118: 03 00 05 00 30 00 00 00
> [gio feb 16 16:08:33 2017] usb 2-1: 120: 00 93 ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 128: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 130: f6 a8 98 2d 03 92 98 00
> [gio feb 16 16:08:33 2017] usb 2-1: 138: fc 8c 00 11 9b 44 02 0a
> [gio feb 16 16:08:33 2017] usb 2-1: 140: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 148: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 150: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 158: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 160: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 168: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 170: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 178: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 180: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 188: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 190: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 198: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1a0: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1a8: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1b0: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1b8: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1c0: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1c8: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1d0: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1d8: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1e0: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1e8: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1f0: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: 1f8: ff ff ff ff ff ff ff ff
> [gio feb 16 16:08:33 2017] usb 2-1: RTL8192EU rev B (SMIC) 2T2R, TX
> queues 3, WiFi=1, BT=0, GPS=0, HI PA=0
> [gio feb 16 16:08:33 2017] usb 2-1: RTL8192EU MAC: 98:de:d0:1e:a4:d7
> [gio feb 16 16:08:33 2017] usb 2-1: rtl8xxxu: Loading firmware
> rtlwifi/rtl8192eu_nic.bin
>

^ permalink raw reply

* Re: ath10k regression on XPS13
From: Linus Torvalds @ 2017-02-21 18:52 UTC (permalink / raw)
  To: David Miller
  Cc: Kalle Valo, Jiri Kosina, Linux Kernel Mailing List,
	open list:QUALCOMM ATHEROS ATH10K WIRELESS DRIVER,
	Linux Wireless List
In-Reply-To: <20170221.131858.949421414784612398.davem@davemloft.net>

On Tue, Feb 21, 2017 at 10:18 AM, David Miller <davem@davemloft.net> wrote:
>
> Kalle I really wanted to send my net-next pull request to Linus later
> today.  But I guess I have to wait for this ath10k first.

Feel free to send it to me - it sounds like the regression is
 (a) easy to work around
and
 (b) has a fix coming up.

And it won't even be something that I personally notice, since I have
the prev-gen XPS13 that has intel wireless.

              Linus

^ permalink raw reply

* Re: ath10k regression on XPS13
From: David Miller @ 2017-02-21 18:53 UTC (permalink / raw)
  To: kvalo; +Cc: torvalds, jikos, linux-kernel, ath10k, linux-wireless
In-Reply-To: <87y3wzbd8n.fsf@kamboji.qca.qualcomm.com>

From: Kalle Valo <kvalo@codeaurora.org>
Date: Tue, 21 Feb 2017 20:38:48 +0200

> David Miller <davem@davemloft.net> writes:
> 
>> From: Kalle Valo <kvalo@codeaurora.org>
>> Date: Tue, 21 Feb 2017 11:32:49 +0200
>>
>>> We are working on a fix so that ath10k continues to work with older
>>> board-2.bin, but that might take a day or two still.
>>
>> Kalle I really wanted to send my net-next pull request to Linus later
>> today.  But I guess I have to wait for this ath10k first.
>>
>> Please get this to me as soon as possible, thanks.
> 
> We have a fix now but it's not really tested that well so I'm reluctant
> to submit it yet. As I don't want to make you wait I think I'll submit
> you a patch reverting f2593cb1b291 in an hour or two. And later in the
> week I send you a properly fixed (and tested) version of f2593cb1b291.
> 
> Does that sound ok to you?

Sure.

^ permalink raw reply

* Problem with RTL8191SU driver
From: Marius Melzer @ 2017-02-21 19:23 UTC (permalink / raw)
  To: linux-wireless

Hi,

I have a usb wifi stick with a RTL8191SU chipset and the driver doesn't
work for me (at least I think that's the problem). I'm using the
following driver: [1] which refers on its page to this email address for
reports.

I listed all relevant information in a post [2] in the archlinux forum,
espescially interesting is probably the dmesg output [3] and the
systemctl status NetworkManager output [4]. Also with NetworkManager
stopped it doesn't work (which was one of the proposed solutions): [5]

Is this a driver problem? If yes, how can I solve this? Espescially the
"does not support SSID scanning" is a bit weird for a usb wifi stick
which should at least support this, right?

Thanks in advance,
Marius

PS: Please keep me in CC or send me a quick message if I need to
subscribe to the mailinglist to follow the thread.

[1] https://github.com/chunkeey/rtl8192su
[2] https://bbs.archlinux.org/viewtopic.php?id=223264
[3] https://bbs.archlinux.org/viewtopic.php?pid=1691938#p1691938
[4] https://bbs.archlinux.org/viewtopic.php?pid=1692639#p1692639
[5] https://bbs.archlinux.org/viewtopic.php?pid=1692790#p1692790

^ permalink raw reply

* [PATCH] Revert "ath10k: Search SMBIOS for OEM board file extension"
From: Kalle Valo @ 2017-02-21 19:47 UTC (permalink / raw)
  To: netdev; +Cc: linux-wireless, ath10k

This reverts commit f2593cb1b29185d38db706cbcbe22ed538720ae1.

Paul reported that this patch with older board-2.bin ath10k initialisation
fails on Dell XPS 13:

ath10k_pci 0000:3a:00.0: failed to fetch board data for bus=pci,vendor=168c,
device=003e,subsystem-vendor=1a56,subsystem-device=1535,variant=RV_0520 from
ath10k/QCA6174/hw3.0/board-2.bin

The reason is that the older board-2.bin does not have the variant version of
the image name and ath10k does not fallback to the older naming scheme.

Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=185621#c9
Fixes: f2593cb1b291 ("ath10k: Search SMBIOS for OEM board file extension")
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---

Dave, please take this directly if you can.

 drivers/net/wireless/ath/ath10k/core.c | 84 ++--------------------------------
 drivers/net/wireless/ath/ath10k/core.h | 19 --------
 2 files changed, 3 insertions(+), 100 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 59729aa8cd82..dd902b43f8f7 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -18,8 +18,6 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/of.h>
-#include <linux/dmi.h>
-#include <linux/ctype.h>
 #include <asm/byteorder.h>
 
 #include "core.h"
@@ -713,72 +711,6 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
 	return 0;
 }
 
-static void ath10k_core_check_bdfext(const struct dmi_header *hdr, void *data)
-{
-	struct ath10k *ar = data;
-	const char *bdf_ext;
-	const char *magic = ATH10K_SMBIOS_BDF_EXT_MAGIC;
-	u8 bdf_enabled;
-	int i;
-
-	if (hdr->type != ATH10K_SMBIOS_BDF_EXT_TYPE)
-		return;
-
-	if (hdr->length != ATH10K_SMBIOS_BDF_EXT_LENGTH) {
-		ath10k_dbg(ar, ATH10K_DBG_BOOT,
-			   "wrong smbios bdf ext type length (%d).\n",
-			   hdr->length);
-		return;
-	}
-
-	bdf_enabled = *((u8 *)hdr + ATH10K_SMBIOS_BDF_EXT_OFFSET);
-	if (!bdf_enabled) {
-		ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not found.\n");
-		return;
-	}
-
-	/* Only one string exists (per spec) */
-	bdf_ext = (char *)hdr + hdr->length;
-
-	if (memcmp(bdf_ext, magic, strlen(magic)) != 0) {
-		ath10k_dbg(ar, ATH10K_DBG_BOOT,
-			   "bdf variant magic does not match.\n");
-		return;
-	}
-
-	for (i = 0; i < strlen(bdf_ext); i++) {
-		if (!isascii(bdf_ext[i]) || !isprint(bdf_ext[i])) {
-			ath10k_dbg(ar, ATH10K_DBG_BOOT,
-				   "bdf variant name contains non ascii chars.\n");
-			return;
-		}
-	}
-
-	/* Copy extension name without magic suffix */
-	if (strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic),
-		    sizeof(ar->id.bdf_ext)) < 0) {
-		ath10k_dbg(ar, ATH10K_DBG_BOOT,
-			   "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
-			    bdf_ext);
-		return;
-	}
-
-	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-		   "found and validated bdf variant smbios_type 0x%x bdf %s\n",
-		   ATH10K_SMBIOS_BDF_EXT_TYPE, bdf_ext);
-}
-
-static int ath10k_core_check_smbios(struct ath10k *ar)
-{
-	ar->id.bdf_ext[0] = '\0';
-	dmi_walk(ath10k_core_check_bdfext, ar);
-
-	if (ar->id.bdf_ext[0] == '\0')
-		return -ENODATA;
-
-	return 0;
-}
-
 static int ath10k_download_and_run_otp(struct ath10k *ar)
 {
 	u32 result, address = ar->hw_params.patch_load_addr;
@@ -1125,9 +1057,6 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
 static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
 					 size_t name_len)
 {
-	/* strlen(',variant=') + strlen(ar->id.bdf_ext) */
-	char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };
-
 	if (ar->id.bmi_ids_valid) {
 		scnprintf(name, name_len,
 			  "bus=%s,bmi-chip-id=%d,bmi-board-id=%d",
@@ -1137,15 +1066,12 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
 		goto out;
 	}
 
-	if (ar->id.bdf_ext[0] != '\0')
-		scnprintf(variant, sizeof(variant), ",variant=%s",
-			  ar->id.bdf_ext);
-
 	scnprintf(name, name_len,
-		  "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
+		  "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x",
 		  ath10k_bus_str(ar->hif.bus),
 		  ar->id.vendor, ar->id.device,
-		  ar->id.subsystem_vendor, ar->id.subsystem_device, variant);
+		  ar->id.subsystem_vendor, ar->id.subsystem_device);
+
 out:
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name);
 
@@ -2202,10 +2128,6 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 		goto err_free_firmware_files;
 	}
 
-	ret = ath10k_core_check_smbios(ar);
-	if (ret)
-		ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not set.\n");
-
 	ret = ath10k_core_fetch_board_file(ar);
 	if (ret) {
 		ath10k_err(ar, "failed to fetch board file: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 88d14be7fcce..757242ef52ac 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -69,23 +69,6 @@
 #define ATH10K_NAPI_BUDGET      64
 #define ATH10K_NAPI_QUOTA_LIMIT 60
 
-/* SMBIOS type containing Board Data File Name Extension */
-#define ATH10K_SMBIOS_BDF_EXT_TYPE 0xF8
-
-/* SMBIOS type structure length (excluding strings-set) */
-#define ATH10K_SMBIOS_BDF_EXT_LENGTH 0x9
-
-/* Offset pointing to Board Data File Name Extension */
-#define ATH10K_SMBIOS_BDF_EXT_OFFSET 0x8
-
-/* Board Data File Name Extension string length.
- * String format: BDF_<Customer ID>_<Extension>\0
- */
-#define ATH10K_SMBIOS_BDF_EXT_STR_LENGTH 0x20
-
-/* The magic used by QCA spec */
-#define ATH10K_SMBIOS_BDF_EXT_MAGIC "BDF_"
-
 struct ath10k;
 
 enum ath10k_bus {
@@ -815,8 +798,6 @@ struct ath10k {
 		bool bmi_ids_valid;
 		u8 bmi_board_id;
 		u8 bmi_chip_id;
-
-		char bdf_ext[ATH10K_SMBIOS_BDF_EXT_STR_LENGTH];
 	} id;
 
 	int fw_api;
-- 
2.7.4

^ permalink raw reply related

* Re: ath10k regression on XPS13
From: Kalle Valo @ 2017-02-21 19:49 UTC (permalink / raw)
  To: David Miller; +Cc: torvalds, jikos, linux-kernel, ath10k, linux-wireless
In-Reply-To: <20170221.135337.291678413491553794.davem@davemloft.net>

David Miller <davem@davemloft.net> writes:

> From: Kalle Valo <kvalo@codeaurora.org>
> Date: Tue, 21 Feb 2017 20:38:48 +0200
>
>> David Miller <davem@davemloft.net> writes:
>> 
>>> From: Kalle Valo <kvalo@codeaurora.org>
>>> Date: Tue, 21 Feb 2017 11:32:49 +0200
>>>
>>>> We are working on a fix so that ath10k continues to work with older
>>>> board-2.bin, but that might take a day or two still.
>>>
>>> Kalle I really wanted to send my net-next pull request to Linus later
>>> today.  But I guess I have to wait for this ath10k first.
>>>
>>> Please get this to me as soon as possible, thanks.
>> 
>> We have a fix now but it's not really tested that well so I'm reluctant
>> to submit it yet. As I don't want to make you wait I think I'll submit
>> you a patch reverting f2593cb1b291 in an hour or two. And later in the
>> week I send you a properly fixed (and tested) version of f2593cb1b291.
>> 
>> Does that sound ok to you?
>
> Sure.

Here's the revert:

https://patchwork.ozlabs.org/patch/730735/

I didn't send a pull request because that felt overkill to do just for
one patch.

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH] cfg80211: support 4-way handshake offloading for WPA/WPA2-PSK
From: Arend Van Spriel @ 2017-02-21 19:57 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: Eliad Peller, Jouni Malinen, Jithu Jance
In-Reply-To: <1487680651.2215.5.camel@sipsolutions.net>

On 21-2-2017 13:37, Johannes Berg wrote:
> 
>> What I am also missing is how to deal with NL80211_CMD_CONNECTED
>> event signalling. Should that be given after (un)successful
>> completion of the 4-way handshake or should we have a separate event
>> for that? 
> 
> That's a good point. I don't think a new event really works well, but
> perhaps we should extend the NL80211_TIMEOUT_* values with this? It's
> not strictly a timeout, I guess, but it's not a direct rejection of the
> association either.
> 
> Any thoughts?

I discussed about the event mechanism with Jithu which is who asked me
to look at their patches for this feature. His suggestion was to have a
"port authorized" event after successful handshake as it will help in
key mgmt offload cases. He gave the following example: Suppose you are
doing a fresh 8021x followed by 4way handshake offload. Right now there
is no event to indicate to the upper layer that the 4way handshake have
been completed successfully. So the only thing to do in wpa_supplicant
is to consider it completed and if not be hit with deauth.

Regards,
Arend

^ permalink raw reply

* Re: [RFC 2/5] iwlwifi: fix request_module() use
From: Luis R. Rodriguez @ 2017-02-21 20:17 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Grumbach, Emmanuel, Berg, Johannes, Coelho, Luciano,
	tj@kernel.org, arjan@linux.intel.com, ming.lei@canonical.com,
	zajec5@gmail.com, jeyu@redhat.com, rusty@rustcorp.com.au,
	pmladek@suse.com, gregkh@linuxfoundation.org, linuxwifi,
	linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20170221181541.GN31264@wotan.suse.de>

On Tue, Feb 21, 2017 at 07:15:41PM +0100, Luis R. Rodriguez wrote:
> On Tue, Feb 21, 2017 at 07:16:16AM +0000, Grumbach, Emmanuel wrote:
> > > 
> > > a) just remove the print and use instead request_module_nowait() (this is
> > > more in alignment of what your code actually does today; or
> > > 
> > > b) fix the request_module() use so that the error print matches the
> > > expected and proper recommended use of request_module() (what this patch
> > > does)
> > > 
> > > I prefer a) actually but I had to show what b) looked like first :)
> >
> > Me too. Let's do the simple thing. After all, it's been working for 5 years
> > now (maybe more?) and I don't see a huge need to verify that the opmode
> > module has been loaded.  It is very unlikely to fail anyway, and in the case
> > it did fail, it's not that we can do much from iwlwifi point of view. 
> 
> I tend to agree with you on this, retries would be the only sensible thing to
> do, but why do that -- the error should be logged right and addressed by any
> upper layers. Its one reason to consider in the future adding verifiers
> as built-in optional part of module loading.

It would seem we still need to offload the opmode start as it is the one that
really should be issuing the completion, otherwise we would end up sending a
completion while the opmode module is being loaded asynchronously. The changes
are for that are still very likely desirable as it should help with speeding
boot up.

So the sharing of the opcode start will go first.

Will send v2.

  Luis

^ permalink raw reply


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