qcacmn: Move multicast enhancement feature out of common code
Move WIN specific multicast enhancement feature API/data structure outside common code Change-Id: I35b10d61bd969a4ab6a864a55dd215049981c0c9
This commit is contained in:
@@ -35,8 +35,10 @@
|
||||
#ifdef FEATURE_WDS
|
||||
#include "dp_txrx_wds.h"
|
||||
#endif
|
||||
#ifdef ATH_SUPPORT_IQUE
|
||||
#include "dp_txrx_me.h"
|
||||
#endif
|
||||
|
||||
#define DP_TX_QUEUE_MASK 0x3
|
||||
|
||||
/* TODO Add support in TSO */
|
||||
#define DP_DESC_NUM_FRAG(x) 0
|
||||
@@ -63,57 +65,6 @@ static const uint8_t sec_type_map[MAX_CDP_SEC_TYPE] = {
|
||||
HAL_TX_ENCRYPT_TYPE_AES_GCMP_256,
|
||||
HAL_TX_ENCRYPT_TYPE_WAPI_GCM_SM4};
|
||||
|
||||
#ifdef WLAN_TX_PKT_CAPTURE_ENH
|
||||
#include "dp_tx_capture.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* dp_tx_get_queue() - Returns Tx queue IDs to be used for this Tx frame
|
||||
* @vdev: DP Virtual device handle
|
||||
* @nbuf: Buffer pointer
|
||||
* @queue: queue ids container for nbuf
|
||||
*
|
||||
* TX packet queue has 2 instances, software descriptors id and dma ring id
|
||||
* Based on tx feature and hardware configuration queue id combination
|
||||
* could be different.
|
||||
* For example -
|
||||
* With XPS enabled,all TX descriptor pools and dma ring are assigned
|
||||
* per cpu id
|
||||
* With no XPS,lock based resource protection, Descriptor pool ids are
|
||||
* different for each vdev, dma ring id will be same as single pdev id
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
#ifdef QCA_OL_TX_MULTIQ_SUPPORT
|
||||
static inline void dp_tx_get_queue(struct dp_vdev *vdev,
|
||||
qdf_nbuf_t nbuf, struct dp_tx_queue *queue)
|
||||
{
|
||||
uint16_t queue_offset = qdf_nbuf_get_queue_mapping(nbuf) & DP_TX_QUEUE_MASK;
|
||||
queue->desc_pool_id = queue_offset;
|
||||
queue->ring_id = vdev->pdev->soc->tx_ring_map[queue_offset];
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
|
||||
"%s, pool_id:%d ring_id: %d",
|
||||
__func__, queue->desc_pool_id, queue->ring_id);
|
||||
|
||||
return;
|
||||
}
|
||||
#else /* QCA_OL_TX_MULTIQ_SUPPORT */
|
||||
static inline void dp_tx_get_queue(struct dp_vdev *vdev,
|
||||
qdf_nbuf_t nbuf, struct dp_tx_queue *queue)
|
||||
{
|
||||
/* get flow id */
|
||||
queue->desc_pool_id = DP_TX_GET_DESC_POOL_ID(vdev);
|
||||
queue->ring_id = DP_TX_GET_RING_ID(vdev);
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
|
||||
"%s, pool_id:%d ring_id: %d",
|
||||
__func__, queue->desc_pool_id, queue->ring_id);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FEATURE_TSO)
|
||||
/**
|
||||
* dp_tx_tso_unmap_segment() - Unmap TSO segment
|
||||
@@ -1550,9 +1501,8 @@ fail_return:
|
||||
* nbuf when it fails to send
|
||||
*/
|
||||
#if QDF_LOCK_STATS
|
||||
static noinline
|
||||
noinline
|
||||
#else
|
||||
static
|
||||
#endif
|
||||
qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
|
||||
struct dp_tx_msdu_info_s *msdu_info)
|
||||
@@ -4117,232 +4067,3 @@ fail:
|
||||
dp_tx_soc_detach(soc);
|
||||
return QDF_STATUS_E_RESOURCES;
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_tx_me_mem_free(): Function to free allocated memory in mcast enahncement
|
||||
* pdev: pointer to DP PDEV structure
|
||||
* seg_info_head: Pointer to the head of list
|
||||
*
|
||||
* return: void
|
||||
*/
|
||||
static void dp_tx_me_mem_free(struct dp_pdev *pdev,
|
||||
struct dp_tx_seg_info_s *seg_info_head)
|
||||
{
|
||||
struct dp_tx_me_buf_t *mc_uc_buf;
|
||||
struct dp_tx_seg_info_s *seg_info_new = NULL;
|
||||
qdf_nbuf_t nbuf = NULL;
|
||||
uint64_t phy_addr;
|
||||
|
||||
while (seg_info_head) {
|
||||
nbuf = seg_info_head->nbuf;
|
||||
mc_uc_buf = (struct dp_tx_me_buf_t *)
|
||||
seg_info_head->frags[0].vaddr;
|
||||
phy_addr = seg_info_head->frags[0].paddr_hi;
|
||||
phy_addr = (phy_addr << 32) | seg_info_head->frags[0].paddr_lo;
|
||||
qdf_mem_unmap_nbytes_single(pdev->soc->osdev,
|
||||
phy_addr,
|
||||
QDF_DMA_TO_DEVICE , QDF_MAC_ADDR_SIZE);
|
||||
dp_tx_me_free_buf(pdev, mc_uc_buf);
|
||||
qdf_nbuf_free(nbuf);
|
||||
seg_info_new = seg_info_head;
|
||||
seg_info_head = seg_info_head->next;
|
||||
qdf_mem_free(seg_info_new);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_tx_me_send_convert_ucast(): function to convert multicast to unicast
|
||||
* @vdev: DP VDEV handle
|
||||
* @nbuf: Multicast nbuf
|
||||
* @newmac: Table of the clients to which packets have to be sent
|
||||
* @new_mac_cnt: No of clients
|
||||
*
|
||||
* return: no of converted packets
|
||||
*/
|
||||
uint16_t
|
||||
dp_tx_me_send_convert_ucast(struct cdp_vdev *vdev_handle, qdf_nbuf_t nbuf,
|
||||
uint8_t newmac[][QDF_MAC_ADDR_SIZE], uint8_t new_mac_cnt)
|
||||
{
|
||||
struct dp_vdev *vdev = (struct dp_vdev *) vdev_handle;
|
||||
struct dp_pdev *pdev = vdev->pdev;
|
||||
qdf_ether_header_t *eh;
|
||||
uint8_t *data;
|
||||
uint16_t len;
|
||||
|
||||
/* reference to frame dst addr */
|
||||
uint8_t *dstmac;
|
||||
/* copy of original frame src addr */
|
||||
uint8_t srcmac[QDF_MAC_ADDR_SIZE];
|
||||
|
||||
/* local index into newmac */
|
||||
uint8_t new_mac_idx = 0;
|
||||
struct dp_tx_me_buf_t *mc_uc_buf;
|
||||
qdf_nbuf_t nbuf_clone;
|
||||
struct dp_tx_msdu_info_s msdu_info;
|
||||
struct dp_tx_seg_info_s *seg_info_head = NULL;
|
||||
struct dp_tx_seg_info_s *seg_info_tail = NULL;
|
||||
struct dp_tx_seg_info_s *seg_info_new;
|
||||
qdf_dma_addr_t paddr_data;
|
||||
qdf_dma_addr_t paddr_mcbuf = 0;
|
||||
uint8_t empty_entry_mac[QDF_MAC_ADDR_SIZE] = {0};
|
||||
QDF_STATUS status;
|
||||
|
||||
qdf_mem_zero(&msdu_info, sizeof(msdu_info));
|
||||
|
||||
dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue);
|
||||
|
||||
eh = (qdf_ether_header_t *)nbuf;
|
||||
qdf_mem_copy(srcmac, eh->ether_shost, QDF_MAC_ADDR_SIZE);
|
||||
|
||||
len = qdf_nbuf_len(nbuf);
|
||||
|
||||
data = qdf_nbuf_data(nbuf);
|
||||
|
||||
status = qdf_nbuf_map(vdev->osdev, nbuf,
|
||||
QDF_DMA_TO_DEVICE);
|
||||
|
||||
if (status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
"Mapping failure Error:%d", status);
|
||||
DP_STATS_INC(vdev, tx_i.mcast_en.dropped_map_error, 1);
|
||||
qdf_nbuf_free(nbuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
paddr_data = qdf_nbuf_mapped_paddr_get(nbuf) + QDF_MAC_ADDR_SIZE;
|
||||
|
||||
for (new_mac_idx = 0; new_mac_idx < new_mac_cnt; new_mac_idx++) {
|
||||
dstmac = newmac[new_mac_idx];
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
|
||||
"added mac addr (%pM)", dstmac);
|
||||
|
||||
/* Check for NULL Mac Address */
|
||||
if (!qdf_mem_cmp(dstmac, empty_entry_mac, QDF_MAC_ADDR_SIZE))
|
||||
continue;
|
||||
|
||||
/* frame to self mac. skip */
|
||||
if (!qdf_mem_cmp(dstmac, srcmac, QDF_MAC_ADDR_SIZE))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* TODO: optimize to avoid malloc in per-packet path
|
||||
* For eg. seg_pool can be made part of vdev structure
|
||||
*/
|
||||
seg_info_new = qdf_mem_malloc(sizeof(*seg_info_new));
|
||||
|
||||
if (!seg_info_new) {
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
"alloc failed");
|
||||
DP_STATS_INC(vdev, tx_i.mcast_en.fail_seg_alloc, 1);
|
||||
goto fail_seg_alloc;
|
||||
}
|
||||
|
||||
mc_uc_buf = dp_tx_me_alloc_buf(pdev);
|
||||
if (!mc_uc_buf)
|
||||
goto fail_buf_alloc;
|
||||
|
||||
/*
|
||||
* TODO: Check if we need to clone the nbuf
|
||||
* Or can we just use the reference for all cases
|
||||
*/
|
||||
if (new_mac_idx < (new_mac_cnt - 1)) {
|
||||
nbuf_clone = qdf_nbuf_clone((qdf_nbuf_t)nbuf);
|
||||
if (!nbuf_clone) {
|
||||
DP_STATS_INC(vdev, tx_i.mcast_en.clone_fail, 1);
|
||||
goto fail_clone;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Update the ref
|
||||
* to account for frame sent without cloning
|
||||
*/
|
||||
qdf_nbuf_ref(nbuf);
|
||||
nbuf_clone = nbuf;
|
||||
}
|
||||
|
||||
qdf_mem_copy(mc_uc_buf->data, dstmac, QDF_MAC_ADDR_SIZE);
|
||||
|
||||
status = qdf_mem_map_nbytes_single(vdev->osdev, mc_uc_buf->data,
|
||||
QDF_DMA_TO_DEVICE, QDF_MAC_ADDR_SIZE,
|
||||
&paddr_mcbuf);
|
||||
|
||||
if (status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
"Mapping failure Error:%d", status);
|
||||
DP_STATS_INC(vdev, tx_i.mcast_en.dropped_map_error, 1);
|
||||
goto fail_map;
|
||||
}
|
||||
|
||||
seg_info_new->frags[0].vaddr = (uint8_t *)mc_uc_buf;
|
||||
seg_info_new->frags[0].paddr_lo = (uint32_t) paddr_mcbuf;
|
||||
seg_info_new->frags[0].paddr_hi =
|
||||
(uint16_t)((uint64_t)paddr_mcbuf >> 32);
|
||||
seg_info_new->frags[0].len = QDF_MAC_ADDR_SIZE;
|
||||
|
||||
/*preparing data fragment*/
|
||||
seg_info_new->frags[1].vaddr =
|
||||
qdf_nbuf_data(nbuf) + QDF_MAC_ADDR_SIZE;
|
||||
seg_info_new->frags[1].paddr_lo = (uint32_t)paddr_data;
|
||||
seg_info_new->frags[1].paddr_hi =
|
||||
(uint16_t)(((uint64_t)paddr_data) >> 32);
|
||||
seg_info_new->frags[1].len = len - QDF_MAC_ADDR_SIZE;
|
||||
|
||||
seg_info_new->nbuf = nbuf_clone;
|
||||
seg_info_new->frag_cnt = 2;
|
||||
seg_info_new->total_len = len;
|
||||
|
||||
seg_info_new->next = NULL;
|
||||
|
||||
if (!seg_info_head)
|
||||
seg_info_head = seg_info_new;
|
||||
else
|
||||
seg_info_tail->next = seg_info_new;
|
||||
|
||||
seg_info_tail = seg_info_new;
|
||||
}
|
||||
|
||||
if (!seg_info_head) {
|
||||
goto free_return;
|
||||
}
|
||||
|
||||
msdu_info.u.sg_info.curr_seg = seg_info_head;
|
||||
msdu_info.num_seg = new_mac_cnt;
|
||||
msdu_info.frm_type = dp_tx_frm_me;
|
||||
|
||||
msdu_info.tid = HTT_INVALID_TID;
|
||||
if (qdf_unlikely(vdev->mcast_enhancement_en > 0) &&
|
||||
qdf_unlikely(pdev->hmmc_tid_override_en))
|
||||
msdu_info.tid = pdev->hmmc_tid;
|
||||
|
||||
DP_STATS_INC(vdev, tx_i.mcast_en.ucast, new_mac_cnt);
|
||||
dp_tx_send_msdu_multiple(vdev, nbuf, &msdu_info);
|
||||
|
||||
while (seg_info_head->next) {
|
||||
seg_info_new = seg_info_head;
|
||||
seg_info_head = seg_info_head->next;
|
||||
qdf_mem_free(seg_info_new);
|
||||
}
|
||||
qdf_mem_free(seg_info_head);
|
||||
|
||||
qdf_nbuf_unmap(pdev->soc->osdev, nbuf, QDF_DMA_TO_DEVICE);
|
||||
qdf_nbuf_free(nbuf);
|
||||
return new_mac_cnt;
|
||||
|
||||
fail_map:
|
||||
qdf_nbuf_free(nbuf_clone);
|
||||
|
||||
fail_clone:
|
||||
dp_tx_me_free_buf(pdev, mc_uc_buf);
|
||||
|
||||
fail_buf_alloc:
|
||||
qdf_mem_free(seg_info_new);
|
||||
|
||||
fail_seg_alloc:
|
||||
dp_tx_me_mem_free(pdev, seg_info_head);
|
||||
|
||||
free_return:
|
||||
qdf_nbuf_unmap(pdev->soc->osdev, nbuf, QDF_DMA_TO_DEVICE);
|
||||
qdf_nbuf_free(nbuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user