diff options
| author | Nirav Shah <nnshah@codeaurora.org> | 2016-04-30 14:06:12 +0530 |
|---|---|---|
| committer | Vishwajith Upendra <vishwaji@codeaurora.org> | 2016-06-14 14:28:44 -0700 |
| commit | 2e583a034454a19764c99554e3771fb39269d6cd (patch) | |
| tree | bf589200646828e91380f17afd7b7f00c2cd7003 | |
| parent | 1da77683858edb15bbfc7393612a14a75b9af1b9 (diff) | |
qcacld-3.0: Datapath changes for WiSA specification
Datapath changes for WiSA specification.
- Multicast packets with 50000 as destination
port should go at 6Mbps.
- Multicast packets with 50001 as destination
port should go at 24Mbps.
Change-Id: Ic219f58f3e8b2f6863a275928429153defe63b5a
CRs-Fixed: 1010412
| -rw-r--r-- | core/dp/htt/htt.c | 22 | ||||
| -rw-r--r-- | core/dp/htt/htt_tx.c | 356 | ||||
| -rw-r--r-- | core/dp/ol/inc/ol_htt_tx_api.h | 207 | ||||
| -rw-r--r-- | core/dp/txrx/ol_rx_fwd.c | 2 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx.c | 60 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx_desc.c | 59 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx_desc.h | 8 | ||||
| -rw-r--r-- | core/dp/txrx/ol_txrx.c | 19 | ||||
| -rw-r--r-- | core/dp/txrx/ol_txrx.h | 3 | ||||
| -rw-r--r-- | core/dp/txrx/ol_txrx_types.h | 2 | ||||
| -rw-r--r-- | core/wma/src/wma_data.c | 5 |
11 files changed, 491 insertions, 252 deletions
diff --git a/core/dp/htt/htt.c b/core/dp/htt/htt.c index fe30c3405d3a..68ca137aa1ea 100644 --- a/core/dp/htt/htt.c +++ b/core/dp/htt/htt.c @@ -392,28 +392,6 @@ void htt_detach_target(htt_pdev_handle pdev) { } -#ifdef WLAN_FEATURE_FASTPATH -/** - * htt_pkt_dl_len_get() HTT packet download length for fastpath case - * - * @htt_dev: pointer to htt device. - * - * As fragment one already downloaded HTT/HTC header, download length is - * remaining bytes. - * - * Return: download length - */ -int htt_pkt_dl_len_get(struct htt_pdev_t *htt_dev) -{ - return htt_dev->download_len - sizeof(struct htt_host_tx_desc_t); -} -#else -int htt_pkt_dl_len_get(struct htt_pdev_t *htt_dev) -{ - return 0; -} -#endif - static inline int htt_update_endpoint(struct htt_pdev_t *pdev, uint16_t service_id, HTC_ENDPOINT_ID ep) diff --git a/core/dp/htt/htt_tx.c b/core/dp/htt/htt_tx.c index eb011a7ecbde..dd75737991b3 100644 --- a/core/dp/htt/htt_tx.c +++ b/core/dp/htt/htt_tx.c @@ -605,6 +605,10 @@ int htt_tx_send_std(htt_pdev_handle pdev, qdf_nbuf_t msdu, uint16_t msdu_id) download_len = packet_len; } + if (QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_EXT_HEADER(msdu)) + download_len += sizeof(struct htt_tx_msdu_desc_ext_t); + + QDF_NBUF_UPDATE_TX_PKT_COUNT(msdu, QDF_NBUF_TX_PKT_HTT); DPTRACE(qdf_dp_trace(msdu, QDF_DP_TRACE_HTT_PACKET_PTR_RECORD, qdf_nbuf_data_addr(msdu), @@ -1154,3 +1158,355 @@ htt_tx_desc_fill_tso_info(htt_pdev_handle pdev, void *desc, } } #endif /* FEATURE_TSO */ + +/** + * htt_get_ext_tid() - get ext_tid value + * @type: extension header type + * @ext_header_data: header data + * @msdu_info: msdu info + * + * Return: ext_tid value + */ +static inline +int htt_get_ext_tid(enum extension_header_type type, + void *ext_header_data, struct htt_msdu_info_t *msdu_info) +{ + if (type == OCB_MODE_EXT_HEADER && ext_header_data) + return ((struct ocb_tx_ctrl_hdr_t *)ext_header_data)->ext_tid; + else + return msdu_info->info.ext_tid; +} + +/** + * htt_get_channel_freq() - get channel frequency + * @type: extension header type + * @ext_header_data: header data + * + * Return: channel frequency number + */ +static inline +int htt_get_channel_freq(enum extension_header_type type, + void *ext_header_data) +{ + if (type == OCB_MODE_EXT_HEADER && ext_header_data) + return ((struct ocb_tx_ctrl_hdr_t *)ext_header_data) + ->channel_freq; + else + return HTT_INVALID_CHANNEL; +} + +/** + * htt_fill_ocb_ext_header() - fill OCB extension header + * @msdu: network buffer + * @local_desc_ext: extension descriptor + * @type: extension header type + * @ext_header_data: header data + * @is_dsrc: is dsrc is eenabled or not + * + * Return: none + */ +static +void htt_fill_ocb_ext_header(qdf_nbuf_t msdu, + struct htt_tx_msdu_desc_ext_t *local_desc_ext, + enum extension_header_type type, void *ext_header_data) +{ + struct ocb_tx_ctrl_hdr_t *tx_ctrl = + (struct ocb_tx_ctrl_hdr_t *)ext_header_data; + + if (tx_ctrl->all_flags == 0) + return; + /* + * Copy the info that was read from TX control header from the + * user application to the extended HTT header. + * First copy everything + * to a local temp structure, and then copy everything to the + * actual uncached structure in one go to save memory writes. + */ + local_desc_ext->valid_pwr = tx_ctrl->valid_pwr; + local_desc_ext->valid_mcs_mask = tx_ctrl->valid_datarate; + local_desc_ext->valid_retries = tx_ctrl->valid_retries; + local_desc_ext->valid_expire_tsf = tx_ctrl->valid_expire_tsf; + local_desc_ext->valid_chainmask = tx_ctrl->valid_chain_mask; + + local_desc_ext->pwr = tx_ctrl->pwr; + if (tx_ctrl->valid_datarate && + tx_ctrl->datarate <= htt_ofdm_datarate_max) + local_desc_ext->mcs_mask = + (1 << (tx_ctrl->datarate + 4)); + local_desc_ext->retry_limit = tx_ctrl->retry_limit; + local_desc_ext->expire_tsf_lo = tx_ctrl->expire_tsf_lo; + local_desc_ext->expire_tsf_hi = tx_ctrl->expire_tsf_hi; + local_desc_ext->chain_mask = tx_ctrl->chain_mask; + local_desc_ext->is_dsrc = 1; + qdf_nbuf_push_head(msdu, sizeof(struct htt_tx_msdu_desc_ext_t)); + qdf_mem_copy(qdf_nbuf_data(msdu), local_desc_ext, + sizeof(struct htt_tx_msdu_desc_ext_t)); + QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_EXT_HEADER(msdu) = 1; +} + +/** + * htt_fill_wisa_ext_header() - fill WiSA extension header + * @msdu: network buffer + * @local_desc_ext: extension descriptor + * @type: extension header type + * @ext_header_data: header data + * + * Return: none + */ +static +void htt_fill_wisa_ext_header(qdf_nbuf_t msdu, + struct htt_tx_msdu_desc_ext_t *local_desc_ext, + enum extension_header_type type, void *ext_header_data) +{ + void *qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); + QDF_STATUS status; + + local_desc_ext->valid_mcs_mask = 1; + if (WISA_MODE_EXT_HEADER_6MBPS == type) + local_desc_ext->mcs_mask = htt_ofdm_datarate_6_mbps; + else + local_desc_ext->mcs_mask = htt_ofdm_datarate_24_mbps; + local_desc_ext->valid_nss_mask = 1; + local_desc_ext->nss_mask = 1; + local_desc_ext->valid_bandwidth = 1; + local_desc_ext->bandwidth_mask = htt_tx_bandwidth_20MHz; + local_desc_ext->valid_guard_interval = 1; + local_desc_ext->guard_interval = htt_tx_guard_interval_regular; + + /* + * Do dma_unmap and dma_map again if already mapped + * as adding extra bytes in skb + */ + if (QDF_NBUF_CB_PADDR(msdu) != 0) + qdf_nbuf_unmap_single(qdf_ctx, msdu, QDF_DMA_TO_DEVICE); + + qdf_nbuf_push_head(msdu, sizeof(struct htt_tx_msdu_desc_ext_t)); + qdf_mem_copy(qdf_nbuf_data(msdu), local_desc_ext, + sizeof(struct htt_tx_msdu_desc_ext_t)); + + if (QDF_NBUF_CB_PADDR(msdu) != 0) { + status = qdf_nbuf_map_single(qdf_ctx, msdu, QDF_DMA_TO_DEVICE); + if (qdf_unlikely(status != QDF_STATUS_SUCCESS)) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, + "%s: nbuf map failed", __func__); + return; + } + } + QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_EXT_HEADER(msdu) = 1; +} + +/** + * htt_push_ext_header() - fill extension header + * @msdu: network buffer + * @local_desc_ext: extension descriptor + * @type: extension header type + * @ext_header_data: header data + * @is_dsrc: is dsrc is eenabled or not + * + * Return: none + */ +static +void htt_push_ext_header(qdf_nbuf_t msdu, + struct htt_tx_msdu_desc_ext_t *local_desc_ext, + enum extension_header_type type, void *ext_header_data) +{ + switch (type) { + case OCB_MODE_EXT_HEADER: + htt_fill_ocb_ext_header(msdu, local_desc_ext, + type, ext_header_data); + break; + case WISA_MODE_EXT_HEADER_6MBPS: + case WISA_MODE_EXT_HEADER_24MBPS: + htt_fill_wisa_ext_header(msdu, local_desc_ext, + type, ext_header_data); + break; + default: + QDF_TRACE(QDF_MODULE_ID_HTT, QDF_TRACE_LEVEL_INFO, + "Invalid EXT header type %d\n", type); + break; + } +} + +/** + * htt_tx_desc_init() - Initialize the per packet HTT Tx descriptor + * @pdev: The handle of the physical device sending the + * tx data + * @htt_tx_desc: Abstract handle to the tx descriptor + * @htt_tx_desc_paddr_lo: Physical address of the HTT tx descriptor + * @msdu_id: ID to tag the descriptor with. + * The FW sends this ID back to host as a cookie + * during Tx completion, which the host uses to + * identify the MSDU. + * This ID is an index into the OL Tx desc. array. + * @msdu: The MSDU that is being prepared for transmission + * @msdu_info: Tx MSDU meta-data + * @tso_info: Storage for TSO meta-data + * @ext_header_data: extension header data + * @type: extension header type + * + * This function initializes the HTT tx descriptor. + * HTT Tx descriptor is a host-f/w interface structure, and meta-data + * accompanying every packet downloaded to f/w via the HTT interface. + */ +void +htt_tx_desc_init(htt_pdev_handle pdev, + void *htt_tx_desc, + qdf_dma_addr_t htt_tx_desc_paddr, + uint16_t msdu_id, + qdf_nbuf_t msdu, struct htt_msdu_info_t *msdu_info, + struct qdf_tso_info_t *tso_info, + void *ext_header_data, + enum extension_header_type type) +{ + uint8_t pkt_type, pkt_subtype = 0, ce_pkt_type = 0; + uint32_t hw_classify = 0, data_attr = 0; + uint32_t *word0, *word1, local_word3; +#if HTT_PADDR64 + uint32_t *word4; +#else /* ! HTT_PADDR64 */ + uint32_t *word3; +#endif /* HTT_PADDR64 */ + uint32_t local_word0, local_word1; + struct htt_host_tx_desc_t *htt_host_tx_desc = + (struct htt_host_tx_desc_t *) + (((char *)htt_tx_desc) - HTT_TX_DESC_VADDR_OFFSET); + bool desc_ext_required = (type != EXT_HEADER_NOT_PRESENT); + uint16_t channel_freq; + void *qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); + QDF_STATUS status; + + word0 = (uint32_t *) htt_tx_desc; + word1 = word0 + 1; + /* + * word2 is frag desc pointer + * word3 or 4 is peer_id + */ +#if HTT_PADDR64 + word4 = word0 + 4; /* Dword 3 */ +#else /* ! HTT_PADDR64 */ + word3 = word0 + 3; /* Dword 3 */ +#endif /* HTT_PADDR64 */ + + pkt_type = msdu_info->info.l2_hdr_type; + + if (qdf_likely(pdev->cfg.ce_classify_enabled)) { + if (qdf_likely(pkt_type == htt_pkt_type_eth2 || + pkt_type == htt_pkt_type_ethernet)) + qdf_nbuf_tx_info_get(msdu, pkt_type, pkt_subtype, + hw_classify); + + ce_pkt_type = htt_to_ce_pkt_type[pkt_type]; + if (0xffffffff == ce_pkt_type) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "Invalid HTT pkt type %d\n", pkt_type); + return; + } + } + + /* + * HTT Tx Desc is in uncached memory. Used cached writes per word, to + * reduce unnecessary memory access. + */ + + local_word0 = 0; + if (msdu_info) { + HTT_H2T_MSG_TYPE_SET(local_word0, HTT_H2T_MSG_TYPE_TX_FRM); + HTT_TX_DESC_PKT_TYPE_SET(local_word0, pkt_type); + HTT_TX_DESC_PKT_SUBTYPE_SET(local_word0, pkt_subtype); + HTT_TX_DESC_VDEV_ID_SET(local_word0, msdu_info->info.vdev_id); + HTT_TX_DESC_EXT_TID_SET(local_word0, htt_get_ext_tid(type, + ext_header_data, msdu_info)); + HTT_TX_DESC_EXTENSION_SET(local_word0, desc_ext_required); + HTT_TX_DESC_EXT_TID_SET(local_word0, msdu_info->info.ext_tid); + HTT_TX_DESC_CKSUM_OFFLOAD_SET(local_word0, + msdu_info->action.cksum_offload); + HTT_TX_DESC_NO_ENCRYPT_SET(local_word0, + msdu_info->action.do_encrypt ? + 0 : 1); + } + + *word0 = local_word0; + + local_word1 = 0; + + if (tso_info->is_tso) + HTT_TX_DESC_FRM_LEN_SET(local_word1, tso_info->total_len); + else + HTT_TX_DESC_FRM_LEN_SET(local_word1, qdf_nbuf_len(msdu)); + + HTT_TX_DESC_FRM_ID_SET(local_word1, msdu_id); + *word1 = local_word1; + + /* Initialize peer_id to INVALID_PEER because + this is NOT Reinjection path */ + local_word3 = HTT_INVALID_PEER; + channel_freq = htt_get_channel_freq(type, ext_header_data); + if (channel_freq != HTT_INVALID_CHANNEL) + HTT_TX_DESC_CHAN_FREQ_SET(local_word3, channel_freq); +#if HTT_PADDR64 + *word4 = local_word3; +#else /* ! HTT_PADDR64 */ + *word3 = local_word3; +#endif /* HTT_PADDR64 */ + + /* + * If any of the tx control flags are set, then we need the extended + * HTT header. + */ + if (desc_ext_required) { + struct htt_tx_msdu_desc_ext_t local_desc_ext = {0}; + + htt_push_ext_header(msdu, &local_desc_ext, + type, ext_header_data); + } + + /* + * Specify that the data provided by the OS is a bytestream, + * and thus should not be byte-swapped during the HIF download + * even if the host is big-endian. + * There could be extra fragments added before the OS's fragments, + * e.g. for TSO, so it's incorrect to clear the frag 0 wordstream flag. + * Instead, clear the wordstream flag for the final fragment, which + * is certain to be (one of the) fragment(s) provided by the OS. + * Setting the flag for this final fragment suffices for specifying + * all fragments provided by the OS rather than added by the driver. + */ + qdf_nbuf_set_frag_is_wordstream(msdu, qdf_nbuf_get_num_frags(msdu) - 1, + 0); + + if (QDF_NBUF_CB_PADDR(msdu) == 0) { + status = qdf_nbuf_map_single(qdf_ctx, msdu, QDF_DMA_TO_DEVICE); + if (qdf_unlikely(status != QDF_STATUS_SUCCESS)) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: nbuf map failed", __func__); + return; + } + } + + /* store a link to the HTT tx descriptor within the netbuf */ + qdf_nbuf_frag_push_head(msdu, sizeof(struct htt_host_tx_desc_t), + (char *)htt_host_tx_desc, /* virtual addr */ + htt_tx_desc_paddr); + + /* + * Indicate that the HTT header (and HTC header) is a meta-data + * "wordstream", i.e. series of uint32_t, rather than a data + * bytestream. + * This allows the HIF download to byteswap the HTT + HTC headers if + * the host is big-endian, to convert to the target's little-endian + * format. + */ + qdf_nbuf_set_frag_is_wordstream(msdu, 0, 1); + + if (qdf_likely(pdev->cfg.ce_classify_enabled && + (msdu_info->info.l2_hdr_type != htt_pkt_type_mgmt))) { + uint32_t pkt_offset = qdf_nbuf_get_frag_len(msdu, 0); + + data_attr = hw_classify << QDF_CE_TX_CLASSIFY_BIT_S; + data_attr |= ce_pkt_type << QDF_CE_TX_PKT_TYPE_BIT_S; + data_attr |= pkt_offset << QDF_CE_TX_PKT_OFFSET_BIT_S; + } + + qdf_nbuf_data_attr_set(msdu, data_attr); +} + diff --git a/core/dp/ol/inc/ol_htt_tx_api.h b/core/dp/ol/inc/ol_htt_tx_api.h index a6b785c805f2..f5d0abc66fab 100644 --- a/core/dp/ol/inc/ol_htt_tx_api.h +++ b/core/dp/ol/inc/ol_htt_tx_api.h @@ -47,6 +47,9 @@ #include <ol_htt_api.h> /* htt_pdev_handle */ #include <htt_types.h> #include <qdf_trace.h> +#include <cds_api.h> + +#define HTT_INVALID_CHANNEL -1 /* Remove these macros when they get added to htt.h. */ #ifndef HTT_TX_DESC_EXTENSION_GET @@ -492,6 +495,19 @@ enum htt_ce_tx_pkt_type { tx_pkt_type_mgmt = 4 }; +/** + * enum extension_header_type - extension header type + * @EXT_HEADER_NOT_PRESENT: extension header not present + * @OCB_MODE_EXT_HEADER: Extension header for OCB mode + * @WISA_MODE_EXT_HEADER_6MBPS: WISA mode 6Mbps header + * @WISA_MODE_EXT_HEADER_24MBPS: WISA mode 24Mbps header + */ +enum extension_header_type { + EXT_HEADER_NOT_PRESENT, + OCB_MODE_EXT_HEADER, + WISA_MODE_EXT_HEADER_6MBPS, + WISA_MODE_EXT_HEADER_24MBPS, +}; extern const uint32_t htt_to_ce_pkt_type[]; @@ -507,26 +523,6 @@ extern const uint32_t htt_to_ce_pkt_type[]; */ #define HTT_TX_DESC_VADDR_OFFSET 8 -/** - * htt_tx_desc_init() - Initialize the per packet HTT Tx descriptor - * @pdev: The handle of the physical device sending the - * tx data - * @htt_tx_desc: Abstract handle to the tx descriptor - * @htt_tx_desc_paddr_lo: Physical address of the HTT tx descriptor - * @msdu_id: ID to tag the descriptor with. - * The FW sends this ID back to host as a cookie - * during Tx completion, which the host uses to - * identify the MSDU. - * This ID is an index into the OL Tx desc. array. - * @msdu: The MSDU that is being prepared for transmission - * @msdu_info: Tx MSDU meta-data - * @tso_info: Storage for TSO meta-data - * - * This function initializes the HTT tx descriptor. - * HTT Tx descriptor is a host-f/w interface structure, and meta-data - * accompanying every packet downloaded to f/w via the HTT interface. - */ -static inline void htt_tx_desc_init(htt_pdev_handle pdev, void *htt_tx_desc, @@ -534,175 +530,8 @@ htt_tx_desc_init(htt_pdev_handle pdev, uint16_t msdu_id, qdf_nbuf_t msdu, struct htt_msdu_info_t *msdu_info, struct qdf_tso_info_t *tso_info, - struct ocb_tx_ctrl_hdr_t *tx_ctrl, - uint8_t is_dsrc) -{ - uint8_t pkt_type, pkt_subtype = 0, ce_pkt_type = 0; - uint32_t hw_classify = 0, data_attr = 0; - uint32_t *word0, *word1, local_word3; -#if HTT_PADDR64 - uint32_t *word4; -#else /* ! HTT_PADDR64 */ - uint32_t *word3; -#endif /* HTT_PADDR64 */ - uint32_t local_word0, local_word1; - struct htt_host_tx_desc_t *htt_host_tx_desc = - (struct htt_host_tx_desc_t *) - (((char *)htt_tx_desc) - HTT_TX_DESC_VADDR_OFFSET); - bool desc_ext_required = (tx_ctrl && tx_ctrl->all_flags != 0); - - word0 = (uint32_t *) htt_tx_desc; - word1 = word0 + 1; - /* - * word2 is frag desc pointer - * word3 or 4 is peer_id - */ -#if HTT_PADDR64 - word4 = word0 + 4; /* Dword 3 */ -#else /* ! HTT_PADDR64 */ - word3 = word0 + 3; /* Dword 3 */ -#endif /* HTT_PADDR64 */ - - pkt_type = msdu_info->info.l2_hdr_type; - - if (qdf_likely(pdev->cfg.ce_classify_enabled)) { - if (qdf_likely(pkt_type == htt_pkt_type_eth2 || - pkt_type == htt_pkt_type_ethernet)) - qdf_nbuf_tx_info_get(msdu, pkt_type, pkt_subtype, - hw_classify); - - ce_pkt_type = htt_to_ce_pkt_type[pkt_type]; - if (0xffffffff == ce_pkt_type) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, - "Invalid HTT pkt type %d\n", pkt_type); - return; - } - } - - /* - * HTT Tx Desc is in uncached memory. Used cached writes per word, to - * reduce unnecessary memory access. - */ - - local_word0 = 0; - if (msdu_info) { - HTT_H2T_MSG_TYPE_SET(local_word0, HTT_H2T_MSG_TYPE_TX_FRM); - HTT_TX_DESC_PKT_TYPE_SET(local_word0, pkt_type); - HTT_TX_DESC_PKT_SUBTYPE_SET(local_word0, pkt_subtype); - HTT_TX_DESC_VDEV_ID_SET(local_word0, msdu_info->info.vdev_id); - if (tx_ctrl && tx_ctrl->valid_tid) - HTT_TX_DESC_EXT_TID_SET(local_word0, tx_ctrl->ext_tid); - else - HTT_TX_DESC_EXT_TID_SET(local_word0, - msdu_info->info.ext_tid); - HTT_TX_DESC_EXTENSION_SET(local_word0, desc_ext_required); - HTT_TX_DESC_EXT_TID_SET(local_word0, msdu_info->info.ext_tid); - HTT_TX_DESC_CKSUM_OFFLOAD_SET(local_word0, - msdu_info->action.cksum_offload); - HTT_TX_DESC_NO_ENCRYPT_SET(local_word0, - msdu_info->action.do_encrypt ? - 0 : 1); - } - - *word0 = local_word0; - - local_word1 = 0; - - if (tso_info->is_tso) - HTT_TX_DESC_FRM_LEN_SET(local_word1, tso_info->total_len); - else - HTT_TX_DESC_FRM_LEN_SET(local_word1, qdf_nbuf_len(msdu)); - - HTT_TX_DESC_FRM_ID_SET(local_word1, msdu_id); - *word1 = local_word1; - - /* Initialize peer_id to INVALID_PEER because - this is NOT Reinjection path */ - local_word3 = HTT_INVALID_PEER; - if (tx_ctrl && tx_ctrl->channel_freq) - HTT_TX_DESC_CHAN_FREQ_SET(local_word3, tx_ctrl->channel_freq); -#if HTT_PADDR64 - *word4 = local_word3; -#else /* ! HTT_PADDR64 */ - *word3 = local_word3; -#endif /* HTT_PADDR64 */ - - /* - * If any of the tx control flags are set, then we need the extended - * HTT header. - */ - if (desc_ext_required) { - struct htt_tx_msdu_desc_ext_t local_desc_ext = {0}; - - /* - * Copy the info that was read from TX control header from the - * user application to the extended HTT header. - * First copy everything - * to a local temp structure, and then copy everything to the - * actual uncached structure in one go to save memory writes. - */ - local_desc_ext.valid_pwr = tx_ctrl->valid_pwr; - local_desc_ext.valid_mcs_mask = tx_ctrl->valid_datarate; - local_desc_ext.valid_retries = tx_ctrl->valid_retries; - local_desc_ext.valid_expire_tsf = tx_ctrl->valid_expire_tsf; - local_desc_ext.valid_chainmask = tx_ctrl->valid_chain_mask; - - local_desc_ext.pwr = tx_ctrl->pwr; - if (tx_ctrl->valid_datarate && - tx_ctrl->datarate <= htt_ofdm_datarate_max) - local_desc_ext.mcs_mask = - (1 << (tx_ctrl->datarate + 4)); - local_desc_ext.retry_limit = tx_ctrl->retry_limit; - local_desc_ext.expire_tsf_lo = tx_ctrl->expire_tsf_lo; - local_desc_ext.expire_tsf_hi = tx_ctrl->expire_tsf_hi; - local_desc_ext.chain_mask = tx_ctrl->chain_mask; - - local_desc_ext.is_dsrc = (is_dsrc != 0); - - qdf_nbuf_push_head(msdu, sizeof(local_desc_ext)); - qdf_mem_copy(qdf_nbuf_data(msdu), &local_desc_ext, - sizeof(local_desc_ext)); - } - - /* - * Specify that the data provided by the OS is a bytestream, - * and thus should not be byte-swapped during the HIF download - * even if the host is big-endian. - * There could be extra fragments added before the OS's fragments, - * e.g. for TSO, so it's incorrect to clear the frag 0 wordstream flag. - * Instead, clear the wordstream flag for the final fragment, which - * is certain to be (one of the) fragment(s) provided by the OS. - * Setting the flag for this final fragment suffices for specifying - * all fragments provided by the OS rather than added by the driver. - */ - qdf_nbuf_set_frag_is_wordstream(msdu, qdf_nbuf_get_num_frags(msdu) - 1, - 0); - - /* store a link to the HTT tx descriptor within the netbuf */ - qdf_nbuf_frag_push_head(msdu, sizeof(struct htt_host_tx_desc_t), - (char *)htt_host_tx_desc, /* virtual addr */ - htt_tx_desc_paddr); - - /* - * Indicate that the HTT header (and HTC header) is a meta-data - * "wordstream", i.e. series of uint32_t, rather than a data - * bytestream. - * This allows the HIF download to byteswap the HTT + HTC headers if - * the host is big-endian, to convert to the target's little-endian - * format. - */ - qdf_nbuf_set_frag_is_wordstream(msdu, 0, 1); - - if (qdf_likely(pdev->cfg.ce_classify_enabled && - (msdu_info->info.l2_hdr_type != htt_pkt_type_mgmt))) { - uint32_t pkt_offset = qdf_nbuf_get_frag_len(msdu, 0); - data_attr = hw_classify << QDF_CE_TX_CLASSIFY_BIT_S; - data_attr |= ce_pkt_type << QDF_CE_TX_PKT_TYPE_BIT_S; - data_attr |= pkt_offset << QDF_CE_TX_PKT_OFFSET_BIT_S; - } - - qdf_nbuf_data_attr_set(msdu, data_attr); -} + void *ext_header_data, + enum extension_header_type type); /** * @brief Set a flag to indicate that the MSDU in question was postponed. diff --git a/core/dp/txrx/ol_rx_fwd.c b/core/dp/txrx/ol_rx_fwd.c index 317d12cdff38..7d33ae3cafce 100644 --- a/core/dp/txrx/ol_rx_fwd.c +++ b/core/dp/txrx/ol_rx_fwd.c @@ -119,7 +119,6 @@ static inline void ol_rx_fwd_to_tx(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu) * Map the netbuf, so it's accessible to the DMA that * sends it to the target. */ - qdf_nbuf_map_single(pdev->osdev, msdu, QDF_DMA_TO_DEVICE); qdf_nbuf_set_next(msdu, NULL); /* add NULL terminator */ msdu = OL_TX_LL(vdev, msdu); @@ -130,7 +129,6 @@ static inline void ol_rx_fwd_to_tx(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu) * We could store the frame and try again later, * but the simplest solution is to discard the frames. */ - qdf_nbuf_unmap_single(pdev->osdev, msdu, QDF_DMA_TO_DEVICE); qdf_nbuf_tx_free(msdu, QDF_NBUF_PKT_ERROR); } } diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index d1b59c80e401..789dae36d7bb 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -54,8 +54,8 @@ #include <htt_types.h> /* htc_endpoint */ #include <cdp_txrx_peer_ops.h> -int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t *msdus, - unsigned int num_msdus, unsigned int transfer_id); +int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t msdu, + unsigned int transfer_id, uint32_t download_len); #endif /* WLAN_FEATURE_FASTPATH */ /* @@ -141,10 +141,8 @@ static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev, */ qdf_nbuf_t ol_tx_data(ol_txrx_vdev_handle vdev, qdf_nbuf_t skb) { - void *qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); struct ol_txrx_pdev_t *pdev; qdf_nbuf_t ret; - QDF_STATUS status; if (qdf_unlikely(!vdev)) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, @@ -159,18 +157,6 @@ qdf_nbuf_t ol_tx_data(ol_txrx_vdev_handle vdev, qdf_nbuf_t skb) "%s:pdev is null", __func__); return skb; } - if (qdf_unlikely(!qdf_ctx)) { - TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, - "%s:qdf_ctx is null", __func__); - return skb; - } - - status = qdf_nbuf_map_single(qdf_ctx, skb, QDF_DMA_TO_DEVICE); - if (qdf_unlikely(status != QDF_STATUS_SUCCESS)) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, - "%s: nbuf map failed", __func__); - return skb; - } if ((ol_cfg_is_ip_tcp_udp_checksum_offload_enabled(pdev->ctrl_pdev)) && (qdf_nbuf_get_protocol(skb) == htons(ETH_P_IP)) @@ -183,7 +169,6 @@ qdf_nbuf_t ol_tx_data(ol_txrx_vdev_handle vdev, qdf_nbuf_t skb) if (ret) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, "%s: Failed to tx", __func__); - qdf_nbuf_unmap_single(qdf_ctx, ret, QDF_DMA_TO_DEVICE); return ret; } @@ -384,6 +369,7 @@ ol_tx_prepare_ll_fast(struct ol_txrx_pdev_t *pdev, uint32_t *htt_tx_desc; void *htc_hdr_vaddr; u_int32_t num_frags, i; + enum extension_header_type type; tx_desc = ol_tx_desc_alloc_wrapper(pdev, vdev, msdu_info); if (qdf_unlikely(!tx_desc)) @@ -410,13 +396,15 @@ ol_tx_prepare_ll_fast(struct ol_txrx_pdev_t *pdev, /* HTT Header */ /* TODO : Take care of multiple fragments */ + type = ol_tx_get_ext_header_type(vdev, msdu); + /* TODO: Precompute and store paddr in ol_tx_desc_t */ /* Virtual address of the HTT/HTC header, added by driver */ htc_hdr_vaddr = (char *)htt_tx_desc - HTC_HEADER_LEN; htt_tx_desc_init(pdev->htt_pdev, htt_tx_desc, tx_desc->htt_tx_desc_paddr, tx_desc->id, msdu, &msdu_info->htt, &msdu_info->tso_info, - NULL, vdev->opmode == wlan_op_mode_ocb); + NULL, type); num_frags = qdf_nbuf_get_num_frags(msdu); /* num_frags are expected to be 2 max */ @@ -447,6 +435,12 @@ ol_tx_prepare_ll_fast(struct ol_txrx_pdev_t *pdev, frag_len = qdf_nbuf_get_frag_len(msdu, i); frag_paddr = qdf_nbuf_get_frag_paddr(msdu, i); + if (type != EXT_HEADER_NOT_PRESENT) { + frag_paddr += + sizeof(struct htt_tx_msdu_desc_ext_t); + frag_len -= + sizeof(struct htt_tx_msdu_desc_ext_t); + } #if defined(HELIUMPLUS_PADDR64) htt_tx_desc_frag(pdev->htt_pdev, tx_desc->htt_frag_desc, i - 1, frag_paddr, frag_len); @@ -473,6 +467,11 @@ ol_tx_prepare_ll_fast(struct ol_txrx_pdev_t *pdev, /* * TODO : Can we remove this check and always download a fixed length ? * */ + + + if (QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_EXT_HEADER(msdu)) + pkt_download_len += sizeof(struct htt_tx_msdu_desc_ext_t); + if (qdf_unlikely(qdf_nbuf_len(msdu) < pkt_download_len)) pkt_download_len = qdf_nbuf_len(msdu); @@ -589,9 +588,14 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) * data being downloaded to the target via the * HTT tx descriptor. */ + if (QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_EXT_HEADER + (msdu)) + pkt_download_len += + sizeof(struct htt_tx_msdu_desc_ext_t); + htt_tx_desc_display(tx_desc->htt_tx_desc); - if ((0 == ce_send_fast(pdev->ce_tx_hdl, &msdu, - 1, ep_id))) { + if ((0 == ce_send_fast(pdev->ce_tx_hdl, msdu, + ep_id, pkt_download_len))) { /* * The packet could not be sent. * Free the descriptor, return the @@ -687,6 +691,10 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) * If debug display is enabled, show the meta-data being * downloaded to the target via the HTT tx descriptor. */ + if (QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_EXT_HEADER(msdu)) + pkt_download_len += + sizeof(struct htt_tx_msdu_desc_ext_t); + htt_tx_desc_display(tx_desc->htt_tx_desc); /* * The netbuf may get linked into a different list @@ -694,8 +702,8 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) * pointer before the ce_send call. */ next = qdf_nbuf_next(msdu); - if ((0 == ce_send_fast(pdev->ce_tx_hdl, &msdu, 1, - ep_id))) { + if ((0 == ce_send_fast(pdev->ce_tx_hdl, msdu, + ep_id, pkt_download_len))) { /* The packet could not be sent */ /* Free the descriptor, return the packet to the * caller */ @@ -1340,7 +1348,7 @@ ol_txrx_mgmt_send_ext(ol_txrx_vdev_handle vdev, tx_msdu_info.peer = NULL; - qdf_nbuf_map_single(pdev->osdev, tx_mgmt_frm, QDF_DMA_TO_DEVICE); + /* For LL tx_comp_req is not used so initialized to 0 */ tx_msdu_info.htt.action.tx_comp_req = 0; tx_desc = ol_tx_desc_ll(pdev, vdev, tx_mgmt_frm, &tx_msdu_info); @@ -1371,11 +1379,9 @@ ol_txrx_mgmt_send_ext(ol_txrx_vdev_handle vdev, tx_desc); #endif /* defined(HELIUMPLUS_PADDR64) */ } - if (!tx_desc) { - qdf_nbuf_unmap_single(pdev->osdev, tx_mgmt_frm, - QDF_DMA_TO_DEVICE); + if (!tx_desc) return -EINVAL; /* can't accept the tx mgmt frame */ - } + TXRX_STATS_MSDU_INCR(pdev, tx.mgmt, tx_mgmt_frm); TXRX_ASSERT1(type < OL_TXRX_MGMT_NUM_TYPES); tx_desc->pkt_type = type + OL_TXRX_MGMT_TYPE_BASE; diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index a1d71ba61b4c..5635abc61b8d 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -327,6 +327,59 @@ const uint32_t htt_to_ce_pkt_type[] = { [htt_pkt_num_types] = 0xffffffff }; +#define WISA_DEST_PORT_6MBPS 50000 +#define WISA_DEST_PORT_24MBPS 50001 + +/** + * ol_tx_get_wisa_ext_hdr_type() - get header type for WiSA mode + * @netbuf: network buffer + * + * Return: extension header type + */ +enum extension_header_type +ol_tx_get_wisa_ext_hdr_type(qdf_nbuf_t netbuf) +{ + uint8_t *buf = qdf_nbuf_data(netbuf); + uint16_t dport; + + if (qdf_is_macaddr_group( + (struct qdf_mac_addr *)(buf + QDF_NBUF_DEST_MAC_OFFSET))) { + + dport = (uint16_t)(*(uint16_t *)(buf + + QDF_NBUF_TRAC_IPV4_OFFSET + + QDF_NBUF_TRAC_IPV4_HEADER_SIZE + sizeof(uint16_t))); + + if (dport == QDF_SWAP_U16(WISA_DEST_PORT_6MBPS)) + return WISA_MODE_EXT_HEADER_6MBPS; + else if (dport == QDF_SWAP_U16(WISA_DEST_PORT_24MBPS)) + return WISA_MODE_EXT_HEADER_24MBPS; + else + return EXT_HEADER_NOT_PRESENT; + } else { + return EXT_HEADER_NOT_PRESENT; + } +} + +/** + * ol_tx_get_ext_header_type() - extension header is required or not + * @vdev: vdev pointer + * @netbuf: network buffer + * + * This function returns header type and if extension header is + * not required than returns EXT_HEADER_NOT_PRESENT. + * + * Return: extension header type + */ +enum extension_header_type +ol_tx_get_ext_header_type(struct ol_txrx_vdev_t *vdev, + qdf_nbuf_t netbuf) +{ + if (vdev->is_wisa_mode_enable == true) + return ol_tx_get_wisa_ext_hdr_type(netbuf); + else + return EXT_HEADER_NOT_PRESENT; +} + struct ol_tx_desc_t *ol_tx_desc_ll(struct ol_txrx_pdev_t *pdev, struct ol_txrx_vdev_t *vdev, qdf_nbuf_t netbuf, @@ -335,6 +388,7 @@ struct ol_tx_desc_t *ol_tx_desc_ll(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc; unsigned int i; uint32_t num_frags; + enum extension_header_type type; msdu_info->htt.info.vdev_id = vdev->vdev_id; msdu_info->htt.action.cksum_offload = qdf_nbuf_get_tx_cksum(netbuf); @@ -369,12 +423,13 @@ struct ol_tx_desc_t *ol_tx_desc_ll(struct ol_txrx_pdev_t *pdev, tx_desc->pkt_type = OL_TX_FRM_STD; } + type = ol_tx_get_ext_header_type(vdev, netbuf); + /* initialize the HW tx descriptor */ htt_tx_desc_init(pdev->htt_pdev, tx_desc->htt_tx_desc, tx_desc->htt_tx_desc_paddr, ol_tx_desc_id(pdev, tx_desc), netbuf, &msdu_info->htt, - &msdu_info->tso_info, - NULL, vdev->opmode == wlan_op_mode_ocb); + &msdu_info->tso_info, NULL, type); /* * Initialize the fragmentation descriptor. diff --git a/core/dp/txrx/ol_tx_desc.h b/core/dp/txrx/ol_tx_desc.h index ed726503ae6d..2509fecdb484 100644 --- a/core/dp/txrx/ol_tx_desc.h +++ b/core/dp/txrx/ol_tx_desc.h @@ -36,6 +36,7 @@ #include <qdf_nbuf.h> /* qdf_nbuf_t */ #include <cdp_txrx_cmn.h> /* ol_txrx_vdev_t, etc. */ #include <ol_txrx_internal.h> /*TXRX_ASSERT2 */ +#include <ol_htt_tx_api.h> #define DIV_BY_8 3 #define DIV_BY_32 5 @@ -374,4 +375,11 @@ void ol_tx_desc_dup_detect_reset(struct ol_txrx_pdev_t *pdev, } #endif +enum extension_header_type +ol_tx_get_ext_header_type(struct ol_txrx_vdev_t *vdev, + qdf_nbuf_t netbuf); +enum extension_header_type +ol_tx_get_wisa_ext_type(qdf_nbuf_t netbuf); + + #endif /* _OL_TX_DESC__H_ */ diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index d0133c9a62c6..0a4b6f7f75a0 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -559,9 +559,6 @@ ol_txrx_pdev_post_attach(ol_txrx_pdev_handle pdev) if (ret) goto ol_attach_fail; - /* Update bus pkt download length */ - hif_bus_pkt_dl_len_set((void *)osc, htt_pkt_dl_len_get(pdev->htt_pdev)); - /* Attach micro controller data path offload resource */ if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) if (htt_ipa_uc_attach(pdev->htt_pdev)) @@ -4020,3 +4017,19 @@ ol_txrx_vdev_handle ol_txrx_get_vdev_from_vdev_id(uint8_t vdev_id) return vdev; } + +/** + * ol_txrx_set_wisa_mode() - set wisa mode + * @vdev: vdev handle + * @enable: enable flag + * + * Return: QDF STATUS + */ +QDF_STATUS ol_txrx_set_wisa_mode(ol_txrx_vdev_handle vdev, bool enable) +{ + if (!vdev) + return QDF_STATUS_E_INVAL; + + vdev->is_wisa_mode_enable = enable; + return QDF_STATUS_SUCCESS; +} diff --git a/core/dp/txrx/ol_txrx.h b/core/dp/txrx/ol_txrx.h index 41f8aa5cd486..791a0ecb2395 100644 --- a/core/dp/txrx/ol_txrx.h +++ b/core/dp/txrx/ol_txrx.h @@ -40,6 +40,7 @@ void ol_txrx_peer_unref_delete(struct ol_txrx_peer_t *peer); ol_txrx_vdev_handle ol_txrx_get_vdev_from_vdev_id(uint8_t vdev_id); - void htt_pkt_log_init(struct ol_txrx_pdev_t *handle, void *scn); +QDF_STATUS ol_txrx_set_wisa_mode(ol_txrx_vdev_handle vdev, + bool enable); #endif /* _OL_TXRX__H_ */ diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index f66c755059ad..042715286577 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -880,10 +880,10 @@ struct ol_txrx_vdev_t { #ifdef QCA_LL_TX_FLOW_CONTROL_V2 struct ol_tx_flow_pool_t *pool; #endif - /* intra bss forwarded tx and rx packets count */ uint64_t fwd_tx_packets; uint64_t fwd_rx_packets; + bool is_wisa_mode_enable; }; struct ol_rx_reorder_array_elem_t { diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index f077249bd408..7ffe857a8f11 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -2575,9 +2575,6 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen, /* Zero out skb's context buffer for the driver to use */ qdf_mem_set(skb->cb, sizeof(skb->cb), 0); - /* Do the DMA Mapping */ - qdf_nbuf_map_single(pdev->osdev, skb, QDF_DMA_TO_DEVICE); - /* Terminate the (single-element) list of tx frames */ skb->next = NULL; @@ -2593,8 +2590,6 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen, if (ret) { WMA_LOGE("TxRx Rejected. Fail to do Tx"); - qdf_nbuf_unmap_single(pdev->osdev, skb, - QDF_DMA_TO_DEVICE); /* Call Download Cb so that umac can free the buffer */ if (tx_frm_download_comp_cb) tx_frm_download_comp_cb(wma_handle->mac_context, |
