ath10k: htt: High latency TX support
Add HTT TX function for HL interfaces. Intended for SDIO and USB. Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
4daacc950d
commit
a2097d6444
@ -495,6 +495,9 @@ int ath10k_htt_tx_start(struct ath10k_htt *htt)
|
||||
if (htt->tx_mem_allocated)
|
||||
return 0;
|
||||
|
||||
if (ar->dev_type == ATH10K_DEV_TYPE_HL)
|
||||
return 0;
|
||||
|
||||
ret = ath10k_htt_tx_alloc_buf(htt);
|
||||
if (ret)
|
||||
goto free_idr_pending_tx;
|
||||
@ -1186,6 +1189,94 @@ err:
|
||||
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)
|
||||
@ -1616,6 +1707,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)
|
||||
|
Loading…
Reference in New Issue
Block a user