[RFC 09/10] ath10k: htt: High latency TX support

2017-01-13 Thread Erik Stromdahl
Add HTT TX function for HL interfaces.
Intended for SDIO and USB.

Signed-off-by: Erik Stromdahl 
---
 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 dd9e582..d40b3a0 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1826,9 +1826,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 *);
-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 505d3ed..e64c249 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, >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_le16(HTT_INVALID_PEERID);
+
+   res = ath10k_htc_send(>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 28bf199..477e170 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3531,7 +3531,10 @@ static int 

[RFC 08/10] ath10k: add start_once support

2017-01-13 Thread Erik Stromdahl
Add possibility to configure the driver to only start target once.
This can reduce startup time of SDIO devices significantly since
loading the firmware can take a substantial amount of time.

The patch is also necessary for high latency devices in general
since it does not seem to be possible to rerun the BMI phase
(fw upload) without power-cycling the device.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.c | 20 
 drivers/net/wireless/ath/ath10k/core.h |  2 ++
 drivers/net/wireless/ath/ath10k/hw.h   |  6 ++
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 31a9471..250e32b 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -302,6 +302,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
.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,
@@ -1841,6 +1842,9 @@ int ath10k_core_start(struct ath10k *ar, enum 
ath10k_firmware_mode mode,
int status;
u32 val;
 
+   if (ar->is_started && ar->hw_params.start_once)
+   return 0;
+
lockdep_assert_held(>conf_mutex);
 
clear_bit(ATH10K_FLAG_CRASH_FLUSH, >dev_flags);
@@ -2053,6 +2057,7 @@ int ath10k_core_start(struct ath10k *ar, enum 
ath10k_firmware_mode mode,
if (status)
goto err_hif_stop;
 
+   ar->is_started = true;
return 0;
 
 err_hif_stop:
@@ -2105,6 +2110,7 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_htt_tx_stop(>htt);
ath10k_htt_rx_free(>htt);
ath10k_wmi_detach(ar);
+   ar->is_started = false;
 }
 EXPORT_SYMBOL(ath10k_core_stop);
 
@@ -2202,12 +2208,18 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_unlock;
}
 
-   ath10k_debug_print_boot_info(ar);
-   ath10k_core_stop(ar);
+   /* Leave target running if hw_params.start_once is set */
+   if (ar->hw_params.start_once) {
+   mutex_unlock(>conf_mutex);
+   } else {
+   ath10k_debug_print_boot_info(ar);
+   ath10k_core_stop(ar);
 
-   mutex_unlock(>conf_mutex);
+   mutex_unlock(>conf_mutex);
+
+   ath10k_hif_power_down(ar);
+   }
 
-   ath10k_hif_power_down(ar);
return 0;
 
 err_unlock:
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index d9d7805..800f058 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -746,6 +746,8 @@ struct ath10k {
 
bool is_high_latency;
 
+   bool is_started;
+
struct {
enum ath10k_bus bus;
const struct ath10k_hif_ops *ops;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h 
b/drivers/net/wireless/ath/ath10k/hw.h
index 33186be..04ae66d 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -436,6 +436,12 @@ struct ath10k_hw_params {
bool is_high_latency;
 
enum ath10k_bus bus;
+
+   /* Specifies whether or not the device should be started once.
+* If set, the device will be started once by the early fw probe
+* and it will not be terminated afterwards.
+*/
+   bool start_once;
 };
 
 struct htt_rx_desc;
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC 04/10] ath10k: new fw fetch functionality

2017-01-13 Thread Erik Stromdahl
A new function for creating the fw file name dynamically.

Since both SDIO and USB based chipsets will use different
firmware from the PCIe and AHB chipsets, the fw file name
is created dynamically.

The new firmware names are:

For PCIe and AHB:
firmware-.bin (same as before)

For SDIO:
firmware-sdio-.bin

For USB:
firmware-usb-.bin

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.c | 56 --
 drivers/net/wireless/ath/ath10k/hw.h   |  4 +++
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index e985316..c275a52 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1284,44 +1284,40 @@ int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, 
const char *name,
return ret;
 }
 
+static void ath10k_core_get_fw_name(struct ath10k *ar, char *fw_name,
+   int fw_api)
+{
+   if ((ar->hif.bus != ATH10K_BUS_PCI) && (ar->hif.bus != ATH10K_BUS_AHB))
+   snprintf(fw_name, ATH10K_FW_FILE_NAME_MAX_LEN, "%s-%s-%d.bin",
+ATH10K_FW_FILE_BASE, ath10k_bus_str(ar->hif.bus),
+fw_api);
+   else
+   snprintf(fw_name, ATH10K_FW_FILE_NAME_MAX_LEN, "%s-%d.bin",
+ATH10K_FW_FILE_BASE, fw_api);
+}
+
 static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
 {
-   int ret;
+   int ret, i;
+   char fw_name[ATH10K_FW_FILE_NAME_MAX_LEN];
 
/* calibration file is optional, don't check for any errors */
ath10k_fetch_cal_file(ar);
 
-   ar->fw_api = 5;
-   ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-
-   ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE,
-  >normal_mode_fw.fw_file);
-   if (ret == 0)
-   goto success;
-
-   ar->fw_api = 4;
-   ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-
-   ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE,
-  >normal_mode_fw.fw_file);
-   if (ret == 0)
-   goto success;
-
-   ar->fw_api = 3;
-   ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-
-   ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE,
-  >normal_mode_fw.fw_file);
-   if (ret == 0)
-   goto success;
+   for (i = 5; i >= 2; i--) {
+   ar->fw_api = i;
+   ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n",
+  ar->fw_api);
 
-   ar->fw_api = 2;
-   ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
+   ath10k_core_get_fw_name(ar, fw_name, ar->fw_api);
+   ret = ath10k_core_fetch_firmware_api_n(ar, fw_name,
+  
>normal_mode_fw.fw_file);
+   if (!ret)
+   goto success;
+   }
 
-   ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE,
-  >normal_mode_fw.fw_file);
-   if (ret)
-   return ret;
+   /* We end up here if we couldn't fetch any firmware */
+   return ret;
 
 success:
ath10k_dbg(ar, ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
diff --git a/drivers/net/wireless/ath/ath10k/hw.h 
b/drivers/net/wireless/ath/ath10k/hw.h
index 6bdea86..9f4cd76 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -128,6 +128,10 @@ enum qca9377_chip_id_rev {
 #define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin"
 #define QCA4019_HW_1_0_PATCH_LOAD_ADDR  0x1234
 
+#define ATH10K_FW_FILE_NAME_MAX_LEN100
+
+#define ATH10K_FW_FILE_BASE"firmware"
+
 #define ATH10K_FW_API2_FILE"firmware-2.bin"
 #define ATH10K_FW_API3_FILE"firmware-3.bin"
 
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC 07/10] ath10k: per target configurablity of various items

2017-01-13 Thread Erik Stromdahl
Added ability to set bus type and configure the max number of
peers in the ath10k_hw_params struct.

With this functionality it is possible to have a different
hw configuration depending on bus type for the same radio
chipset.

E.g. SDIO and USB devices using the same chipset as PCIe
devices will potentially use different board files and perhaps
other configuration parameters.

One such parameter is the max number of peers.
Instead of using a default value (suitable for PCIe devices)
derived from the WMI op version, a per target value can be
used instead.

This is needed by the QCA9377 USB device in order to prevent
the target fw to crash after HTT RX ring cfg is issued.

Apparently, the QCA9377 HL device does not seem to handle the
same amount of peers as the LL devices.

A new struct ath10k_hw_params item for QCA9377 USB devices was
also added to ath10k_hw_params_list.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.c| 55 ++-
 drivers/net/wireless/ath/ath10k/core.h|  7 
 drivers/net/wireless/ath/ath10k/hw.h  | 23 +
 drivers/net/wireless/ath/ath10k/wmi-tlv.c |  4 +--
 4 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 573e772..31a9471 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -282,6 +282,28 @@ 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 = _ops,
+   .decap_align_bytes = 4,
+   .max_num_peers = TARGET_QCA9377_HL_NUM_PEERS,
+   .is_high_latency = true,
+   .bus = ATH10K_BUS_USB,
+   },
+   {
.id = QCA4019_HW_1_0_DEV_VERSION,
.dev_id = 0,
.name = "qca4019 hw1.0",
@@ -1487,9 +1509,19 @@ static int ath10k_init_hw_params(struct ath10k *ar)
for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
hw_params = _hw_params_list[i];
 
-   if (hw_params->id == ar->target_version &&
-   hw_params->dev_id == ar->dev_id)
-   break;
+   if (ar->is_high_latency) {
+   /* High latency devices will use different fw depending
+* on if it is a USB or SDIO device.
+*/
+   if (hw_params->bus == ar->hif.bus &&
+   hw_params->id == ar->target_version &&
+   hw_params->dev_id == ar->dev_id)
+   break;
+   } else {
+   if (hw_params->id == ar->target_version &&
+   hw_params->dev_id == ar->dev_id)
+   break;
+   }
}
 
if (i == ARRAY_SIZE(ath10k_hw_params_list)) {
@@ -1580,6 +1612,7 @@ static void ath10k_core_set_coverage_class_work(struct 
work_struct *work)
 static int ath10k_core_init_firmware_features(struct ath10k *ar)
 {
struct ath10k_fw_file *fw_file = >normal_mode_fw.fw_file;
+   int max_num_peers;
 
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) &&
!test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) {
@@ -1664,7 +1697,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
 
switch (fw_file->wmi_op_version) {
case ATH10K_FW_WMI_OP_VERSION_MAIN:
-   ar->max_num_peers = TARGET_NUM_PEERS;
+   max_num_peers = TARGET_NUM_PEERS;
ar->max_num_stations = TARGET_NUM_STATIONS;
ar->max_num_vdevs = TARGET_NUM_VDEVS;
ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;
@@ -1676,10 +1709,10 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
case ATH10K_FW_WMI_OP_VERSION_10_2:
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
if (ath10k_peer_stats_enabled(ar)) {
-   ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
+   max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;

[RFC 06/10] ath10k: disable frame aggregation for high latency

2017-01-13 Thread Erik Stromdahl
This patch disables frame aggregation for HL interfaces.
It is safest to do so until a mechanism for setting the limits
from fw etc. has been implemented.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.c | 9 +++--
 drivers/net/wireless/ath/ath10k/htt.h  | 4 
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index c275a52..573e772 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1615,8 +1615,13 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
return -EINVAL;
}
 
-   ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
-   ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;
+   if (ar->is_high_latency) {
+   ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_HL;
+   ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_HL;
+   } else {
+   ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
+   ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;
+   }
 
if (rawmode) {
if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
diff --git a/drivers/net/wireless/ath/ath10k/htt.h 
b/drivers/net/wireless/ath/ath10k/htt.h
index 3d1bd6f..dd9e582 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1777,6 +1777,10 @@ struct htt_rx_desc {
 #define ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT 3
 #define ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT 64
 
+/* Disable frame aggregation for high latency devices */
+#define ATH10K_HTT_MAX_NUM_AMSDU_HL 1
+#define ATH10K_HTT_MAX_NUM_AMPDU_HL 1
+
 int ath10k_htt_connect(struct ath10k_htt *htt);
 int ath10k_htt_init(struct ath10k *ar);
 int ath10k_htt_setup(struct ath10k_htt *htt);
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC 02/10] ath10k: usb support

2017-01-13 Thread Erik Stromdahl
usb HIF implementation

Signed-off-by: Erik Stromdahl 
---
 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 9a03178..c8b95e0 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -27,6 +27,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 000..4ccf36a
--- /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 Erik Stromdahl.
+ *
+ * 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 
+#include 
+
+#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(>ar_usb->cs_lock, flags);
+   if (!list_empty(>urb_list_head)) {
+   urb_context =
+   list_first_entry(>urb_list_head,
+struct ath10k_urb_context, link);
+   list_del(_context->link);
+   pipe->urb_cnt--;
+   }
+   spin_unlock_irqrestore(>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(>ar_usb->cs_lock, flags);
+   pipe->urb_cnt++;
+
+   list_add(_context->link, >urb_list_head);
+   spin_unlock_irqrestore(>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 

[RFC 01/10] ath10k: various usb related definitions

2017-01-13 Thread Erik Stromdahl
Definitions for USB based chipsets

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.h  | 3 +++
 drivers/net/wireless/ath/ath10k/debug.h | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index 1ffef90..3f865c0 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -75,6 +75,7 @@ enum ath10k_bus {
ATH10K_BUS_PCI,
ATH10K_BUS_AHB,
ATH10K_BUS_SDIO,
+   ATH10K_BUS_USB,
 };
 
 static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@@ -86,6 +87,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
return "ahb";
case ATH10K_BUS_SDIO:
return "sdio";
+   case ATH10K_BUS_USB:
+   return "usb";
}
 
return "unknown";
diff --git a/drivers/net/wireless/ath/ath10k/debug.h 
b/drivers/net/wireless/ath/ath10k/debug.h
index 257d109..548ad54 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -40,6 +40,8 @@ enum ath10k_debug_mask {
ATH10K_DBG_AHB  = 0x8000,
ATH10K_DBG_SDIO = 0x0001,
ATH10K_DBG_SDIO_DUMP= 0x0002,
+   ATH10K_DBG_USB  = 0x0004,
+   ATH10K_DBG_USB_BULK = 0x0008,
ATH10K_DBG_ANY  = 0x,
 };
 
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC 03/10] ath10k: high_latency detection

2017-01-13 Thread Erik Stromdahl
The setup of high latency chips (USB and SDIO) is
sometimes different than for chips using low latency
interfaces.

The bus type is used to determine if the interface is
a high latency interface.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.c | 1 +
 drivers/net/wireless/ath/ath10k/core.h | 7 +++
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index e34c734..e985316 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2294,6 +2294,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, 
struct device *dev,
ar->hw_rev = hw_rev;
ar->hif.ops = hif_ops;
ar->hif.bus = bus;
+   ar->is_high_latency = ath10k_is_high_latency(bus);
 
switch (hw_rev) {
case ATH10K_HW_QCA988X:
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index 3f865c0..c58250c 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -751,6 +751,8 @@ struct ath10k {
 
bool p2p;
 
+   bool is_high_latency;
+
struct {
enum ath10k_bus bus;
const struct ath10k_hif_ops *ops;
@@ -967,6 +969,11 @@ static inline bool ath10k_peer_stats_enabled(struct ath10k 
*ar)
return false;
 }
 
+static inline bool ath10k_is_high_latency(enum ath10k_bus bus)
+{
+   return ((bus == ATH10K_BUS_SDIO) || (bus == ATH10K_BUS_USB));
+}
+
 struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
  enum ath10k_bus bus,
  enum ath10k_hw_rev hw_rev,
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC 00/10] ath10k usb support

2017-01-13 Thread Erik Stromdahl
This patch series adds usb support to ath10k.

The target device used during development was a Linksys WUSB6100M
based on QCA9377.

I have tried to verify that the patches have not broken the existing
PCIe support since some of the patches affect the generic code as well.
To this end I have used a QCA9880 PCIe device operating in STA mode.

This patch series is depending on my previous sdio RFC (currently
version 3) since both these implementations share a lot of common
code. Hence, the sdio patches must be applied before these patches
can be applied!

* overview of patches *

patch 1 adds some usb definitions needed by the HIF layer.

patch 2 contains the actual usb HIF implementation.

patch 3 adds a is_high_latency check functionality

patch 4 introduces a new mechanism for fw fetch where the bus name is
used to determine which files to fetch (so we can have different fw for
usb and sdio).

patch 5 adds a HL version of the RX ring config.
This patch is applicable for sdio as well.

patch 6 sets the AMPDU and AMSDU limit to 1 for HL interfaces.
I believe this is the same thing as disabling frame aggregation but
I am not entirely sure (perhaps it just disables aggregation from
target to host). The reason for this patch is to have a simple setup
as possible. I have tried without this patch and the behavior is
identical so perhaps it should be removed from the series.

patch 7 adds more members to the ath10k_hw_params structure. These is
done in order to make it easier to separate HL config from LL config.
Some of stuff in here could potentially be added as elements in the
firmware file.

patch 8 adds "start once" functionality. It is used to leave the target
running after the BMI init phase in ath10k_core_probe_fw.
Could potentially be added as an element in the firmware file.

The last two patches (9 and 10) adds high latency RX and TX support.
These patches are applicable for sdio as well.

* testing *

The following functionality have been tested:

- connection to an 802.11ac AP with WPA2 PSK security.
- dhcp lease of ipv4 address
- pinging of access point and a few other devices on my home network
- TX/RX of TCP and UDP messages using netcat

UDP and TCP RX/TX is unfortunately not stable.
Currently I am only capable of receiving ~2.7 Mbytes over TCP before
the device stops receiving.

My RX/TX test looks like this:

Computer A (receiver):
nc -l -p 12345 > /tmp/random-out

Computer B (transmitter):
time nc -w 3 192.168.1.233 12345 < random-test-file

192.168.1.233 was the IPv4 address the WUSB6100M was assigned on my
home network.

The TCP RX data is identical to the TX data (no data is lost) but the
receiver stops receiving after ~2.7 Mbytes, so the RX data (/tmp/random-out
in my example) will be a truncated version of the TX file (random-test-file)

Adding a "-u" flag to netcat will do the same with UDP instead of TCP.

IMPORTANT:
It is possible to make the fw crash if an unsupported command or a
command with an unsupported setting is issued. This was the initial
problem I had with a crashing firmware after the RX ring config.
In this particular case the problem was related to an invalid init
message (containing an invalid maximum number of peers setting). There
could be more of this stuff in there that has not yet been fixed.
Depending on how wpa_supplicant etc. is configured there is a possibility
that the usb device will receive an unsupported command and crash.
It this happens, please enable logging and post the logs on the ath10k
mailing list.

* usb firmware *

Special firmware for usb is needed.
Linksys provide firmware for the QCA9377 version here:

http://www.linksys.com/us/support-article?articleNum=198580

The firmware must be converted into ath10k firmware using the below
command:

ath10k-fwencoder --create \
--otp=otp_AR6320.bin \
--firmware=athwlan_AR6320.bin \
--set-wmi-op-version=tlv \
--set-htt-op-version=tlv \
--set-fw-api=5 \
--features=ignore-otp-result

The firmware should be named firmware-usb-5.bin and should be placed
in /lib/firmware/ath10k/QCA9377/hw1.0

A board file is also needed:

cd /lib/firmware/ath10k/QCA9377/hw1.0
ln -s eeprom_qca9377_7_1p1_Robin_clpc_XXX.bin board-usb.bin

Pre-converted firmware can be obtained from my github fork of
ath10k-firmware:

https://github.com/erstrom/ath10k-firmware.git
branch: usb

Erik Stromdahl (10):
  ath10k: various usb related definitions
  ath10k: usb support
  ath10k: high_latency detection
  ath10k: new fw fetch functionality
  ath10k: htt: RX ring config HL support
  ath10k: disable frame aggregation for high latency
  ath10k: per target configurablity of various items
  ath10k: add start_once support
  ath10k: htt: High latency TX support
  ath10k: htt: High latency RX support

 drivers/net/wireless/ath/ath10k/Kconfig   |6 +
 drivers/net/wireless/ath/ath10k/Makefile  |3 +
 drivers/net/wireless/ath/ath10k/core.c|  179 +++--
 drivers/net/wireless/ath/ath10k/core.h|   17 +-
 drivers/net/wireless/ath/ath10k/debug.h   

[RFC 05/10] ath10k: htt: RX ring config HL support

2017-01-13 Thread Erik Stromdahl
Special HTT RX ring config message used by high latency
devices.

The main difference between HL and LL is that HL devices
do not use shared memory between device and host and thus,
no host paddr's are added to the RX config message.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htt.c|  5 +++-
 drivers/net/wireless/ath/ath10k/htt.h|  1 +
 drivers/net/wireless/ath/ath10k/htt_tx.c | 51 
 3 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.c 
b/drivers/net/wireless/ath/ath10k/htt.c
index cd160b1..29ed4af 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -258,7 +258,10 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
if (status)
return status;
 
-   status = ath10k_htt_send_rx_ring_cfg_ll(htt);
+   if (ar->is_high_latency)
+   status = ath10k_htt_send_rx_ring_cfg_hl(htt);
+   else
+   status = ath10k_htt_send_rx_ring_cfg_ll(htt);
if (status) {
ath10k_warn(ar, "failed to setup rx ring: %d\n",
status);
diff --git a/drivers/net/wireless/ath/ath10k/htt.h 
b/drivers/net/wireless/ath/ath10k/htt.h
index 44b25cf..3d1bd6f 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1797,6 +1797,7 @@ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
 int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
 int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt);
 int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt);
+int ath10k_htt_send_rx_ring_cfg_hl(struct ath10k_htt *htt);
 int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c 
b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 86b427f..505d3ed 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -692,6 +692,57 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
return 0;
 }
 
+int ath10k_htt_send_rx_ring_cfg_hl(struct ath10k_htt *htt)
+{
+   struct ath10k *ar = htt->ar;
+   struct sk_buff *skb;
+   struct htt_cmd *cmd;
+   struct htt_rx_ring_setup_ring *ring;
+   const int num_rx_ring = 1;
+   u16 flags;
+   int len;
+   int ret;
+
+   /*
+* the HW expects the buffer to be an integral number of 4-byte
+* "words"
+*/
+   BUILD_BUG_ON(!IS_ALIGNED(HTT_RX_BUF_SIZE, 4));
+   BUILD_BUG_ON((HTT_RX_BUF_SIZE & HTT_MAX_CACHE_LINE_SIZE_MASK) != 0);
+
+   len = sizeof(cmd->hdr) + sizeof(cmd->rx_setup.hdr)
+   + (sizeof(*ring) * num_rx_ring);
+   skb = ath10k_htc_alloc_skb(ar, len);
+   if (!skb)
+   return -ENOMEM;
+
+   skb_put(skb, len);
+
+   cmd = (struct htt_cmd *)skb->data;
+   ring = >rx_setup.rings[0];
+
+   cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_RX_RING_CFG;
+   cmd->rx_setup.hdr.num_rings = 1;
+
+   flags = 0;
+   flags |= HTT_RX_RING_FLAGS_MSDU_PAYLOAD;
+   flags |= HTT_RX_RING_FLAGS_UNICAST_RX;
+   flags |= HTT_RX_RING_FLAGS_MULTICAST_RX;
+
+   memset(ring, 0, sizeof(*ring));
+   ring->rx_ring_len = __cpu_to_le32(HTT_RX_RING_SIZE_MIN);
+   ring->rx_ring_bufsize = __cpu_to_le32(HTT_RX_BUF_SIZE);
+   ring->flags = __cpu_to_le16(flags);
+
+   ret = ath10k_htc_send(>ar->htc, htt->eid, skb);
+   if (ret) {
+   dev_kfree_skb_any(skb);
+   return ret;
+   }
+
+   return 0;
+}
+
 int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu)
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC v3 6/8] ath10k: sdio support

2017-01-13 Thread Erik Stromdahl
sdio/mailbox HIF implementation.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/Kconfig  |6 +
 drivers/net/wireless/ath/ath10k/Makefile |3 +
 drivers/net/wireless/ath/ath10k/sdio.c   | 2105 ++
 drivers/net/wireless/ath/ath10k/sdio.h   |  259 
 4 files changed, 2373 insertions(+)
 create mode 100644 drivers/net/wireless/ath/ath10k/sdio.c
 create mode 100644 drivers/net/wireless/ath/ath10k/sdio.h

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig 
b/drivers/net/wireless/ath/ath10k/Kconfig
index db1ca62..9a03178 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -21,6 +21,12 @@ config ATH10K_AHB
---help---
  This module adds support for AHB bus
 
+config ATH10K_SDIO
+   tristate "Atheros ath10k SDIO support (EXPERIMENTAL)"
+   depends on ATH10K && MMC
+   ---help---
+ This module adds support for SDIO/MMC 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 930fadd..b0b19a7 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -27,5 +27,8 @@ ath10k_pci-y += pci.o \
 
 ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o
 
+obj-$(CONFIG_ATH10K_SDIO) += ath10k_sdio.o
+ath10k_sdio-y += sdio.o
+
 # for tracing framework to find trace.h
 CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
new file mode 100644
index 000..cf911f3
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -0,0 +1,2105 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
+ * Copyright (c) 2016 Erik Stromdahl
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "core.h"
+#include "bmi.h"
+#include "debug.h"
+#include "hif.h"
+#include "htc.h"
+#include "targaddrs.h"
+#include "trace.h"
+#include "sdio.h"
+
+/* inlined helper functions */
+
+static inline int ath10k_sdio_calc_txrx_padded_len(struct ath10k_sdio *ar_sdio,
+  size_t len)
+{
+   return __ALIGN_MASK((len), ar_sdio->mbox_info.block_mask);
+}
+
+static inline enum ath10k_htc_ep_id pipe_id_to_eid(u8 pipe_id)
+{
+   return (enum ath10k_htc_ep_id)pipe_id;
+}
+
+static inline void ath10k_sdio_mbox_free_rx_pkt(struct ath10k_sdio_rx_data 
*pkt)
+{
+   dev_kfree_skb(pkt->skb);
+   pkt->skb = NULL;
+   pkt->alloc_len = 0;
+   pkt->act_len = 0;
+   pkt->trailer_only = false;
+}
+
+static inline int ath10k_sdio_mbox_alloc_rx_pkt(struct ath10k_sdio_rx_data 
*pkt,
+   size_t act_len, size_t full_len,
+   bool part_of_bundle,
+   bool last_in_bundle)
+{
+   pkt->skb = dev_alloc_skb(full_len);
+   if (!pkt->skb)
+   return -ENOMEM;
+
+   pkt->act_len = act_len;
+   pkt->alloc_len = full_len;
+   pkt->part_of_bundle = part_of_bundle;
+   pkt->last_in_bundle = last_in_bundle;
+   pkt->trailer_only = false;
+
+   return 0;
+}
+
+static inline bool is_trailer_only_msg(struct ath10k_sdio_rx_data *pkt)
+{
+   bool trailer_only = false;
+   struct ath10k_htc_hdr *htc_hdr =
+   (struct ath10k_htc_hdr *)pkt->skb->data;
+   u16 len = __le16_to_cpu(htc_hdr->len);
+
+   if (len == htc_hdr->trailer_len)
+   trailer_only = true;
+
+   return trailer_only;
+}
+
+/* sdio/mmc functions */
+
+static inline void ath10k_sdio_set_cmd52_arg(u32 *arg, u8 write, u8 raw,
+unsigned int address,
+unsigned char val)
+{
+   *arg = FIELD_PREP(BIT(31), write) |
+  FIELD_PREP(BIT(27), raw) |
+  FIELD_PREP(BIT(26), 1) |
+  FIELD_PREP(GENMASK(25, 9), address) |
+  FIELD_PREP(BIT(8), 1) |
+  

[RFC v3 3/8] ath10k: htc: move htc ctrl ep connect to htc_init

2017-01-13 Thread Erik Stromdahl
This patch moves the HTC ctrl service connect from
htc_wait_target to htc_init.

This is done in order to make sure the htc ctrl service
is setup properly before hif_start is called.

The reason for this is that we want the HTC ctrl service
callback to be initialized before the target sends the
HTC ready message.

The ready message will always be transmitted on endpoint 0
(which is always assigned to the HTC control service) so it
makes more sense if HTC control has been connected before the
ready message is received.

Since the service to pipe mapping is done as a part of
the service connect, the get_default_pipe call is redundant
and was removed.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htc.c | 39 +++
 1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c 
b/drivers/net/wireless/ath/ath10k/htc.c
index e72f385..f39eef6 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -584,8 +584,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
struct ath10k *ar = htc->ar;
int i, status = 0;
unsigned long time_left;
-   struct ath10k_htc_svc_conn_req conn_req;
-   struct ath10k_htc_svc_conn_resp conn_resp;
struct ath10k_htc_msg *msg;
u16 message_id;
u16 credit_count;
@@ -648,22 +646,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
return -ECOMM;
}
 
-   /* setup our pseudo HTC control endpoint connection */
-   memset(_req, 0, sizeof(conn_req));
-   memset(_resp, 0, sizeof(conn_resp));
-   conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete;
-   conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete;
-   conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS;
-   conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL;
-
-   /* connect fake service */
-   status = ath10k_htc_connect_service(htc, _req, _resp);
-   if (status) {
-   ath10k_err(ar, "could not connect to htc service (%d)\n",
-  status);
-   return status;
-   }
-
return 0;
 }
 
@@ -873,8 +855,10 @@ int ath10k_htc_start(struct ath10k_htc *htc)
 /* registered target arrival callback from the HIF layer */
 int ath10k_htc_init(struct ath10k *ar)
 {
-   struct ath10k_htc_ep *ep = NULL;
+   int status;
struct ath10k_htc *htc = >htc;
+   struct ath10k_htc_svc_conn_req conn_req;
+   struct ath10k_htc_svc_conn_resp conn_resp;
 
spin_lock_init(>tx_lock);
 
@@ -882,10 +866,21 @@ int ath10k_htc_init(struct ath10k *ar)
 
htc->ar = ar;
 
-   /* Get HIF default pipe for HTC message exchange */
-   ep = >endpoint[ATH10K_HTC_EP_0];
+   /* setup our pseudo HTC control endpoint connection */
+   memset(_req, 0, sizeof(conn_req));
+   memset(_resp, 0, sizeof(conn_resp));
+   conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete;
+   conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete;
+   conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS;
+   conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL;
 
-   ath10k_hif_get_default_pipe(ar, >ul_pipe_id, >dl_pipe_id);
+   /* connect fake service */
+   status = ath10k_htc_connect_service(htc, _req, _resp);
+   if (status) {
+   ath10k_err(ar, "could not connect to htc service (%d)\n",
+  status);
+   return status;
+   }
 
init_completion(>ctl_resp);
 
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC v3 7/8] ath10k: sdio get target info

2017-01-13 Thread Erik Stromdahl
Special BMI get target info function for SDIO.

Signed-off-by: Erik Stromdahl 
---
 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 2872d34..d9db153 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.c
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
@@ -88,6 +88,76 @@ int ath10k_bmi_get_target_info(struct ath10k *ar,
return 0;
 }
 
+#define TARGET_VERSION_SENTINAL 0xu
+
+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, , cmdlen, , );
+   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, ,
+ );
+   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: 
%lu\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,
+ _target_info.version,
+ );
+   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 7d3231a..8a5ef1b 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 874c2a7..e34c734 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2084,7 +2084,10 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
}
 
memset(_info, 0, sizeof(target_info));
-   ret = ath10k_bmi_get_target_info(ar, _info);
+   if (ar->hif.bus == ATH10K_BUS_SDIO)
+   ret = ath10k_bmi_get_target_info_sdio(ar, _info);
+   else
+   ret = ath10k_bmi_get_target_info(ar, _info);
if (ret) {
ath10k_err(ar, "could not get target info (%d)\n", ret);
goto err_power_down;
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC v3 4/8] ath10k: htc: refactorization

2017-01-13 Thread Erik Stromdahl
Code refactorization:

Moved the code for ep 0 in ath10k_htc_rx_completion_handler
to ath10k_htc_control_rx_complete.

This eases the implementation of SDIO/mbox significantly since
the ep_rx_complete cb is invoked directly from the SDIO/mbox
hif layer.

Since the ath10k_htc_control_rx_complete already is present
(only containing a warning message) there is no reason for not
using it (instead of having a special case for ep 0 in
ath10k_htc_rx_completion_handler).

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htc.c | 73 ---
 1 file changed, 34 insertions(+), 39 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c 
b/drivers/net/wireless/ath/ath10k/htc.c
index f39eef6..eb036b3 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -459,42 +459,6 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, 
struct sk_buff *skb)
/* zero length packet with trailer data, just drop these */
goto out;
 
-   if (eid == ATH10K_HTC_EP_0) {
-   struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
-
-   switch (__le16_to_cpu(msg->hdr.message_id)) {
-   case ATH10K_HTC_MSG_READY_ID:
-   case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
-   /* handle HTC control message */
-   if (completion_done(>ctl_resp)) {
-   /*
-* this is a fatal error, target should not be
-* sending unsolicited messages on the ep 0
-*/
-   ath10k_warn(ar, "HTC rx ctrl still 
processing\n");
-   complete(>ctl_resp);
-   goto out;
-   }
-
-   htc->control_resp_len =
-   min_t(int, skb->len,
- ATH10K_HTC_MAX_CTRL_MSG_LEN);
-
-   memcpy(htc->control_resp_buffer, skb->data,
-  htc->control_resp_len);
-
-   complete(>ctl_resp);
-   break;
-   case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
-   htc->htc_ops.target_send_suspend_complete(ar);
-   break;
-   default:
-   ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n");
-   break;
-   }
-   goto out;
-   }
-
ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
   eid, skb);
ep->ep_ops.ep_rx_complete(ar, skb);
@@ -509,9 +473,40 @@ EXPORT_SYMBOL(ath10k_htc_rx_completion_handler);
 static void ath10k_htc_control_rx_complete(struct ath10k *ar,
   struct sk_buff *skb)
 {
-   /* This is unexpected. FW is not supposed to send regular rx on this
-* endpoint. */
-   ath10k_warn(ar, "unexpected htc rx\n");
+   struct ath10k_htc *htc = >htc;
+   struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
+
+   switch (__le16_to_cpu(msg->hdr.message_id)) {
+   case ATH10K_HTC_MSG_READY_ID:
+   case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
+   /* handle HTC control message */
+   if (completion_done(>ctl_resp)) {
+   /* this is a fatal error, target should not be
+* sending unsolicited messages on the ep 0
+*/
+   ath10k_warn(ar, "HTC rx ctrl still processing\n");
+   complete(>ctl_resp);
+   goto out;
+   }
+
+   htc->control_resp_len =
+   min_t(int, skb->len,
+ ATH10K_HTC_MAX_CTRL_MSG_LEN);
+
+   memcpy(htc->control_resp_buffer, skb->data,
+  htc->control_resp_len);
+
+   complete(>ctl_resp);
+   break;
+   case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
+   htc->htc_ops.target_send_suspend_complete(ar);
+   break;
+   default:
+   ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n");
+   break;
+   }
+
+out:
kfree_skb(skb);
 }
 
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC v3 5/8] ath10k: various sdio related definitions

2017-01-13 Thread Erik Stromdahl
Debug masks for SDIO HIF layer.
Address definitions for SDIO/mbox based chipsets.
Augmented struct host_interest with more members.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.h  |  3 ++
 drivers/net/wireless/ath/ath10k/debug.h |  2 ++
 drivers/net/wireless/ath/ath10k/hw.h| 53 +
 drivers/net/wireless/ath/ath10k/targaddrs.h | 24 +
 4 files changed, 82 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index c7664d6..1ffef90 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -74,6 +74,7 @@ struct ath10k;
 enum ath10k_bus {
ATH10K_BUS_PCI,
ATH10K_BUS_AHB,
+   ATH10K_BUS_SDIO,
 };
 
 static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@@ -83,6 +84,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
return "pci";
case ATH10K_BUS_AHB:
return "ahb";
+   case ATH10K_BUS_SDIO:
+   return "sdio";
}
 
return "unknown";
diff --git a/drivers/net/wireless/ath/ath10k/debug.h 
b/drivers/net/wireless/ath/ath10k/debug.h
index 2368f47..257d109 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -38,6 +38,8 @@ enum ath10k_debug_mask {
ATH10K_DBG_WMI_PRINT= 0x2000,
ATH10K_DBG_PCI_PS   = 0x4000,
ATH10K_DBG_AHB  = 0x8000,
+   ATH10K_DBG_SDIO = 0x0001,
+   ATH10K_DBG_SDIO_DUMP= 0x0002,
ATH10K_DBG_ANY  = 0x,
 };
 
diff --git a/drivers/net/wireless/ath/ath10k/hw.h 
b/drivers/net/wireless/ath/ath10k/hw.h
index 7feffec..6bdea86 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -814,6 +814,59 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params 
*hw,
 #define QCA9887_EEPROM_ADDR_LO_MASK0x00ff
 #define QCA9887_EEPROM_ADDR_LO_LSB 16
 
+#define MBOX_RESET_CONTROL_ADDRESS 0x
+#define MBOX_HOST_INT_STATUS_ADDRESS   0x0800
+#define MBOX_HOST_INT_STATUS_ERROR_LSB 7
+#define MBOX_HOST_INT_STATUS_ERROR_MASK0x0080
+#define MBOX_HOST_INT_STATUS_CPU_LSB   6
+#define MBOX_HOST_INT_STATUS_CPU_MASK  0x0040
+#define MBOX_HOST_INT_STATUS_COUNTER_LSB   4
+#define MBOX_HOST_INT_STATUS_COUNTER_MASK  0x0010
+#define MBOX_CPU_INT_STATUS_ADDRESS0x0801
+#define MBOX_ERROR_INT_STATUS_ADDRESS  0x0802
+#define MBOX_ERROR_INT_STATUS_WAKEUP_LSB   2
+#define MBOX_ERROR_INT_STATUS_WAKEUP_MASK  0x0004
+#define MBOX_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 1
+#define MBOX_ERROR_INT_STATUS_RX_UNDERFLOW_MASK0x0002
+#define MBOX_ERROR_INT_STATUS_TX_OVERFLOW_LSB  0
+#define MBOX_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x0001
+#define MBOX_COUNTER_INT_STATUS_ADDRESS0x0803
+#define MBOX_COUNTER_INT_STATUS_COUNTER_LSB0
+#define MBOX_COUNTER_INT_STATUS_COUNTER_MASK   0x00ff
+#define MBOX_RX_LOOKAHEAD_VALID_ADDRESS0x0805
+#define MBOX_INT_STATUS_ENABLE_ADDRESS 0x0828
+#define MBOX_INT_STATUS_ENABLE_ERROR_LSB   7
+#define MBOX_INT_STATUS_ENABLE_ERROR_MASK  0x0080
+#define MBOX_INT_STATUS_ENABLE_CPU_LSB 6
+#define MBOX_INT_STATUS_ENABLE_CPU_MASK0x0040
+#define MBOX_INT_STATUS_ENABLE_INT_LSB 5
+#define MBOX_INT_STATUS_ENABLE_INT_MASK0x0020
+#define MBOX_INT_STATUS_ENABLE_COUNTER_LSB 4
+#define MBOX_INT_STATUS_ENABLE_COUNTER_MASK0x0010
+#define MBOX_INT_STATUS_ENABLE_MBOX_DATA_LSB   0
+#define MBOX_INT_STATUS_ENABLE_MBOX_DATA_MASK  0x000f
+#define MBOX_CPU_INT_STATUS_ENABLE_ADDRESS 0x0819
+#define MBOX_CPU_INT_STATUS_ENABLE_BIT_LSB 0
+#define MBOX_CPU_INT_STATUS_ENABLE_BIT_MASK0x00ff
+#define MBOX_ERROR_STATUS_ENABLE_ADDRESS   0x081a
+#define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB  1
+#define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x0002
+#define MBOX_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB   0
+#define MBOX_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK  0x0001
+#define MBOX_COUNTER_INT_STATUS_ENABLE_ADDRESS 0x081b
+#define MBOX_COUNTER_INT_STATUS_ENABLE_BIT_LSB 0
+#define MBOX_COUNTER_INT_STATUS_ENABLE_BIT_MASK0x00ff
+#define MBOX_COUNT_ADDRESS 0x0820
+#define MBOX_COUNT_DEC_ADDRESS 0x0840
+#define MBOX_WINDOW_DATA_ADDRESS   0x0874
+#define MBOX_WINDOW_WRITE_ADDR_ADDRESS 0x0878
+#define MBOX_WINDOW_READ_ADDR_ADDRESS  0x087c
+#define MBOX_CPU_DBG_SEL_ADDRESS   0x0883
+#define MBOX_CPU_DBG_ADDRESS   0x0884
+#define MBOX_RTC_BASE_ADDRESS  0x
+#define 

[RFC v3 0/8] ath10k sdio support

2017-01-13 Thread Erik Stromdahl
This is the third version of the sdio RFC patch series.
The actual sdio code (patch 6) has been subject to a massive overhaul,
mainly as a result of Kalle's review comments.
It no longer has any strong resemblance of the original ath6kl code from
which it was originally based upon.

Previous pathes 6 to 10 have been merged into one single patch.

The previous series had a rework of the "HTC fake service" connect
(ep 0 connect) that introduced a race between the actual endpoint
connect and the HTC ready message. This issue has been addressed,
and the current patches (3 and 4) has been rewritten accordingly.

* overview of patches *

Patches 1 to 4 are more or less identical to the previous RFC, with an
exception for patch 3 that changes the "HTC fake service" connect
(mentioned above).

Patch 5 is a squashed version of previous patches 6 to 10.

Patch 6 is the actual sdio patch

Patches 7 to 8 are new and adds special sdio versions of BMI get
target info and HTC ready.

The new version was built and tested against:
tag: ath-201701121109

Erik Stromdahl (8):
  ath10k: htc: made static function public
  ath10k: htc: rx trailer lookahead support
  ath10k: htc: move htc ctrl ep connect to htc_init
  ath10k: htc: refactorization
  ath10k: various sdio related definitions
  ath10k: sdio support
  ath10k: sdio get target info
  ath10k: htc: ready_ext msg support

 drivers/net/wireless/ath/ath10k/Kconfig |6 +
 drivers/net/wireless/ath/ath10k/Makefile|3 +
 drivers/net/wireless/ath/ath10k/bmi.c   |   70 +
 drivers/net/wireless/ath/ath10k/bmi.h   |2 +
 drivers/net/wireless/ath/ath10k/core.c  |5 +-
 drivers/net/wireless/ath/ath10k/core.h  |3 +
 drivers/net/wireless/ath/ath10k/debug.h |2 +
 drivers/net/wireless/ath/ath10k/htc.c   |  241 ++-
 drivers/net/wireless/ath/ath10k/htc.h   |   39 +-
 drivers/net/wireless/ath/ath10k/hw.h|   53 +
 drivers/net/wireless/ath/ath10k/sdio.c  | 2105 +++
 drivers/net/wireless/ath/ath10k/sdio.h  |  259 
 drivers/net/wireless/ath/ath10k/targaddrs.h |   24 +
 13 files changed, 2737 insertions(+), 75 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/sdio.c
 create mode 100644 drivers/net/wireless/ath/ath10k/sdio.h

-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC v3 8/8] ath10k: htc: ready_ext msg support

2017-01-13 Thread Erik Stromdahl
Added support for extended ready message.
The extended ready message contains the maximum bundle
count supported by SDIO chipsets.

It is transmitted by SDIO chipset only and replaces the
"standard" ready message in this case.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htc.c | 28 ++--
 drivers/net/wireless/ath/ath10k/htc.h |  5 +
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c 
b/drivers/net/wireless/ath/ath10k/htc.c
index eb036b3..3eaa9a8 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -581,8 +581,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
unsigned long time_left;
struct ath10k_htc_msg *msg;
u16 message_id;
-   u16 credit_count;
-   u16 credit_size;
 
time_left = wait_for_completion_timeout(>ctl_resp,
ATH10K_HTC_WAIT_TIMEOUT_HZ);
@@ -619,16 +617,14 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 
msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
message_id   = __le16_to_cpu(msg->hdr.message_id);
-   credit_count = __le16_to_cpu(msg->ready.credit_count);
-   credit_size  = __le16_to_cpu(msg->ready.credit_size);
 
if (message_id != ATH10K_HTC_MSG_READY_ID) {
ath10k_err(ar, "Invalid HTC ready msg: 0x%x\n", message_id);
return -ECOMM;
}
 
-   htc->total_transmit_credits = credit_count;
-   htc->target_credit_size = credit_size;
+   htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count);
+   htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size);
 
ath10k_dbg(ar, ATH10K_DBG_HTC,
   "Target ready! transmit resources: %d size:%d\n",
@@ -641,6 +637,19 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
return -ECOMM;
}
 
+   /* The only way to determine if the ready message is an extended
+* message is from the size.
+*/
+   if (htc->control_resp_len >=
+   sizeof(msg->hdr) + sizeof(msg->ready_ext)) {
+   htc->max_msgs_per_htc_bundle =
+   min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle,
+ HTC_HOST_MAX_MSG_PER_BUNDLE);
+   ath10k_dbg(ar, ATH10K_DBG_HTC,
+  "Extended ready message. RX bundle size: %d\n",
+  htc->max_msgs_per_htc_bundle);
+   }
+
return 0;
 }
 
@@ -836,6 +845,13 @@ int ath10k_htc_start(struct ath10k_htc *htc)
msg->hdr.message_id =
__cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID);
 
+   if (ar->hif.bus == ATH10K_BUS_SDIO) {
+   /* Extra setup params used by SDIO */
+   msg->setup_complete_ext.flags =
+   
__cpu_to_le32(ATH10K_HTC_SETUP_COMPLETE_FLAGS_RX_BNDL_EN);
+   msg->setup_complete_ext.max_msgs_per_bundled_recv =
+   htc->max_msgs_per_htc_bundle;
+   }
ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC is using TX credit flow control\n");
 
status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
diff --git a/drivers/net/wireless/ath/ath10k/htc.h 
b/drivers/net/wireless/ath/ath10k/htc.h
index 9a1db90..566e437 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -112,6 +112,10 @@ enum ath10k_htc_conn_svc_status {
ATH10K_HTC_CONN_SVC_STATUS_NO_MORE_EP   = 4
 };
 
+enum ath10k_htc_setup_complete_flags {
+   ATH10K_HTC_SETUP_COMPLETE_FLAGS_RX_BNDL_EN = 1
+};
+
 struct ath10k_ath10k_htc_msg_hdr {
__le16 message_id; /* @enum htc_message_id */
 } __packed;
@@ -360,6 +364,7 @@ struct ath10k_htc {
 
int total_transmit_credits;
int target_credit_size;
+   u8 max_msgs_per_htc_bundle;
 };
 
 int ath10k_htc_init(struct ath10k *ar);
-- 
2.7.4


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[RFC v3 2/8] ath10k: htc: rx trailer lookahead support

2017-01-13 Thread Erik Stromdahl
The RX trailer parsing is now capable of parsing lookahead reports.
A lookahead contains the first 4 bytes of the next HTC message
(that will be read in the next SDIO read operation).
Lookaheads are used by the SDIO/mbox HIF layer to determine if
the next message is part of a bundle, which endpoint it belongs
to and how long it is.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htc.c | 93 ++-
 drivers/net/wireless/ath/ath10k/htc.h | 30 +--
 2 files changed, 118 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c 
b/drivers/net/wireless/ath/ath10k/htc.c
index 35e67c4..e72f385 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -228,10 +228,76 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc,
spin_unlock_bh(>tx_lock);
 }
 
+static int
+ath10k_htc_process_lookahead(struct ath10k_htc *htc,
+const struct ath10k_htc_lookahead_report *report,
+int len,
+enum ath10k_htc_ep_id eid,
+void *next_lookaheads,
+int *next_lookaheads_len)
+{
+   struct ath10k *ar = htc->ar;
+
+   /* Invalid lookahead flags are actually transmitted by
+* the target in the HTC control message.
+* Since this will happen at every boot we silently ignore
+* the lookahead in this case
+*/
+   if (report->pre_valid != ((~report->post_valid) & 0xFF))
+   return 0;
+
+   if (next_lookaheads && next_lookaheads_len) {
+   ath10k_dbg(ar, ATH10K_DBG_HTC,
+  "htc rx lookahead found pre_valid 0x%x post_valid 
0x%x\n",
+  report->pre_valid, report->post_valid);
+
+   /* look ahead bytes are valid, copy them over */
+   memcpy((u8 *)next_lookaheads, report->lookahead, 4);
+
+   *next_lookaheads_len = 1;
+   }
+
+   return 0;
+}
+
+static int
+ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc,
+   const struct 
ath10k_htc_lookahead_report_bundle *report,
+   int len,
+   enum ath10k_htc_ep_id eid,
+   void *next_lookaheads,
+   int *next_lookaheads_len)
+{
+   struct ath10k *ar = htc->ar;
+   int bundle_cnt = len / sizeof(*report);
+
+   if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE)) {
+   ath10k_warn(ar, "Invalid lookahead bundle count: %d\n",
+   bundle_cnt);
+   return -EINVAL;
+   }
+
+   if (next_lookaheads && next_lookaheads_len) {
+   int i;
+
+   for (i = 0; i < bundle_cnt; i++) {
+   memcpy(((u8 *)next_lookaheads) + 4 * i,
+  report->lookahead, 4);
+   report++;
+   }
+
+   *next_lookaheads_len = bundle_cnt;
+   }
+
+   return 0;
+}
+
 int ath10k_htc_process_trailer(struct ath10k_htc *htc,
   u8 *buffer,
   int length,
-  enum ath10k_htc_ep_id src_eid)
+  enum ath10k_htc_ep_id src_eid,
+  void *next_lookaheads,
+  int *next_lookaheads_len)
 {
struct ath10k *ar = htc->ar;
int status = 0;
@@ -272,6 +338,28 @@ int ath10k_htc_process_trailer(struct ath10k_htc *htc,
 record->hdr.len,
 src_eid);
break;
+   case ATH10K_HTC_RECORD_LOOKAHEAD:
+   len = sizeof(struct ath10k_htc_lookahead_report);
+   if (record->hdr.len < len) {
+   ath10k_warn(ar, "Lookahead report too long\n");
+   status = -EINVAL;
+   break;
+   }
+   status = ath10k_htc_process_lookahead(htc,
+ 
record->lookahead_report,
+ record->hdr.len,
+ src_eid,
+ next_lookaheads,
+ 
next_lookaheads_len);
+   break;
+   case ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE:
+   status = ath10k_htc_process_lookahead_bundle(htc,
+
record->lookahead_bundle,
+   

Re: ath10k: Fix Tx legacy rate reporting

2017-01-13 Thread Kalle Valo
Mohammed Shafi Shajakhan  wrote:
> From: Mohammed Shafi Shajakhan 
> 
> Tx legacy rate is reported 10 fold, as below
> 
> iw dev wlan#N station dump | grep "tx bitrate"
> tx bitrate: 240.0 MBit/s
> 
> This is because by mistake we muliply by the hardware reported
> rate twice by 10, fix this.
> 
> Fixes: cec17c382140 ("ath10k: add per peer htt tx stats support for 10.4")
> Signed-off-by: Mohammed Shafi Shajakhan 

Patch applied to ath-next branch of ath.git, thanks.

cd59102779ac ath10k: fix tx legacy rate reporting

-- 
https://patchwork.kernel.org/patch/9508075/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


Re: ath10k: Fix wifi connectivity and warning in Rx with channel 169

2017-01-13 Thread Kalle Valo
Mohammed Shafi Shajakhan  wrote:
> From: Mohammed Shafi Shajakhan 
> 
> In countries where basic operation of channel 169 is allowed,
> this fixes the below WARN_ON_ONCE in Rx and fixes the station
> connectivity failure in channel 169 as the packet is dropped
> in the driver as the current check limits to channel 165. As of
> now all the packets beyond channel 165 is dropped, fix this
> by extending the range to channel 169.
> 
> Call trace:
> 
> drivers/net/wireless/ath/ath10k/wmi.c:1505
> ath10k_wmi_event_mgmt_rx+0x278/0x440 [ath10k_core]()
> Call Trace:
>  [] ? printk+0x2d/0x2f
>  [] warn_slowpath_common+0x72/0xa0
>  [] ? ath10k_wmi_event_mgmt_rx+0x278/0x440
> 
>  [] ? ath10k_wmi_event_mgmt_rx+0x278/0x440
> 
>  [] warn_slowpath_null+0x22/0x30
>  [] ath10k_wmi_event_mgmt_rx+0x278/0x440
> 
>  [] ? ath10k_pci_sleep+0x8b/0xb0 [ath10k_pci]
>  [] ath10k_wmi_10_2_op_rx+0xf3/0x3b0
> 
>  [] ath10k_wmi_process_rx+0x1e/0x60
> 
>  [] ath10k_htc_rx_completion_handler+0x347/0x4d0 [ath10k_core]
>  [] ? ath10k_ce_completed_recv_next+0x53/0x70 [ath10k_pci]
>  [] ath10k_pci_ce_recv_data+0x171/0x1d0 [ath10k_pci]
>  [] ? ath10k_pci_write32+0x39/0x80 [ath10k_pci]
>  [] ath10k_ce_per_engine_service+0x5c/0xa0 [ath10k_pci]
>  [] ath10k_ce_per_engine_service_any+0x5f/0x70 [ath10k_pci]
>  [] ? local_bh_enable_ip+0x90/0x90
>  [] ath10k_pci_tasklet+0x1b/0x50 [ath10k_pci]
> 
> Fixes: 34c30b0a5e97 ("ath10k: enable advertising support for channel 169, 
> 5Ghz")
> Signed-off-by: Mohammed Shafi Shajakhan 

Patch applied to ath-next branch of ath.git, thanks.

c486dc571a37 ath10k: fix wifi connectivity and warning in rx with channel 169

-- 
https://patchwork.kernel.org/patch/9508031/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


Re: [1/2] ath10k: add accounting for the extended peer statistics

2017-01-13 Thread Kalle Valo
Christian Lamparter  wrote:
> The 10.4 firmware adds extended peer information to the
> firmware's statistics payload. This additional info is
> stored as a separate data field and the elements are
> stored in their own "peers_extd" list.
> 
> These elements can pile up in the same way as the peer
> information elements. This is because the
> ath10k_wmi_10_4_op_pull_fw_stats() function tries to
> pull the same amount (num_peer_stats) for every statistic
> data unit.
> 
> Fixes: 4a49ae94a448faa ("ath10k: fix 10.4 extended peer stats update")
> Signed-off-by: Christian Lamparter 

Patch applied to ath-next branch of ath.git, thanks.

c1e3330f22bc ath10k: add accounting for the extended peer statistics

-- 
https://patchwork.kernel.org/patch/9461631/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


Re: [v2,1/2] ath10k: refactor ath10k_peer_assoc_h_phymode()

2017-01-13 Thread Kalle Valo
Kalle Valo  wrote:
> When adding VHT160 support to ath10k_peer_assoc_h_phymode() the VHT mode
> selection code becomes too complex. Simplify it by refactoring the vht part to
> a separate function.
> 
> Signed-off-by: Kalle Valo 

2 patches applied to ath-next branch of ath.git, thanks.

06efdbe70f9c ath10k: refactor ath10k_peer_assoc_h_phymode()
bc1efd739b61 ath10k: add VHT160 support

-- 
https://patchwork.kernel.org/patch/9376371/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


[PATCH] ath10k: Search SMBIOS for OEM board file extension

2017-01-13 Thread Waldemar Rymarkiewicz
Board Data File (BDF) is loaded upon driver boot-up procedure. The right
board data file is identified, among others, by device and sybsystem ids.

The problem, however, can occur when the (default) board data file cannot
fulfill with the vendor requirements and it is necessary to use a different
board data file.

To solve the issue QCA uses SMBIOS type 0xF8 to store Board Data File Name
Extension to specify the extension/variant name. The driver will take the
extension suffix into consideration and will load the right (non-default)
board data file if necessary.

If it is unnecessary to use extension board data file, please leave the
SMBIOS field blank and default configuration will be used.

Example:
If a default board data file for a specific board is identified by a string
  "bus=pci,vendor=168c,device=003e,subsystem-vendor=1028,
   subsystem-device=0310"
then the OEM specific data file, if used, could be identified by variant
suffix:
  "bus=pci,vendor=168c,device=003e,subsystem-vendor=1028,
   subsystem-device=0310,variant=DE_1AB"

Signed-off-by: Waldemar Rymarkiewicz 
---
 drivers/net/wireless/ath/ath10k/core.c | 79 --
 drivers/net/wireless/ath/ath10k/core.h | 19 
 2 files changed, 95 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 874c2a755c66..e6276027ec83 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -18,6 +18,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 #include "core.h"
@@ -707,6 +709,67 @@ 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 */
+   strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic),
+   sizeof(ar->id.bdf_ext));
+
+   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;
@@ -1053,6 +1116,9 @@ 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];
+
if (ar->id.bmi_ids_valid) {
scnprintf(name, name_len,
  "bus=%s,bmi-chip-id=%d,bmi-board-id=%d",
@@ -1062,12 +1128,15 @@ 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",
+ 
"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
  ath10k_bus_str(ar->hif.bus),
  ar->id.vendor, ar->id.device,
- 

[PATCH] ath10k: Fix per station tx bit rate reporting

2017-01-13 Thread Mohammed Shafi Shajakhan
From: Mohammed Shafi Shajakhan 

Not clearing the previous tx bit rate status
results in a ambigous tx bit rate reporting to
mac80211/cfg80211, for example the previous bit
rate status would have been marked as legacy rate
, while the current rate would have been an HT/VHT
rate with the tx bit rate flags set and this results
in exporting tx bitrate as legacy rate but with HT/VHT
rate flags set, fix this by clearing the tx bitrate
status for each event. This also fixes the below
warning when we do:

iw dev wlan#N station dump

WARNING: net/wireless/util.c:1222 cfg80211

[] (warn_slowpath_null) from []
(cfg80211_calculate_bitrate+0x110/0x1f4 [cfg80211])
[] (cfg80211_calculate_bitrate [cfg80211]) from
[] (nl80211_put_sta_rate+0x44/0x1dc [cfg80211])
[] (nl80211_put_sta_rate [cfg80211]) from
[] (nl80211_set_interface+0x724/0xd70 [cfg80211])
[] (nl80211_set_interface [cfg80211]) from
[] (nl80211_dump_station+0xdc/0x100 [cfg80211])
[] (nl80211_dump_station [cfg80211])

Fixes: cec17c382140 ("ath10k: add per peer htt tx stats support for 10.4")
Signed-off-by: Mohammed Shafi Shajakhan 
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c 
b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 0bc7fe8..74b66e5 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2231,6 +2231,8 @@ static inline bool is_valid_legacy_rate(u8 rate)
return;
}
 
+   memset(>txrate, 0, sizeof(arsta->txrate));
+
if (txrate.flags == WMI_RATE_PREAMBLE_CCK ||
txrate.flags == WMI_RATE_PREAMBLE_OFDM) {
rate = ATH10K_HW_LEGACY_RATE(peer_stats->ratecode);
-- 
1.9.1


___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


Re: [PATCH] ath10k: prevent sta pointer rcu violation

2017-01-13 Thread Michal Kazior
On 13 January 2017 at 08:24, Johannes Berg  wrote:
>
>> Unless you then continue to use that sta pointer after you release
>> data_lock.
>
> Ouch, ok. That's rather strangely hidden though.
>
>> Consider this:
>>
>> >  CPU0 CPU1
>> > 1   synchronize_net()
>> > 2drv_sta_state()
>> > 3  htt_fetch_ind(pid,tid) called
>> > 4  rcu_read_lock()
>> > 5  get(data_lock)
>> > 6  txq=peers[pid]->sta->txq[tid]
>> > 7  put(data_lock)
>> > 8get(data_lock)
>> > 9 peer->sta=0
>> > 10   put(data_lock)
>> > 11 kfree(sta)
>> > 12 ieee80211_tx_dequeue(txq)
>>
>> Even though there's no code like (9) per se you can think of it as
>> anything that tries to "remove" the peer--sta association
>> (ath10k_peer
>> is removed implicitly via wmi peer delete command and waiting for htt
>> event completion).
>>
>> Holding data_lock for the entire duration of handling fetch
>> indication isn't really good for performance so it's better to fix
>> RCU handling.
>
> Yeah, I see it now - also the comment where this happens. You probably
> should mark some things __rcu though and actually use RCU primitives,
> so the code is actually understandable :)

Good point. I'll do that in another patch.


MichaƂ

___
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k