ath10k: implement basic support for new tx path firmware
authorMichal Kazior <michal.kazior@tieto.com>
Thu, 21 Jan 2016 13:13:27 +0000 (14:13 +0100)
committerKalle Valo <kvalo@qca.qualcomm.com>
Thu, 28 Jan 2016 08:45:29 +0000 (10:45 +0200)
This allows to use the new firmware which
implements the new tx data path. Without this
patch firmware supporting new tx path stops
responding shortly after booting.

This patch doesn't implement the entire pull-push
logic available in the new firmware. This will be
done in subsequent patches.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/htt.h
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/htt_tx.c

index 0c5628dafabf70d15df0b97347c1bb03d8fff365..13391ea4422d3f5acf0adf3d0e10ed35a3b535b1 100644 (file)
@@ -1665,6 +1665,14 @@ struct ath10k_htt {
                dma_addr_t paddr;
                struct ath10k_htt_txbuf *vaddr;
        } txbuf;
+
+       struct {
+               struct htt_q_state *vaddr;
+               dma_addr_t paddr;
+               u16 num_peers;
+               u16 num_tids;
+               enum htt_q_depth_type type;
+       } tx_q_state;
 };
 
 #define RX_HTT_HDR_STATUS_LEN 64
index 84abe4f25c73ab5b48f9fda45d930b3a643af81c..cc957a6256053593c083d91522dca4487c8778fe 100644 (file)
@@ -2123,10 +2123,12 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                break;
        case HTT_T2H_MSG_TYPE_AGGR_CONF:
                break;
-       case HTT_T2H_MSG_TYPE_EN_STATS:
        case HTT_T2H_MSG_TYPE_TX_FETCH_IND:
        case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM:
        case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND:
+               /* TODO: Implement pull-push logic */
+               break;
+       case HTT_T2H_MSG_TYPE_EN_STATS:
        default:
                ath10k_warn(ar, "htt event (%d) not handled\n",
                            resp->hdr.msg_type);
index 28b8d7af8506b35d445244dac3926a274afc5b17..95acb727c068f242f1324a39f04c540291071126 100644 (file)
@@ -132,6 +132,50 @@ static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt)
        return 0;
 }
 
+static void ath10k_htt_tx_free_txq(struct ath10k_htt *htt)
+{
+       struct ath10k *ar = htt->ar;
+       size_t size;
+
+       if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features))
+               return;
+
+       size = sizeof(*htt->tx_q_state.vaddr);
+
+       dma_unmap_single(ar->dev, htt->tx_q_state.paddr, size, DMA_TO_DEVICE);
+       kfree(htt->tx_q_state.vaddr);
+}
+
+static int ath10k_htt_tx_alloc_txq(struct ath10k_htt *htt)
+{
+       struct ath10k *ar = htt->ar;
+       size_t size;
+       int ret;
+
+       if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features))
+               return 0;
+
+       htt->tx_q_state.num_peers = HTT_TX_Q_STATE_NUM_PEERS;
+       htt->tx_q_state.num_tids = HTT_TX_Q_STATE_NUM_TIDS;
+       htt->tx_q_state.type = HTT_Q_DEPTH_TYPE_BYTES;
+
+       size = sizeof(*htt->tx_q_state.vaddr);
+       htt->tx_q_state.vaddr = kzalloc(size, GFP_KERNEL);
+       if (!htt->tx_q_state.vaddr)
+               return -ENOMEM;
+
+       htt->tx_q_state.paddr = dma_map_single(ar->dev, htt->tx_q_state.vaddr,
+                                              size, DMA_TO_DEVICE);
+       ret = dma_mapping_error(ar->dev, htt->tx_q_state.paddr);
+       if (ret) {
+               ath10k_warn(ar, "failed to dma map tx_q_state: %d\n", ret);
+               kfree(htt->tx_q_state.vaddr);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
 {
        struct ath10k *ar = htt->ar;
@@ -159,8 +203,17 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
                goto free_txbuf;
        }
 
+       ret = ath10k_htt_tx_alloc_txq(htt);
+       if (ret) {
+               ath10k_err(ar, "failed to alloc txq: %d\n", ret);
+               goto free_frag_desc;
+       }
+
        return 0;
 
+free_frag_desc:
+       ath10k_htt_tx_free_cont_frag_desc(htt);
+
 free_txbuf:
        size = htt->max_num_pending_tx *
                          sizeof(struct ath10k_htt_txbuf);
@@ -203,6 +256,7 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
                                  htt->txbuf.paddr);
        }
 
+       ath10k_htt_tx_free_txq(htt);
        ath10k_htt_tx_free_cont_frag_desc(htt);
 }
 
@@ -292,7 +346,9 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt)
        struct ath10k *ar = htt->ar;
        struct sk_buff *skb;
        struct htt_cmd *cmd;
+       struct htt_frag_desc_bank_cfg *cfg;
        int ret, size;
+       u8 info;
 
        if (!ar->hw_params.continuous_frag_desc)
                return 0;
@@ -310,14 +366,30 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt)
        skb_put(skb, size);
        cmd = (struct htt_cmd *)skb->data;
        cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG;
-       cmd->frag_desc_bank_cfg.info = 0;
-       cmd->frag_desc_bank_cfg.num_banks = 1;
-       cmd->frag_desc_bank_cfg.desc_size = sizeof(struct htt_msdu_ext_desc);
-       cmd->frag_desc_bank_cfg.bank_base_addrs[0] =
-                               __cpu_to_le32(htt->frag_desc.paddr);
-       cmd->frag_desc_bank_cfg.bank_id[0].bank_min_id = 0;
-       cmd->frag_desc_bank_cfg.bank_id[0].bank_max_id =
-                               __cpu_to_le16(htt->max_num_pending_tx - 1);
+
+       info = 0;
+       info |= SM(htt->tx_q_state.type,
+                  HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE);
+
+       if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features))
+               info |= HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID;
+
+       cfg = &cmd->frag_desc_bank_cfg;
+       cfg->info = info;
+       cfg->num_banks = 1;
+       cfg->desc_size = sizeof(struct htt_msdu_ext_desc);
+       cfg->bank_base_addrs[0] = __cpu_to_le32(htt->frag_desc.paddr);
+       cfg->bank_id[0].bank_min_id = 0;
+       cfg->bank_id[0].bank_max_id = __cpu_to_le16(htt->max_num_pending_tx -
+                                                   1);
+
+       cfg->q_state.paddr = cpu_to_le32(htt->tx_q_state.paddr);
+       cfg->q_state.num_peers = cpu_to_le16(htt->tx_q_state.num_peers);
+       cfg->q_state.num_tids = cpu_to_le16(htt->tx_q_state.num_tids);
+       cfg->q_state.record_size = HTT_TX_Q_STATE_ENTRY_SIZE;
+       cfg->q_state.record_multiplier = HTT_TX_Q_STATE_ENTRY_MULTIPLIER;
+
+       ath10k_dbg(ar, ATH10K_DBG_HTT, "htt frag desc bank cmd\n");
 
        ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
        if (ret) {