Re: [PATCH v2] ath10k: transmit queued frames after waking queues

2018-05-23 Thread Erik Stromdahl



On 05/22/2018 11:15 PM, Niklas Cassel wrote:




Earlier we observed performance issues in calling push_pending from each
tx completion. IMHO this change may introduce the same problem again.


I prefer functional TX over performance issues,
but I agree that it is unfortunate that SDIO doesn't use
ath10k_htt_txrx_compl_task().
Erik, is there a reason for this?

The reason is that the SDIO code has been derived mainly from qcacld and ath6kl
and they don't implement napi.

ath10k_htt_txrx_compl_task is currently only called from the napi poll function,
and the sdio bus driver doesn't have such a function.



Perhaps it would be possible to call ath10k_mac_tx_push_pending()
from the equivalent to ath10k_htt_txrx_compl_task(),
but from SDIO's point of view.

An equivalent for SDIO would most likely be *ath10k_htt_htc_t2h_msg_handler*
or any of the other functions called from this function.

*ath10k_txrx_tx_unref* is actually called from *ath10k_htt_htc_t2h_msg_handler*,
so that function could be viewed as an equivalent.

If the call should be added in the bus driver (sdio.c) it should most likely be
placed in *ath10k_sdio_mbox_rx_process_packets*

if (!pkt->trailer_only) {
ep->ep_ops.ep_rx_complete(ar_sdio->ar, pkt->skb);
ath10k_mac_tx_push_pending(ar_sdio->ar);
} else {
kfree_skb(pkt->skb)
}

The above call would of course result in lot's of calls to 
*ath10k_mac_tx_push_pending*
Adding a htt_num_pending check here wouldn't look nice.

The HL RX path differs from the LL path in that the t2h_msg_handler returns
false indicating that it has consumed the skb.

This is because it is the HL RX indication handler that delivers the skb's
to mac80211.

Another solution could be to add an *else-statement* as a part of the *if 
(release)*
in *ath10k_htt_htc_t2h_msg_handler*, where *ath10k_mac_tx_push_pending* could 
be called.

Something like this perhaps:

/* Free the indication buffer */
if (release)
dev_kfree_skb_any(skb);
else if (!ar->htt.num_pending_tx)
ath10k_mac_tx_push_pending(ar);

I think I prefer your original patch though.


Another solution might be to change so that we only call
ath10k_mac_tx_push_pending() from ath10k_txrx_tx_unref()
if (htt->num_pending_tx == 0). That should decrease the number
of calls to ath10k_mac_tx_push_pending(), while still avoiding
a "TX deadlock" scenario for SDIO.

Just out of curiosity, where did the limit of 3 come from?
If it works with a limit of 0, I think it should be used instead.

Another intersting thing that I stumbled upon when looking into the
code (while writing this email) is the *wake_up(&htt->empty_tx_wq);*

For some reason I have considered it not to be applicable for HL devices.

The queue is waited for in the flush op (*ath10k_flush*).
I am unsure what it is used for, but I don't think it affects the TX
deadlock scenario.

--
Erik


Re: ath10k wake_tx_queue issues

2018-05-16 Thread Erik Stromdahl

Hello Niklas

Quick question:
Are you using my patch: "ath10k: add htt_tx num_pending window"?

I assume (from your logs below) that you are not...

See more comments below.




I guess the best way to describe this is to show my ftrace buffer:

  ksoftirqd/2-21[002] .ns474.711744: ath10k_htt_tx_dec_pending: 
num_pen: 60
  ksoftirqd/2-21[002] .ns374.711761: ath10k_mac_op_wake_tx_queue: 
txq: frame_cnt: 1 byte_cnt: 1534 f_txq: frame_cnt: 1 byte_cnt: 1534 num_pen: 60 
queue: 0
  ksoftirqd/2-21[002] .ns474.711765: ath10k_htt_tx_inc_pending: 
num_pen: 61
  ksoftirqd/2-21[002] .ns474.711781: ath10k_htt_tx_inc_pending: 
num_pen: 62
  ksoftirqd/2-21[002] .ns474.711787: ath10k_htt_tx_dec_pending: 
num_pen: 61
  ksoftirqd/2-21[002] .ns374.711803: ath10k_mac_op_wake_tx_queue: 
txq: frame_cnt: 1 byte_cnt: 1534 f_txq: frame_cnt: 1 byte_cnt: 1534 num_pen: 61 
queue: 0
  ksoftirqd/2-21[002] .ns474.711807: ath10k_htt_tx_inc_pending: 
num_pen: 62
  ksoftirqd/2-21[002] .ns474.711823: ath10k_htt_tx_inc_pending: 
num_pen: 63
  ksoftirqd/2-21[002] .ns474.711829: ath10k_htt_tx_dec_pending: 
num_pen: 62
  ksoftirqd/2-21[002] .ns374.711845: ath10k_mac_op_wake_tx_queue: 
txq: frame_cnt: 1 byte_cnt: 1534 f_txq: frame_cnt: 1 byte_cnt: 1534 num_pen: 62 
queue: 0
  ksoftirqd/2-21[002] .ns474.711849: ath10k_htt_tx_inc_pending: 
num_pen: 63
  ksoftirqd/2-21[002] .ns474.711865: ath10k_htt_tx_inc_pending: 
num_pen: 64

For high latency devices, when the num_pending counter reaches this point (64),
ath10k calls ieee80211_stop_queues (from ath10k_htt_tx_inc_pending -> 
ath10k_mac_tx_lock).
This will stop all per-TID queues (16 in total).


  ksoftirqd/2-21[002] dns574.711870: stop_queue: phy0 queue:0, 
reason:0
  ksoftirqd/2-21[002] dns574.711874: stop_queue: phy0 queue:1, 
reason:0
  ksoftirqd/2-21[002] dns574.711877: stop_queue: phy0 queue:2, 
reason:0
  ksoftirqd/2-21[002] dns574.711880: stop_queue: phy0 queue:3, 
reason:0
  ksoftirqd/2-21[002] dns574.711882: stop_queue: phy0 queue:4, 
reason:0
  ksoftirqd/2-21[002] dns574.711885: stop_queue: phy0 queue:5, 
reason:0
  ksoftirqd/2-21[002] dns574.711887: stop_queue: phy0 queue:6, 
reason:0
  ksoftirqd/2-21[002] dns574.711890: stop_queue: phy0 queue:7, 
reason:0
  ksoftirqd/2-21[002] dns574.711892: stop_queue: phy0 queue:8, 
reason:0
  ksoftirqd/2-21[002] dns574.711895: stop_queue: phy0 queue:9, 
reason:0
  ksoftirqd/2-21[002] dns574.711898: stop_queue: phy0 queue:10, 
reason:0
  ksoftirqd/2-21[002] dns574.711900: stop_queue: phy0 queue:11, 
reason:0
  ksoftirqd/2-21[002] dns574.711903: stop_queue: phy0 queue:12, 
reason:0
  ksoftirqd/2-21[002] dns574.711905: stop_queue: phy0 queue:13, 
reason:0
  ksoftirqd/2-21[002] dns574.711908: stop_queue: phy0 queue:14, 
reason:0
  ksoftirqd/2-21[002] dns574.711910: stop_queue: phy0 queue:15, 
reason:0
  ksoftirqd/2-21[002] .ns474.711917: ath10k_htt_tx_dec_pending: 
num_pen: 63

At this point, the driver have received a TX_COMPL_IND (since num_pending has 
been decremented to 63).
Without the patch I mentioned above, the logic is that the TX queues will be 
re-enabled immediately.
This is achieved by calling ieee80211_stop_queues.


  ksoftirqd/2-21[002] dns574.711922: wake_queue: phy0 queue:0, 
reason:0
  ksoftirqd/2-21[002] dns574.711929: wake_queue: phy0 queue:15, 
reason:0

2 queues have been enabled here. I don't know why not all queues have been 
re-enabled.
Perhaps it is due to that mac80211 immediately gets more data on one of the 
just re-enabled queues,
resulting in...

  ksoftirqd/2-21[002] .ns374.711948: ath10k_mac_op_wake_tx_queue: 
txq: frame_cnt: 1 byte_cnt: 1534 f_txq: frame_cnt: 1 byte_cnt: 1534 num_pen: 63 
queue: 0

...the the wake_tx_queue op beeing invoked again ...

  ksoftirqd/2-21[002] .ns474.711952: ath10k_htt_tx_inc_pending: 
num_pen: 64

... and the num_pending counter beeing incremented as a result of this.
This results in all queues beeing ...

  ksoftirqd/2-21[002] dns574.711956: stop_queue: phy0 queue:0, 
reason:0
  ksoftirqd/2-21[002] dns574.711959: stop_queue: phy0 queue:1, 
reason:0
  ksoftirqd/2-21[002] dns574.711962: stop_queue: phy0 queue:2, 
reason:0
  ksoftirqd/2-21[002] dns574.711964: stop_queue: phy0 queue:3, 
reason:0
  ksoftirqd/2-21[002] dns574.711967: stop_queue: phy0 queue:4, 
reason:0
  ksoftirqd/2-21[002] dns574.711969: stop_queue: phy0 queue:5, 
reason:0
  ksoftirqd/2-21[002] dns574.711972: stop_queue: phy0 queue:6, 
reason:0
  ksoftirqd/2-21[002] dns574.711974: stop_queue: phy0 queue:7, 
reason:0
  ksoftirqd/2-21  

[PATCH] ath10k: fix return value check in wake_tx_q op

2018-05-06 Thread Erik Stromdahl
ath10k_mac_tx_push_txq returns either a postive integer (length) on
success or a negative error code on error.

The "if (ret) break;" statement will thus always break out of the loop
immediately after ath10k_mac_tx_push_txq has returned (making the loop
pointless).

A side effect of this fix is that we will iterate the queue until
ath10k_mac_tx_push_txq returns -ENOENT. This will make sure the queue is
not added back to ar->txqs when it is empty. This could potentially
improve performance somewhat (I have seen a small improvement with SDIO
devices).

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/mac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c 
b/drivers/net/wireless/ath/ath10k/mac.c
index 3d7119ad7c7a..487a7a7380fd 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4290,7 +4290,7 @@ static void ath10k_mac_op_wake_tx_queue(struct 
ieee80211_hw *hw,
 
while (ath10k_mac_tx_can_push(hw, f_txq) && max--) {
ret = ath10k_mac_tx_push_txq(hw, f_txq);
-   if (ret)
+   if (ret < 0)
break;
}
if (ret != -ENOENT)
-- 
2.17.0



[PATCH 0/2] ath10k: HTT ops wrappers

2018-04-15 Thread Erik Stromdahl
These two patches were included in the High latency v4 RFC
submitted a few months ago.

I think it would be appropriate to add them separately since
they are not really related to the HL patches.

This will make the next HL patch set somewhat smaller.

Erik Stromdahl (2):
  ath10k: add inlined wrappers for htt tx ops
  ath10k: add inlined wrappers for htt rx ops

 drivers/net/wireless/ath/ath10k/htt.c|  4 +-
 drivers/net/wireless/ath/ath10k/htt.h| 88 
 drivers/net/wireless/ath/ath10k/htt_rx.c | 14 ++--
 drivers/net/wireless/ath/ath10k/htt_tx.c | 12 ++--
 drivers/net/wireless/ath/ath10k/mac.c|  2 +-
 5 files changed, 104 insertions(+), 16 deletions(-)

-- 
2.17.0



[PATCH 1/2] ath10k: add inlined wrappers for htt tx ops

2018-04-15 Thread Erik Stromdahl
These wrappers makes the HTT ops align better with the HIF ops
(where similar wrappers are used).

It also makes it easier for a target to have unsupported ops
(by letting the corresponding function pointer be NULL).

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

diff --git a/drivers/net/wireless/ath/ath10k/htt.c 
b/drivers/net/wireless/ath/ath10k/htt.c
index 625198dea18b..21a67f82f037 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -257,11 +257,11 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
return status;
}
 
-   status = htt->tx_ops->htt_send_frag_desc_bank_cfg(htt);
+   status = ath10k_htt_send_frag_desc_bank_cfg(htt);
if (status)
return status;
 
-   status = htt->tx_ops->htt_send_rx_ring_cfg(htt);
+   status = ath10k_htt_send_rx_ring_cfg(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 8cc2a8b278e4..c76f6daafe70 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1848,6 +1848,57 @@ struct ath10k_htt_tx_ops {
void (*htt_free_txbuff)(struct ath10k_htt *htt);
 };
 
+static inline int ath10k_htt_send_rx_ring_cfg(struct ath10k_htt *htt)
+{
+   if (!htt->tx_ops->htt_send_rx_ring_cfg)
+   return -EOPNOTSUPP;
+
+   return htt->tx_ops->htt_send_rx_ring_cfg(htt);
+}
+
+static inline int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt)
+{
+   if (!htt->tx_ops->htt_send_frag_desc_bank_cfg)
+   return -EOPNOTSUPP;
+
+   return htt->tx_ops->htt_send_frag_desc_bank_cfg(htt);
+}
+
+static inline int ath10k_htt_alloc_frag_desc(struct ath10k_htt *htt)
+{
+   if (!htt->tx_ops->htt_alloc_frag_desc)
+   return -EOPNOTSUPP;
+
+   return htt->tx_ops->htt_alloc_frag_desc(htt);
+}
+
+static inline void ath10k_htt_free_frag_desc(struct ath10k_htt *htt)
+{
+   if (htt->tx_ops->htt_free_frag_desc)
+   htt->tx_ops->htt_free_frag_desc(htt);
+}
+
+static inline int ath10k_htt_tx(struct ath10k_htt *htt,
+   enum ath10k_hw_txrx_mode txmode,
+   struct sk_buff *msdu)
+{
+   return htt->tx_ops->htt_tx(htt, txmode, msdu);
+}
+
+static inline int ath10k_htt_alloc_txbuff(struct ath10k_htt *htt)
+{
+   if (!htt->tx_ops->htt_alloc_txbuff)
+   return -EOPNOTSUPP;
+
+   return htt->tx_ops->htt_alloc_txbuff(htt);
+}
+
+static inline void ath10k_htt_free_txbuff(struct ath10k_htt *htt)
+{
+   if (htt->tx_ops->htt_free_txbuff)
+   htt->tx_ops->htt_free_txbuff(htt);
+}
+
 struct ath10k_htt_rx_ops {
size_t (*htt_get_rx_ring_size)(struct ath10k_htt *htt);
void (*htt_config_paddrs_ring)(struct ath10k_htt *htt, void *vaddr);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c 
b/drivers/net/wireless/ath/ath10k/htt_tx.c
index d334b7be1fea..a086958c39b6 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -443,13 +443,13 @@ static int ath10k_htt_tx_alloc_buf(struct ath10k_htt *htt)
struct ath10k *ar = htt->ar;
int ret;
 
-   ret = htt->tx_ops->htt_alloc_txbuff(htt);
+   ret = ath10k_htt_alloc_txbuff(htt);
if (ret) {
ath10k_err(ar, "failed to alloc cont tx buffer: %d\n", ret);
return ret;
}
 
-   ret = htt->tx_ops->htt_alloc_frag_desc(htt);
+   ret = ath10k_htt_alloc_frag_desc(htt);
if (ret) {
ath10k_err(ar, "failed to alloc cont frag desc: %d\n", ret);
goto free_txbuf;
@@ -473,10 +473,10 @@ static int ath10k_htt_tx_alloc_buf(struct ath10k_htt *htt)
ath10k_htt_tx_free_txq(htt);
 
 free_frag_desc:
-   htt->tx_ops->htt_free_frag_desc(htt);
+   ath10k_htt_free_frag_desc(htt);
 
 free_txbuf:
-   htt->tx_ops->htt_free_txbuff(htt);
+   ath10k_htt_free_txbuff(htt);
 
return ret;
 }
@@ -530,9 +530,9 @@ void ath10k_htt_tx_destroy(struct ath10k_htt *htt)
if (!htt->tx_mem_allocated)
return;
 
-   htt->tx_ops->htt_free_txbuff(htt);
+   ath10k_htt_free_txbuff(htt);
ath10k_htt_tx_free_txq(htt);
-   htt->tx_ops->htt_free_frag_desc(htt);
+   ath10k_htt_free_frag_desc(htt);
ath10k_htt_tx_free_txdone_fifo(htt);
htt->tx_mem_allocated = false;

[PATCH 2/2] ath10k: add inlined wrappers for htt rx ops

2018-04-15 Thread Erik Stromdahl
Added for the same reason as the TX wrappers.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htt.h| 37 
 drivers/net/wireless/ath/ath10k/htt_rx.c | 14 -
 2 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.h 
b/drivers/net/wireless/ath/ath10k/htt.h
index c76f6daafe70..3fa1be7749b2 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1908,6 +1908,43 @@ struct ath10k_htt_rx_ops {
void (*htt_reset_paddrs_ring)(struct ath10k_htt *htt, int idx);
 };
 
+static inline size_t ath10k_htt_get_rx_ring_size(struct ath10k_htt *htt)
+{
+   if (!htt->rx_ops->htt_get_rx_ring_size)
+   return 0;
+
+   return htt->rx_ops->htt_get_rx_ring_size(htt);
+}
+
+static inline void ath10k_htt_config_paddrs_ring(struct ath10k_htt *htt,
+void *vaddr)
+{
+   if (htt->rx_ops->htt_config_paddrs_ring)
+   htt->rx_ops->htt_config_paddrs_ring(htt, vaddr);
+}
+
+static inline void ath10k_htt_set_paddrs_ring(struct ath10k_htt *htt,
+ dma_addr_t paddr,
+ int idx)
+{
+   if (htt->rx_ops->htt_set_paddrs_ring)
+   htt->rx_ops->htt_set_paddrs_ring(htt, paddr, idx);
+}
+
+static inline void *ath10k_htt_get_vaddr_ring(struct ath10k_htt *htt)
+{
+   if (!htt->rx_ops->htt_get_vaddr_ring)
+   return NULL;
+
+   return htt->rx_ops->htt_get_vaddr_ring(htt);
+}
+
+static inline void ath10k_htt_reset_paddrs_ring(struct ath10k_htt *htt, int 
idx)
+{
+   if (htt->rx_ops->htt_reset_paddrs_ring)
+   htt->rx_ops->htt_reset_paddrs_ring(htt, idx);
+}
+
 #define RX_HTT_HDR_STATUS_LEN 64
 
 /* This structure layout is programmed via rx ring setup
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c 
b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 5e02e26158f6..5e8a84fa5422 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -181,7 +181,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt 
*htt, int num)
rxcb = ATH10K_SKB_RXCB(skb);
rxcb->paddr = paddr;
htt->rx_ring.netbufs_ring[idx] = skb;
-   htt->rx_ops->htt_set_paddrs_ring(htt, paddr, idx);
+   ath10k_htt_set_paddrs_ring(htt, paddr, idx);
htt->rx_ring.fill_cnt++;
 
if (htt->rx_ring.in_ord_rx) {
@@ -286,8 +286,8 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt)
ath10k_htt_rx_ring_free(htt);
 
dma_free_coherent(htt->ar->dev,
- htt->rx_ops->htt_get_rx_ring_size(htt),
- htt->rx_ops->htt_get_vaddr_ring(htt),
+ ath10k_htt_get_rx_ring_size(htt),
+ ath10k_htt_get_vaddr_ring(htt),
  htt->rx_ring.base_paddr);
 
dma_free_coherent(htt->ar->dev,
@@ -314,7 +314,7 @@ static inline struct sk_buff 
*ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
idx = htt->rx_ring.sw_rd_idx.msdu_payld;
msdu = htt->rx_ring.netbufs_ring[idx];
htt->rx_ring.netbufs_ring[idx] = NULL;
-   htt->rx_ops->htt_reset_paddrs_ring(htt, idx);
+   ath10k_htt_reset_paddrs_ring(htt, idx);
 
idx++;
idx &= htt->rx_ring.size_mask;
@@ -586,13 +586,13 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
if (!htt->rx_ring.netbufs_ring)
goto err_netbuf;
 
-   size = htt->rx_ops->htt_get_rx_ring_size(htt);
+   size = ath10k_htt_get_rx_ring_size(htt);
 
vaddr_ring = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_KERNEL);
if (!vaddr_ring)
goto err_dma_ring;
 
-   htt->rx_ops->htt_config_paddrs_ring(htt, vaddr_ring);
+   ath10k_htt_config_paddrs_ring(htt, vaddr_ring);
htt->rx_ring.base_paddr = paddr;
 
vaddr = dma_alloc_coherent(htt->ar->dev,
@@ -626,7 +626,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
 
 err_dma_idx:
dma_free_coherent(htt->ar->dev,
- htt->rx_ops->htt_get_rx_ring_size(htt),
+ ath10k_htt_get_rx_ring_size(htt),
  vaddr_ring,
  htt->rx_ring.base_paddr);
 err_dma_ring:
-- 
2.17.0



[RFC v4 16/18] ath10k: remove htt pending TX count for high latency

2017-12-31 Thread Erik Stromdahl
High latency chipsets does not seem to send any
HTT_T2H_MSG_TYPE_TX_COMPL_IND for outgoing frames.

This means that htt->num_pending_tx will never be
decremented and we will eventually hit the maximum
limit. All outgoing packets will then be discarded.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htt_tx.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c 
b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 7ea27454ef3f..0c14fb3b7181 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -153,6 +153,9 @@ void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw,
 
 void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
 {
+   if (htt->ar->is_high_latency)
+   return;
+
lockdep_assert_held(&htt->tx_lock);
 
htt->num_pending_tx--;
@@ -162,6 +165,9 @@ void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
 
 int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
 {
+   if (htt->ar->is_high_latency)
+   return 0;
+
lockdep_assert_held(&htt->tx_lock);
 
if (htt->num_pending_tx >= htt->max_num_pending_tx)
-- 
2.15.1



[RFC v4 06/18] ath10k: per target config of max_num_peers

2017-12-31 Thread Erik Stromdahl
This patch makes sure the value of max_num_peers matches
num_peers in hw_params (if set to a non zero value).

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

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 41e6b5a08885..4e849ec924c6 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1905,6 +1905,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 = &ar->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)) {
@@ -1984,7 +1985,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;
@@ -1996,10 +1997,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;
ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
} else {
-   ar->max_num_peers = TARGET_10X_NUM_PEERS;
+   max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
}
ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
@@ -2008,7 +2009,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
-   ar->max_num_peers = TARGET_TLV_NUM_PEERS;
+   max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
@@ -2019,7 +2020,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_10_4:
-   ar->max_num_peers = TARGET_10_4_NUM_PEERS;
+   max_num_peers = TARGET_10_4_NUM_PEERS;
ar->max_num_stations = TARGET_10_4_NUM_STATIONS;
ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;
ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
@@ -2037,10 +2038,16 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
+   default:
WARN_ON(1);
return -EINVAL;
}
 
+   if (ar->hw_params.num_peers)
+   ar->max_num_peers = ar->hw_params.num_peers;
+   else
+   ar->max_num_peers = max_num_peers;
+
/* Backwards compatibility for firmwares without
 * ATH10K_FW_IE_HTT_OP_VERSION.
 */
diff --git a/drivers/net/wireless/ath/ath10k/hw.h 
b/drivers/net/wireless/ath/ath10k/hw.h
index 3043fd17942e..53276950c95c 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -692,6 +692,9 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
 #define TARGET_HL_10_TLV_AST_SKID_LIMIT6
 #define TARGET_HL_10_TLV_NUM_WDS_ENTRIES   2
 
+/* Target specific defines for QCA9377 high latency firmware */
+#define TARGET_QCA9377_HL_NUM_PEERS15
+
 /* Diagnostic Window */
 #define CE_DIAG_PIPE   7
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c 
b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index ae77a007ae07..6b58bcbb36c1 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -1439,7 +1439,6 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct 
ath10k *ar)
cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
 
cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
-
c

[RFC v4 04/18] ath10k: high_latency detection

2017-12-31 Thread Erik Stromdahl
Add is_high_latency parameter to struct ath10k_bus_params.

The setup of high latency chips is sometimes different than
for chips using low latency interfaces.

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

diff --git a/drivers/net/wireless/ath/ath10k/ahb.c 
b/drivers/net/wireless/ath/ath10k/ahb.c
index 6f902f355fca..b342f3393e2c 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -814,6 +814,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
 
ath10k_pci_ce_deinit(ar);
 
+   bus_params.is_high_latency = false;
bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
if (bus_params.chip_id == 0x) {
ath10k_err(ar, "failed to get chip id\n");
diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 3440ccc45d60..09b6ad481414 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2613,6 +2613,7 @@ int ath10k_core_register(struct ath10k *ar,
 const struct ath10k_bus_params *bus_params)
 {
ar->chip_id = bus_params->chip_id;
+   ar->is_high_latency = bus_params->is_high_latency;
queue_work(ar->workqueue, &ar->register_work);
 
return 0;
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index f2e851d91170..17827ce3752d 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -771,6 +771,7 @@ struct ath10k_per_peer_tx_stats {
 
 struct ath10k_bus_params {
u32 chip_id;
+   bool is_high_latency;
 };
 
 struct ath10k {
@@ -783,6 +784,7 @@ struct ath10k {
enum ath10k_hw_rev hw_rev;
u16 dev_id;
u32 chip_id;
+   bool is_high_latency;
u32 target_version;
u8 fw_version_major;
u32 fw_version_minor;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c 
b/drivers/net/wireless/ath/ath10k/pci.c
index 124443d45873..9fd8f1576f0c 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -3555,6 +3555,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_free_irq;
}
 
+   bus_params.is_high_latency = false;
bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
if (bus_params.chip_id == 0x) {
ath10k_err(ar, "failed to get chip id\n");
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 03dc748317f8..f0f1b2b8c7a7 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -2026,6 +2026,7 @@ static int ath10k_sdio_probe(struct sdio_func *func,
goto err_free_wq;
}
 
+   bus_params.is_high_latency = true;
/* TODO: don't know yet how to get chip_id with SDIO */
bus_params.chip_id = 0;
ret = ath10k_core_register(ar, &bus_params);
diff --git a/drivers/net/wireless/ath/ath10k/usb.c 
b/drivers/net/wireless/ath/ath10k/usb.c
index 275e00bafcb1..3b330e9607aa 100644
--- a/drivers/net/wireless/ath/ath10k/usb.c
+++ b/drivers/net/wireless/ath/ath10k/usb.c
@@ -1016,6 +1016,7 @@ static int ath10k_usb_probe(struct usb_interface 
*interface,
ar->id.vendor = vendor_id;
ar->id.device = product_id;
 
+   bus_params.is_high_latency = true;
/* TODO: don't know yet how to get chip_id with USB */
bus_params.chip_id = 0;
ret = ath10k_core_register(ar, &bus_params);
-- 
2.15.1



[RFC v4 07/18] ath10k: DMA related fixes for high latency devices

2017-12-31 Thread Erik Stromdahl
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 
---
 drivers/net/wireless/ath/ath10k/htc.c| 19 ---
 drivers/net/wireless/ath/ath10k/htt_tx.c |  3 ++-
 drivers/net/wireless/ath/ath10k/txrx.c   |  3 ++-
 3 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c 
b/drivers/net/wireless/ath/ath10k/htc.c
index 492dc5b4bbf2..dd69345f911e 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -53,7 +53,8 @@ static inline void ath10k_htc_restore_tx_skb(struct 
ath10k_htc *htc,
 {
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
 
-   dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
+   if (!htc->ar->is_high_latency)
+   dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, 
DMA_TO_DEVICE);
skb_pull(skb, sizeof(struct ath10k_htc_hdr));
 }
 
@@ -137,11 +138,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;
@@ -157,7 +161,8 @@ int ath10k_htc_send(struct ath10k_htc *htc,
return 0;
 
 err_unmap:
-   dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
+   if (!ar->is_high_latency)
+   dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
 err_credits:
if (ep->tx_credit_flow_enabled) {
spin_lock_bh(&htc->tx_lock);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c 
b/drivers/net/wireless/ath/ath10k/htt_tx.c
index a086958c39b6..4d0bfb47d162 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -1125,7 +1125,8 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct 
sk_buff *msdu)
return 0;
 
 err_unmap_msdu:
-   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);
 err_free_txdesc:
dev_kfree_skb_any(txdesc);
 err_free_msdu_id:
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c 
b/drivers/net/wireless/ath/ath10k/txrx.c
index 5b3b021526ab..febc3eb93fbd 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -94,7 +94,8 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
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.15.1



[RFC v4 02/18] ath10k: add inlined wrappers for htt rx ops

2017-12-31 Thread Erik Stromdahl
Added for the same reason as the TX wrappers.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htt.h| 38 
 drivers/net/wireless/ath/ath10k/htt_rx.c | 14 ++--
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.h 
b/drivers/net/wireless/ath/ath10k/htt.h
index cdd87ef86c00..3fa1be7749b2 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1907,6 +1907,44 @@ struct ath10k_htt_rx_ops {
void* (*htt_get_vaddr_ring)(struct ath10k_htt *htt);
void (*htt_reset_paddrs_ring)(struct ath10k_htt *htt, int idx);
 };
+
+static inline size_t ath10k_htt_get_rx_ring_size(struct ath10k_htt *htt)
+{
+   if (!htt->rx_ops->htt_get_rx_ring_size)
+   return 0;
+
+   return htt->rx_ops->htt_get_rx_ring_size(htt);
+}
+
+static inline void ath10k_htt_config_paddrs_ring(struct ath10k_htt *htt,
+void *vaddr)
+{
+   if (htt->rx_ops->htt_config_paddrs_ring)
+   htt->rx_ops->htt_config_paddrs_ring(htt, vaddr);
+}
+
+static inline void ath10k_htt_set_paddrs_ring(struct ath10k_htt *htt,
+ dma_addr_t paddr,
+ int idx)
+{
+   if (htt->rx_ops->htt_set_paddrs_ring)
+   htt->rx_ops->htt_set_paddrs_ring(htt, paddr, idx);
+}
+
+static inline void *ath10k_htt_get_vaddr_ring(struct ath10k_htt *htt)
+{
+   if (!htt->rx_ops->htt_get_vaddr_ring)
+   return NULL;
+
+   return htt->rx_ops->htt_get_vaddr_ring(htt);
+}
+
+static inline void ath10k_htt_reset_paddrs_ring(struct ath10k_htt *htt, int 
idx)
+{
+   if (htt->rx_ops->htt_reset_paddrs_ring)
+   htt->rx_ops->htt_reset_paddrs_ring(htt, idx);
+}
+
 #define RX_HTT_HDR_STATUS_LEN 64
 
 /* This structure layout is programmed via rx ring setup
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c 
b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 6d96f9560950..7b3d6bf015c7 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -180,7 +180,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt 
*htt, int num)
rxcb = ATH10K_SKB_RXCB(skb);
rxcb->paddr = paddr;
htt->rx_ring.netbufs_ring[idx] = skb;
-   htt->rx_ops->htt_set_paddrs_ring(htt, paddr, idx);
+   ath10k_htt_set_paddrs_ring(htt, paddr, idx);
htt->rx_ring.fill_cnt++;
 
if (htt->rx_ring.in_ord_rx) {
@@ -285,8 +285,8 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt)
ath10k_htt_rx_ring_free(htt);
 
dma_free_coherent(htt->ar->dev,
- htt->rx_ops->htt_get_rx_ring_size(htt),
- htt->rx_ops->htt_get_vaddr_ring(htt),
+ ath10k_htt_get_rx_ring_size(htt),
+ ath10k_htt_get_vaddr_ring(htt),
  htt->rx_ring.base_paddr);
 
dma_free_coherent(htt->ar->dev,
@@ -313,7 +313,7 @@ static inline struct sk_buff 
*ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
idx = htt->rx_ring.sw_rd_idx.msdu_payld;
msdu = htt->rx_ring.netbufs_ring[idx];
htt->rx_ring.netbufs_ring[idx] = NULL;
-   htt->rx_ops->htt_reset_paddrs_ring(htt, idx);
+   ath10k_htt_reset_paddrs_ring(htt, idx);
 
idx++;
idx &= htt->rx_ring.size_mask;
@@ -585,13 +585,13 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
if (!htt->rx_ring.netbufs_ring)
goto err_netbuf;
 
-   size = htt->rx_ops->htt_get_rx_ring_size(htt);
+   size = ath10k_htt_get_rx_ring_size(htt);
 
vaddr_ring = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_KERNEL);
if (!vaddr_ring)
goto err_dma_ring;
 
-   htt->rx_ops->htt_config_paddrs_ring(htt, vaddr_ring);
+   ath10k_htt_config_paddrs_ring(htt, vaddr_ring);
htt->rx_ring.base_paddr = paddr;
 
vaddr = dma_alloc_coherent(htt->ar->dev,
@@ -625,7 +625,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
 
 err_dma_idx:
dma_free_coherent(htt->ar->dev,
- htt->rx_ops->htt_get_rx_ring_size(htt),
+ ath10k_htt_get_rx_ring_size(htt),
  vaddr_ring,
  htt->rx_ring.base_paddr);
 err_dma_ring:
-- 
2.15.1



[RFC v4 08/18] ath10k: various fixes for high latency devices

2017-12-31 Thread Erik Stromdahl
A few execution paths are not applicable for high latency
devices and can be skipped.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 3 ++-
 drivers/net/wireless/ath/ath10k/txrx.c   | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c 
b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 7b3d6bf015c7..1432d5b3e9d3 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2686,7 +2686,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/txrx.c 
b/drivers/net/wireless/ath/ath10k/txrx.c
index febc3eb93fbd..a151abe5e97b 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -90,7 +90,7 @@ 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);
 
-- 
2.15.1



[RFC v4 12/18] ath10k: htt: RX ring config HL support

2017-12-31 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_tx.c | 52 
 1 file changed, 52 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c 
b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 321f131e417d..1f6470de7b8d 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -934,6 +934,57 @@ static int ath10k_htt_send_rx_ring_cfg_64(struct 
ath10k_htt *htt)
return 0;
 }
 
+static 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_ring32 *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_32.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 = &cmd->rx_setup_32.rings[0];
+
+   cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_RX_RING_CFG;
+   cmd->rx_setup_32.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_le16(HTT_RX_RING_SIZE_MIN);
+   ring->rx_ring_bufsize = __cpu_to_le16(HTT_RX_BUF_SIZE);
+   ring->flags = __cpu_to_le16(flags);
+
+   ret = ath10k_htc_send(&htt->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)
@@ -1566,6 +1617,7 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_64 = {
 };
 
 static const struct ath10k_htt_tx_ops htt_tx_ops_hl = {
+   .htt_send_rx_ring_cfg = ath10k_htt_send_rx_ring_cfg_hl,
.htt_send_frag_desc_bank_cfg = ath10k_htt_send_frag_desc_bank_cfg_32,
 };
 
-- 
2.15.1



[RFC v4 13/18] ath10k: htt: High latency TX support

2017-12-31 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_tx.c | 92 
 1 file changed, 92 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c 
b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 1f6470de7b8d..7ea27454ef3f 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -495,6 +495,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;
@@ -1188,6 +1191,94 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct 
sk_buff *msdu)
return res;
 }
 
+#define HTT_TX_HL_NEEDED_HEADROOM \
+   (unsigned int)(sizeof(struct htt_cmd_hdr) + \
+   sizeof(struct htt_data_tx_desc) + \
+   sizeof(struct ath10k_htc_hdr))
+
+static 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);
+   struct sk_buff *tmp_skb;
+   bool is_eth = (txmode == ATH10K_HW_TXRX_ETHERNET);
+   u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
+   u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth);
+   u8 flags0 = 0;
+   u16 flags1 = 0;
+
+   data_len = msdu->len;
+
+   switch (txmode) {
+   case ATH10K_HW_TXRX_RAW:
+   case ATH10K_HW_TXRX_NATIVE_WIFI:
+   flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
+   /* fall through */
+   case ATH10K_HW_TXRX_ETHERNET:
+   flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+   break;
+   case ATH10K_HW_TXRX_MGMT:
+   flags0 |= SM(ATH10K_HW_TXRX_MGMT,
+HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+   flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
+   break;
+   }
+
+   if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
+   flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
+
+   flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
+   flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID);
+   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) {
+   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;
+}
+
 static int ath10k_htt_tx_32(struct ath10k_htt *htt,
enum ath10k_hw_txrx_mode txmode,
struct sk_buff *msdu)
@@ -1619,6 +1710,7 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_64 = {
 static const struct ath10k_htt_tx_ops htt_tx_ops_hl = {
.htt_send_rx_ring_cfg = ath10k_htt_send_rx_ring_cfg_hl,
.htt_send_frag_desc_bank_cfg = ath10k_htt_send_frag_desc_bank_cfg_32,
+   .htt_tx = ath10k_htt_tx_hl,
 };
 
 void ath10k_htt_set_tx_ops(struct ath10k_htt *htt)
-- 
2.15.1



[RFC v4 18/18] ath10k: add QCA9377 sdio hw_param item

2017-12-31 Thread Erik Stromdahl
Hardware parameters for QCA9377 sdio devices.

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

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index bc22d8c46252..038f58152a83 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -438,6 +438,32 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
.ast_skid_limit = 0x10,
.num_wds_entries = 0x20,
},
+   {
+   .id = QCA9377_HW_1_1_DEV_VERSION,
+   .dev_id = QCA9377_1_0_DEVICE_ID,
+   .bus = ATH10K_BUS_SDIO,
+   .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 = 17600,
+   .decap_align_bytes = 4,
+   .start_once = true,
+   .num_peers = TARGET_QCA9377_HL_NUM_PEERS,
+   .ast_skid_limit = 0x10,
+   .num_wds_entries = 0x20,
+   },
{
.id = QCA4019_HW_1_0_DEV_VERSION,
.dev_id = 0,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h 
b/drivers/net/wireless/ath/ath10k/hw.h
index 38cecbe4ddd9..d610b9cff812 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -129,6 +129,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.15.1



[RFC v4 11/18] ath10k: add HTT RX HL ops

2017-12-31 Thread Erik Stromdahl
Initial (empty) HTT RX ops for high latency devices.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c 
b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 1432d5b3e9d3..f7d071ca8b76 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2917,11 +2917,16 @@ static const struct ath10k_htt_rx_ops htt_rx_ops_64 = {
.htt_reset_paddrs_ring = ath10k_htt_reset_paddrs_ring_64,
 };
 
+static const struct ath10k_htt_rx_ops htt_rx_ops_hl = {
+};
+
 void ath10k_htt_set_rx_ops(struct ath10k_htt *htt)
 {
struct ath10k *ar = htt->ar;
 
-   if (ar->hw_params.target_64bit)
+   if (ar->is_high_latency)
+   htt->rx_ops = &htt_rx_ops_hl;
+   else if (ar->hw_params.target_64bit)
htt->rx_ops = &htt_rx_ops_64;
else
htt->rx_ops = &htt_rx_ops_32;
-- 
2.15.1



[RFC v4 14/18] ath10k: htt: High latency RX support

2017-12-31 Thread Erik Stromdahl
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 
---
 drivers/net/wireless/ath/ath10k/htt.h |  47 +++
 drivers/net/wireless/ath/ath10k/htt_rx.c  | 126 +-
 drivers/net/wireless/ath/ath10k/rx_desc.h |  15 
 3 files changed, 185 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.h 
b/drivers/net/wireless/ath/ath10k/htt.h
index 3fa1be7749b2..e5fb8e0155b6 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -699,6 +699,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)
 {
@@ -711,6 +720,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,
@@ -1621,6 +1642,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;
@@ -1973,6 +1995,31 @@ struct htt_rx_desc {
u8 msdu_payload[0];
 };
 
+#define HTT_RX_DESC_HL_INFO_SEQ_NUM_MASK   0x0fff
+#define HTT_RX_DESC_HL_INFO_SEQ_NUM_LSB0
+#define HTT_RX_DESC_HL_INFO_ENCRYPTED_MASK 0x1000
+#define HTT_RX_DESC_HL_INFO_ENCRYPTED_LSB  12
+#define HTT_RX_DESC_HL_INFO_CHAN_INFO_PRESENT_MASK 0x2000
+#define HTT_RX_DESC_HL_INFO_CHAN_INFO_PRESENT_LSB  13
+#define HTT_RX_DESC_HL_INFO_MCAST_BCAST_MASK   0x8000
+#define HTT_RX_DESC_HL_INFO_MCAST_BCAST_LSB15
+#define HTT_RX_DESC_HL_INFO_FRAGMENT_MASK  0x0001
+#define HTT_RX_DESC_HL_INFO_FRAGMENT_LSB   16
+#define HTT_RX_DESC_HL_INFO_KEY_ID_OCT_MASK0x01fe
+#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 f7d071ca8b76..3e0273ea9ad0 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -263,6 +263,9 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
struct ath10k_htt *htt = &ar->htt;
int ret;
 
+   if (ar->is_high_latency)
+   return 0;
+
spin_lock_bh(&htt->rx_ring.lock);
ret = ath10k_htt_rx_ring_fill_n(htt, (htt->rx_ring.fill_level -
  htt->rx_ring.fill_cnt));
@@ -276,6 +279,9 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
 
 void ath10k_htt_rx_free(struct ath10k_htt *htt)
 {
+   if (htt->ar->is_high_latency)
+   return;
+
del_timer_sync(&htt->rx_ring.refill_retry_timer);
 
skb_queue_purge(&htt->rx_msdus_q);
@@ -565,6 +571,9 @@ int ath10k_htt_rx_alloc(struct ath10k_

[RFC v4 03/18] ath10k: add struct ath10k_bus_params

2017-12-31 Thread Erik Stromdahl
This struct is used as argument to ath10k_core_register in order to
make it easier to add more bus parameters in the future.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/ahb.c  |  8 
 drivers/net/wireless/ath/ath10k/core.c |  5 +++--
 drivers/net/wireless/ath/ath10k/core.h |  7 ++-
 drivers/net/wireless/ath/ath10k/pci.c  | 12 ++--
 drivers/net/wireless/ath/ath10k/sdio.c |  7 ---
 drivers/net/wireless/ath/ath10k/usb.c  |  6 +++---
 6 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/ahb.c 
b/drivers/net/wireless/ath/ath10k/ahb.c
index 35d10490f6c3..6f902f355fca 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -758,7 +758,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
enum ath10k_hw_rev hw_rev;
size_t size;
int ret;
-   u32 chip_id;
+   struct ath10k_bus_params bus_params;
 
of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev);
if (!of_id) {
@@ -814,14 +814,14 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
 
ath10k_pci_ce_deinit(ar);
 
-   chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
-   if (chip_id == 0x) {
+   bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
+   if (bus_params.chip_id == 0x) {
ath10k_err(ar, "failed to get chip id\n");
ret = -ENODEV;
goto err_halt_device;
}
 
-   ret = ath10k_core_register(ar, chip_id);
+   ret = ath10k_core_register(ar, &bus_params);
if (ret) {
ath10k_err(ar, "failed to register driver core: %d\n", ret);
goto err_halt_device;
diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index fe9341c97f31..3440ccc45d60 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2609,9 +2609,10 @@ static void ath10k_core_register_work(struct work_struct 
*work)
return;
 }
 
-int ath10k_core_register(struct ath10k *ar, u32 chip_id)
+int ath10k_core_register(struct ath10k *ar,
+const struct ath10k_bus_params *bus_params)
 {
-   ar->chip_id = chip_id;
+   ar->chip_id = bus_params->chip_id;
queue_work(ar->workqueue, &ar->register_work);
 
return 0;
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index fe6b30356d3b..f2e851d91170 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -769,6 +769,10 @@ struct ath10k_per_peer_tx_stats {
u32 reserved2;
 };
 
+struct ath10k_bus_params {
+   u32 chip_id;
+};
+
 struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
@@ -1049,7 +1053,8 @@ int ath10k_core_start(struct ath10k *ar, enum 
ath10k_firmware_mode mode,
  const struct ath10k_fw_components *fw_components);
 int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
 void ath10k_core_stop(struct ath10k *ar);
-int ath10k_core_register(struct ath10k *ar, u32 chip_id);
+int ath10k_core_register(struct ath10k *ar,
+const struct ath10k_bus_params *bus_params);
 void ath10k_core_unregister(struct ath10k *ar);
 
 #endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/pci.c 
b/drivers/net/wireless/ath/ath10k/pci.c
index 8abaccc25227..124443d45873 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -3420,7 +3420,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
struct ath10k *ar;
struct ath10k_pci *ar_pci;
enum ath10k_hw_rev hw_rev;
-   u32 chip_id;
+   struct ath10k_bus_params bus_params;
bool pci_ps;
int (*pci_soft_reset)(struct ath10k *ar);
int (*pci_hard_reset)(struct ath10k *ar);
@@ -3555,19 +3555,19 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_free_irq;
}
 
-   chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
-   if (chip_id == 0x) {
+   bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
+   if (bus_params.chip_id == 0x) {
ath10k_err(ar, "failed to get chip id\n");
goto err_free_irq;
}
 
-   if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) {
+   if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) {
ath10k_err(ar, "device %04x with chip_id %08x isn't 
supported\n",
-  pdev->device, chip_id);
+  pdev->device, bus_params.chip_id);
goto err_free_irq;
}
 
-   ret = ath10k_core_register(ar, chip_id);
+   ret = 

[RFC v4 05/18] ath10k: add bus type check in ath10k_init_hw_params

2017-12-31 Thread Erik Stromdahl
The bus type is used together with the other hw parameters
to find a matching entry in ath10k_hw_params_list for the device.

This is necessary since HL devices can have the same dev_id and
target_version as a corresponding LL device (same chipset) and
yet use a totally different configuration.

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

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 09b6ad481414..41e6b5a08885 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -64,6 +64,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] 
= {
{
.id = QCA988X_HW_2_0_VERSION,
.dev_id = QCA988X_2_0_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca988x hw2.0",
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -93,6 +94,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] 
= {
{
.id = QCA9887_HW_1_0_VERSION,
.dev_id = QCA9887_1_0_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca9887 hw1.0",
.patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -122,6 +124,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
{
.id = QCA6174_HW_2_1_VERSION,
.dev_id = QCA6164_2_1_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca6164 hw2.1",
.patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -150,6 +153,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
{
.id = QCA6174_HW_2_1_VERSION,
.dev_id = QCA6174_2_1_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca6174 hw2.1",
.patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -178,6 +182,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
{
.id = QCA6174_HW_3_0_VERSION,
.dev_id = QCA6174_2_1_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca6174 hw3.0",
.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -206,6 +211,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
{
.id = QCA6174_HW_3_2_VERSION,
.dev_id = QCA6174_2_1_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca6174 hw3.2",
.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -237,6 +243,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
{
.id = QCA99X0_HW_2_0_DEV_VERSION,
.dev_id = QCA99X0_2_0_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca99x0 hw2.0",
.patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -271,6 +278,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
{
.id = QCA9984_HW_1_0_DEV_VERSION,
.dev_id = QCA9984_1_0_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca9984/qca9994 hw1.0",
.patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -310,6 +318,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
{
.id = QCA9888_HW_2_0_DEV_VERSION,
.dev_id = QCA9888_2_0_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca9888 hw2.0",
.patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -348,6 +357,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
{
.id = QCA9377_HW_1_0_DEV_VERSION,
.dev_id = QCA9377_1_0_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca9377 hw1.0",
.patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -376,6 +386,7 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
{
.id = QCA9377_HW_1_1_DEV_VERSION,
.dev_id = QCA9377_1_0_DEVICE_ID,
+   .bus = ATH10K_BUS_PCI,
.name = "qca9377 hw1.1",
.patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
@@ -4

[RFC v4 09/18] ath10k: add start_once support

2017-12-31 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 | 19 +++
 drivers/net/wireless/ath/ath10k/core.h |  2 ++
 drivers/net/wireless/ath/ath10k/hw.h   |  6 ++
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 4e849ec924c6..d42f6a1e5bfc 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2130,6 +2130,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(&ar->conf_mutex);
 
clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
@@ -2364,6 +2367,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:
@@ -2416,6 +2420,7 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_htt_tx_stop(&ar->htt);
ath10k_htt_rx_free(&ar->htt);
ath10k_wmi_detach(ar);
+   ar->is_started = false;
 }
 EXPORT_SYMBOL(ath10k_core_stop);
 
@@ -2545,12 +2550,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(&ar->conf_mutex);
+   } else {
+   ath10k_debug_print_boot_info(ar);
+   ath10k_core_stop(ar);
 
-   mutex_unlock(&ar->conf_mutex);
+   mutex_unlock(&ar->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 32cfa14d3053..ed96f9ef5209 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -798,6 +798,8 @@ struct ath10k {
 
bool p2p;
 
+   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 53276950c95c..98f9f3ccbf96 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -576,6 +576,12 @@ struct ath10k_hw_params {
 
/* Target rx ring fill level */
u32 rx_ring_fill_level;
+
+   /* 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.15.1



[RFC v4 15/18] ath10k: wmi: disable softirq's while calling ieee80211_rx

2017-12-31 Thread Erik Stromdahl
This is done in order not to trig the below warning in
ieee80211_rx_napi:

WARN_ON_ONCE(softirq_count() == 0);

ieee80211_rx_napi requires that softirq's are disabled during
execution.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/wmi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c 
b/drivers/net/wireless/ath/ath10k/wmi.c
index 58dc2189ba49..3a81d106789d 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2409,7 +2409,8 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct 
sk_buff *skb)
   status->freq, status->band, status->signal,
   status->rate_idx);
 
-   ieee80211_rx(ar->hw, skb);
+   ieee80211_rx_ni(ar->hw, skb);
+
return 0;
 }
 
-- 
2.15.1



[RFC v4 17/18] ath10k: add QCA9377 usb hw_param item

2017-12-31 Thread Erik Stromdahl
Hardware parameters for QCA9377 usb devices.

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

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index d42f6a1e5bfc..bc22d8c46252 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -414,6 +414,30 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
.target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
},
+   {
+   .id = QCA9377_HW_1_1_DEV_VERSION,
+   .dev_id = QCA9377_1_0_DEVICE_ID,
+   .bus = ATH10K_BUS_USB,
+   .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,
+   .start_once = true,
+   .num_peers = TARGET_QCA9377_HL_NUM_PEERS,
+   .ast_skid_limit = 0x10,
+   .num_wds_entries = 0x20,
+   },
{
.id = QCA4019_HW_1_0_DEV_VERSION,
.dev_id = 0,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h 
b/drivers/net/wireless/ath/ath10k/hw.h
index 98f9f3ccbf96..38cecbe4ddd9 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 {
 /* 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.15.1



[RFC v4 10/18] ath10k: add HTT TX HL ops

2017-12-31 Thread Erik Stromdahl
Initial HTT TX ops for high latency devices.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htt_tx.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c 
b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 4d0bfb47d162..321f131e417d 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -1565,11 +1565,17 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_64 = {
.htt_free_txbuff = ath10k_htt_tx_free_cont_txbuf_64,
 };
 
+static const struct ath10k_htt_tx_ops htt_tx_ops_hl = {
+   .htt_send_frag_desc_bank_cfg = ath10k_htt_send_frag_desc_bank_cfg_32,
+};
+
 void ath10k_htt_set_tx_ops(struct ath10k_htt *htt)
 {
struct ath10k *ar = htt->ar;
 
-   if (ar->hw_params.target_64bit)
+   if (ar->is_high_latency)
+   htt->tx_ops = &htt_tx_ops_hl;
+   else if (ar->hw_params.target_64bit)
htt->tx_ops = &htt_tx_ops_64;
else
htt->tx_ops = &htt_tx_ops_32;
-- 
2.15.1



[RFC v4 00/18] ath10k high latency

2017-12-31 Thread Erik Stromdahl
This is the fourth version of the high latency patches (stuff common for
usb and sdio).

Most of Kalles comments have been addressed, except the start_once patch
which is identical to the previous version. I need to investigate more
how this feature affects the case where the interface is brought up and
down several times.

The first two patches adds inline wrappers to the newly introduced htt
ops. I think these patches could have been submitted separately (as
PATCH and not RFC) but I decided to include them in this RFC series
instead.
Adding them separately would have reduced the size of the patchset
somewhat, but since the rest of the patches are depending on the first
two, I decided not to submit them separately.

I have tested USB support and the performance is similar to previous
versions.

Below are the results from iperf with a WUSB6100M:

192.168.1.190: WUSB6100M
192.168.1.244: other computer

Uplink test results (WUSB6100M -> other computer):

# iperf-client.sh 192.168.1.244
/usr/bin/iperf

Client connecting to 192.168.1.244, TCP port 1234
TCP window size: 85.0 KByte (default)

[  3] local 192.168.1.190 port 50524 connected with 192.168.1.244 port
1234
[ ID] Interval   Transfer Bandwidth
[  3]  0.0-10.1 sec  10.8 MBytes  8.95 Mbits/sec

The result is not so good (I expect more from an 11ac device),
but hopefully it is configuration related.

Downlink test results (other computer -> WUSB6100M):

# iperf-server.sh
/usr/bin/iperf

Server listening on TCP port 1234
TCP window size: 85.3 KByte (default)

[  4] local 192.168.1.190 port 1234 connected with 192.168.1.244 port
44824
[  349.641149] usb 1-1: failed to transmit packet, dropping: -12
[  349.643246] usb 1-1: failed to submit frame: -12
[  349.643644] usb 1-1: failed to push frame: -12
[  349.663267] usb 1-1: failed to transmit packet, dropping: -12
[  349.664250] usb 1-1: failed to submit frame: -12
[  349.665405] usb 1-1: failed to push frame: -12
[  349.670244] usb 1-1: failed to transmit packet, dropping: -12
[  349.670907] usb 1-1: failed to submit frame: -12
[  349.671419] usb 1-1: failed to push frame: -12
[  349.671887] usb 1-1: failed to transmit packet, dropping: -12
[  350.703418] random: crng init done
[  354.877329] ath10k_warn: 10661 callbacks suppressed
[  354.877331] usb 1-1: failed to transmit packet, dropping: -12
[  354.879931] usb 1-1: failed to submit frame: -12
[  354.880307] usb 1-1: failed to push frame: -12
[  354.940557] usb 1-1: failed to transmit packet, dropping: -12
[  354.942516] usb 1-1: failed to submit frame: -12
[  354.943062] usb 1-1: failed to push frame: -12
[  355.134808] usb 1-1: failed to transmit packet, dropping: -12
[  355.136463] usb 1-1: failed to submit frame: -12
[  355.137425] usb 1-1: failed to push frame: -12
[  355.159841] usb 1-1: failed to transmit packet, dropping: -12
[ ID] Interval   Transfer Bandwidth
[  4]  0.0-10.0 sec   225 MBytes   188 Mbits/sec

As you can see, there are a lot of ENOMEM errors in the TX path.
I think they could be related to patch 16 (that removes the pending
TX counter), but since I don't know how to configure the device
to generate HTT_T2H_MSG_TYPE_TX_COMPL_IND's the sw flow control had
to be disabled.

Since I no longer have access to any SDIO hardware I have not been able
to try the SDIO stuff, so it might be broken.

Erik Stromdahl (18):
  ath10k: add inlined wrappers for htt tx ops
  ath10k: add inlined wrappers for htt rx ops
  ath10k: add struct ath10k_bus_params
  ath10k: high_latency detection
  ath10k: add bus type check in ath10k_init_hw_params
  ath10k: per target config of max_num_peers
  ath10k: DMA related fixes for high latency devices
  ath10k: various fixes for high latency devices
  ath10k: add start_once support
  ath10k: add HTT TX HL ops
  ath10k: add HTT RX HL ops
  ath10k: htt: RX ring config HL support
  ath10k: htt: High latency TX support
  ath10k: htt: High latency RX support
  ath10k: wmi: disable softirq's while calling ieee80211_rx
  ath10k: remove htt pending TX count for high latency
  ath10k: add QCA9377 usb hw_param item
  ath10k: add QCA9377 sdio hw_param item

 drivers/net/wireless/ath/ath10k/ahb.c |   9 +-
 drivers/net/wireless/ath/ath10k/core.c| 108 ---
 drivers/net/wireless/ath/ath10k/core.h|  19 ++--
 drivers/net/wireless/ath/ath10k/htc.c |  19 ++--
 drivers/net/wireless/ath/ath10k/htt.c |   4 +-
 drivers/net/wireless/ath/ath10k/htt.h | 136 +++
 drivers/net/wireless/ath/ath10k/htt_rx.c  | 150 +++---
 drivers/net/wireless/ath/ath10k/htt_tx.c  | 173 --
 drivers/net/wireless/ath/ath10k/hw.h  |  20 
 drivers/net/wireless/ath/ath10k/mac.c 

[RFC v4 01/18] ath10k: add inlined wrappers for htt tx ops

2017-12-31 Thread Erik Stromdahl
These wrappers makes the HTT ops align better with the HIF ops
(where similar wrappers are used).

It also makes it easier for a target to have unsupported ops
(by letting the corresponding function pointer be NULL).

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

diff --git a/drivers/net/wireless/ath/ath10k/htt.c 
b/drivers/net/wireless/ath/ath10k/htt.c
index 625198dea18b..21a67f82f037 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -257,11 +257,11 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
return status;
}
 
-   status = htt->tx_ops->htt_send_frag_desc_bank_cfg(htt);
+   status = ath10k_htt_send_frag_desc_bank_cfg(htt);
if (status)
return status;
 
-   status = htt->tx_ops->htt_send_rx_ring_cfg(htt);
+   status = ath10k_htt_send_rx_ring_cfg(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 360c71b106d7..cdd87ef86c00 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1848,6 +1848,57 @@ struct ath10k_htt_tx_ops {
void (*htt_free_txbuff)(struct ath10k_htt *htt);
 };
 
+static inline int ath10k_htt_send_rx_ring_cfg(struct ath10k_htt *htt)
+{
+   if (!htt->tx_ops->htt_send_rx_ring_cfg)
+   return -EOPNOTSUPP;
+
+   return htt->tx_ops->htt_send_rx_ring_cfg(htt);
+}
+
+static inline int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt)
+{
+   if (!htt->tx_ops->htt_send_frag_desc_bank_cfg)
+   return -EOPNOTSUPP;
+
+   return htt->tx_ops->htt_send_frag_desc_bank_cfg(htt);
+}
+
+static inline int ath10k_htt_alloc_frag_desc(struct ath10k_htt *htt)
+{
+   if (!htt->tx_ops->htt_alloc_frag_desc)
+   return -EOPNOTSUPP;
+
+   return htt->tx_ops->htt_alloc_frag_desc(htt);
+}
+
+static inline void ath10k_htt_free_frag_desc(struct ath10k_htt *htt)
+{
+   if (htt->tx_ops->htt_free_frag_desc)
+   htt->tx_ops->htt_free_frag_desc(htt);
+}
+
+static inline int ath10k_htt_tx(struct ath10k_htt *htt,
+   enum ath10k_hw_txrx_mode txmode,
+   struct sk_buff *msdu)
+{
+   return htt->tx_ops->htt_tx(htt, txmode, msdu);
+}
+
+static inline int ath10k_htt_alloc_txbuff(struct ath10k_htt *htt)
+{
+   if (!htt->tx_ops->htt_alloc_txbuff)
+   return -EOPNOTSUPP;
+
+   return htt->tx_ops->htt_alloc_txbuff(htt);
+}
+
+static inline void ath10k_htt_free_txbuff(struct ath10k_htt *htt)
+{
+   if (htt->tx_ops->htt_free_txbuff)
+   htt->tx_ops->htt_free_txbuff(htt);
+}
+
 struct ath10k_htt_rx_ops {
size_t (*htt_get_rx_ring_size)(struct ath10k_htt *htt);
void (*htt_config_paddrs_ring)(struct ath10k_htt *htt, void *vaddr);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c 
b/drivers/net/wireless/ath/ath10k/htt_tx.c
index d334b7be1fea..a086958c39b6 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -443,13 +443,13 @@ static int ath10k_htt_tx_alloc_buf(struct ath10k_htt *htt)
struct ath10k *ar = htt->ar;
int ret;
 
-   ret = htt->tx_ops->htt_alloc_txbuff(htt);
+   ret = ath10k_htt_alloc_txbuff(htt);
if (ret) {
ath10k_err(ar, "failed to alloc cont tx buffer: %d\n", ret);
return ret;
}
 
-   ret = htt->tx_ops->htt_alloc_frag_desc(htt);
+   ret = ath10k_htt_alloc_frag_desc(htt);
if (ret) {
ath10k_err(ar, "failed to alloc cont frag desc: %d\n", ret);
goto free_txbuf;
@@ -473,10 +473,10 @@ static int ath10k_htt_tx_alloc_buf(struct ath10k_htt *htt)
ath10k_htt_tx_free_txq(htt);
 
 free_frag_desc:
-   htt->tx_ops->htt_free_frag_desc(htt);
+   ath10k_htt_free_frag_desc(htt);
 
 free_txbuf:
-   htt->tx_ops->htt_free_txbuff(htt);
+   ath10k_htt_free_txbuff(htt);
 
return ret;
 }
@@ -530,9 +530,9 @@ void ath10k_htt_tx_destroy(struct ath10k_htt *htt)
if (!htt->tx_mem_allocated)
return;
 
-   htt->tx_ops->htt_free_txbuff(htt);
+   ath10k_htt_free_txbuff(htt);
ath10k_htt_tx_free_txq(htt);
-   htt->tx_ops->htt_free_frag_desc(htt);
+   ath10k_htt_free_frag_desc(htt);
ath10k_htt_tx_free_txdone_fifo(htt);
htt->tx_mem_alloca

[PATCH 0/3] ath10k: a few minor fixes

2017-12-28 Thread Erik Stromdahl
I discovered these issues while working with the next round of
patches for High Latency devices.

In order to reduce the size of that patchset, I think it is best
if these patches could be added in advance.

The last patch fixes an actual bug that was introduced in
commit 71e9c29fbd28ec14bb8f920c7afd515a75c00234

The other two are just cleanups.

Erik Stromdahl (3):
  ath10k: fix spelling error
  ath10k: remove unused prototype
  ath10k: bugfix: add USB case in ath10k_core_probe_fw

 drivers/net/wireless/ath/ath10k/core.c | 1 +
 drivers/net/wireless/ath/ath10k/htt.h  | 1 -
 drivers/net/wireless/ath/ath10k/wmi.h  | 2 +-
 3 files changed, 2 insertions(+), 2 deletions(-)

-- 
2.15.1



[PATCH 1/3] ath10k: fix spelling error

2017-12-28 Thread Erik Stromdahl
Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/wmi.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.h 
b/drivers/net/wireless/ath/ath10k/wmi.h
index b0ed38c05bf8..c7b30ed9015d 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2929,7 +2929,7 @@ struct wmi_ext_resource_config_10_4_cmd {
__le32 max_tdls_concurrent_buffer_sta;
 };
 
-/* strucutre describing host memory chunk. */
+/* structure describing host memory chunk. */
 struct host_memory_chunk {
/* id of the request that is passed up in service ready */
__le32 req_id;
-- 
2.15.1



[PATCH 2/3] ath10k: remove unused prototype

2017-12-28 Thread Erik Stromdahl
The function does not exist and thus, the prototype can be removed.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htt.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.h 
b/drivers/net/wireless/ath/ath10k/htt.h
index 783640032216..360c71b106d7 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1933,7 +1933,6 @@ void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, 
struct sk_buff *skb);
 bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
 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_rx_ring_cfg_ll(struct ath10k_htt *htt);
 int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu);
-- 
2.15.1



[PATCH 3/3] ath10k: bugfix: add USB case in ath10k_core_probe_fw

2017-12-28 Thread Erik Stromdahl
Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 51444d34a06c..fe9341c97f31 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2427,6 +2427,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
break;
case ATH10K_BUS_PCI:
case ATH10K_BUS_AHB:
+   case ATH10K_BUS_USB:
memset(&target_info, 0, sizeof(target_info));
ret = ath10k_bmi_get_target_info(ar, &target_info);
if (ret) {
-- 
2.15.1



Re: [RFC v3 03/11] ath10k: per target configurablity of various items

2017-12-28 Thread Erik Stromdahl



On 2017-12-22 16:19, Kalle Valo wrote:

Erik Stromdahl  writes:


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.

Signed-off-by: Erik Stromdahl 


I was a bit torn about this, I definitely see the need for this but on
the other hand it creates duplicate data (for example two entries for
QCA9377 chip). I guess this is the right approach, at least I cannot
come up anything better.

But this patch should be split into two:

1) add bus field to struct ath10k_hw_params

2) add max_num_peers field to struct ath10k_hw_params

And it seems 2) is already implemented in commit 9f2992fea580 ("ath10k:
wmi: get wmi init parameter values from hw params"), so hopefully we
only need 1) anymore.



Before commit 9f2992fea580a48135591873e5e3ac7e01444207,
TARGET_TLV_NUM_PEERS was used both in the WMI TLV init command
and as the value of *max_num_peers* in *struct ath10k* (ar->max_num_peers).

commit 9f2992fea580a48135591873e5e3ac7e01444207 does not set
*ar->max_num_peers* to the value of *ar->hw_param->num_peers*.

Is this correct?

As I see it, there is a possible mismatch between what is written
to the device in the WMI init message and the value of *ar->max_num_peers*.

Do we still need *max_num_peers* in *struct ath10k* now that we have the
*num_peers* member in *struct ath10k_hw_params*?

I am currently rewriting my HL patches and I was thinking about adding
a separate patch related to this.


--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1663,9 +1663,19 @@ static int ath10k_init_hw_params(struct ath10k *ar)
for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
hw_params = &ath10k_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;
+   }


I don't like the is_high_latency test here at all. The bus field should
be checked with all entries, not just high latency ones. And because of
this even most of the hw_param bus field entries were not initialised.

So only thing to do is to initialise the bus field for all the entries
and the ugly test here can be removed. Just remember that QCA4019 uses
AHB, I think all the rest is PCI. Or do we have AHB devices supported?


I noticed that there has been introduced a new bus type (SNOC).
Do you know which devices are SNOC devices?
Btw, what the heck is SNOC anyway?




@@ -550,6 +557,18 @@ struct ath10k_hw_params {
 */
int vht160_mcs_rx_highest;
int vht160_mcs_tx_highest;
+
+   /* max_num_peers can be used to override the setting derived from
+* the WMI op version. If this value is non-zero, it will always
+* be used instead of the default value derived from the WMI op
+* version.
+*/
+   int max_num_peers;
+
+   /* Specifies whether or not the device is a high latency device */
+   bool is_high_latency;
+
+   enum ath10k_bus bus;
  };


Please move the bus field between dev_id and name fields. It's so
important that it should not be in the end.



Re: [PATCH 09/11] ath10k_sdio: virtual scatter gather for receive

2017-10-04 Thread Erik Stromdahl



On 2017-09-30 19:37, silexcom...@gmail.com wrote:

From: Alagu Sankar 

The existing implementation of initiating multiple sdio transfers for
receive bundling is slowing down the receive speed. Combining the
transfers using a scatter gather method would be ideal. This results in
significant performance improvement.

Since the sg implementation for sdio transfers are not reliable due to
buffer start and size alignment, a virtual scatter gather implementation
is used.

Signed-off-by: Alagu Sankar 
---
  drivers/net/wireless/ath/ath10k/htc.h  |   1 +
  drivers/net/wireless/ath/ath10k/sdio.c | 122 -
  drivers/net/wireless/ath/ath10k/sdio.h |   5 +-
  3 files changed, 93 insertions(+), 35 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.h 
b/drivers/net/wireless/ath/ath10k/htc.h
index 24663b0..5d87908 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -58,6 +58,7 @@ enum ath10k_htc_tx_flags {
  };
  
  enum ath10k_htc_rx_flags {

+   ATH10K_HTC_FLAGS_RECV_1MORE_BLOCK = 0x01,
ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02,
ATH10K_HTC_FLAG_BUNDLE_MASK = 0xF0
  };
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index bb6fa67..45df9db 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -35,6 +35,7 @@
  #include "sdio.h"
  
  #define ATH10K_SDIO_DMA_BUF_SIZE	(32 * 1024)

+#define ATH10K_SDIO_VSG_BUF_SIZE   (32 * 1024)
  
  static int ath10k_sdio_read(struct ath10k *ar, u32 addr, void *buf,

u32 len, bool incr);
@@ -430,6 +431,7 @@ static int ath10k_sdio_mbox_rx_process_packet(struct ath10k 
*ar,
int ret;
  
  	payload_len = le16_to_cpu(htc_hdr->len);

+   skb->len = payload_len + sizeof(struct ath10k_htc_hdr);
  
  	if (trailer_present) {

trailer = skb->data + sizeof(*htc_hdr) +
@@ -468,12 +470,13 @@ static int ath10k_sdio_mbox_rx_process_packets(struct 
ath10k *ar,
enum ath10k_htc_ep_id id;
int ret, i, *n_lookahead_local;
u32 *lookaheads_local;
+   int lookahd_idx = 0;


I think the variable should be named *lookahead_idx* instead of *lookahd_idx*,
since all other variables are using the string lookahead without abbreviations.

  
  	for (i = 0; i < ar_sdio->n_rx_pkts; i++) {

lookaheads_local = lookaheads;
n_lookahead_local = n_lookahead;
  
-		id = ((struct ath10k_htc_hdr *)&lookaheads[i])->eid;

+   id = ((struct ath10k_htc_hdr *)&lookaheads[lookahd_idx++])->eid;
  
  		if (id >= ATH10K_HTC_EP_COUNT) {

ath10k_warn(ar, "invalid endpoint in look-ahead: %d\n",
@@ -496,6 +499,7 @@ static int ath10k_sdio_mbox_rx_process_packets(struct 
ath10k *ar,
/* Only read lookahead's from RX trailers
 * for the last packet in a bundle.
 */
+   lookahd_idx--;
lookaheads_local = NULL;
n_lookahead_local = NULL;
}
@@ -529,11 +533,11 @@ static int ath10k_sdio_mbox_rx_process_packets(struct 
ath10k *ar,
return ret;
  }
  
-static int ath10k_sdio_mbox_alloc_pkt_bundle(struct ath10k *ar,

-struct ath10k_sdio_rx_data 
*rx_pkts,
-struct ath10k_htc_hdr *htc_hdr,
-size_t full_len, size_t act_len,
-size_t *bndl_cnt)
+static int ath10k_sdio_mbox_alloc_bundle(struct ath10k *ar,
+struct ath10k_sdio_rx_data *rx_pkts,
+struct ath10k_htc_hdr *htc_hdr,
+size_t full_len, size_t act_len,
+size_t *bndl_cnt)
  {
int ret, i;
  
@@ -574,6 +578,7 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,

size_t full_len, act_len;
bool last_in_bundle;
int ret, i;
+   int pkt_cnt = 0;
  
  	if (n_lookaheads > ATH10K_SDIO_MAX_RX_MSGS) {

ath10k_warn(ar,
@@ -616,16 +621,22 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
 * optimally fetched as a full bundle.
 */
size_t bndl_cnt;
-
-   ret = ath10k_sdio_mbox_alloc_pkt_bundle(ar,
-   
&ar_sdio->rx_pkts[i],
-   htc_hdr,
-   full_len,
-   act_len,
-   &bndl_cnt);
-
-   n_lookaheads += bndl_cnt;
-   

Re: [PATCH 00/11] SDIO support for ath10k

2017-10-04 Thread Erik Stromdahl



On 2017-10-04 08:22, Alagu Sankar wrote:

Hi Erik,

We will work to have this support mainlined as soon as possible. Would 
appreciate your support
in making sure that the patches do not affect the USB high latency path.


I have added the patches in my own ath-repo and I have tested with the
WUSB6100M without any problems.


On 02-10-2017 14:32, Erik Stromdahl wrote:

Hi Alagu,

It is great to see that we are finally about have fully working
mainline support for QCA9377 SDIO chipsets!

Great job!

On 2017-09-30 19:37, silexcom...@gmail.com wrote:

From: Alagu Sankar 

This patchset, generated against master-pending branch, enables a fully
functional SDIO interface driver for ath10k.  Patches have been verified on
QCA9377-3 WB396 and Silex's SX-SDCAC reference cards with Station, Access Point
and P2P modes.

The driver is verified with the firmware WLAN.TF.1.1.1-00061-QCATFSWPZ-1
with the board data from respective SDIO card vendors. Receive performance
matches the QCA reference driver when used with SDIO3.0 enabled platforms.
iperf tests indicate a downlink UDP of 275Mbit/s and TCP of 150Mbit/s


Can you share any scripts etc. (wrapping hostapd and wpa_supplicant stuff)
or provide some more info about you test setup?


I am not using any specific scripts for this. The standard ones from the ath10k 
configuration page
https://wireless.wiki.kernel.org/en/users/drivers/ath10k/configuration works 
just fine with the
NL80211 path.

I made a quick socat based test on an old laptop (I don't think it has SDIO
3.0 support) and I did unfortunately not get the same figures as you did :(


If it is SDIO v1.x, then the max bus speed is only 100Mbit/s.  With v2.x it is 
200Mbit/s and 3.x it is
832 Mbit/s.  Throughput primarily depends on it. We used i.MX6 SoloX Sabre SDB 
platform
which supports SDIO3.x and could see the maximum performance.

This patchset differs from the previous high latency patches, specific to SDIO.
HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET is enabled for HI_ACS. This instructs the
firmware to use HTT_T2H_MSG_TYPE_TX_COMPL_IND for outgoing packets. Without
this flag, the management frames are not sent out by the firmware. Possibility
of management frames being sent via WMI and data frames through the reduced Tx
completion needs to be probed further.


Ah, so that explains why I couldn't see any messages in the air.


Further improvements can be done on the transmit path by implementing packet
bundle. Scatter Gather is another area of improvement for both Transmit and
Receive, but may not work on all platforms

Known issues: Surprise removal of the card, when the device is in connected
state, delays sdio function remove due to delayed WMI command failures.
Existing ath10k framework can not differentiate between a kernel module
removal and the surprise removal of teh card.

Alagu Sankar (11):
   ath10k_sdio: sdio htt data transfer fixes
   ath10k_sdio: wb396 reference card fix
   ath10k_sdio: DMA bounce buffers for read write
   ath10k_sdio: reduce transmit msdu count
   ath10k_sdio: use clean packet headers
   ath10k_sdio: high latency fixes for beacon buffer
   ath10k_sdio: fix rssi indication
   ath10k_sdio: common read write
   ath10k_sdio: virtual scatter gather for receive
   ath10k_sdio: enable firmware crash dump
   ath10k_sdio: hif start once addition

  drivers/net/wireless/ath/ath10k/core.c    |  35 ++-
  drivers/net/wireless/ath/ath10k/debug.c   |   3 +
  drivers/net/wireless/ath/ath10k/htc.c |   4 +-
  drivers/net/wireless/ath/ath10k/htc.h |   1 +
  drivers/net/wireless/ath/ath10k/htt_rx.c  |  19 +-
  drivers/net/wireless/ath/ath10k/htt_tx.c  |  24 +-
  drivers/net/wireless/ath/ath10k/hw.c  |   2 +
  drivers/net/wireless/ath/ath10k/hw.h  |   1 +
  drivers/net/wireless/ath/ath10k/mac.c |  31 ++-
  drivers/net/wireless/ath/ath10k/sdio.c    | 398 ++
  drivers/net/wireless/ath/ath10k/sdio.h    |  10 +-
  drivers/net/wireless/ath/ath10k/wmi-tlv.c |   2 +-
  12 files changed, 403 insertions(+), 127 deletions(-)







Re: [PATCH 02/11] ath10k_sdio: wb396 reference card fix

2017-10-02 Thread Erik Stromdahl

Hi Alagu,

On 2017-10-02 09:02, Alagu Sankar wrote:

Hi Steve,

On 2017-10-02 04:17, Steve deRosier wrote:

Hi Alagu,


On Sat, Sep 30, 2017 at 10:37 AM,  wrote:


From: Alagu Sankar 

The QCA9377-3 WB396 sdio reference card does not get initialized
due to the conflict in uart gpio pins. This fix is not required
for other QCA9377 sdio cards.

Signed-off-by: Alagu Sankar 
---
 drivers/net/wireless/ath/ath10k/core.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index b4f66cd..86247c8 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1708,8 +1708,15 @@ static int ath10k_init_uart(struct ath10k *ar)
    return ret;
    }

-   if (!uart_print)
+   if (!uart_print) {
+   /* Hack: override dbg TX pin to avoid side effects of default
+    * GPIO_6 in QCA9377 WB396 reference card
+    */
+   if (ar->hif.bus == ATH10K_BUS_SDIO)
+   ath10k_bmi_write32(ar, hi_dbg_uart_txpin,
+  ar->hw_params.uart_pin);


If it is indeed a "hack", then I don't think the maintainer should
accept this upstream. If you want it upstream you need a clean enough
implementation that doesn't need to be labeled a "hack".


It is a hack as per the qcacld reference driver.


Your commit message states that this is only needed for a very
specific card and not for other QCA9377 sdio cards. Yet, you're doing
this for all ATH10K_BUS_SDIO devices. Not good. I think that it's a
quirk and it's limited to a particular implementation of the device.
My suggestion: if it can be automatically determined, then do so
explicitly. If not, then it needs to be a DT setting or a module
parameter or something like that so the platform maker can decide to
do it. Having it affect all users of a SDIO QCA9377 when it doesn't
apply doesn't seem like a good idea to me.


- Steve


Got it. The qcacld reference driver had it for all the QCA9377 sdio cards.
But we found it to be a problem only for the WB396 reference card. Will
have this checked again and release a v2 patch accordingly.


While you are at it, you might as well change the commit comments to:

"ath10k: sdio: "

or perhaps just:

"ath10k: "


Best Regards,
Alagu Sankar

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


Re: [PATCH 00/11] SDIO support for ath10k

2017-10-02 Thread Erik Stromdahl

Hi Alagu,

It is great to see that we are finally about have fully working
mainline support for QCA9377 SDIO chipsets!

Great job!

On 2017-09-30 19:37, silexcom...@gmail.com wrote:

From: Alagu Sankar 

This patchset, generated against master-pending branch, enables a fully
functional SDIO interface driver for ath10k.  Patches have been verified on
QCA9377-3 WB396 and Silex's SX-SDCAC reference cards with Station, Access Point
and P2P modes.

The driver is verified with the firmware WLAN.TF.1.1.1-00061-QCATFSWPZ-1
with the board data from respective SDIO card vendors. Receive performance
matches the QCA reference driver when used with SDIO3.0 enabled platforms.
iperf tests indicate a downlink UDP of 275Mbit/s and TCP of 150Mbit/s


Can you share any scripts etc. (wrapping hostapd and wpa_supplicant stuff)
or provide some more info about you test setup?

I made a quick socat based test on an old laptop (I don't think it has SDIO
3.0 support) and I did unfortunately not get the same figures as you did :(


This patchset differs from the previous high latency patches, specific to SDIO.
HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET is enabled for HI_ACS. This instructs the
firmware to use HTT_T2H_MSG_TYPE_TX_COMPL_IND for outgoing packets. Without
this flag, the management frames are not sent out by the firmware. Possibility
of management frames being sent via WMI and data frames through the reduced Tx
completion needs to be probed further.


Ah, so that explains why I couldn't see any messages in the air.


Further improvements can be done on the transmit path by implementing packet
bundle. Scatter Gather is another area of improvement for both Transmit and
Receive, but may not work on all platforms

Known issues: Surprise removal of the card, when the device is in connected
state, delays sdio function remove due to delayed WMI command failures.
Existing ath10k framework can not differentiate between a kernel module
removal and the surprise removal of teh card.

Alagu Sankar (11):
   ath10k_sdio: sdio htt data transfer fixes
   ath10k_sdio: wb396 reference card fix
   ath10k_sdio: DMA bounce buffers for read write
   ath10k_sdio: reduce transmit msdu count
   ath10k_sdio: use clean packet headers
   ath10k_sdio: high latency fixes for beacon buffer
   ath10k_sdio: fix rssi indication
   ath10k_sdio: common read write
   ath10k_sdio: virtual scatter gather for receive
   ath10k_sdio: enable firmware crash dump
   ath10k_sdio: hif start once addition

  drivers/net/wireless/ath/ath10k/core.c|  35 ++-
  drivers/net/wireless/ath/ath10k/debug.c   |   3 +
  drivers/net/wireless/ath/ath10k/htc.c |   4 +-
  drivers/net/wireless/ath/ath10k/htc.h |   1 +
  drivers/net/wireless/ath/ath10k/htt_rx.c  |  19 +-
  drivers/net/wireless/ath/ath10k/htt_tx.c  |  24 +-
  drivers/net/wireless/ath/ath10k/hw.c  |   2 +
  drivers/net/wireless/ath/ath10k/hw.h  |   1 +
  drivers/net/wireless/ath/ath10k/mac.c |  31 ++-
  drivers/net/wireless/ath/ath10k/sdio.c| 398 ++
  drivers/net/wireless/ath/ath10k/sdio.h|  10 +-
  drivers/net/wireless/ath/ath10k/wmi-tlv.c |   2 +-
  12 files changed, 403 insertions(+), 127 deletions(-)



[RFC v3 10/11] ath10k: wmi: disable softirq's while calling ieee80211_rx

2017-09-17 Thread Erik Stromdahl
Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/wmi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c 
b/drivers/net/wireless/ath/ath10k/wmi.c
index 38a97086708b..10bb5be6ab00 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2408,7 +2408,10 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct 
sk_buff *skb)
   status->freq, status->band, status->signal,
   status->rate_idx);
 
+   local_bh_disable();
ieee80211_rx(ar->hw, skb);
+   local_bh_enable();
+
return 0;
 }
 
-- 
2.14.1



[RFC v3 02/11] ath10k: htt: RX ring config HL support

2017-09-17 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 cd160b16db1e..29ed4afe52a4 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 6305308422c4..7ffa1d41f478 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1805,6 +1805,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 685faac1368f..8d85f82ad8f8 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -693,6 +693,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 = &cmd->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_le16(HTT_RX_RING_SIZE_MIN);
+   ring->rx_ring_bufsize = __cpu_to_le16(HTT_RX_BUF_SIZE);
+   ring->flags = __cpu_to_le16(flags);
+
+   ret = ath10k_htc_send(&htt->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.14.1



[RFC v3 11/11] ath10k: remove htt pending TX count for high latency

2017-09-17 Thread Erik Stromdahl
High latency chipsest does not seem to send any
HTT_T2H_MSG_TYPE_TX_COMPL_IND for outgoing frames.

This means that htt->num_pending_tx will never be
decremented and we will eventually hit the maximum
limit. All outgoing packets will then be discarded.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htt_tx.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c 
b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 82d01139ff92..c74fc137ac67 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -153,6 +153,9 @@ void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw,
 
 void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
 {
+   if (htt->ar->is_high_latency)
+   return;
+
lockdep_assert_held(&htt->tx_lock);
 
htt->num_pending_tx--;
@@ -162,6 +165,9 @@ void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
 
 int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
 {
+   if (htt->ar->is_high_latency)
+   return 0;
+
lockdep_assert_held(&htt->tx_lock);
 
if (htt->num_pending_tx >= htt->max_num_pending_tx)
-- 
2.14.1



[RFC v3 08/11] ath10k: add QCA9377 usb hw_param item

2017-09-17 Thread Erik Stromdahl
Hardware parameters for QCA9377 usb devices.

Signed-off-by: Erik Stromdahl 
---
 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 1880570989ae..b6893254ef53 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -328,6 +328,29 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
+   {
+   .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,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h 
b/drivers/net/wireless/ath/ath10k/hw.h
index fd0536077404..420851e26a09 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.14.1



[RFC v3 00/11] ath10k high latency

2017-09-17 Thread Erik Stromdahl
This is the third version of the high latency patches (stuff common for
usb and sdio).

One major difference between this version and the previous is that the
num_pending_tx counter has been disabled for high latency devices (last patch).

This fixes the previous issue with the halted USB RX.
I have tested these patches with a Linksys WUSB6100M and it looks
much better than the previous version.

High latency devices does not seem to send HTT_T2H_MSG_TYPE_TX_COMPL_IND's
to the host for outgoing packets, resulting in a transmit stop when the
upper limit of num_pending_tx is reached.

The qcacld driver mentions that the TX_COMPL_IND can be disabled for HL
devices in order to achieve better throughput:

/*
 * HTT option TLV for specifying whether HL systems should indicate
 * over-the-air tx completion for individual frames, or should instead
 * send a bulk TX_CREDIT_UPDATE_IND except when the host explicitly
 * requests an OTA tx completion for a particular tx frame.
 * This option does not apply to LL systems, where the TX_COMPL_IND
 * is mandatory.
 * This option is primarily intended for HL systems in which the tx frame
 * downloads over the host --> target bus are as slow as or slower than
 * the transmissions over the WLAN PHY.  For cases where the bus is faster
 * than the WLAN PHY, the target will transmit relatively large A-MPDUs,
 * and consquently will send one TX_COMPL_IND message that covers several
 * tx frames.  For cases where the WLAN PHY is faster than the bus,
 * the target will end up transmitting very short A-MPDUs, and consequently
 * sending many TX_COMPL_IND messages, which each cover a very small number
 * of tx frames.
 * The HL_SUPPRESS_TX_COMPL_IND TLV can be sent by the host to the target as
 * a suffix to the VERSION_REQ message to request whether the host desires to
 * use TX_CREDIT_UPDATE_IND rather than TX_COMPL_IND.  The target can then
 * send a HTT_SUPPRESS_TX_COMPL_IND TLV to the host as a suffix to the
 * VERSION_CONF message to confirm whether TX_CREDIT_UPDATE_IND will be used
 * rather than TX_COMPL_IND.  TX_CREDIT_UPDATE_IND shall only be used if the
 * host sends a HL_SUPPRESS_TX_COMPL_IND TLV requesting use of
 * TX_CREDIT_UPDATE_IND, and the target sends a HL_SUPPRESS_TX_COMPLE_IND TLV
 * back to the host confirming use of TX_CREDIT_UPDATE_IND.
 * Lack of a HL_SUPPRESS_TX_COMPL_IND TLV from either host --> target or
 * target --> host is equivalent to a HL_SUPPRESS_TX_COMPL_IND that
 * explicitly specifies HL_ALLOW_TX_COMPL_IND in the value payload of the
 * TLV.
 */

I am suspecting this is the default behavior in the firmware.

I have tried a simple wget test where I download a Linux kernel tar ball
from kernel.org. I got the below results:

wget --no-check-certificate \
https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.11.4.tar.xz

2017-09-17 16:46:20 (13.3 MB/s) - 'linux-4.11.4.tar.xz' saved
[95549228/95549228]

13.3 MB/s is a fairly OK result since I have a 100 Mbit/s internet
connection.

Changes since v2:

- Disabled htt num_pending_tx counter for HL.
- Fixed transmit flags for HL HTT TX.
- Proper marking of aggregated frames in the HL HTT RX handler.
- A few other minor fixes

Erik Stromdahl (11):
  ath10k: high_latency detection
  ath10k: htt: RX ring config HL support
  ath10k: per target configurablity of various items
  ath10k: add start_once support
  ath10k: htt: High latency TX support
  ath10k: htt: High latency RX support
  ath10k: various fixes for high latency devices
  ath10k: add QCA9377 usb hw_param item
  ath10k: add QCA9377 sdio hw_param item
  ath10k: wmi: disable softirq's while calling ieee80211_rx
  ath10k: remove htt pending TX count for high latency

 drivers/net/wireless/ath/ath10k/core.c| 128 +++-
 drivers/net/wireless/ath/ath10k/core.h|  16 +--
 drivers/net/wireless/ath/ath10k/htc.c |  19 ++--
 drivers/net/wireless/ath/ath10k/htt.c |   5 +-
 drivers/net/wireless/ath/ath10k/htt.h |  57 ++-
 drivers/net/wireless/ath/ath10k/htt_rx.c  | 122 ++-
 drivers/net/wireless/ath/ath10k/htt_tx.c  | 157 +-
 drivers/net/wireless/ath/ath10k/hw.h  |  30 ++
 drivers/net/wireless/ath/ath10k/mac.c |   5 +-
 drivers/net/wireless/ath/ath10k/rx_desc.h |  15 +++
 drivers/net/wireless/ath/ath10k/txrx.c|   5 +-
 drivers/net/wireless/ath/ath10k/wmi-tlv.c |   4 +-
 drivers/net/wireless/ath/ath10k/wmi.c |   3 +
 13 files changed, 513 insertions(+), 53 deletions(-)

-- 
2.14.1



[RFC v3 04/11] ath10k: add start_once support

2017-09-17 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 | 19 +++
 drivers/net/wireless/ath/ath10k/core.h |  2 ++
 drivers/net/wireless/ath/ath10k/hw.h   |  6 ++
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index a4a326c89e0d..c21227a74996 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1999,6 +1999,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(&ar->conf_mutex);
 
clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
@@ -2226,6 +2229,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:
@@ -2278,6 +2282,7 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_htt_tx_stop(&ar->htt);
ath10k_htt_rx_free(&ar->htt);
ath10k_wmi_detach(ar);
+   ar->is_started = false;
 }
 EXPORT_SYMBOL(ath10k_core_stop);
 
@@ -2380,12 +2385,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(&ar->conf_mutex);
+   } else {
+   ath10k_debug_print_boot_info(ar);
+   ath10k_core_stop(ar);
 
-   mutex_unlock(&ar->conf_mutex);
+   mutex_unlock(&ar->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 64dadcd6e531..0b5b1dd00e16 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -784,6 +784,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 8cf7b963f3d4..fd0536077404 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -569,6 +569,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.14.1



[RFC v3 03/11] ath10k: per target configurablity of various items

2017-09-17 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.

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

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index f1924c974a12..a4a326c89e0d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1663,9 +1663,19 @@ static int ath10k_init_hw_params(struct ath10k *ar)
for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
hw_params = &ath10k_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)) {
@@ -1764,6 +1774,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 = &ar->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)) {
@@ -1843,7 +1854,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;
@@ -1855,10 +1866,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;
ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
} else {
-   ar->max_num_peers = TARGET_10X_NUM_PEERS;
+   max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
}
ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
@@ -1867,7 +1878,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
-   ar->max_num_peers = TARGET_TLV_NUM_PEERS;
+   max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
@@ -1878,7 +1889,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_10_4:
-   ar->max_num_peers = TARGE

[RFC v3 01/11] ath10k: high_latency detection

2017-09-17 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 a4f635820f35..f1924c974a12 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2496,6 +2496,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 949ebb3e967b..dc9ecf773d51 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -789,6 +789,8 @@ struct ath10k {
 
bool p2p;
 
+   bool is_high_latency;
+
struct {
enum ath10k_bus bus;
const struct ath10k_hif_ops *ops;
@@ -1013,6 +1015,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.14.1



[RFC v3 07/11] ath10k: various fixes for high latency devices

2017-09-17 Thread Erik Stromdahl
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.

A few other execution paths are not applicable for high latency
devices and can be skipped.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/htc.c| 19 ---
 drivers/net/wireless/ath/ath10k/htt_rx.c |  3 ++-
 drivers/net/wireless/ath/ath10k/htt_tx.c |  9 +++--
 drivers/net/wireless/ath/ath10k/txrx.c   |  5 +++--
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c 
b/drivers/net/wireless/ath/ath10k/htc.c
index e5c80f582ff5..75c2a3ea7ec9 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -53,7 +53,8 @@ static inline void ath10k_htc_restore_tx_skb(struct 
ath10k_htc *htc,
 {
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
 
-   dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
+   if (!htc->ar->is_high_latency)
+   dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, 
DMA_TO_DEVICE);
skb_pull(skb, sizeof(struct ath10k_htc_hdr));
 }
 
@@ -137,11 +138,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;
@@ -157,7 +161,8 @@ int ath10k_htc_send(struct ath10k_htc *htc,
return 0;
 
 err_unmap:
-   dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
+   if (!ar->is_high_latency)
+   dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
 err_credits:
if (ep->tx_credit_flow_enabled) {
spin_lock_bh(&htc->tx_lock);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c 
b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 7461555ccad5..569edd0720c6 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2541,7 +2541,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 a3d69f852e38..82d01139ff92 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;
@@ -445,7 +448,8 @@ void ath10k_htt_tx_destroy(struct ath10k_htt *htt)
return;
 
ath10k_htt_tx_free_cont_txbuf(htt);
-   ath10k_htt_tx_free_txq(htt);
+   if (!htt->ar->is_high_latency)
+   ath10k_htt_tx_free_txq(htt);
ath10k_htt_tx_free_cont_frag_desc(htt);
ath10k_htt_tx_free_txdone_fifo(htt);
htt->tx_mem_allocated = false;
@@ -935,7 +939,8 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct 
sk_buff *msdu)
return 0;
 
 err_unmap_msdu:
-   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);
 err_free_txdesc:
dev_kfree_skb_any(txdesc);
 err_free_msdu_id:
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c 
b/drivers/net/wireless/ath/ath10k/txrx.c
index d4986f626c35..fae143e4dcfa 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -90,11 +90,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))
w

[RFC v3 06/11] ath10k: htt: High latency RX support

2017-09-17 Thread Erik Stromdahl
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 
---
 drivers/net/wireless/ath/ath10k/core.c|  27 ---
 drivers/net/wireless/ath/ath10k/htt.h |  47 
 drivers/net/wireless/ath/ath10k/htt_rx.c  | 119 +-
 drivers/net/wireless/ath/ath10k/rx_desc.h |  15 
 4 files changed, 195 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index c21227a74996..1880570989ae 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2083,10 +2083,12 @@ int ath10k_core_start(struct ath10k *ar, enum 
ath10k_firmware_mode mode,
ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
ar->wmi.svc_map));
 
-   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);
@@ -2203,10 +2205,13 @@ int ath10k_core_start(struct ath10k *ar, enum 
ath10k_firmware_mode mode,
}
}
 
-   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->is_high_latency) {
+   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)
@@ -2235,7 +2240,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:
@@ -2280,7 +2286,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 bac453f5753e..ac5603ef4ba5 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -646,6 +646,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)
 {
@@ -658,6 +667,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,
@@ -1530,6 +1551,7 @@ struct htt_resp {
struct htt_mgmt_tx_completion mgmt_tx

[RFC v3 09/11] ath10k: add QCA9377 sdio hw_param item

2017-09-17 Thread Erik Stromdahl
Hardware parameters for QCA9377 sdio devices.

Signed-off-by: Erik Stromdahl 
---
 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 b6893254ef53..146a9f61b5f0 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -351,6 +351,31 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
.bus = ATH10K_BUS_USB,
.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 = 17600,
+   .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,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h 
b/drivers/net/wireless/ath/ath10k/hw.h
index 420851e26a09..77011a6cafa1 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.14.1



[RFC v3 05/11] ath10k: htt: High latency TX support

2017-09-17 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 | 91 +++-
 drivers/net/wireless/ath/ath10k/mac.c|  5 +-
 3 files changed, 99 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.h 
b/drivers/net/wireless/ath/ath10k/htt.h
index 7ffa1d41f478..bac453f5753e 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1830,9 +1830,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 8d85f82ad8f8..a3d69f852e38 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -946,8 +946,95 @@ 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);
+   bool is_eth = (txmode == ATH10K_HW_TXRX_ETHERNET);
+   u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
+   u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth);
+   u8 flags0 = 0;
+   u16 flags1 = 0;
+
+   data_len = msdu->len;
+
+   switch (txmode) {
+   case ATH10K_HW_TXRX_RAW:
+   case ATH10K_HW_TXRX_NATIVE_WIFI:
+   flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
+   /* fall through */
+   case ATH10K_HW_TXRX_ETHERNET:
+   flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+   break;
+   case ATH10K_HW_TXRX_MGMT:
+   flags0 |= SM(ATH10K_HW_TXRX_MGMT,
+HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+   flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
+   break;
+   }
+
+   if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
+   flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
+
+   flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
+   flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID);
+   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_

[PATCH v2] ath10k: sdio: remove unused struct member

2017-08-23 Thread Erik Stromdahl
irq_wq in struct ath10k_sdio is a remnant from an earlier
version of the sdio patchset.

Its use was removed as a result of Kalle's review, but somehow
the struct member survived.

It is not used and can therefore safely be removed.

Signed-off-by: Erik Stromdahl 
---
V2: Fix typo in commit log (It's -> Its)
---
 drivers/net/wireless/ath/ath10k/sdio.c | 4 
 drivers/net/wireless/ath/ath10k/sdio.h | 2 --
 2 files changed, 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 48268f0..03a69e5 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1344,8 +1344,6 @@ static void ath10k_sdio_irq_handler(struct sdio_func 
*func)
 
sdio_claim_host(ar_sdio->func);
 
-   wake_up(&ar_sdio->irq_wq);
-
if (ret && ret != -ECANCELED)
ath10k_warn(ar, "failed to process pending SDIO interrupts: 
%d\n",
ret);
@@ -2000,8 +1998,6 @@ static int ath10k_sdio_probe(struct sdio_func *func,
goto err_free_bmi_buf;
}
 
-   init_waitqueue_head(&ar_sdio->irq_wq);
-
for (i = 0; i < ATH10K_SDIO_BUS_REQUEST_MAX_NUM; i++)
ath10k_sdio_free_bus_req(ar, &ar_sdio->bus_req[i]);
 
diff --git a/drivers/net/wireless/ath/ath10k/sdio.h 
b/drivers/net/wireless/ath/ath10k/sdio.h
index 3f61c67..4ff7b54 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.h
+++ b/drivers/net/wireless/ath/ath10k/sdio.h
@@ -210,8 +210,6 @@ struct ath10k_sdio {
/* temporary buffer for BMI requests */
u8 *bmi_buf;
 
-   wait_queue_head_t irq_wq;
-
bool is_disabled;
 
struct workqueue_struct *workqueue;
-- 
2.7.4



[PATCH] ath10k: sdio: remove unused struct member

2017-08-19 Thread Erik Stromdahl
irq_wq in struct ath10k_sdio is a remnant from an earlier
version of the sdio patchset.

It's use was removed as a result of Kalle's review, but somehow
the struct member survived.

It is not used and can therefore safely be removed.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/sdio.c | 4 
 drivers/net/wireless/ath/ath10k/sdio.h | 2 --
 2 files changed, 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 48268f0..03a69e5 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1344,8 +1344,6 @@ static void ath10k_sdio_irq_handler(struct sdio_func 
*func)
 
sdio_claim_host(ar_sdio->func);
 
-   wake_up(&ar_sdio->irq_wq);
-
if (ret && ret != -ECANCELED)
ath10k_warn(ar, "failed to process pending SDIO interrupts: 
%d\n",
ret);
@@ -2000,8 +1998,6 @@ static int ath10k_sdio_probe(struct sdio_func *func,
goto err_free_bmi_buf;
}
 
-   init_waitqueue_head(&ar_sdio->irq_wq);
-
for (i = 0; i < ATH10K_SDIO_BUS_REQUEST_MAX_NUM; i++)
ath10k_sdio_free_bus_req(ar, &ar_sdio->bus_req[i]);
 
diff --git a/drivers/net/wireless/ath/ath10k/sdio.h 
b/drivers/net/wireless/ath/ath10k/sdio.h
index 3f61c67..4ff7b54 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.h
+++ b/drivers/net/wireless/ath/ath10k/sdio.h
@@ -210,8 +210,6 @@ struct ath10k_sdio {
/* temporary buffer for BMI requests */
u8 *bmi_buf;
 
-   wait_queue_head_t irq_wq;
-
bool is_disabled;
 
struct workqueue_struct *workqueue;
-- 
2.7.4



[PATCH] ath10k: sdio: fix compile warning

2017-07-08 Thread Erik Stromdahl
As suggested by Arnd Bergmann, replace
"while (time_before_...) {}"
with
"do {} while (time_before_...)"

This fixes the following warnings detected by gcc 4.1.2:

drivers/net/wireless/ath/ath10k/sdio.c: In function
‘ath10k_sdio_mbox_rxmsg_pending_handler’:
drivers/net/wireless/ath/ath10k/sdio.c:676: warning: ‘ret’ may be used 
uninitialized in this function

...

drivers/net/wireless/ath/ath10k/sdio.c: In function
‘ath10k_sdio_irq_handler’:
drivers/net/wireless/ath/ath10k/sdio.c:1331: warning: ‘ret’ may be used 
uninitialized in this function

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/sdio.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 859ed87..48268f0 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -683,7 +683,7 @@ static int ath10k_sdio_mbox_rxmsg_pending_handler(struct 
ath10k *ar,
lookaheads[0] = msg_lookahead;
 
timeout = jiffies + SDIO_MBOX_PROCESSING_TIMEOUT_HZ;
-   while (time_before(jiffies, timeout)) {
+   do {
/* Try to allocate as many HTC RX packets indicated by
 * n_lookaheads.
 */
@@ -719,7 +719,7 @@ static int ath10k_sdio_mbox_rxmsg_pending_handler(struct 
ath10k *ar,
 * performance in high throughput situations.
 */
*done = false;
-   }
+   } while (time_before(jiffies, timeout));
 
if (ret && (ret != -ECANCELED))
ath10k_warn(ar, "failed to get pending recv messages: %d\n",
@@ -1336,11 +1336,11 @@ static void ath10k_sdio_irq_handler(struct sdio_func 
*func)
sdio_release_host(ar_sdio->func);
 
timeout = jiffies + ATH10K_SDIO_HIF_COMMUNICATION_TIMEOUT_HZ;
-   while (time_before(jiffies, timeout) && !done) {
+   do {
ret = ath10k_sdio_mbox_proc_pending_irqs(ar, &done);
if (ret)
break;
-   }
+   } while (time_before(jiffies, timeout) && !done);
 
sdio_claim_host(ar_sdio->func);
 
-- 
2.7.4



Re: ath10k: ret used but uninitialized (was: Re: ath10k: add initial SDIO support)

2017-07-06 Thread Erik Stromdahl

With gcc 4.1.2:

drivers/net/wireless/ath/ath10k/sdio.c: In function
‘ath10k_sdio_mbox_rxmsg_pending_handler’:
drivers/net/wireless/ath/ath10k/sdio.c:676: warning: ‘ret’ may be used
uninitialized in this function


+
+   *done = true;
+
+   /* Copy the lookahead obtained from the HTC register table into our
+* temp array as a start value.
+*/
+   lookaheads[0] = msg_lookahead;
+
+   timeout = jiffies + SDIO_MBOX_PROCESSING_TIMEOUT_HZ;


Although very unlikely due to the long timeout, if the code is preempted here,
and the loop below never entered, ret will indeed be uninitialized.

It's unclear to me what the proper initialization would be, though, so
that's why I didn't send a patch.


I think it would be best to use 0 as initial value of ret in this case.
This will make all other interrupts be processed in a normal way.

Kalle: Should I create a new patch (initializing ret with zero)?


+   while (time_before(jiffies, timeout)) {
+   /* Try to allocate as many HTC RX packets indicated by
+* n_lookaheads.
+*/
+   ret = ath10k_sdio_mbox_rx_alloc(ar, lookaheads,
+   n_lookaheads);
+   if (ret)
+   break;
+
+   if (ar_sdio->n_rx_pkts >= 2)
+   /* A recv bundle was detected, force IRQ status
+* re-check again.
+*/
+   *done = false;
+
+   ret = ath10k_sdio_mbox_rx_fetch(ar);
+
+   /* Process fetched packets. This will potentially update
+* n_lookaheads depending on if the packets contain lookahead
+* reports.
+*/
+   n_lookaheads = 0;
+   ret = ath10k_sdio_mbox_rx_process_packets(ar,
+ lookaheads,
+ &n_lookaheads);
+
+   if (!n_lookaheads || ret)
+   break;
+
+   /* For SYNCH processing, if we get here, we are running
+* through the loop again due to updated lookaheads. Set
+* flag that we should re-check IRQ status registers again
+* before leaving IRQ processing, this can net better
+* performance in high throughput situations.
+*/
+   *done = false;
+   }
+
+   if (ret && (ret != -ECANCELED))
+   ath10k_warn(ar, "failed to get pending recv messages: %d\n",
+   ret);
+
+   return ret;
+}



+static void ath10k_sdio_irq_handler(struct sdio_func *func)
+{
+   struct ath10k_sdio *ar_sdio = sdio_get_drvdata(func);
+   struct ath10k *ar = ar_sdio->ar;
+   unsigned long timeout;
+   bool done = false;
+   int ret;


drivers/net/wireless/ath/ath10k/sdio.c: In function ‘ath10k_sdio_irq_handler’:
drivers/net/wireless/ath/ath10k/sdio.c:1331: warning: ‘ret’ may be
used uninitialized in this function


+
+   /* Release the host during interrupts so we can pick it back up when
+* we process commands.
+*/
+   sdio_release_host(ar_sdio->func);
+
+   timeout = jiffies + ATH10K_SDIO_HIF_COMMUNICATION_TIMEOUT_HZ;


Same here.

Should ret be preinitialized to 0, -ECANCELED, or something else?


ret = 0 or ret = -ECANCELED, will result in no warning message.
-ETIMEDOUT could be used perhaps.

Note that the function is a void function so the error will not get
propagated.

I am fine with ret = 0 in this case as well.

+   while (time_before(jiffies, timeout) && !done) {
+   ret = ath10k_sdio_mbox_proc_pending_irqs(ar, &done);
+   if (ret)
+   break;
+   }
+
+   sdio_claim_host(ar_sdio->func);
+
+   wake_up(&ar_sdio->irq_wq);
+
+   if (ret && ret != -ECANCELED)
+   ath10k_warn(ar, "failed to process pending SDIO interrupts: 
%d\n",
+   ret);
+}


Gr{oetje,eeting}s,

 Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
 -- Linus Torvalds



Re: [RFC v2 05/10] ath10k: htt: High latency TX support

2017-06-17 Thread Erik Stromdahl



On 2017-06-13 19:38, Peter Oh wrote:

On 06/12/2017 08:03 AM, Erik Stromdahl wrote:

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

Signed-off-by: Erik Stromdahl 
---

diff --git a/drivers/net/wireless/ath/ath10k/mac.c 
b/drivers/net/wireless/ath/ath10k/mac.c
index 48418f9..c5fd803 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3572,7 +3572,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)

Can we use function pointers at initial time to avoid condition check at hot 
path?
I'm afraid adding more lines on hot path.

I haven't made any comparison of assembly code between if-paths or function 
pointers,
but since most architectures have conditional instructions I don't think the
penalty is that big (if there is any penalty at all).
There are plenty of other condition checks in the RX path (mac80211 is full of 
them),
so I don't really see this as an issue.
That being said, any improvement is always welcome (even micro optimizations
if they are beneficial).
I will think about this and see if adding function pointers can be done in a 
nice way.


[RFC v2 04/10] ath10k: add start_once support

2017-06-12 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 | 19 +++
 drivers/net/wireless/ath/ath10k/core.h |  2 ++
 drivers/net/wireless/ath/ath10k/hw.h   |  6 ++
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 587c013..a1a4610 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1966,6 +1966,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(&ar->conf_mutex);
 
clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
@@ -2185,6 +2188,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:
@@ -2237,6 +2241,7 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_htt_tx_stop(&ar->htt);
ath10k_htt_rx_free(&ar->htt);
ath10k_wmi_detach(ar);
+   ar->is_started = false;
 }
 EXPORT_SYMBOL(ath10k_core_stop);
 
@@ -2339,12 +2344,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(&ar->conf_mutex);
+   } else {
+   ath10k_debug_print_boot_info(ar);
+   ath10k_core_stop(ar);
 
-   mutex_unlock(&ar->conf_mutex);
+   mutex_unlock(&ar->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 cdac923..0e75441 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -784,6 +784,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 160377aa..f733e73 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -473,6 +473,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



[RFC v2 09/10] ath10k: add QCA9377 sdio hw_param item

2017-06-12 Thread Erik Stromdahl
Hardware parameters for QCA9377 sdio devices.

Signed-off-by: Erik Stromdahl 
---
 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 dc8ea5e..675ce08 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -322,6 +322,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 = 17600,
+   .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 cc3d0eb..676c855 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



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

2017-06-12 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.

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

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index d3bf5c4..587c013 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1631,9 +1631,19 @@ static int ath10k_init_hw_params(struct ath10k *ar)
for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
hw_params = &ath10k_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)) {
@@ -1732,6 +1742,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 = &ar->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)) {
@@ -1811,7 +1822,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;
@@ -1823,10 +1834,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;
ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
} else {
-   ar->max_num_peers = TARGET_10X_NUM_PEERS;
+   max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
}
ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
@@ -1835,7 +1846,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
-   ar->max_num_peers = TARGET_TLV_NUM_PEERS;
+   max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
@@ -1846,7 +1857,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_10_4:
-   ar->max_num_peers = TARGET_10_4_NUM_PEERS;

[RFC v2 07/10] ath10k: dma fixes for high latency devices

2017-06-12 Thread Erik Stromdahl
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 
---
 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 e5c80f5..232740c 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -137,11 +137,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 5833c08..972c21c 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2492,7 +2492,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 e3b820d..27bbc3e 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 d4986f6..fae143e 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -90,11 +90,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



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

2017-06-12 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 7ffa1d4..bac453f 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1830,9 +1830,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 8d85f82..e3b820d 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -946,8 +946,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 48418f9..c5fd803 100644
--- a/drivers/n

[RFC v2 01/10] ath10k: high_latency detection

2017-06-12 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 3fb1429..d3bf5c4 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2455,6 +2455,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 1efe0a1..90069b8 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -789,6 +789,8 @@ struct ath10k {
 
bool p2p;
 
+   bool is_high_latency;
+
struct {
enum ath10k_bus bus;
const struct ath10k_hif_ops *ops;
@@ -1008,6 +1010,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



[RFC v2 08/10] ath10k: add QCA9377 usb hw_param item

2017-06-12 Thread Erik Stromdahl
Hardware parameters for QCA9377 usb devices.

Signed-off-by: Erik Stromdahl 
---
 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 c20b97b..dc8ea5e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -299,6 +299,29 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
.spectral_bin_discard = 0,
},
{
+   .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 f733e73..cc3d0eb 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



[RFC v2 10/10] ath10k: wmi: disable softirq's while calling ieee80211_rx

2017-06-12 Thread Erik Stromdahl
Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/wmi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c 
b/drivers/net/wireless/ath/ath10k/wmi.c
index 472b42b..d5d0d5c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2383,7 +2383,10 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct 
sk_buff *skb)
   status->freq, status->band, status->signal,
   status->rate_idx);
 
+   local_bh_disable();
ieee80211_rx(ar->hw, skb);
+   local_bh_enable();
+
return 0;
 }
 
-- 
2.7.4



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

2017-06-12 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 6305308..7ffa1d4 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1805,6 +1805,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 685faac..8d85f82 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -693,6 +693,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 = &cmd->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_le16(HTT_RX_RING_SIZE_MIN);
+   ring->rx_ring_bufsize = __cpu_to_le16(HTT_RX_BUF_SIZE);
+   ring->flags = __cpu_to_le16(flags);
+
+   ret = ath10k_htc_send(&htt->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



[RFC v2 06/10] ath10k: htt: High latency RX support

2017-06-12 Thread Erik Stromdahl
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 
---
 drivers/net/wireless/ath/ath10k/core.c| 38 +++-
 drivers/net/wireless/ath/ath10k/htt.h | 47 +++
 drivers/net/wireless/ath/ath10k/htt_rx.c  | 97 ++-
 drivers/net/wireless/ath/ath10k/rx_desc.h | 15 +
 4 files changed, 179 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index a1a4610..c20b97b 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2044,10 +2044,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);
@@ -2156,16 +2158,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)
@@ -2194,7 +2200,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:
@@ -2239,7 +2246,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 bac453f..ac5603e 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -646,6 +646,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)
 {
@@ -658,6 +667,18 @@ static inline struct htt_rx_indication_mpdu_range *
return ptr;
 }
 
+static inline struct htt_rx_indicatio

[RFC v2 00/10] ath10k high latency

2017-06-12 Thread Erik Stromdahl
This is the second version of the high latency patches (stuff common for
usb and sdio). The only difference when compared to the previous version
is that explicit calls to *local_bh_disable* have been added before calling
*ieee80211_rx*.

This is a requirement from mac80211.

Adding these calls should not introduce any problem for pcie since the
*local_bh_enable* and *local_bh_disable* functions will only increment
and decrement the softirq counter by one (if softirq's have already been
disabled before calling *local_bh_disable*, the call to *local_bh_enable*
will not enable them).

Adding these calls removes a warning generated by mac80211.

The previous RFC mentioned a problem related to this warning.
>From Linux 4.12, the warning was not handled correctly and the warning
was turned into an oops (I still don't know the reason for this).

This version fixes this.

Erik Stromdahl (10):
  ath10k: high_latency detection
  ath10k: htt: RX ring config HL support
  ath10k: per target configurablity of various items
  ath10k: add start_once support
  ath10k: htt: High latency TX support
  ath10k: htt: High latency RX support
  ath10k: dma fixes for high latency devices
  ath10k: add QCA9377 usb hw_param item
  ath10k: add QCA9377 sdio hw_param item
  ath10k: wmi: disable softirq's while calling ieee80211_rx

 drivers/net/wireless/ath/ath10k/core.c| 139 --
 drivers/net/wireless/ath/ath10k/core.h|  16 ++--
 drivers/net/wireless/ath/ath10k/htc.c |  13 +--
 drivers/net/wireless/ath/ath10k/htt.c |   5 +-
 drivers/net/wireless/ath/ath10k/htt.h |  57 +++-
 drivers/net/wireless/ath/ath10k/htt_rx.c  | 100 -
 drivers/net/wireless/ath/ath10k/htt_tx.c  | 126 ++-
 drivers/net/wireless/ath/ath10k/hw.h  |  30 +++
 drivers/net/wireless/ath/ath10k/mac.c |   5 +-
 drivers/net/wireless/ath/ath10k/rx_desc.h |  15 
 drivers/net/wireless/ath/ath10k/txrx.c|   5 +-
 drivers/net/wireless/ath/ath10k/wmi-tlv.c |   4 +-
 drivers/net/wireless/ath/ath10k/wmi.c |   3 +
 13 files changed, 464 insertions(+), 54 deletions(-)

-- 
2.7.4



Re: [PATCH 1/1] mac80211: ieee80211_rx_napi: remove warning

2017-06-08 Thread Erik Stromdahl



On 2017-06-07 23:57, Johannes Berg wrote:

On Sun, 2017-06-04 at 15:11 +0200, Erik Stromdahl wrote:

The softirq count is not always incremented during driver
operation. This is the case for usb and sdio network
drivers.


I'm pretty sure the warning is correct, and we do rely on having
local_bh_disable(), otherwise we may end up taking a soft-IRQ and I
believe there are some things that could get messed up in that case.


Ok, I will make sure to increment the softirq counter before calling
ieee80211_rx then.


So - I think the warning is there for a reason, and drivers should just
local_bh_disable() before calling into that. What's wrong with that?

I guess there is nothing wrong with that, it's just that ath10k does not
call local_bh_disable anywhere in the code.
I guess it is relying on lower layers (pcie?) to do that.
When introducing sdio and usb support these calls will have to be added
explicitly in ath10k.



johannes



[PATCH 0/1] mac80211: removal of warning in RX path

2017-06-04 Thread Erik Stromdahl
fa002c583 <+1475>:  jmpq   0xa002c33d 

-> 0xa002c588 <+1480>:  cmpb   $0x0,0x66740(%rip)# 
0xa0092ccf
   0xa002c58f <+1487>:  jne0xa002c00c 
   0xa002c595 <+1493>:  mov$0x109d,%esi
   0xa002c59a <+1498>:  mov$0xa0081a66,%rdi
   0xa002c5a1 <+1505>:  movb   $0x1,0x66727(%rip)# 
0xa0092ccf
-> 0xa002c5a8 <+1512>:  callq  0x810a0220 
   0xa002c5ad <+1517>:  jmpq   0xa002c00c 

In this case there is just a jump to a function call (warn_slowpath_null)
that handles the warning (just as I would suspect).

No comes the real problem:
When building mac80211 as a module, the system does not seem to handle
the trap properly and I get the below error message (instead of the
expected warning that this patch addresses):

[   58.423370] BUG: unable to handle kernel paging request at a00818ee  
 
[   58.426085] IP: report_bug+0x94/0x120
 
[   58.427343] PGD 1c0c067  
 
[   58.427345] P4D 1c0c067  
 
[   58.428256] PUD 1c0d063  
 
[   58.428727] PMD 3dd3f067 
 
[   58.429019] PTE 80003dd18161 
 
[   58.429288]  
 
[   58.429765] Oops: 0003 [#1] PREEMPT SMP  
 
[   58.430158] Modules linked in: ehci_pci ehci_hcd i8042 serio ath10k_usb 
ath10k_core ath mac80211
   
[   58.431093] CPU: 0 PID: 16 Comm: kworker/0:1 Not tainted 
4.12.0-rc2-wt-ath-ARCH-QEMU+ #4 
  
[   58.431921] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 
1.10.2-20170228_101828-anatol 04/01/2014
   
[   58.432957] Workqueue: events ath10k_usb_io_comp_work [ath10k_usb]   
 
[   58.433582] task: 880039b2ce00 task.stack: c921  
 
[   58.434135] RIP: 0010:report_bug+0x94/0x120  
 
[   58.434510] RSP: 0018:c9213a68 EFLAGS: 00010202  
 
[   58.434979] RAX: 0907 RBX: c9213bb8 RCX: 
a00818e4 
[   58.435614] RDX: 0001 RSI: 109e RDI: 
0001 
[   58.436255] RBP: c9213a88 R08: c9214000 R09: 0030
[   58.436913] R10: 81c06a80 R11: 0080 R12: a002b498
[   58.437544] R13: a007eab6 R14: 0006 R15: 0004
[   58.438176] FS:  () GS:88003b40() 
knlGS:000
[   58.438910] CS:  0010 DS:  ES:  CR0: 80050033
[   58.439431] CR2: a00818ee CR3: 3e272000 CR4: 06f0
[   58.440239] Call Trace:
[   58.440524]  do_trap+0x16c/0x190
[   58.440884]  do_error_trap+0x89/0x110
[   58.441301]  ? ieee80211_rx_napi+0x598/0xa30 [mac80211]
[   58.441872]  ? __update_load_avg_se.isra.5+0x15b/0x180
[   58.442448]  ? __enqueue_entity+0x6c/0x70
[   58.442902]  ? enqueue_entity+0x401/0xb40
[   58.443347]  do_invalid_op+0x20/0x30
[   58.443755]  invalid_op+0x1e/0x30
[   58.444139] RIP: 0010:ieee80211_rx_napi+0x598/0xa30 [mac80211]
[   58.444794] RSP: 0018:c9213c68 EFLAGS: 00010346
[   58.445383] RAX: 8000 RBX: 88003ddd3300 RCX: 
[   58.446172] RDX: 88003ddd3300 RSI:  RDI: 8800393c0780
[   58.446993] RBP: c9213d38 R08:  R09: fff0
[   58.44] R10: eaf76e00 R11: 0080 R12: 
[   58.448566] R13: 8800393c1560 R14: 0080 R15: 8800393c0780
[   58.449361]  ? __slab_free+0x2a5/0x410
[   58.449782]  ? ieee80211_rx_napi+0xf/0xa30 [mac80211]
[   58.450345]  ath10k_wmi_event_mgmt_rx+0x233/0x430 [ath10k_core]
[   58.450994]  ath10k_wmi_tlv_op_rx+0x2fb/0x7b0 [ath10k_core]
[   58.451608]  ath10k_wmi_process_rx+0x1a/0x40 [ath10k_core]
[   58.452208]  ath10k_usb_io_comp_work+0x13e/0x1a0 [ath10k_usb]
[   58.452839]  ? __schedule+0x2e3/0x840
[   58.453241]  process_one_work+0x1e0/0x420
[   58.453708]  worker_thread+0x48/0x3f0
[   58.454142]  kthread+0x109/0x140
[   58.454393]  ? process_one_work+0x420/0x420
[   58.454882]  ? kthread_create_on_node+0x70/0x70
[   58.455388]  ret_from_fork+0x2c/0x40
[   58.455792] Code: 74 59 0f b7 41 0a 4c 63 69 04 0f b7 71 08 89 c7 49 01 cd 83
e7 01 a8 02 74 15 66 85 ff 74 10 a8 04 ba 01 00 00 00 75 26 83 c8 04 <66> 89 41 0
a 66 85 ff 74 49 0f b6 49 0b 4c 89 e2 45 31 c9 49 89
[   58.457842] RIP: report_bug+0x94/0x120 RSP: c9213a68
[   58.458458]

[PATCH 1/1] mac80211: ieee80211_rx_napi: remove warning

2017-06-04 Thread Erik Stromdahl
The softirq count is not always incremented during driver
operation. This is the case for usb and sdio network
drivers.

The below warning occurs on the first RX frame pushed to
mac80211 (for usb and sdio):

[   27.414995] [ cut here ]
[   27.416444] WARNING: CPU: 0 PID: 16 at net/mac80211/rx.c:4254 
ieee80211_rx_napi+0x598/0xa30
[   27.419161] Modules linked in: i8042 serio ehci_pci ehci_hcd ath10k_usb 
ath10k_core ath
[   27.421660] CPU: 0 PID: 16 Comm: kworker/0:1 Not tainted 
4.12.0-rc2-wt-ath-ARCH-QEMU+ #5
[   27.424323] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 
1.10.2-20170228_101828-anatol 04/01/2014
[   27.425205] Workqueue: events ath10k_usb_io_comp_work [ath10k_usb]
[   27.425760] task: 88003a730d00 task.stack: c921
[   27.426275] RIP: 0010:ieee80211_rx_napi+0x598/0xa30
[   27.426700] RSP: 0018:c9213c68 EFLAGS: 00010346
[   27.427155] RAX: 8000 RBX: 880039d08500 RCX: 
[   27.427764] RDX: 880039d08500 RSI:  RDI: 880039ff0780
[   27.428371] RBP: c9213d38 R08:  R09: fff0
[   27.429015] R10: eae7e200 R11: 0080 R12: 
[   27.429633] R13: 880039ff1560 R14: 0080 R15: 880039ff0780
[   27.430240] FS:  () GS:88003be0() 
knlGS:
[   27.430914] CS:  0010 DS:  ES:  CR0: 80050033
[   27.431392] CR2: 007fe518 CR3: 3f8c CR4: 06f0
[   27.431982] Call Trace:
[   27.432195]  ? ieee80211_rx_napi+0x18/0xa30
[   27.432553]  ath10k_wmi_event_mgmt_rx+0x233/0x430 [ath10k_core]
[   27.433046]  ath10k_wmi_tlv_op_rx+0x2fb/0x7b0 [ath10k_core]
[   27.433567]  ath10k_wmi_process_rx+0x1a/0x40 [ath10k_core]
[   27.434039]  ath10k_usb_io_comp_work+0x13e/0x1a0 [ath10k_usb]
[   27.434527]  ? __schedule+0x2e3/0x840
[   27.434858]  process_one_work+0x1e0/0x420
[   27.435203]  worker_thread+0x48/0x3f0
[   27.435514]  kthread+0x109/0x140
[   27.435846]  ? process_one_work+0x420/0x420
[   27.436231]  ? kthread_create_on_node+0x70/0x70
[   27.436644]  ret_from_fork+0x2c/0x40
[   27.437046] Code: 70 4c 8b ab d8 00 00 00 44 8b 83 80 00 00 00 41 0f b7 55 
00 4d 89 ee 41 89 d4 41 83 e4 0c e9 88 fc ff ff 4d 89 ec e9 c1 fd ff ff <0f> ff 
0f b6 43 4b 3c 02 0f 86 b2 fa ff ff 0f ff e9 30 fb ff ff
[   27.439114] ---[ end trace 89f286e9814e824a ]---

Signed-off-by: Erik Stromdahl 
---
 net/mac80211/rx.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 1f75280ba26c..2ec54232817d 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4251,8 +4251,6 @@ void ieee80211_rx_napi(struct ieee80211_hw *hw, struct 
ieee80211_sta *pubsta,
struct ieee80211_supported_band *sband;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
-   WARN_ON_ONCE(softirq_count() == 0);
-
if (WARN_ON(status->band >= NUM_NL80211_BANDS))
goto drop;
 
-- 
2.13.0



[RFC 4/9] ath10k: add start_once support

2017-05-21 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 | 19 +++
 drivers/net/wireless/ath/ath10k/core.h |  2 ++
 drivers/net/wireless/ath/ath10k/hw.h   |  6 ++
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 0c46004..54bf396 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1956,6 +1956,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(&ar->conf_mutex);
 
clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
@@ -2175,6 +2178,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:
@@ -2227,6 +2231,7 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_htt_tx_stop(&ar->htt);
ath10k_htt_rx_free(&ar->htt);
ath10k_wmi_detach(ar);
+   ar->is_started = false;
 }
 EXPORT_SYMBOL(ath10k_core_stop);
 
@@ -2329,12 +2334,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(&ar->conf_mutex);
+   } else {
+   ath10k_debug_print_boot_info(ar);
+   ath10k_core_stop(ar);
 
-   mutex_unlock(&ar->conf_mutex);
+   mutex_unlock(&ar->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 cdac923..0e75441 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -784,6 +784,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 160377aa..f733e73 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -473,6 +473,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



[RFC 0/9] ath10k high latency

2017-05-21 Thread Erik Stromdahl
]
[  111.810405]  ath10k_usb_io_comp_work+0x13e/0x1a0 [ath10k_usb]
[  111.812527]  ? __schedule+0x2e3/0x840
[  111.814639]  process_one_work+0x1e0/0x420
[  111.816745]  worker_thread+0x48/0x3f0
[  111.818838]  kthread+0x109/0x140
[  111.820920]  ? process_one_work+0x420/0x420
[  111.822997]  ? kthread_create_on_node+0x70/0x70
[  111.825072]  ret_from_fork+0x2c/0x40
[  111.827141] Code: 74 59 0f b7 41 0a 4c 63 69 04 0f b7 71 08 89 c7 49 01 cd 
83 e7 01 a8 02 74 15 66 85 ff 74 10 a8 04 ba 01 00 00 00 75 26 83 c8 04 <66> 89 
41 0a 66 85 ff 74 49 0f b6 49 0b 4c 89 e2 45 31 c9 49 89 
[  111.831620] RIP: report_bug+0x94/0x120 RSP: c90001127a68
[  111.833863] CR2: a04ba83e
[  111.836095] ---[ end trace 887d2ccc4510936b ]---

Erik Stromdahl (9):
  ath10k: high_latency detection
  ath10k: htt: RX ring config HL support
  ath10k: per target configurablity of various items
  ath10k: add start_once support
  ath10k: htt: High latency TX support
  ath10k: htt: High latency RX support
  ath10k: dma fixes for high latency devices
  ath10k: add QCA9377 usb hw_param item
  ath10k: add QCA9377 sdio hw_param item

 drivers/net/wireless/ath/ath10k/core.c| 139 --
 drivers/net/wireless/ath/ath10k/core.h|  16 ++--
 drivers/net/wireless/ath/ath10k/htc.c |  13 +--
 drivers/net/wireless/ath/ath10k/htt.c |   5 +-
 drivers/net/wireless/ath/ath10k/htt.h |  57 +++-
 drivers/net/wireless/ath/ath10k/htt_rx.c  |  98 -
 drivers/net/wireless/ath/ath10k/htt_tx.c  | 126 ++-
 drivers/net/wireless/ath/ath10k/hw.h  |  30 +++
 drivers/net/wireless/ath/ath10k/mac.c |   5 +-
 drivers/net/wireless/ath/ath10k/rx_desc.h |  15 
 drivers/net/wireless/ath/ath10k/txrx.c|   5 +-
 drivers/net/wireless/ath/ath10k/wmi-tlv.c |   4 +-
 12 files changed, 459 insertions(+), 54 deletions(-)

-- 
2.7.4



[RFC 7/9] ath10k: dma fixes for high latency devices

2017-05-21 Thread Erik Stromdahl
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 
---
 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 e5c80f5..232740c 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -137,11 +137,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 31654bd..e1cb754 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2484,7 +2484,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 e3b820d..27bbc3e 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 d4986f6..fae143e 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -90,11 +90,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



[RFC 6/9] ath10k: htt: High latency RX support

2017-05-21 Thread Erik Stromdahl
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 
---
 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 54bf396..da5377f 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2034,10 +2034,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);
@@ -2146,16 +2148,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)
@@ -2184,7 +2190,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:
@@ -2229,7 +2236,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 bac453f..ac5603e 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -646,6 +646,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)
 {
@@ -658,6 +667,18 @@ static inline struct htt_rx_indication_mpdu_range *
return ptr;
 }
 
+static inline struct htt_rx_indicatio

[RFC 3/9] ath10k: per target configurablity of various items

2017-05-21 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.

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

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 627954e..0c46004 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1621,9 +1621,19 @@ static int ath10k_init_hw_params(struct ath10k *ar)
for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
hw_params = &ath10k_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)) {
@@ -1722,6 +1732,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 = &ar->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)) {
@@ -1801,7 +1812,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;
@@ -1813,10 +1824,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;
ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
} else {
-   ar->max_num_peers = TARGET_10X_NUM_PEERS;
+   max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
}
ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
@@ -1825,7 +1836,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
-   ar->max_num_peers = TARGET_TLV_NUM_PEERS;
+   max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
@@ -1836,7 +1847,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_10_4:
-   ar->max_num_peers = TARGET_10_4_NUM_PEERS;

[RFC 2/9] ath10k: htt: RX ring config HL support

2017-05-21 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 6305308..7ffa1d4 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1805,6 +1805,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 685faac..8d85f82 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -693,6 +693,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 = &cmd->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_le16(HTT_RX_RING_SIZE_MIN);
+   ring->rx_ring_bufsize = __cpu_to_le16(HTT_RX_BUF_SIZE);
+   ring->flags = __cpu_to_le16(flags);
+
+   ret = ath10k_htc_send(&htt->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



[RFC 5/9] ath10k: htt: High latency TX support

2017-05-21 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 7ffa1d4..bac453f 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1830,9 +1830,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 8d85f82..e3b820d 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -946,8 +946,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 4674ff3..596d7cf1 100644
--- a/drivers/n

[RFC 1/9] ath10k: high_latency detection

2017-05-21 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 46ce263..627954e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2445,6 +2445,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 1efe0a1..90069b8 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -789,6 +789,8 @@ struct ath10k {
 
bool p2p;
 
+   bool is_high_latency;
+
struct {
enum ath10k_bus bus;
const struct ath10k_hif_ops *ops;
@@ -1008,6 +1010,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



[RFC 8/9] ath10k: add QCA9377 usb hw_param item

2017-05-21 Thread Erik Stromdahl
Hardware parameters for QCA9377 usb devices.

Signed-off-by: Erik Stromdahl 
---
 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 da5377f..edf9943 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -299,6 +299,29 @@ static const struct ath10k_hw_params 
ath10k_hw_params_list[] = {
.spectral_bin_discard = 0,
},
{
+   .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 f733e73..cc3d0eb 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



[RFC 9/9] ath10k: add QCA9377 sdio hw_param item

2017-05-21 Thread Erik Stromdahl
Hardware parameters for QCA9377 sdio devices.

Signed-off-by: Erik Stromdahl 
---
 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 edf9943..2a9afde 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -322,6 +322,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 = 17600,
+   .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 cc3d0eb..676c855 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



[RFC v2 0/3] ath10k usb support

2017-05-20 Thread Erik Stromdahl
This is the 2nd version of the ath10k USB RFC. There are only minor updates
since last version.

The main difference when compared to the previous RFC is that the
high latency stuff that is common between USB and SDIO has been moved out
of this patchset and into another (separate) patchset.

I was actually thinking about squashing all the patches into one, but
decided not to do so since I wanted usb.h, usb.c and the update Kconfig +
Makefile in one separate patch.

Perhaps patch 1 and 2 should be squashed?

Erik Stromdahl (3):
  ath10k: various usb related definitions
  ath10k: different fw file names for usb
  ath10k: add initial USB support

 drivers/net/wireless/ath/ath10k/Kconfig  |7 +
 drivers/net/wireless/ath/ath10k/Makefile |3 +
 drivers/net/wireless/ath/ath10k/core.c   |1 +
 drivers/net/wireless/ath/ath10k/core.h   |3 +
 drivers/net/wireless/ath/ath10k/debug.h  |2 +
 drivers/net/wireless/ath/ath10k/usb.c| 1128 ++
 drivers/net/wireless/ath/ath10k/usb.h|  128 
 7 files changed, 1272 insertions(+)
 create mode 100644 drivers/net/wireless/ath/ath10k/usb.c
 create mode 100644 drivers/net/wireless/ath/ath10k/usb.h

-- 
2.7.4



[RFC v2 2/3] ath10k: different fw file names for usb

2017-05-20 Thread Erik Stromdahl
USB firmware will be named in the same way as SDIO files,
i.e, the bus type will be added to the firmware file name.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index eea111d..46ce263 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1412,6 +1412,7 @@ static void ath10k_core_get_fw_name(struct ath10k *ar, 
char *fw_name,
 {
switch (ar->hif.bus) {
case ATH10K_BUS_SDIO:
+   case ATH10K_BUS_USB:
scnprintf(fw_name, fw_name_len, "%s-%s-%d.bin",
  ATH10K_FW_FILE_BASE, ath10k_bus_str(ar->hif.bus),
  fw_api);
-- 
2.7.4



[RFC v2 3/3] ath10k: add initial USB support

2017-05-20 Thread Erik Stromdahl
Chipsets like QCA9377 have support for USB so add initial USB bus
support to ath10k. With this patch we have the low level HIF and
HTC protocol working and it's possible to boot the firmware,
but it's still not possible to connect or anything like.

More changes are needed for full functionality. For that reason
we print during initialisation:

WARNING: ath10k USB support is incomplete, don't expect anything to work!

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/Kconfig  |7 +
 drivers/net/wireless/ath/ath10k/Makefile |3 +
 drivers/net/wireless/ath/ath10k/usb.c| 1128 ++
 drivers/net/wireless/ath/ath10k/usb.h|  128 
 4 files changed, 1266 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 412eb13..87f56d0 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -29,6 +29,13 @@ config ATH10K_SDIO
  This module adds experimental support for SDIO/MMC bus. Currently
  work in progress and will not fully work.
 
+config ATH10K_USB
+   tristate "Atheros ath10k USB support (EXPERIMENTAL)"
+   depends on ATH10K && USB
+   ---help---
+ This module adds experimental support for USB bus. Currently
+ work in progress and will not fully work.
+
 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..698665c
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/usb.c
@@ -0,0 +1,1128 @@
+/*
+ * Copyright (c) 2007-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2016-2017 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(&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_

[RFC v2 1/3] ath10k: various usb related definitions

2017-05-20 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 8fc08a5..1efe0a1 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -92,6 +92,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)
@@ -103,6 +104,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



Re: [PATCH v7 00/10] ath10k: sdio support

2017-04-22 Thread Erik Stromdahl



On 2017-04-13 10:28, Kalle Valo wrote:

More changes to Erik's SDIO patches. The biggest change in this round
is refactoring of the ugly ath10k_sdio_io() function.

Only compile tested, I don't have any SDIO boards at the moment.


I have tested the patches and they are working as expected...

--
Erik


Re: [PATCH 0/7] ath10k: remove ath10k_sdio_io()

2017-04-09 Thread Erik Stromdahl

I have made some basic testing (AP scanning) with this patchset and as far as I 
can
see they haven't broken anything.

I have not exercised all code (like error interrupt handling etc.) so those 
patches
might contain bugs (I noticed a FIXME comment in one of them).

I will review those patches and get back with more comments (if I find 
anything).

Erik

On 2017-04-05 09:06, Kalle Valo wrote:

Using ath10k_sdio_io() and ath10k_sdio_read_write_sync() are just
confusing. Refactor the code by following the plan outlined
below.

I'm planning to fold all these seven patches into Erik's patch
adding sdio.c[1] so I didn't write any commit logs. I'm just
submitting these separately to make it easier to review the
changes.

Kalle

ath10k_sdio_read_write_sync():
X HIF_RD_SYNC_BLOCK_FIX -> ath10k_sdio_readsb()
X HIF_RD_SYNC_BYTE_INC  -> ath10k_sdio_read(), ath10k_sdio_read32()
X HIF_WR_SYNC_BYTE_FIX  -> ath10k_sdio_writesb32()
X HIF_WR_SYNC_BYTE_INC  -> ath10k_sdio_write()

ath10k_sdio_prep_async_req():
X HIF_WRITE -> HIF_WR_SYNC_BYTE_INC -> ath10k_sdio_write()

ath10k_sdio_read/write32():
sdio_readl()/sdio_writel() (those use endian macros)

ath10k_sdio_writesb32():
kmalloc()
sdio_writesb(len)
kfree()

ath10k_sdio_readsb():
len = round_down(len, ar_sdio->mbox_info.block_size);
sdio_readsb(len)

ath10k_sdio_read():
sdio_memcpy_fromio()

ath10k_sdio_write():
sdio_memcpy_toio()


[1] https://patchwork.kernel.org/patch/9626001/

---

Kalle Valo (7):
  ath10k: add ath10k_sdio_write32/read32()
  ath10k: add ath10k_sdio_writesb()
  ath10k: add ath10k_sdio_read()
  ath10k: add ath10k_sdio_write()
  ath10k: add ath10k_sdio_readsb()
  ath10k: convert __ath10k_sdio_write_async() to use ath10k_sdio_write()
  ath10k: remove unused sdio wrappers


 drivers/net/wireless/ath/ath10k/sdio.c |  419 +---
 drivers/net/wireless/ath/ath10k/sdio.h |   40 ---
 2 files changed, 219 insertions(+), 240 deletions(-)


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



Re: [PATCH 0/7] ath10k: remove ath10k_sdio_io()

2017-04-05 Thread Erik Stromdahl

On 2017-04-05 18:53, Kalle Valo wrote:

Erik Stromdahl  writes:


I can't find patch 1/7...


Odd, apparently it didn't get delivered to ath10k list but did get to
linux-wireless. You can find the patch from linux-wireless patchwork:

https://patchwork.kernel.org/patch/9663097/

Also copying it below.

Kalle



ok, thanks.

I will add the patches to my tree and try them out.

--
Erik


Re: [PATCH 0/7] ath10k: remove ath10k_sdio_io()

2017-04-05 Thread Erik Stromdahl

I can't find patch 1/7...

On 2017-04-05 09:06, Kalle Valo wrote:

Using ath10k_sdio_io() and ath10k_sdio_read_write_sync() are just
confusing. Refactor the code by following the plan outlined
below.

I'm planning to fold all these seven patches into Erik's patch
adding sdio.c[1] so I didn't write any commit logs. I'm just
submitting these separately to make it easier to review the
changes.

Kalle

ath10k_sdio_read_write_sync():
X HIF_RD_SYNC_BLOCK_FIX -> ath10k_sdio_readsb()
X HIF_RD_SYNC_BYTE_INC  -> ath10k_sdio_read(), ath10k_sdio_read32()
X HIF_WR_SYNC_BYTE_FIX  -> ath10k_sdio_writesb32()
X HIF_WR_SYNC_BYTE_INC  -> ath10k_sdio_write()

ath10k_sdio_prep_async_req():
X HIF_WRITE -> HIF_WR_SYNC_BYTE_INC -> ath10k_sdio_write()

ath10k_sdio_read/write32():
sdio_readl()/sdio_writel() (those use endian macros)

ath10k_sdio_writesb32():
kmalloc()
sdio_writesb(len)
kfree()

ath10k_sdio_readsb():
len = round_down(len, ar_sdio->mbox_info.block_size);
sdio_readsb(len)

ath10k_sdio_read():
sdio_memcpy_fromio()

ath10k_sdio_write():
sdio_memcpy_toio()


[1] https://patchwork.kernel.org/patch/9626001/

---

Kalle Valo (7):
  ath10k: add ath10k_sdio_write32/read32()
  ath10k: add ath10k_sdio_writesb()
  ath10k: add ath10k_sdio_read()
  ath10k: add ath10k_sdio_write()
  ath10k: add ath10k_sdio_readsb()
  ath10k: convert __ath10k_sdio_write_async() to use ath10k_sdio_write()
  ath10k: remove unused sdio wrappers


 drivers/net/wireless/ath/ath10k/sdio.c |  419 +---
 drivers/net/wireless/ath/ath10k/sdio.h |   40 ---
 2 files changed, 219 insertions(+), 240 deletions(-)


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



Re: [PATCH v6 00/10] ath10k: sdio support

2017-03-28 Thread Erik Stromdahl


Please let me know if there is anything I can help with...

I will test the patches as soon as v7 is submitted.

On 2017-03-28 13:53, Kalle Valo wrote:

Kalle Valo  writes:


I did some changes while reviewing Erik's SDIO patches. Only compile
tested, I don't have any SDIO boards at the moment.


[...]


still todo:

o fix remaining memory leaks (if any)

o endian support, eg ath10k_sdio_hif_set_mbox_sleep()

o are ath10k_sdio_io() and ath10k_sdio_read_write_sync() really
  necessary? looks like just an unnecessary abstraction layer


It took me longer than I planned, but here are my notes about what I'm
planning to do to remove unnecessary ath10k_sdio_io() abstraction:

ath10k_sdio_read_write_sync():
HIF_RD_SYNC_BLOCK_FIX   -> ath10k_sdio_readsb()
HIF_RD_SYNC_BYTE_INC-> ath10k_sdio_read(), ath10k_sdio_read32()
HIF_WR_SYNC_BYTE_FIX-> ath10k_sdio_writesb()
HIF_WR_SYNC_BYTE_INC-> ath10k_sdio_write()

ath10k_sdio_prep_async_req():
HIF_WRITE   -> HIF_WR_SYNC_BYTE_INC -> ath10k_sdio_write()

ath10k_sdio_read/write32():
sdio_readl()/sdio_writel() (those use endian macros)

ath10k_sdio_readsb():
len = round_down(len, ar_sdio->mbox_info.block_size);
sdio_memcpy_fromio(len)

With these changes I'm hoping to get rid of also the memory leaks and
have proper endian support.



Re: [RFC v4 06/21] ath10k: sdio support

2017-03-17 Thread Erik Stromdahl



On 2017-03-16 10:33, Kalle Valo wrote:

Erik Stromdahl  writes:


There seems to be same pattern for reading four bytes, what if we should
add a helper for that? Something like ath10k_sdio_read32()? It could
handle the kmalloc and switch endianess also.

But please don't make any chances to sdio.c for the moment, let me
submit v5 first.


I notice that you have submitted v5 (and v6) of the sdio patches. Great!

I assume you will add them to master-pending soon so I will try out
everything (usb too) as soon as they are on master-pending.


v6 is now in master-pending.



I have added my usb patches on top of sdio v6 and everything works as expected
(both usb and sdio).

Your changes does not seem to have broken anything.


Re: [PATCH v6 03/10] ath10k: htc: move htc ctrl ep connect to htc_init

2017-03-16 Thread Erik Stromdahl



On 2017-03-16 02:06, Ryan Hsu wrote:

On 03/15/2017 08:45 AM, Kalle Valo wrote:


From: 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 
Signed-off-by: Kalle Valo 
---
 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 fd5be4484984..92d5ac45327a 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -586,8 +586,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;
@@ -650,22 +648,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
return -ECOMM;
}

-   /* setup our pseudo HTC control endpoint connection */
-   memset(&conn_req, 0, sizeof(conn_req));
-   memset(&conn_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, &conn_req, &conn_resp);
-   if (status) {
-   ath10k_err(ar, "could not connect to htc service (%d)\n",
-  status);
-   return status;
-   }
-
return 0;
 }

@@ -875,8 +857,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 = &ar->htc;
+   struct ath10k_htc_svc_conn_req conn_req;
+   struct ath10k_htc_svc_conn_resp conn_resp;

spin_lock_init(&htc->tx_lock);

@@ -884,10 +868,21 @@ int ath10k_htc_init(struct ath10k *ar)

htc->ar = ar;

-   /* Get HIF default pipe for HTC message exchange */
-   ep = &htc->endpoint[ATH10K_HTC_EP_0];
+   /* setup our pseudo HTC control endpoint connection */
+   memset(&conn_req, 0, sizeof(conn_req));
+   memset(&conn_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, &ep->ul_pipe_id, &ep->dl_pipe_id);
+   /* connect fake service */
+   status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
+   if (status) {
+   ath10k_err(ar, "could not connect to htc service (%d)\n",
+  status);
+   return status;
+   }



I haven't tracked down why, but just curious.
ath10K-htc_connect_service() will use ath10k_htc_send() and ath10k_hif_tx 
interface to send data down.
I am not sure if this is proper to just move it before ath10k_hif_init() is 
called, will have to check further...


The service connect of service 1 (ATH10K_HTC_SVC_ID_RSVD_CTRL) will not result 
in any bus
traffic (no ath10k_htc_send will be invoked).

ath10k_htc_connect_service has a special case for this service that assigns it 
to endpoint 0
always.

I initially had a comment about this in the commit log, but it "got lost" 
during some rebase...


init_completion(&htc->ctl_resp);



ath10k_htc_connect_service() will expect to use htc->ctrl_resp to synchronize.
Though there is a reinit_completion() call inside that, but logically, you 
should still do the init_completion() before using it.


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



Re: [RFC v4 06/21] ath10k: sdio support

2017-03-15 Thread Erik Stromdahl



On 2017-03-15 13:09, Kalle Valo wrote:

Erik Stromdahl  writes:


On 2017-03-10 13:43, Valo, Kalle wrote:

"Valo, Kalle"  writes:


Erik Stromdahl  writes:


sdio/mailbox HIF implementation.

Signed-off-by: Erik Stromdahl 


I'm looking at this more carefully now and noticed this:


+static int ath10k_sdio_bmi_credits(struct ath10k *ar)
+{
+   int ret;
+   u32 addr, *cmd_credits;
+   unsigned long timeout;
+
+   cmd_credits = kzalloc(sizeof(*cmd_credits), GFP_KERNEL);
+   if (!cmd_credits) {
+   ret = -ENOMEM;
+   goto err;
+   }
+
+   /* Read the counter register to get the command credits */
+   addr = MBOX_COUNT_DEC_ADDRESS + ATH10K_HIF_MBOX_NUM_MAX * 4;
+
+   timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+   while (time_before(jiffies, timeout) && !*cmd_credits) {
+   /* Hit the credit counter with a 4-byte access, the first byte
+* read will hit the counter and cause a decrement, while the
+* remaining 3 bytes has no effect. The rationale behind this
+* is to make all HIF accesses 4-byte aligned.
+*/
+   ret = ath10k_sdio_read_write_sync(ar, addr,
+ (u8 *)cmd_credits,
+ sizeof(*cmd_credits),
+ HIF_RD_SYNC_BYTE_INC);
+   if (ret) {
+   ath10k_warn(ar,
+ "Unable to decrement the command credit count register: %d\n",
+   ret);
+   goto err_free;
+   }
+
+   /* The counter is only 8 bits.
+* Ignore anything in the upper 3 bytes
+*/
+   *cmd_credits &= 0xFF;
+   }
+
+   if (!*cmd_credits) {
+   ath10k_warn(ar, "bmi communication timeout\n");
+   ret = -ETIMEDOUT;
+   goto err_free;
+   }
+
+   return 0;
+err_free:
+   kfree(cmd_credits);
+err:
+   return ret;
+}


AFAICS we are leaking cmd_credits if there's no error. Or is the buffer
freed somewhere within the mmc stack or something? The reason why I ask
is that I saw the same pattern in multiple functions so I'm curious.


Also I'm worried about endianness. We are reading from the device
directly to an u32 variable and not converting the bytes. Is the MMC
subsystem doing the conversion, I guess not?


You are right, there is definitely a memory leak (and there are similar problems
in a couple of other functions as well as you have pointed out).

This was introduced in version 3 of the
RFC when I removed the bounce buffer from ath6kl. Instead I introduced a bunch 
of
local "bounce" buffers in order to make sure that the buffers passed to the sdio
subsystem is dma-able (malloc'ed buffer instead of stack allocated).

Regarding endianess: That particular code construct is an artifact from ath6kl.
I am not sure it makes any sense to use a u32 in that particular case.
A u8 array is most likely more convenient.


There seems to be same pattern for reading four bytes, what if we should
add a helper for that? Something like ath10k_sdio_read32()? It could
handle the kmalloc and switch endianess also.

But please don't make any chances to sdio.c for the moment, let me
submit v5 first.


I notice that you have submitted v5 (and v6) of the sdio patches. Great!

I assume you will add them to master-pending soon so I will try out
everything (usb too) as soon as they are on master-pending.


Re: [RFC v4 06/21] ath10k: sdio support

2017-03-11 Thread Erik Stromdahl



On 2017-03-11 16:04, Kalle Valo wrote:

Erik Stromdahl  writes:


You are right, there is definitely a memory leak (and there are similar problems
in a couple of other functions as well as you have pointed out).

This was introduced in version 3 of the
RFC when I removed the bounce buffer from ath6kl. Instead I introduced a bunch 
of
local "bounce" buffers in order to make sure that the buffers passed to the sdio
subsystem is dma-able (malloc'ed buffer instead of stack allocated).

Regarding endianess: That particular code construct is an artifact from ath6kl.
I am not sure it makes any sense to use a u32 in that particular case.
A u8 array is most likely more convenient.

It is really nice you have found some time to review the patches!


After doing some reviewing myself I have found some more endianess related 
issues.
I will fix those (and the memory leaks) and submit v5 some time next week.


Actually let me send v5 (for the sdio part, I'm ignoring usb for now). I
have made some small changes while looking at the patches.


Ok, I have made some fixes in the branch:

ath-201703090806-ath10k-sdio-usb

in my ath tree:
https://github.com/erstrom/linux-ath.git

Perhaps you can have a look at the updated sdio.c

--
Erik


Re: [RFC v4 06/21] ath10k: sdio support

2017-03-11 Thread Erik Stromdahl



On 2017-03-10 17:29, Erik Stromdahl wrote:



On 2017-03-10 13:43, Valo, Kalle wrote:

"Valo, Kalle"  writes:


Erik Stromdahl  writes:


sdio/mailbox HIF implementation.

Signed-off-by: Erik Stromdahl 


I'm looking at this more carefully now and noticed this:


+static int ath10k_sdio_bmi_credits(struct ath10k *ar)
+{
+int ret;
+u32 addr, *cmd_credits;
+unsigned long timeout;
+
+cmd_credits = kzalloc(sizeof(*cmd_credits), GFP_KERNEL);
+if (!cmd_credits) {
+ret = -ENOMEM;
+goto err;
+}
+
+/* Read the counter register to get the command credits */
+addr = MBOX_COUNT_DEC_ADDRESS + ATH10K_HIF_MBOX_NUM_MAX * 4;
+
+timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+while (time_before(jiffies, timeout) && !*cmd_credits) {
+/* Hit the credit counter with a 4-byte access, the first byte
+ * read will hit the counter and cause a decrement, while the
+ * remaining 3 bytes has no effect. The rationale behind this
+ * is to make all HIF accesses 4-byte aligned.
+ */
+ret = ath10k_sdio_read_write_sync(ar, addr,
+  (u8 *)cmd_credits,
+  sizeof(*cmd_credits),
+  HIF_RD_SYNC_BYTE_INC);
+if (ret) {
+ath10k_warn(ar,
+ "Unable to decrement the command credit count register: %d\n",
+ret);
+goto err_free;
+}
+
+/* The counter is only 8 bits.
+ * Ignore anything in the upper 3 bytes
+ */
+*cmd_credits &= 0xFF;
+}
+
+if (!*cmd_credits) {
+ath10k_warn(ar, "bmi communication timeout\n");
+ret = -ETIMEDOUT;
+goto err_free;
+}
+
+return 0;
+err_free:
+kfree(cmd_credits);
+err:
+return ret;
+}


AFAICS we are leaking cmd_credits if there's no error. Or is the buffer
freed somewhere within the mmc stack or something? The reason why I ask
is that I saw the same pattern in multiple functions so I'm curious.


Also I'm worried about endianness. We are reading from the device
directly to an u32 variable and not converting the bytes. Is the MMC
subsystem doing the conversion, I guess not?


You are right, there is definitely a memory leak (and there are similar problems
in a couple of other functions as well as you have pointed out).

This was introduced in version 3 of the
RFC when I removed the bounce buffer from ath6kl. Instead I introduced a bunch 
of
local "bounce" buffers in order to make sure that the buffers passed to the sdio
subsystem is dma-able (malloc'ed buffer instead of stack allocated).

Regarding endianess: That particular code construct is an artifact from ath6kl.
I am not sure it makes any sense to use a u32 in that particular case.
A u8 array is most likely more convenient.

It is really nice you have found some time to review the patches!

--
Erik


After doing some reviewing myself I have found some more endianess related 
issues.
I will fix those (and the memory leaks) and submit v5 some time next week.


Re: [RFC v4 06/21] ath10k: sdio support

2017-03-10 Thread Erik Stromdahl



On 2017-03-10 13:43, Valo, Kalle wrote:

"Valo, Kalle"  writes:


Erik Stromdahl  writes:


sdio/mailbox HIF implementation.

Signed-off-by: Erik Stromdahl 


I'm looking at this more carefully now and noticed this:


+static int ath10k_sdio_bmi_credits(struct ath10k *ar)
+{
+   int ret;
+   u32 addr, *cmd_credits;
+   unsigned long timeout;
+
+   cmd_credits = kzalloc(sizeof(*cmd_credits), GFP_KERNEL);
+   if (!cmd_credits) {
+   ret = -ENOMEM;
+   goto err;
+   }
+
+   /* Read the counter register to get the command credits */
+   addr = MBOX_COUNT_DEC_ADDRESS + ATH10K_HIF_MBOX_NUM_MAX * 4;
+
+   timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+   while (time_before(jiffies, timeout) && !*cmd_credits) {
+   /* Hit the credit counter with a 4-byte access, the first byte
+* read will hit the counter and cause a decrement, while the
+* remaining 3 bytes has no effect. The rationale behind this
+* is to make all HIF accesses 4-byte aligned.
+*/
+   ret = ath10k_sdio_read_write_sync(ar, addr,
+ (u8 *)cmd_credits,
+ sizeof(*cmd_credits),
+ HIF_RD_SYNC_BYTE_INC);
+   if (ret) {
+   ath10k_warn(ar,
+ "Unable to decrement the command credit count register: %d\n",
+   ret);
+   goto err_free;
+   }
+
+   /* The counter is only 8 bits.
+* Ignore anything in the upper 3 bytes
+*/
+   *cmd_credits &= 0xFF;
+   }
+
+   if (!*cmd_credits) {
+   ath10k_warn(ar, "bmi communication timeout\n");
+   ret = -ETIMEDOUT;
+   goto err_free;
+   }
+
+   return 0;
+err_free:
+   kfree(cmd_credits);
+err:
+   return ret;
+}


AFAICS we are leaking cmd_credits if there's no error. Or is the buffer
freed somewhere within the mmc stack or something? The reason why I ask
is that I saw the same pattern in multiple functions so I'm curious.


Also I'm worried about endianness. We are reading from the device
directly to an u32 variable and not converting the bytes. Is the MMC
subsystem doing the conversion, I guess not?


You are right, there is definitely a memory leak (and there are similar problems
in a couple of other functions as well as you have pointed out).

This was introduced in version 3 of the
RFC when I removed the bounce buffer from ath6kl. Instead I introduced a bunch 
of
local "bounce" buffers in order to make sure that the buffers passed to the sdio
subsystem is dma-able (malloc'ed buffer instead of stack allocated).

Regarding endianess: That particular code construct is an artifact from ath6kl.
I am not sure it makes any sense to use a u32 in that particular case.
A u8 array is most likely more convenient.

It is really nice you have found some time to review the patches!

--
Erik


[RFC v4 15/21] ath10k: per target configurablity of various items

2017-02-21 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.

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

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 9d60f4b..6b667c7 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1592,9 +1592,19 @@ static int ath10k_init_hw_params(struct ath10k *ar)
for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
hw_params = &ath10k_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)) {
@@ -1685,6 +1695,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 = &ar->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)) {
@@ -1764,7 +1775,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;
@@ -1776,10 +1787,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;
ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
} else {
-   ar->max_num_peers = TARGET_10X_NUM_PEERS;
+   max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
}
ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
@@ -1788,7 +1799,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
-   ar->max_num_peers = TARGET_TLV_NUM_PEERS;
+   max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
@@ -1799,7 +1810,7 @@ static int ath10k_core_init_firmware_features(struct 
ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_10_4:
-   ar->max_num_peers = TARGET_10_4_NUM_PEERS;

[RFC v4 11/21] ath10k: usb support

2017-02-21 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 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 000..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 
+ *
+ * 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(&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,
+  

[RFC v4 08/21] ath10k: sdio get target info

2017-02-21 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 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 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, &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



[RFC v4 17/21] ath10k: htt: High latency TX support

2017-02-21 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 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/n

[RFC v4 18/21] ath10k: htt: High latency RX support

2017-02-21 Thread Erik Stromdahl
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 
---
 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_indicatio

[RFC v4 20/21] ath10k: add QCA9377 sdio hw_param item

2017-02-21 Thread Erik Stromdahl
Hardware parameters for QCA9377 sdio devices.

Signed-off-by: Erik Stromdahl 
---
 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 = 17600,
+   .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



[RFC v4 07/21] ath10k: add sdio extra initializations

2017-02-21 Thread Erik Stromdahl
Extra initializations needed by all sdio boards.
Derived from qcacld.

Signed-off-by: Erik Stromdahl 
---
 drivers/net/wireless/ath/ath10k/core.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 83ab651..eae502e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -377,6 +377,27 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
complete(&ar->target_suspend);
 }
 
+static void ath10k_sdio_extra_initialization(struct ath10k *ar)
+{
+   u32 param = 0;
+
+   /* Turn on fwlog.
+*/
+   ath10k_bmi_read32(ar, hi_option_flag, ¶m);
+   param &= ~(HI_OPTION_DISABLE_DBGLOG);
+   ath10k_bmi_write32(ar, hi_option_flag, param);
+
+   ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
+   ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
+   ath10k_bmi_read32(ar, hi_acs_flags, ¶m);
+
+   param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET |
+ HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET |
+ HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE);
+
+   ath10k_bmi_write32(ar, hi_acs_flags, param);
+}
+
 static int ath10k_init_configure_target(struct ath10k *ar)
 {
u32 param_host;
@@ -1916,6 +1937,9 @@ int ath10k_core_start(struct ath10k *ar, enum 
ath10k_firmware_mode mode,
if (status)
goto err;
 
+   if (ar->hif.bus == ATH10K_BUS_SDIO)
+   ath10k_sdio_extra_initialization(ar);
+
ar->htc.htc_ops.target_send_suspend_complete =
ath10k_send_suspend_complete;
 
-- 
2.7.4



[RFC v4 10/21] ath10k: various usb related definitions

2017-02-21 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 5965d18..2768b07 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -92,6 +92,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)
@@ -103,6 +104,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



[RFC v4 21/21] ath10k: dma fixes for high latency devices

2017-02-21 Thread Erik Stromdahl
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 
---
 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



[RFC v4 12/21] ath10k: high_latency detection

2017-02-21 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 a0b331d..39c407e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2400,6 +2400,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 2768b07..0c970fe 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -785,6 +785,8 @@ struct ath10k {
 
bool p2p;
 
+   bool is_high_latency;
+
struct {
enum ath10k_bus bus;
const struct ath10k_hif_ops *ops;
@@ -1003,6 +1005,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



  1   2   >