qcacmn: DP changes to create li/be TX files

Move DP TX target specific functionality to dp/wifi3.0/be
and dp/wifi3.0/li folders. DP Functionality common to both lithium and
beryllium targets stays in dp/wifi3.0.

Change-Id: I3497284153e2ea30a9cb1faf05bd41422329b804
CRs-Fixed: 2891038
This commit is contained in:
Mohit Khanna
2021-02-17 01:06:06 -08:00
committed by Rakesh Pillai
parent ca2db4bfa8
commit e135b3e106
15 changed files with 1496 additions and 303 deletions

View File

@@ -103,6 +103,35 @@ void *dp_soc_init_wifi3(struct cdp_soc_t *soc,
} }
#endif /* QCA_WIFI_QCA8074 */ #endif /* QCA_WIFI_QCA8074 */
static inline int cdp_get_arch_type_from_devid(uint16_t devid)
{
switch (devid) {
case LITHIUM_DP: /*FIXME Add lithium devide IDs */
case QCA8074_DEVICE_ID: /* Hawekeye */
case QCA8074V2_DEVICE_ID: /* Hawekeye V2*/
case QCA5018_DEVICE_ID:
case QCA6290_DEVICE_ID:
case QCN9000_DEVICE_ID:
case QCN6122_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCA6490_DEVICE_ID:
case QCA6750_DEVICE_ID:
case QCA6390_EMULATION_DEVICE_ID:
case RUMIM2M_DEVICE_ID_NODE0: /*lithium emulation */
case RUMIM2M_DEVICE_ID_NODE1: /*lithium emulation */
case RUMIM2M_DEVICE_ID_NODE2: /*lithium emulation */
case RUMIM2M_DEVICE_ID_NODE3: /*lithium emulation */
case RUMIM2M_DEVICE_ID_NODE4: /*lithium emulation */
case RUMIM2M_DEVICE_ID_NODE5: /*lithium emulation */
return LITHIUM_DP;
case BERYLLIUM_DP:
case WCN7850_DEVICE_ID:
return BERYLLIUM_DP;
default:
return -1;
}
}
static inline static inline
ol_txrx_soc_handle cdp_soc_attach(u_int16_t devid, ol_txrx_soc_handle cdp_soc_attach(u_int16_t devid,
struct hif_opaque_softc *hif_handle, struct hif_opaque_softc *hif_handle,

113
dp/wifi3.0/be/dp_be.c Normal file
View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2021 The Linux Foundation. All rights reserved.
*
* 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 "dp_be.h"
#include "dp_be_tx.h"
#include "dp_be_rx.h"
qdf_size_t dp_get_context_size_be(enum dp_context_type context_type)
{
switch (context_type) {
case DP_CONTEXT_TYPE_SOC:
return sizeof(struct dp_soc_be);
case DP_CONTEXT_TYPE_PDEV:
return sizeof(struct dp_pdev_be);
case DP_CONTEXT_TYPE_VDEV:
return sizeof(struct dp_vdev_be);
case DP_CONTEXT_TYPE_PEER:
return sizeof(struct dp_peer_be);
default:
return 0;
}
}
static QDF_STATUS dp_soc_attach_be(struct dp_soc *soc)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
soc->wbm_sw0_bm_id = hal_tx_get_wbm_sw0_bm_id();
qdf_status = dp_tx_init_bank_profiles(be_soc);
return qdf_status;
}
static QDF_STATUS dp_soc_detach_be(struct dp_soc *soc)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
dp_tx_deinit_bank_profiles(be_soc);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_pdev_attach_be(struct dp_pdev *pdev)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_pdev_detach_be(struct dp_pdev *pdev)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_vdev_attach_be(struct dp_soc *soc, struct dp_vdev *vdev)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_vdev_be *be_vdev = dp_get_be_vdev_from_dp_vdev(vdev);
be_vdev->bank_id = dp_tx_get_bank_profile(be_soc, be_vdev);
/* Needs to be enabled after bring-up*/
be_vdev->vdev_id_check_en = false;
if (be_vdev->bank_id == DP_BE_INVALID_BANK_ID) {
QDF_BUG(0);
return QDF_STATUS_E_FAULT;
}
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_vdev_detach_be(struct dp_soc *soc, struct dp_vdev *vdev)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_vdev_be *be_vdev = dp_get_be_vdev_from_dp_vdev(vdev);
dp_tx_put_bank_profile(be_soc, be_vdev);
return QDF_STATUS_SUCCESS;
}
qdf_size_t dp_get_soc_context_size_be(void)
{
return sizeof(struct dp_soc_be);
}
void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops)
{
arch_ops->tx_hw_enqueue = dp_tx_hw_enqueue_be;
arch_ops->txrx_get_context_size = dp_get_context_size_be;
arch_ops->dp_rx_process = dp_rx_process_be;
arch_ops->txrx_soc_attach = dp_soc_attach_be;
arch_ops->txrx_soc_detach = dp_soc_detach_be;
arch_ops->txrx_pdev_attach = dp_pdev_attach_be;
arch_ops->txrx_pdev_detach = dp_pdev_detach_be;
arch_ops->txrx_vdev_attach = dp_vdev_attach_be;
arch_ops->txrx_vdev_detach = dp_vdev_detach_be;
arch_ops->tx_comp_get_params_from_hal_desc =
dp_tx_comp_get_params_from_hal_desc_be;
}

147
dp/wifi3.0/be/dp_be.h Normal file
View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2021 The Linux Foundation. All rights reserved.
*
* 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.
*/
#ifndef __DP_BE_H
#define __DP_BE_H
#include <dp_types.h>
#include <hal_be_tx.h>
/**
* struct dp_tx_bank_profile - DP wrapper for TCL banks
* @is_configured: flag indicating if this bank is configured
* @ref_count: ref count indicating number of users of the bank
* @bank_config: HAL TX bank configuration
*/
struct dp_tx_bank_profile {
uint8_t is_configured;
qdf_atomic_t ref_count;
union hal_tx_bank_config bank_config;
};
/**
* struct dp_soc_be - Extended DP soc for BE targets
* @soc: dp soc structure
* @num_bank_profiles: num TX bank profiles
* @bank_profiles: bank profiles for various TX banks
*/
struct dp_soc_be {
struct dp_soc soc;
uint8_t num_bank_profiles;
qdf_mutex_t tx_bank_lock;
struct dp_tx_bank_profile *bank_profiles;
};
/**
* struct dp_pdev_be - Extended DP pdev for BE targets
* @pdev: dp pdev structure
*/
struct dp_pdev_be {
struct dp_pdev pdev;
};
/**
* struct dp_vdev_be - Extended DP vdev for BE targets
* @vdev: dp vdev structure
* @bank_id: bank_id to be used for TX
* @vdev_id_check_en: flag if HW vdev_id check is enabled for vdev
*/
struct dp_vdev_be {
struct dp_vdev vdev;
int8_t bank_id;
uint8_t vdev_id_check_en;
};
/**
* struct dp_peer_be - Extended DP peer for BE targets
* @dp_peer: dp peer structure
*/
struct dp_peer_be {
struct dp_peer peer;
};
/**
* dp_get_soc_context_size_be() - get context size for target specific DP soc
*
* Return: value in bytes for BE specific soc structure
*/
qdf_size_t dp_get_soc_context_size_be(void);
/**
* dp_initialize_arch_ops_be() - initialize BE specific arch ops
* @arch_ops: arch ops pointer
*
* Return: none
*/
void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops);
/**
* dp_get_context_size_be() - get BE specific size for peer/vdev/pdev/soc
* @arch_ops: arch ops pointer
*
* Return: size in bytes for the context_type
*/
qdf_size_t dp_get_context_size_be(enum dp_context_type context_type);
/**
* dp_get_be_soc_from_dp_soc() - get dp_soc_be from dp_soc
* @soc: dp_soc pointer
*
* Return: dp_soc_be pointer
*/
static inline struct dp_soc_be *dp_get_be_soc_from_dp_soc(struct dp_soc *soc)
{
return (struct dp_soc_be *)soc;
}
/**
* dp_get_be_pdev_from_dp_pdev() - get dp_pdev_be from dp_pdev
* @pdev: dp_pdev pointer
*
* Return: dp_pdev_be pointer
*/
static inline
struct dp_pdev_be *dp_get_be_pdev_from_dp_pdev(struct dp_pdev *pdev)
{
return (struct dp_pdev_be *)pdev;
}
/**
* dp_get_be_vdev_from_dp_vdev() - get dp_vdev_be from dp_vdev
* @vdev: dp_vdev pointer
*
* Return: dp_vdev_be pointer
*/
static inline
struct dp_vdev_be *dp_get_be_vdev_from_dp_vdev(struct dp_vdev *vdev)
{
return (struct dp_vdev_be *)vdev;
}
/**
* dp_get_be_peer_from_dp_peer() - get dp_peer_be from dp_peer
* @peer: dp_peer pointer
*
* Return: dp_peer_be pointer
*/
static inline
struct dp_peer_be *dp_get_be_peer_from_dp_peer(struct dp_peer *peer)
{
return (struct dp_peer_be *)peer;
}
#endif

325
dp/wifi3.0/be/dp_be_tx.c Normal file
View File

@@ -0,0 +1,325 @@
/*
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
*
* 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 "cdp_txrx_cmn_struct.h"
#include "dp_types.h"
#include "dp_tx.h"
#include "dp_be_tx.h"
#include "dp_tx_desc.h"
#include "hal_tx.h"
#include <hal_be_api.h>
void dp_tx_comp_get_params_from_hal_desc_be(struct dp_soc *soc,
void *tx_comp_hal_desc,
struct dp_tx_desc_s **r_tx_desc)
{
uint8_t pool_id;
uint32_t tx_desc_id;
tx_desc_id = hal_tx_comp_get_desc_id(tx_comp_hal_desc);
pool_id = (tx_desc_id & DP_TX_DESC_ID_POOL_MASK) >>
DP_TX_DESC_ID_POOL_OS;
/* Find Tx descriptor */
*r_tx_desc = dp_tx_desc_find(soc, pool_id,
(tx_desc_id & DP_TX_DESC_ID_PAGE_MASK) >>
DP_TX_DESC_ID_PAGE_OS,
(tx_desc_id & DP_TX_DESC_ID_OFFSET_MASK) >>
DP_TX_DESC_ID_OFFSET_OS);
}
QDF_STATUS
dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc, uint16_t fw_metadata,
struct cdp_tx_exception_metadata *tx_exc_metadata,
struct dp_tx_msdu_info_s *msdu_info)
{
void *hal_tx_desc;
uint32_t *hal_tx_desc_cached;
int coalesce = 0;
struct dp_tx_queue *tx_q = &msdu_info->tx_queue;
uint8_t ring_id = tx_q->ring_id & DP_TX_QUEUE_MASK;
uint8_t tid = msdu_info->tid;
struct dp_vdev_be *be_vdev;
uint8_t cached_desc[HAL_TX_DESC_LEN_BYTES] = { 0 };
uint8_t bm_id = dp_tx_get_rbm_id(soc, ring_id);
hal_ring_handle_t hal_ring_hdl = NULL;
QDF_STATUS status = QDF_STATUS_E_RESOURCES;
be_vdev = dp_get_be_vdev_from_dp_vdev(vdev);
if (!dp_tx_is_desc_id_valid(soc, tx_desc->id)) {
dp_err_rl("Invalid tx desc id:%d", tx_desc->id);
return QDF_STATUS_E_RESOURCES;
}
hal_tx_desc_cached = (void *)cached_desc;
hal_tx_desc_set_buf_addr(soc->hal_soc, hal_tx_desc_cached,
tx_desc->dma_addr, bm_id, tx_desc->id,
(tx_desc->flags & DP_TX_DESC_FLAG_FRAG));
hal_tx_desc_set_lmac_id(soc->hal_soc, hal_tx_desc_cached,
vdev->lmac_id);
hal_tx_desc_set_search_index(soc->hal_soc, hal_tx_desc_cached,
vdev->bss_ast_idx);
/*
* Bank_ID is used as DSCP_TABLE number in beryllium
* So there is no explicit field used for DSCP_TID_TABLE_NUM.
*/
hal_tx_desc_set_cache_set_num(soc->hal_soc, hal_tx_desc_cached,
(vdev->bss_ast_hash & 0xF));
hal_tx_desc_set_fw_metadata(hal_tx_desc_cached, fw_metadata);
hal_tx_desc_set_buf_length(hal_tx_desc_cached, tx_desc->length);
hal_tx_desc_set_buf_offset(hal_tx_desc_cached, tx_desc->pkt_offset);
if (tx_desc->flags & DP_TX_DESC_FLAG_TO_FW)
hal_tx_desc_set_to_fw(hal_tx_desc_cached, 1);
/* verify checksum offload configuration*/
if (vdev->csum_enabled &&
((qdf_nbuf_get_tx_cksum(tx_desc->nbuf) ==
QDF_NBUF_TX_CKSUM_TCP_UDP) ||
qdf_nbuf_is_tso(tx_desc->nbuf))) {
hal_tx_desc_set_l3_checksum_en(hal_tx_desc_cached, 1);
hal_tx_desc_set_l4_checksum_en(hal_tx_desc_cached, 1);
}
hal_tx_desc_set_bank_id(hal_tx_desc_cached, be_vdev->bank_id);
hal_tx_desc_set_vdev_id(hal_tx_desc_cached, vdev->vdev_id);
if (tid != HTT_TX_EXT_TID_INVALID)
hal_tx_desc_set_hlos_tid(hal_tx_desc_cached, tid);
if (qdf_unlikely(vdev->pdev->delay_stats_flag) ||
qdf_unlikely(wlan_cfg_is_peer_ext_stats_enabled(soc->wlan_cfg_ctx)))
tx_desc->timestamp = qdf_ktime_to_ms(qdf_ktime_real_get());
dp_verbose_debug("length:%d , type = %d, dma_addr %llx, offset %d desc id %u",
tx_desc->length,
(tx_desc->flags & DP_TX_DESC_FLAG_FRAG),
(uint64_t)tx_desc->dma_addr, tx_desc->pkt_offset,
tx_desc->id);
hal_ring_hdl = dp_tx_get_hal_ring_hdl(soc, ring_id);
if (qdf_unlikely(dp_tx_hal_ring_access_start(soc, hal_ring_hdl))) {
dp_err("HAL RING Access Failed -- %pK", hal_ring_hdl);
DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1);
return status;
}
hal_tx_desc = hal_srng_src_get_next(soc->hal_soc, hal_ring_hdl);
if (qdf_unlikely(!hal_tx_desc)) {
dp_verbose_debug("TCL ring full ring_id:%d", ring_id);
DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1);
goto ring_access_fail;
}
tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX;
dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf);
/* Sync cached descriptor with HW */
hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc);
coalesce = dp_tx_attempt_coalescing(soc, vdev, tx_desc, tid);
DP_STATS_INC_PKT(vdev, tx_i.processed, 1, tx_desc->length);
dp_tx_update_stats(soc, tx_desc->nbuf);
status = QDF_STATUS_SUCCESS;
dp_tx_hw_desc_update_evt((uint8_t *)hal_tx_desc_cached,
hal_ring_hdl, soc);
ring_access_fail:
dp_tx_ring_access_end_wrapper(soc, hal_ring_hdl, coalesce);
return status;
}
QDF_STATUS dp_tx_init_bank_profiles(struct dp_soc_be *be_soc)
{
int i, num_tcl_banks;
num_tcl_banks = hal_tx_get_num_tcl_banks(be_soc->soc.hal_soc);
be_soc->num_bank_profiles = num_tcl_banks;
be_soc->bank_profiles = qdf_mem_malloc(num_tcl_banks *
sizeof(*be_soc->bank_profiles));
if (!be_soc->bank_profiles) {
dp_err("unable to allocate memory for DP TX Profiles!");
return QDF_STATUS_E_NOMEM;
}
qdf_mutex_create(&be_soc->tx_bank_lock);
for (i = 0; i < num_tcl_banks; i++) {
be_soc->bank_profiles[i].is_configured = false;
qdf_atomic_init(&be_soc->bank_profiles[i].ref_count);
}
return QDF_STATUS_SUCCESS;
}
void dp_tx_deinit_bank_profiles(struct dp_soc_be *be_soc)
{
qdf_mem_free(be_soc->bank_profiles);
qdf_mutex_destroy(&be_soc->tx_bank_lock);
}
static
void dp_tx_get_vdev_bank_config(struct dp_vdev_be *be_vdev,
union hal_tx_bank_config *bank_config)
{
struct dp_vdev *vdev = &be_vdev->vdev;
struct dp_soc *soc = vdev->pdev->soc;
bank_config->epd = 0;
bank_config->encap_type = vdev->tx_encap_type;
/* Only valid for raw frames. Needs work for RAW mode */
bank_config->encrypt_type = 0;
bank_config->src_buffer_swap = 0;
bank_config->link_meta_swap = 0;
if (soc->is_peer_map_unmap_v2 && vdev->opmode == wlan_op_mode_sta)
vdev->search_type = HAL_TX_ADDR_INDEX_SEARCH;
else
vdev->search_type = HAL_TX_ADDR_SEARCH_DEFAULT;
bank_config->index_lookup_enable = 0;
bank_config->addrx_en =
(vdev->hal_desc_addr_search_flags & HAL_TX_DESC_ADDRX_EN) ?
1 : 0;
bank_config->addry_en =
(vdev->hal_desc_addr_search_flags & HAL_TX_DESC_ADDRY_EN) ?
1 : 0;
bank_config->mesh_enable = vdev->mesh_vdev ? 1 : 0;
/* Disabling vdev id check for now. Needs revist. */
bank_config->vdev_id_check_en = be_vdev->vdev_id_check_en;
bank_config->pmac_id = vdev->lmac_id;
bank_config->mcast_pkt_ctrl = 0;
}
int dp_tx_get_bank_profile(struct dp_soc_be *be_soc,
struct dp_vdev_be *be_vdev)
{
char *temp_str = "";
bool found_match = false;
int bank_id = DP_BE_INVALID_BANK_ID;
int i;
int unconfigured_slot = DP_BE_INVALID_BANK_ID;
int zero_ref_count_slot = DP_BE_INVALID_BANK_ID;
union hal_tx_bank_config vdev_config = {0};
/* convert vdev params into hal_tx_bank_config */
dp_tx_get_vdev_bank_config(be_vdev, &vdev_config);
qdf_mutex_acquire(&be_soc->tx_bank_lock);
/* go over all banks and find a matching/unconfigured/unsed bank */
for (i = 0; i < be_soc->num_bank_profiles; i++) {
if (be_soc->bank_profiles[i].is_configured &&
(be_soc->bank_profiles[i].bank_config.val ^
vdev_config.val) == 0) {
found_match = true;
break;
}
if (unconfigured_slot == DP_BE_INVALID_BANK_ID &&
!be_soc->bank_profiles[i].is_configured)
unconfigured_slot = i;
else if (zero_ref_count_slot == DP_BE_INVALID_BANK_ID &&
!qdf_atomic_read(&be_soc->bank_profiles[i].ref_count))
zero_ref_count_slot = i;
}
if (found_match) {
temp_str = "matching";
bank_id = i;
goto inc_ref_and_return;
}
if (unconfigured_slot != DP_BE_INVALID_BANK_ID) {
temp_str = "unconfigured";
bank_id = unconfigured_slot;
goto configure_and_return;
}
if (zero_ref_count_slot != DP_BE_INVALID_BANK_ID) {
temp_str = "zero_ref_count";
bank_id = zero_ref_count_slot;
}
if (bank_id == DP_BE_INVALID_BANK_ID) {
dp_alert("unable to find TX bank!");
QDF_BUG(0);
return bank_id;
}
configure_and_return:
be_soc->bank_profiles[bank_id].is_configured = true;
be_soc->bank_profiles[bank_id].bank_config.val = vdev_config.val;
hal_tx_populate_bank_register(be_soc->soc.hal_soc,
&be_soc->bank_profiles[bank_id].bank_config,
bank_id);
inc_ref_and_return:
qdf_atomic_inc(&be_soc->bank_profiles[bank_id].ref_count);
qdf_mutex_release(&be_soc->tx_bank_lock);
dp_info("found %s slot at index %d, input:0x%x match:0x%x ref_count %u",
temp_str, bank_id, vdev_config.val,
be_soc->bank_profiles[bank_id].bank_config.val,
qdf_atomic_read(&be_soc->bank_profiles[bank_id].ref_count));
dp_info("epd:%x encap:%x encryp:%x src_buf_swap:%x link_meta_swap:%x addrx_en:%x addry_en:%x mesh_en:%x vdev_id_check:%x pmac_id:%x mcast_pkt_ctrl:%x",
be_soc->bank_profiles[bank_id].bank_config.epd,
be_soc->bank_profiles[bank_id].bank_config.encap_type,
be_soc->bank_profiles[bank_id].bank_config.encrypt_type,
be_soc->bank_profiles[bank_id].bank_config.src_buffer_swap,
be_soc->bank_profiles[bank_id].bank_config.link_meta_swap,
be_soc->bank_profiles[bank_id].bank_config.addrx_en,
be_soc->bank_profiles[bank_id].bank_config.addry_en,
be_soc->bank_profiles[bank_id].bank_config.mesh_enable,
be_soc->bank_profiles[bank_id].bank_config.vdev_id_check_en,
be_soc->bank_profiles[bank_id].bank_config.pmac_id,
be_soc->bank_profiles[bank_id].bank_config.mcast_pkt_ctrl);
return bank_id;
}
void dp_tx_put_bank_profile(struct dp_soc_be *be_soc,
struct dp_vdev_be *be_vdev)
{
qdf_mutex_acquire(&be_soc->tx_bank_lock);
qdf_atomic_dec(&be_soc->bank_profiles[be_vdev->bank_id].ref_count);
qdf_mutex_release(&be_soc->tx_bank_lock);
}
void dp_tx_update_bank_profile(struct dp_soc_be *be_soc,
struct dp_vdev_be *be_vdev)
{
dp_tx_put_bank_profile(be_soc, be_vdev);
be_vdev->bank_id = dp_tx_get_bank_profile(be_soc, be_vdev);
}

112
dp/wifi3.0/be/dp_be_tx.h Normal file
View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
*
* 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.
*/
#ifndef __DP_BE_TX_H
#define __DP_BE_TX_H
/**
* DOC: dp_be_tx.h
*
* BE specific TX Datapath header file. Need not be exposed to common DP code.
*
*/
#include <dp_types.h>
#include "dp_be.h"
/* Invalid TX Bank ID value */
#define DP_BE_INVALID_BANK_ID -1
/**
* dp_tx_hw_enqueue_be() - Enqueue to TCL HW for transmit for BE target
* @soc: DP Soc Handle
* @vdev: DP vdev handle
* @tx_desc: Tx Descriptor Handle
* @fw_metadata: Metadata to send to Target Firmware along with frame
* @tx_exc_metadata: Handle that holds exception path meta data
* @msdu_info: msdu_info containing information about TX buffer
*
* Gets the next free TCL HW DMA descriptor and sets up required parameters
* from software Tx descriptor
*
* Return: QDF_STATUS_SUCCESS: success
* QDF_STATUS_E_RESOURCES: Error return
*/
QDF_STATUS dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc,
uint16_t fw_metadata,
struct cdp_tx_exception_metadata *metadata,
struct dp_tx_msdu_info_s *msdu_info);
/**
* dp_tx_comp_get_params_from_hal_desc_be() - Get TX desc from HAL comp desc
* @soc: DP soc handle
* @tx_comp_hal_desc: HAL TX Comp Descriptor
* @r_tx_desc: SW Tx Descriptor retrieved from HAL desc.
*
* Return: None
*/
void dp_tx_comp_get_params_from_hal_desc_be(struct dp_soc *soc,
void *tx_comp_hal_desc,
struct dp_tx_desc_s **r_tx_desc);
/**
* dp_tx_init_bank_profiles() - Init TX bank profiles
* @soc: DP soc handle
*
* Return: QDF_STATUS_SUCCESS or QDF error code.
*/
QDF_STATUS dp_tx_init_bank_profiles(struct dp_soc_be *soc);
/**
* dp_tx_deinit_bank_profiles() - De-Init TX bank profiles
* @soc: DP soc handle
*
* Return: None
*/
void dp_tx_deinit_bank_profiles(struct dp_soc_be *soc);
/**
* dp_tx_get_bank_profile() - get TX bank profile for vdev
* @soc: DP soc handle
* @be_vdev: BE vdev pointer
*
* Return: bank profile allocated to vdev or DP_BE_INVALID_BANK_ID
*/
int dp_tx_get_bank_profile(struct dp_soc_be *soc,
struct dp_vdev_be *be_vdev);
/**
* dp_tx_put_bank_profile() - release TX bank profile for vdev
* @soc: DP soc handle
*
* Return: None
*/
void dp_tx_put_bank_profile(struct dp_soc_be *soc, struct dp_vdev_be *be_vdev);
/**
* dp_tx_update_bank_profile() - release existing and allocate new bank profile
* @soc: DP soc handle
* @be_vdev: pointer to be_vdev structure
*
* The function releases the existing bank profile allocated to the vdev and
* looks for a new bank profile based on updated dp_vdev TX params.
*
* Return: None
*/
void dp_tx_update_bank_profile(struct dp_soc_be *be_soc,
struct dp_vdev_be *be_vdev);
#endif

80
dp/wifi3.0/dp_arch_ops.c Normal file
View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
*
* 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 "dp_types.h"
#include "cdp_txrx_cmn_reg.h"
void dp_configure_arch_ops(struct dp_soc *soc);
qdf_size_t dp_get_soc_context_size(uint16_t device_id);
#ifdef CONFIG_LITHIUM
void dp_initialize_arch_ops_li(struct dp_arch_ops *arch_ops);
qdf_size_t dp_get_soc_context_size_li(void);
#endif
#ifdef CONFIG_BERYLLIUM
void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops);
qdf_size_t dp_get_soc_context_size_be(void);
#endif
static void dp_initialize_default_arch_ops(struct dp_arch_ops *arch_ops)
{
/* assign dummy functions for arch_ops which are architecture specific */
}
qdf_size_t dp_get_soc_context_size(uint16_t device_id)
{
switch (cdp_get_arch_type_from_devid(device_id)) {
#ifdef CONFIG_LITHIUM
case LITHIUM_DP:
return dp_get_soc_context_size_li();
#endif
#ifdef CONFIG_BERYLLIUM
case BERYLLIUM_DP:
return dp_get_soc_context_size_be();
break;
#endif
default:
QDF_BUG(0);
}
return 0;
}
void dp_configure_arch_ops(struct dp_soc *soc)
{
dp_initialize_default_arch_ops(&soc->arch_ops);
switch (cdp_get_arch_type_from_devid(soc->device_id)) {
#ifdef CONFIG_LITHIUM
case LITHIUM_DP:
dp_initialize_arch_ops_li(&soc->arch_ops);
break;
#endif
#ifdef CONFIG_BERYLLIUM
case BERYLLIUM_DP:
dp_initialize_arch_ops_be(&soc->arch_ops);
break;
#endif
default:
QDF_BUG(0);
}
}

View File

@@ -1835,9 +1835,19 @@ void dp_peer_stats_update_protocol_cnt(struct cdp_soc_t *soc,
bool is_egress, bool is_egress,
bool is_rx); bool is_rx);
void dp_vdev_peer_stats_update_protocol_cnt_tx(struct dp_vdev *vdev_hdl,
qdf_nbuf_t nbuf);
#else #else
#define dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, peer, \ #define dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, peer, \
is_egress, is_rx) is_egress, is_rx)
static inline
void dp_vdev_peer_stats_update_protocol_cnt_tx(struct dp_vdev *vdev_hdl,
qdf_nbuf_t nbuf)
{
}
#endif #endif
#ifdef QCA_LL_TX_FLOW_CONTROL_V2 #ifdef QCA_LL_TX_FLOW_CONTROL_V2

View File

@@ -54,6 +54,7 @@
#include "qdf_mem.h" /* qdf_mem_malloc,free */ #include "qdf_mem.h" /* qdf_mem_malloc,free */
#include "cfg_ucfg_api.h" #include "cfg_ucfg_api.h"
#include "dp_mon_filter.h" #include "dp_mon_filter.h"
#ifdef QCA_LL_TX_FLOW_CONTROL_V2 #ifdef QCA_LL_TX_FLOW_CONTROL_V2
#include "cdp_txrx_flow_ctrl_v2.h" #include "cdp_txrx_flow_ctrl_v2.h"
#else #else
@@ -118,6 +119,9 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc)
__QDF_TRACE_FL(QDF_TRACE_LEVEL_INFO_HIGH, QDF_MODULE_ID_DP_VDEV, ## params) __QDF_TRACE_FL(QDF_TRACE_LEVEL_INFO_HIGH, QDF_MODULE_ID_DP_VDEV, ## params)
#define dp_vdev_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_DP_VDEV, params) #define dp_vdev_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_DP_VDEV, params)
void dp_configure_arch_ops(struct dp_soc *soc);
qdf_size_t dp_get_soc_context_size(uint16_t device_id);
/* /*
* The max size of cdp_peer_stats_param_t is limited to 16 bytes. * The max size of cdp_peer_stats_param_t is limited to 16 bytes.
* If the buffer size is exceeding this size limit, * If the buffer size is exceeding this size limit,
@@ -5345,6 +5349,8 @@ static void dp_soc_detach(struct cdp_soc_t *txrx_soc)
{ {
struct dp_soc *soc = (struct dp_soc *)txrx_soc; struct dp_soc *soc = (struct dp_soc *)txrx_soc;
soc->arch_ops.txrx_soc_detach(soc);
dp_soc_swlm_detach(soc); dp_soc_swlm_detach(soc);
dp_soc_tx_desc_sw_pools_free(soc); dp_soc_tx_desc_sw_pools_free(soc);
dp_soc_srng_free(soc); dp_soc_srng_free(soc);
@@ -6104,12 +6110,17 @@ static QDF_STATUS dp_vdev_attach_wifi3(struct cdp_soc_t *cdp_soc,
enum wlan_op_mode op_mode, enum wlan_op_mode op_mode,
enum wlan_op_subtype subtype) enum wlan_op_subtype subtype)
{ {
int i = 0;
qdf_size_t vdev_context_size;
struct dp_soc *soc = (struct dp_soc *)cdp_soc; struct dp_soc *soc = (struct dp_soc *)cdp_soc;
struct dp_pdev *pdev = struct dp_pdev *pdev =
dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc,
pdev_id); pdev_id);
struct dp_vdev *vdev = qdf_mem_malloc(sizeof(*vdev)); struct dp_vdev *vdev;
int i = 0;
vdev_context_size =
soc->arch_ops.txrx_get_context_size(DP_CONTEXT_TYPE_VDEV);
vdev = qdf_mem_malloc(vdev_context_size);
if (!pdev) { if (!pdev) {
dp_init_err("%pK: DP PDEV is Null for pdev id %d", dp_init_err("%pK: DP PDEV is Null for pdev id %d",
@@ -6221,6 +6232,9 @@ static QDF_STATUS dp_vdev_attach_wifi3(struct cdp_soc_t *cdp_soc,
QDF_MAC_ADDR_REF(vdev->mac_addr.raw)); QDF_MAC_ADDR_REF(vdev->mac_addr.raw));
DP_STATS_INIT(vdev); DP_STATS_INIT(vdev);
if (QDF_IS_STATUS_ERROR(soc->arch_ops.txrx_vdev_attach(soc, vdev)))
goto fail0;
if (wlan_op_mode_sta == vdev->opmode) if (wlan_op_mode_sta == vdev->opmode)
dp_peer_create_wifi3((struct cdp_soc_t *)soc, vdev_id, dp_peer_create_wifi3((struct cdp_soc_t *)soc, vdev_id,
vdev->mac_addr.raw); vdev->mac_addr.raw);
@@ -6411,6 +6425,8 @@ static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc,
if (!vdev) if (!vdev)
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
soc->arch_ops.txrx_vdev_detach(soc, vdev);
pdev = vdev->pdev; pdev = vdev->pdev;
vap_self_peer = dp_sta_vdev_self_peer_ref_n_get(soc, vdev, vap_self_peer = dp_sta_vdev_self_peer_ref_n_get(soc, vdev,
@@ -12871,12 +12887,13 @@ dp_soc_attach(struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
goto fail0; goto fail0;
} }
soc = qdf_mem_malloc(sizeof(*soc)); soc = qdf_mem_malloc(dp_get_soc_context_size(device_id));
if (!soc) { if (!soc) {
dp_err("DP SOC memory allocation failed"); dp_err("DP SOC memory allocation failed");
goto fail0; goto fail0;
} }
dp_info("soc memory allocated %pk", soc);
soc->hif_handle = hif_handle; soc->hif_handle = hif_handle;
soc->hal_soc = hif_get_hal_handle(soc->hif_handle); soc->hal_soc = hif_get_hal_handle(soc->hif_handle);
if (!soc->hal_soc) if (!soc->hal_soc)
@@ -12890,6 +12907,8 @@ dp_soc_attach(struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
soc->osdev = qdf_osdev; soc->osdev = qdf_osdev;
soc->num_hw_dscp_tid_map = HAL_MAX_HW_DSCP_TID_MAPS; soc->num_hw_dscp_tid_map = HAL_MAX_HW_DSCP_TID_MAPS;
dp_configure_arch_ops(soc);
/* Reset wbm sg list and flags */ /* Reset wbm sg list and flags */
dp_rx_wbm_sg_list_reset(soc); dp_rx_wbm_sg_list_reset(soc);
@@ -12925,6 +12944,11 @@ dp_soc_attach(struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
goto fail5; goto fail5;
} }
if (!QDF_IS_STATUS_SUCCESS(soc->arch_ops.txrx_soc_attach(soc))) {
dp_err("unable to do target specific attach");
goto fail6;
}
dp_soc_swlm_attach(soc); dp_soc_swlm_attach(soc);
dp_soc_set_interrupt_mode(soc); dp_soc_set_interrupt_mode(soc);
dp_soc_set_def_pdev(soc); dp_soc_set_def_pdev(soc);
@@ -12935,6 +12959,8 @@ dp_soc_attach(struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
qdf_skb_total_mem_stats_read()); qdf_skb_total_mem_stats_read());
return soc; return soc;
fail6:
dp_soc_tx_desc_sw_pools_free(soc);
fail5: fail5:
dp_soc_srng_free(soc); dp_soc_srng_free(soc);
fail4: fail4:

View File

@@ -58,22 +58,6 @@
/* invalid peer id for reinject*/ /* invalid peer id for reinject*/
#define DP_INVALID_PEER 0XFFFE #define DP_INVALID_PEER 0XFFFE
/*mapping between hal encrypt type and cdp_sec_type*/
#define MAX_CDP_SEC_TYPE 12
static const uint8_t sec_type_map[MAX_CDP_SEC_TYPE] = {
HAL_TX_ENCRYPT_TYPE_NO_CIPHER,
HAL_TX_ENCRYPT_TYPE_WEP_128,
HAL_TX_ENCRYPT_TYPE_WEP_104,
HAL_TX_ENCRYPT_TYPE_WEP_40,
HAL_TX_ENCRYPT_TYPE_TKIP_WITH_MIC,
HAL_TX_ENCRYPT_TYPE_TKIP_NO_MIC,
HAL_TX_ENCRYPT_TYPE_AES_CCMP_128,
HAL_TX_ENCRYPT_TYPE_WAPI,
HAL_TX_ENCRYPT_TYPE_AES_CCMP_256,
HAL_TX_ENCRYPT_TYPE_AES_GCMP_128,
HAL_TX_ENCRYPT_TYPE_AES_GCMP_256,
HAL_TX_ENCRYPT_TYPE_WAPI_GCM_SM4};
#ifdef CONFIG_WLAN_SYSFS_MEM_STATS #ifdef CONFIG_WLAN_SYSFS_MEM_STATS
/** /**
* dp_update_tx_desc_stats - Update the increase or decrease in * dp_update_tx_desc_stats - Update the increase or decrease in
@@ -488,7 +472,7 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id)
qdf_atomic_dec(&soc->num_tx_exception); qdf_atomic_dec(&soc->num_tx_exception);
if (HAL_TX_COMP_RELEASE_SOURCE_TQM == if (HAL_TX_COMP_RELEASE_SOURCE_TQM ==
hal_tx_comp_get_buffer_source(&tx_desc->comp)) tx_desc->buffer_src)
comp_status = hal_tx_comp_get_release_reason(&tx_desc->comp, comp_status = hal_tx_comp_get_release_reason(&tx_desc->comp,
soc->hal_soc); soc->hal_soc);
else else
@@ -1326,28 +1310,28 @@ static void dp_tx_raw_prepare_unset(struct dp_soc *soc,
} }
#ifdef VDEV_PEER_PROTOCOL_COUNT #ifdef VDEV_PEER_PROTOCOL_COUNT
#define dp_vdev_peer_stats_update_protocol_cnt_tx(vdev_hdl, nbuf) \ void dp_vdev_peer_stats_update_protocol_cnt_tx(struct dp_vdev *vdev_hdl,
{ \ qdf_nbuf_t nbuf)
qdf_nbuf_t nbuf_local; \ {
struct dp_vdev *vdev_local = vdev_hdl; \ qdf_nbuf_t nbuf_local;
do { \ struct dp_vdev *vdev_local = vdev_hdl;
if (qdf_likely(!((vdev_local)->peer_protocol_count_track))) \
break; \ do {
nbuf_local = nbuf; \ if (qdf_likely(!((vdev_local)->peer_protocol_count_track)))
if (qdf_unlikely(((vdev_local)->tx_encap_type) == \ break;
htt_cmn_pkt_type_raw)) \ nbuf_local = nbuf;
break; \ if (qdf_unlikely(((vdev_local)->tx_encap_type) ==
else if (qdf_unlikely(qdf_nbuf_is_nonlinear((nbuf_local)))) \ htt_cmn_pkt_type_raw))
break; \ break;
else if (qdf_nbuf_is_tso((nbuf_local))) \ else if (qdf_unlikely(qdf_nbuf_is_nonlinear((nbuf_local))))
break; \ break;
dp_vdev_peer_stats_update_protocol_cnt((vdev_local), \ else if (qdf_nbuf_is_tso((nbuf_local)))
(nbuf_local), \ break;
NULL, 1, 0); \ dp_vdev_peer_stats_update_protocol_cnt((vdev_local),
} while (0); \ (nbuf_local),
NULL, 1, 0);
} while (0);
} }
#else
#define dp_vdev_peer_stats_update_protocol_cnt_tx(vdev_hdl, skb)
#endif #endif
#ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR #ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR
@@ -1358,22 +1342,13 @@ static void dp_tx_raw_prepare_unset(struct dp_soc *soc,
* *
* Returns: none * Returns: none
*/ */
static inline void dp_tx_update_stats(struct dp_soc *soc, void dp_tx_update_stats(struct dp_soc *soc,
qdf_nbuf_t nbuf) qdf_nbuf_t nbuf)
{ {
DP_STATS_INC_PKT(soc, tx.egress, 1, qdf_nbuf_len(nbuf)); DP_STATS_INC_PKT(soc, tx.egress, 1, qdf_nbuf_len(nbuf));
} }
/** int
* dp_tx_attempt_coalescing() - Check and attempt TCL register write coalescing
* @soc: Datapath soc handle
* @tx_desc: tx packet descriptor
* @tid: TID for pkt transmission
*
* Returns: 1, if coalescing is to be done
* 0, if coalescing is not to be done
*/
static inline int
dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev, dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc, struct dp_tx_desc_s *tx_desc,
uint8_t tid) uint8_t tid)
@@ -1409,15 +1384,7 @@ dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev,
return ret; return ret;
} }
/** void
* dp_tx_ring_access_end() - HAL ring access end for data transmission
* @soc: Datapath soc handle
* @hal_ring_hdl: HAL ring handle
* @coalesce: Coalesce the current write or not
*
* Returns: none
*/
static inline void
dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl, dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl,
int coalesce) int coalesce)
{ {
@@ -1427,26 +1394,6 @@ dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl,
dp_tx_hal_ring_access_end(soc, hal_ring_hdl); dp_tx_hal_ring_access_end(soc, hal_ring_hdl);
} }
#else
static inline void dp_tx_update_stats(struct dp_soc *soc,
qdf_nbuf_t nbuf)
{
}
static inline int
dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc,
uint8_t tid)
{
return 0;
}
static inline void
dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl,
int coalesce)
{
dp_tx_hal_ring_access_end(soc, hal_ring_hdl);
}
#endif #endif
#ifdef FEATURE_RUNTIME_PM #ifdef FEATURE_RUNTIME_PM
@@ -1461,7 +1408,7 @@ dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl,
* *
* Returns: none * Returns: none
*/ */
static inline void void
dp_tx_ring_access_end_wrapper(struct dp_soc *soc, dp_tx_ring_access_end_wrapper(struct dp_soc *soc,
hal_ring_handle_t hal_ring_hdl, hal_ring_handle_t hal_ring_hdl,
int coalesce) int coalesce)
@@ -1504,191 +1451,8 @@ dp_tx_ring_access_end_wrapper(struct dp_soc *soc,
dp_runtime_put(soc); dp_runtime_put(soc);
} }
} }
#else
static inline void
dp_tx_ring_access_end_wrapper(struct dp_soc *soc,
hal_ring_handle_t hal_ring_hdl,
int coalesce)
{
dp_tx_ring_access_end(soc, hal_ring_hdl, coalesce);
}
#endif #endif
#ifdef DP_TX_HW_DESC_HISTORY
static inline void
dp_tx_hw_desc_update_evt(uint8_t *hal_tx_desc_cached,
hal_ring_handle_t hal_ring_hdl,
struct dp_soc *soc)
{
struct dp_tx_hw_desc_evt *evt;
uint64_t idx = 0;
if (!soc->tx_hw_desc_history)
return;
idx = ++soc->tx_hw_desc_history->index;
if (idx == DP_TX_HW_DESC_HIST_MAX)
soc->tx_hw_desc_history->index = 0;
idx = qdf_do_div_rem(idx, DP_TX_HW_DESC_HIST_MAX);
evt = &soc->tx_hw_desc_history->entry[idx];
qdf_mem_copy(evt->tcl_desc, hal_tx_desc_cached, HAL_TX_DESC_LEN_BYTES);
evt->posted = qdf_get_log_timestamp();
hal_get_sw_hptp(soc->hal_soc, hal_ring_hdl, &evt->tp, &evt->hp);
}
#else
static inline void
dp_tx_hw_desc_update_evt(uint8_t *hal_tx_desc_cached,
hal_ring_handle_t hal_ring_hdl,
struct dp_soc *soc)
{
}
#endif
/**
* dp_tx_hw_enqueue() - Enqueue to TCL HW for transmit
* @soc: DP Soc Handle
* @vdev: DP vdev handle
* @tx_desc: Tx Descriptor Handle
* @tid: TID from HLOS for overriding default DSCP-TID mapping
* @fw_metadata: Metadata to send to Target Firmware along with frame
* @ring_id: Ring ID of H/W ring to which we enqueue the packet
* @tx_exc_metadata: Handle that holds exception path meta data
*
* Gets the next free TCL HW DMA descriptor and sets up required parameters
* from software Tx descriptor
*
* Return: QDF_STATUS_SUCCESS: success
* QDF_STATUS_E_RESOURCES: Error return
*/
static QDF_STATUS
dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc, uint16_t fw_metadata,
struct cdp_tx_exception_metadata *tx_exc_metadata,
struct dp_tx_msdu_info_s *msdu_info)
{
void *hal_tx_desc;
uint32_t *hal_tx_desc_cached;
int coalesce = 0;
struct dp_tx_queue *tx_q = &msdu_info->tx_queue;
uint8_t ring_id = tx_q->ring_id & DP_TX_QUEUE_MASK;
uint8_t tid = msdu_info->tid;
/*
* Setting it initialization statically here to avoid
* a memset call jump with qdf_mem_set call
*/
uint8_t cached_desc[HAL_TX_DESC_LEN_BYTES] = { 0 };
enum cdp_sec_type sec_type = ((tx_exc_metadata &&
tx_exc_metadata->sec_type != CDP_INVALID_SEC_TYPE) ?
tx_exc_metadata->sec_type : vdev->sec_type);
/* Return Buffer Manager ID */
uint8_t bm_id = dp_tx_get_rbm_id(soc, ring_id);
hal_ring_handle_t hal_ring_hdl = NULL;
QDF_STATUS status = QDF_STATUS_E_RESOURCES;
if (!dp_tx_is_desc_id_valid(soc, tx_desc->id)) {
dp_err_rl("Invalid tx desc id:%d", tx_desc->id);
return QDF_STATUS_E_RESOURCES;
}
hal_tx_desc_cached = (void *) cached_desc;
hal_tx_desc_set_buf_addr(soc->hal_soc, hal_tx_desc_cached,
tx_desc->dma_addr, bm_id, tx_desc->id,
(tx_desc->flags & DP_TX_DESC_FLAG_FRAG));
hal_tx_desc_set_lmac_id(soc->hal_soc, hal_tx_desc_cached,
vdev->lmac_id);
hal_tx_desc_set_search_type(soc->hal_soc, hal_tx_desc_cached,
vdev->search_type);
hal_tx_desc_set_search_index(soc->hal_soc, hal_tx_desc_cached,
vdev->bss_ast_idx);
hal_tx_desc_set_dscp_tid_table_id(soc->hal_soc, hal_tx_desc_cached,
vdev->dscp_tid_map_id);
hal_tx_desc_set_encrypt_type(hal_tx_desc_cached,
sec_type_map[sec_type]);
hal_tx_desc_set_cache_set_num(soc->hal_soc, hal_tx_desc_cached,
(vdev->bss_ast_hash & 0xF));
hal_tx_desc_set_fw_metadata(hal_tx_desc_cached, fw_metadata);
hal_tx_desc_set_buf_length(hal_tx_desc_cached, tx_desc->length);
hal_tx_desc_set_buf_offset(hal_tx_desc_cached, tx_desc->pkt_offset);
hal_tx_desc_set_encap_type(hal_tx_desc_cached, tx_desc->tx_encap_type);
hal_tx_desc_set_addr_search_flags(hal_tx_desc_cached,
vdev->hal_desc_addr_search_flags);
if (tx_desc->flags & DP_TX_DESC_FLAG_TO_FW)
hal_tx_desc_set_to_fw(hal_tx_desc_cached, 1);
/* verify checksum offload configuration*/
if (vdev->csum_enabled &&
((qdf_nbuf_get_tx_cksum(tx_desc->nbuf) == QDF_NBUF_TX_CKSUM_TCP_UDP)
|| qdf_nbuf_is_tso(tx_desc->nbuf))) {
hal_tx_desc_set_l3_checksum_en(hal_tx_desc_cached, 1);
hal_tx_desc_set_l4_checksum_en(hal_tx_desc_cached, 1);
}
if (tid != HTT_TX_EXT_TID_INVALID)
hal_tx_desc_set_hlos_tid(hal_tx_desc_cached, tid);
if (tx_desc->flags & DP_TX_DESC_FLAG_MESH)
hal_tx_desc_set_mesh_en(soc->hal_soc, hal_tx_desc_cached, 1);
if (qdf_unlikely(vdev->pdev->delay_stats_flag) ||
qdf_unlikely(wlan_cfg_is_peer_ext_stats_enabled(
soc->wlan_cfg_ctx)))
tx_desc->timestamp = qdf_ktime_to_ms(qdf_ktime_real_get());
dp_verbose_debug("length:%d , type = %d, dma_addr %llx, offset %d desc id %u",
tx_desc->length,
(tx_desc->flags & DP_TX_DESC_FLAG_FRAG),
(uint64_t)tx_desc->dma_addr, tx_desc->pkt_offset,
tx_desc->id);
hal_ring_hdl = dp_tx_get_hal_ring_hdl(soc, ring_id);
if (qdf_unlikely(dp_tx_hal_ring_access_start(soc, hal_ring_hdl))) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s %d : HAL RING Access Failed -- %pK",
__func__, __LINE__, hal_ring_hdl);
DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1);
return status;
}
/* Sync cached descriptor with HW */
hal_tx_desc = hal_srng_src_get_next(soc->hal_soc, hal_ring_hdl);
if (qdf_unlikely(!hal_tx_desc)) {
dp_verbose_debug("TCL ring full ring_id:%d", ring_id);
DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1);
goto ring_access_fail;
}
tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX;
dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf);
hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc);
coalesce = dp_tx_attempt_coalescing(soc, vdev, tx_desc, tid);
DP_STATS_INC_PKT(vdev, tx_i.processed, 1, tx_desc->length);
dp_tx_update_stats(soc, tx_desc->nbuf);
status = QDF_STATUS_SUCCESS;
dp_tx_hw_desc_update_evt((uint8_t *)hal_tx_desc_cached,
hal_ring_hdl, soc);
ring_access_fail:
dp_tx_ring_access_end_wrapper(soc, hal_ring_hdl, coalesce);
return status;
}
/** /**
* dp_cce_classify() - Classify the frame based on CCE rules * dp_cce_classify() - Classify the frame based on CCE rules
* @vdev: DP vdev handle * @vdev: DP vdev handle
@@ -2244,7 +2008,8 @@ dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
dp_tx_desc_history_add(soc, tx_desc->dma_addr, nbuf, dp_tx_desc_history_add(soc, tx_desc->dma_addr, nbuf,
tx_desc->id, DP_TX_DESC_MAP); tx_desc->id, DP_TX_DESC_MAP);
/* Enqueue the Tx MSDU descriptor to HW for transmit */ /* Enqueue the Tx MSDU descriptor to HW for transmit */
status = dp_tx_hw_enqueue(soc, vdev, tx_desc, htt_tcl_metadata, status = soc->arch_ops.tx_hw_enqueue(soc, vdev, tx_desc,
htt_tcl_metadata,
tx_exc_metadata, msdu_info); tx_exc_metadata, msdu_info);
if (status != QDF_STATUS_SUCCESS) { if (status != QDF_STATUS_SUCCESS) {
@@ -2474,7 +2239,8 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
/* /*
* Enqueue the Tx MSDU descriptor to HW for transmit * Enqueue the Tx MSDU descriptor to HW for transmit
*/ */
status = dp_tx_hw_enqueue(soc, vdev, tx_desc, htt_tcl_metadata, status = soc->arch_ops.tx_hw_enqueue(soc, vdev, tx_desc,
htt_tcl_metadata,
NULL, msdu_info); NULL, msdu_info);
if (status != QDF_STATUS_SUCCESS) { if (status != QDF_STATUS_SUCCESS) {
@@ -4626,8 +4392,6 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc,
{ {
void *tx_comp_hal_desc; void *tx_comp_hal_desc;
uint8_t buffer_src; uint8_t buffer_src;
uint8_t pool_id;
uint32_t tx_desc_id;
struct dp_tx_desc_s *tx_desc = NULL; struct dp_tx_desc_s *tx_desc = NULL;
struct dp_tx_desc_s *head_desc = NULL; struct dp_tx_desc_s *head_desc = NULL;
struct dp_tx_desc_s *tail_desc = NULL; struct dp_tx_desc_s *tail_desc = NULL;
@@ -4662,8 +4426,8 @@ more_data:
tx_comp_hal_desc = dp_srng_dst_get_next(soc, hal_ring_hdl); tx_comp_hal_desc = dp_srng_dst_get_next(soc, hal_ring_hdl);
if (qdf_unlikely(!tx_comp_hal_desc)) if (qdf_unlikely(!tx_comp_hal_desc))
break; break;
buffer_src = hal_tx_comp_get_buffer_source(soc->hal_soc,
buffer_src = hal_tx_comp_get_buffer_source(tx_comp_hal_desc); tx_comp_hal_desc);
/* If this buffer was not released by TQM or FW, then it is not /* If this buffer was not released by TQM or FW, then it is not
* Tx completion indication, assert */ * Tx completion indication, assert */
@@ -4710,18 +4474,15 @@ more_data:
continue; continue;
} }
/* Get descriptor id */ soc->arch_ops.tx_comp_get_params_from_hal_desc(soc,
tx_desc_id = hal_tx_comp_get_desc_id(tx_comp_hal_desc); tx_comp_hal_desc,
pool_id = (tx_desc_id & DP_TX_DESC_ID_POOL_MASK) >> &tx_desc);
DP_TX_DESC_ID_POOL_OS; if (!tx_desc) {
dp_err("unable to retrieve tx_desc!");
/* Find Tx descriptor */ QDF_BUG(0);
tx_desc = dp_tx_desc_find(soc, pool_id, continue;
(tx_desc_id & DP_TX_DESC_ID_PAGE_MASK) >> }
DP_TX_DESC_ID_PAGE_OS, tx_desc->buffer_src = buffer_src;
(tx_desc_id & DP_TX_DESC_ID_OFFSET_MASK) >>
DP_TX_DESC_ID_OFFSET_OS);
/* /*
* If the release source is FW, process the HTT status * If the release source is FW, process the HTT status
*/ */
@@ -4737,6 +4498,7 @@ more_data:
hal_tx_comp_get_peer_id(tx_comp_hal_desc); hal_tx_comp_get_peer_id(tx_comp_hal_desc);
tx_desc->tx_status = tx_desc->tx_status =
hal_tx_comp_get_tx_status(tx_comp_hal_desc); hal_tx_comp_get_tx_status(tx_comp_hal_desc);
tx_desc->buffer_src = buffer_src;
/* /*
* If the fast completion mode is enabled extended * If the fast completion mode is enabled extended
* metadata from descriptor is not copied * metadata from descriptor is not copied
@@ -4753,31 +4515,23 @@ more_data:
((tx_desc->vdev_id == DP_INVALID_VDEV_ID) && ((tx_desc->vdev_id == DP_INVALID_VDEV_ID) &&
!tx_desc->flags)) { !tx_desc->flags)) {
dp_tx_comp_info_rl("Descriptor freed in vdev_detach %d", dp_tx_comp_info_rl("Descriptor freed in vdev_detach %d",
tx_desc_id); tx_desc->id);
continue; continue;
} }
if (qdf_unlikely(tx_desc->pdev->is_pdev_down)) { if (qdf_unlikely(tx_desc->pdev->is_pdev_down)) {
dp_tx_comp_info_rl("pdev in down state %d", dp_tx_comp_info_rl("pdev in down state %d",
tx_desc_id); tx_desc->id);
tx_desc->flags |= DP_TX_DESC_FLAG_TX_COMP_ERR; tx_desc->flags |= DP_TX_DESC_FLAG_TX_COMP_ERR;
dp_tx_comp_free_buf(soc, tx_desc); dp_tx_comp_free_buf(soc, tx_desc);
dp_tx_desc_release(tx_desc, tx_desc->pool_id); dp_tx_desc_release(tx_desc, tx_desc->pool_id);
goto next_desc; goto next_desc;
} }
/* Pool id is not matching. Error */
if (tx_desc->pool_id != pool_id) {
dp_tx_comp_alert("Tx Comp pool id %d not matched %d",
pool_id, tx_desc->pool_id);
qdf_assert_always(0);
}
if (!(tx_desc->flags & DP_TX_DESC_FLAG_ALLOCATED) || if (!(tx_desc->flags & DP_TX_DESC_FLAG_ALLOCATED) ||
!(tx_desc->flags & DP_TX_DESC_FLAG_QUEUED_TX)) { !(tx_desc->flags & DP_TX_DESC_FLAG_QUEUED_TX)) {
dp_tx_comp_alert("Txdesc invalid, flgs = %x,id = %d", dp_tx_comp_alert("Txdesc invalid, flgs = %x,id = %d",
tx_desc->flags, tx_desc_id); tx_desc->flags, tx_desc->id);
qdf_assert_always(0); qdf_assert_always(0);
} }
@@ -5502,3 +5256,4 @@ QDF_STATUS dp_tso_soc_detach(struct cdp_soc_t *txrx_soc)
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }

View File

@@ -25,6 +25,7 @@
#include "if_meta_hdr.h" #include "if_meta_hdr.h"
#endif #endif
#include "dp_internal.h" #include "dp_internal.h"
#include "hal_tx.h"
#define DP_INVALID_VDEV_ID 0xFF #define DP_INVALID_VDEV_ID 0xFF
@@ -457,11 +458,11 @@ static inline hal_ring_handle_t dp_tx_get_hal_ring_hdl(struct dp_soc *soc,
* *
* Return - HAL ring handle * Return - HAL ring handle
*/ */
static inline uint8_t dp_tx_get_rbm_id(struct dp_soc *doc, static inline uint8_t dp_tx_get_rbm_id(struct dp_soc *soc,
uint8_t ring_id) uint8_t ring_id)
{ {
return (ring_id ? HAL_WBM_SW0_BM_ID + (ring_id - 1) : return (ring_id ? soc->wbm_sw0_bm_id + (ring_id - 1) :
HAL_WBM_SW2_BM_ID); HAL_WBM_SW2_BM_ID(soc->wbm_sw0_bm_id));
} }
#else /* QCA_OL_TX_MULTIQ_SUPPORT */ #else /* QCA_OL_TX_MULTIQ_SUPPORT */
@@ -485,7 +486,7 @@ static inline hal_ring_handle_t dp_tx_get_hal_ring_hdl(struct dp_soc *soc,
static inline uint8_t dp_tx_get_rbm_id(struct dp_soc *soc, static inline uint8_t dp_tx_get_rbm_id(struct dp_soc *soc,
uint8_t ring_id) uint8_t ring_id)
{ {
return (ring_id + HAL_WBM_SW0_BM_ID); return (ring_id + soc->wbm_sw0_bm_id);
} }
#endif #endif
@@ -676,4 +677,113 @@ dp_send_completion_to_pkt_capture(struct dp_soc *soc,
{ {
} }
#endif #endif
#ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR
/**
* dp_tx_update_stats() - Update soc level tx stats
* @soc: DP soc handle
* @nbuf: packet being transmitted
*
* Returns: none
*/
void dp_tx_update_stats(struct dp_soc *soc,
qdf_nbuf_t nbuf);
/**
* dp_tx_attempt_coalescing() - Check and attempt TCL register write coalescing
* @soc: Datapath soc handle
* @tx_desc: tx packet descriptor
* @tid: TID for pkt transmission
*
* Returns: 1, if coalescing is to be done
* 0, if coalescing is not to be done
*/
int
dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc,
uint8_t tid);
/**
* dp_tx_ring_access_end() - HAL ring access end for data transmission
* @soc: Datapath soc handle
* @hal_ring_hdl: HAL ring handle
* @coalesce: Coalesce the current write or not
*
* Returns: none
*/
void
dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl,
int coalesce);
#else
/**
* dp_tx_update_stats() - Update soc level tx stats
* @soc: DP soc handle
* @nbuf: packet being transmitted
*
* Returns: none
*/
static inline void dp_tx_update_stats(struct dp_soc *soc,
qdf_nbuf_t nbuf) { }
static inline void
dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl,
int coalesce)
{
dp_tx_hal_ring_access_end(soc, hal_ring_hdl);
}
static inline int
dp_tx_attempt_coalescing(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc,
uint8_t tid)
{
return 0;
}
#endif /* WLAN_DP_FEATURE_SW_LATENCY_MGR */
#ifdef FEATURE_RUNTIME_PM
void
dp_tx_ring_access_end_wrapper(struct dp_soc *soc,
hal_ring_handle_t hal_ring_hdl,
int coalesce);
#else
static inline void
dp_tx_ring_access_end_wrapper(struct dp_soc *soc,
hal_ring_handle_t hal_ring_hdl,
int coalesce)
{
dp_tx_ring_access_end(soc, hal_ring_hdl, coalesce);
}
#endif
#ifdef DP_TX_HW_DESC_HISTORY
static inline void
dp_tx_hw_desc_update_evt(uint8_t *hal_tx_desc_cached,
hal_ring_handle_t hal_ring_hdl,
struct dp_soc *soc)
{
struct dp_tx_hw_desc_evt *evt;
uint64_t idx = 0;
if (!soc->tx_hw_desc_history)
return;
idx = ++soc->tx_hw_desc_history->index;
if (idx == DP_TX_HW_DESC_HIST_MAX)
soc->tx_hw_desc_history->index = 0;
idx = qdf_do_div_rem(idx, DP_TX_HW_DESC_HIST_MAX);
evt = &soc->tx_hw_desc_history->entry[idx];
qdf_mem_copy(evt->tcl_desc, hal_tx_desc_cached, HAL_TX_DESC_LEN_BYTES);
evt->posted = qdf_get_log_timestamp();
hal_get_sw_hptp(soc->hal_soc, hal_ring_hdl, &evt->tp, &evt->hp);
}
#else
static inline void
dp_tx_hw_desc_update_evt(uint8_t *hal_tx_desc_cached,
hal_ring_handle_t hal_ring_hdl,
struct dp_soc *soc)
{
}
#endif
#endif #endif

View File

@@ -57,6 +57,7 @@
#ifdef WLAN_TX_PKT_CAPTURE_ENH #ifdef WLAN_TX_PKT_CAPTURE_ENH
#include "dp_tx_capture.h" #include "dp_tx_capture.h"
#endif #endif
//#include "dp_tx.h"
#define REPT_MU_MIMO 1 #define REPT_MU_MIMO 1
#define REPT_MU_OFDMA_MIMO 3 #define REPT_MU_OFDMA_MIMO 3
@@ -505,6 +506,7 @@ struct dp_tx_ext_desc_pool_s {
* This is maintained in descriptor to allow more efficient * This is maintained in descriptor to allow more efficient
* processing in completion event processing code. * processing in completion event processing code.
* This field is filled in with the htt_pkt_type enum. * This field is filled in with the htt_pkt_type enum.
* @buffer_src: buffer source TQM, REO, FW etc.
* @frm_type: Frame Type - ToDo check if this is redundant * @frm_type: Frame Type - ToDo check if this is redundant
* @pkt_offset: Offset from which the actual packet data starts * @pkt_offset: Offset from which the actual packet data starts
* @me_buffer: Pointer to ME buffer - store this so that it can be freed on * @me_buffer: Pointer to ME buffer - store this so that it can be freed on
@@ -522,7 +524,9 @@ struct dp_tx_desc_s {
uint8_t tx_status; uint8_t tx_status;
uint16_t peer_id; uint16_t peer_id;
struct dp_pdev *pdev; struct dp_pdev *pdev;
uint8_t tx_encap_type; uint8_t tx_encap_type:2,
buffer_src:3,
reserved:3;
uint8_t frm_type; uint8_t frm_type;
uint8_t pkt_offset; uint8_t pkt_offset;
uint8_t pool_id; uint8_t pool_id;
@@ -1491,6 +1495,64 @@ struct ipa_dp_tx_rsc {
}; };
#endif #endif
struct dp_tx_msdu_info_s;
/*
* enum dp_context_type- DP Context Type
* @DP_CONTEXT_TYPE_SOC: Context type DP SOC
* @DP_CONTEXT_TYPE_PDEV: Context type DP PDEV
* @DP_CONTEXT_TYPE_VDEV: Context type DP VDEV
* @DP_CONTEXT_TYPE_PEER: Context type DP PEER
*
* Helper enums to be used to retrieve the size of the corresponding
* data structure by passing the type.
*/
enum dp_context_type {
DP_CONTEXT_TYPE_SOC,
DP_CONTEXT_TYPE_PDEV,
DP_CONTEXT_TYPE_VDEV,
DP_CONTEXT_TYPE_PEER
};
/*
* struct dp_arch_ops- DP target specific arch ops
* @DP_CONTEXT_TYPE_SOC: Context type DP SOC
* @DP_CONTEXT_TYPE_PDEV: Context type DP PDEV
* @tx_hw_enqueue: enqueue TX data to HW
* @tx_comp_get_params_from_hal_desc: get software tx descriptor and release
* source from HAL desc for wbm release ring
* @txrx_set_vdev_param: target specific ops while setting vdev params
*/
struct dp_arch_ops {
/* INIT/DEINIT Arch Ops */
QDF_STATUS (*txrx_soc_attach)(struct dp_soc *soc);
QDF_STATUS (*txrx_soc_detach)(struct dp_soc *soc);
QDF_STATUS (*txrx_pdev_attach)(struct dp_pdev *pdev);
QDF_STATUS (*txrx_pdev_detach)(struct dp_pdev *pdev);
QDF_STATUS (*txrx_vdev_attach)(struct dp_soc *soc,
struct dp_vdev *vdev);
QDF_STATUS (*txrx_vdev_detach)(struct dp_soc *soc,
struct dp_vdev *vdev);
/* TX RX Arch Ops */
QDF_STATUS (*tx_hw_enqueue)(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc,
uint16_t fw_metadata,
struct cdp_tx_exception_metadata *metadata,
struct dp_tx_msdu_info_s *msdu_info);
void (*tx_comp_get_params_from_hal_desc)(struct dp_soc *soc,
void *tx_comp_hal_desc,
struct dp_tx_desc_s **desc);
/* Control Arch Ops */
QDF_STATUS (*txrx_set_vdev_param)(struct dp_soc *soc,
struct dp_vdev *vdev,
enum cdp_vdev_param_type param,
cdp_config_param_type val);
/* Misc Arch Ops */
qdf_size_t (*txrx_get_context_size)(enum dp_context_type);
};
/* SOC level structure for data path */ /* SOC level structure for data path */
struct dp_soc { struct dp_soc {
/** /**
@@ -1506,6 +1568,8 @@ struct dp_soc {
/* OS device abstraction */ /* OS device abstraction */
qdf_device_t osdev; qdf_device_t osdev;
struct dp_arch_ops arch_ops;
/*cce disable*/ /*cce disable*/
bool cce_disable; bool cce_disable;
@@ -1939,6 +2003,8 @@ struct dp_soc {
qdf_spinlock_t reo_desc_deferred_freelist_lock; qdf_spinlock_t reo_desc_deferred_freelist_lock;
bool reo_desc_deferred_freelist_init; bool reo_desc_deferred_freelist_init;
#endif #endif
/* BM id for first WBM2SW ring */
uint32_t wbm_sw0_bm_id;
}; };
#ifdef IPA_OFFLOAD #ifdef IPA_OFFLOAD
@@ -3358,6 +3424,8 @@ struct dp_req_rx_hw_stats_t {
bool is_query_timeout; bool is_query_timeout;
}; };
#endif #endif
/* soc level structure to declare arch specific ops for DP */
void dp_hw_link_desc_pool_banks_free(struct dp_soc *soc, uint32_t mac_id); void dp_hw_link_desc_pool_banks_free(struct dp_soc *soc, uint32_t mac_id);
QDF_STATUS dp_hw_link_desc_pool_banks_alloc(struct dp_soc *soc, QDF_STATUS dp_hw_link_desc_pool_banks_alloc(struct dp_soc *soc,

90
dp/wifi3.0/li/dp_li.c Normal file
View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2021 The Linux Foundation. All rights reserved.
*
* 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 "dp_types.h"
#include "dp_li.h"
#include "dp_li_tx.h"
#include "dp_li_rx.h"
qdf_size_t dp_get_context_size_li(enum dp_context_type context_type)
{
switch (context_type) {
case DP_CONTEXT_TYPE_SOC:
return sizeof(struct dp_soc_li);
case DP_CONTEXT_TYPE_PDEV:
return sizeof(struct dp_pdev_li);
case DP_CONTEXT_TYPE_VDEV:
return sizeof(struct dp_vdev_li);
case DP_CONTEXT_TYPE_PEER:
return sizeof(struct dp_peer_li);
default:
return 0;
}
}
static QDF_STATUS dp_soc_attach_li(struct dp_soc *soc)
{
soc->wbm_sw0_bm_id = hal_tx_get_wbm_sw0_bm_id();
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_soc_detach_li(struct dp_soc *soc)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_pdev_attach_li(struct dp_pdev *pdev)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_pdev_detach_li(struct dp_pdev *pdev)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_vdev_attach_li(struct dp_soc *soc, struct dp_vdev *vdev)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_vdev_detach_li(struct dp_soc *soc, struct dp_vdev *vdev)
{
return QDF_STATUS_SUCCESS;
}
qdf_size_t dp_get_soc_context_size_li(void)
{
return sizeof(struct dp_soc);
}
void dp_initialize_arch_ops_li(struct dp_arch_ops *arch_ops)
{
arch_ops->tx_hw_enqueue = dp_tx_hw_enqueue_li;
arch_ops->txrx_get_context_size = dp_get_context_size_li;
arch_ops->txrx_soc_attach = dp_soc_attach_li;
arch_ops->txrx_soc_detach = dp_soc_detach_li;
arch_ops->txrx_pdev_attach = dp_pdev_attach_li;
arch_ops->txrx_pdev_detach = dp_pdev_detach_li;
arch_ops->txrx_vdev_attach = dp_vdev_attach_li;
arch_ops->txrx_vdev_detach = dp_vdev_detach_li;
arch_ops->tx_comp_get_params_from_hal_desc =
dp_tx_comp_get_params_from_hal_desc_li;
arch_ops->dp_rx_process = dp_rx_process_li;
}

81
dp/wifi3.0/li/dp_li.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2021 The Linux Foundation. All rights reserved.
*
* 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.
*/
#ifndef __DP_LI_H
#define __DP_LI_H
#include <dp_types.h>
#include <hal_li_tx.h>
/**
* struct dp_soc_li - Extended DP soc for LI targets
* @soc: dp soc structure
*/
struct dp_soc_li {
struct dp_soc soc;
};
/**
* struct dp_pdev_li - Extended DP pdev for LI targets
* @pdev: dp_pdev structure
*/
struct dp_pdev_li {
struct dp_pdev pdev;
};
/**
* struct dp_vdev_li - Extended DP vdev for LI targets
* @vdev: dp_vdev structure
*/
struct dp_vdev_li {
struct dp_vdev vdev;
};
/**
* struct dp_peer_li - Extended DP peer for LI targets
* @peer: dp_peer structure
*/
struct dp_peer_li {
struct dp_peer peer;
};
/**
* dp_get_soc_context_size_LI() - get context size for dp_soc_li
*
* Return: value in bytes for LI specific soc structure
*/
qdf_size_t dp_get_soc_context_size_li(void);
/**
* dp_initialize_arch_ops_li() - initialize LI specific arch ops
* @arch_ops: arch ops pointer
*
* Return: none
*/
void dp_initialize_arch_ops_li(struct dp_arch_ops *arch_ops);
/**
* dp_get_context_size_li() - get LI specific size for peer/vdev/pdev/soc
* @arch_ops: arch ops pointer
*
* Return: size in bytes for the context_type
*/
qdf_size_t dp_get_context_size_li(enum dp_context_type context_type);
#endif

192
dp/wifi3.0/li/dp_li_tx.c Normal file
View File

@@ -0,0 +1,192 @@
/*
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
*
* 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 "cdp_txrx_cmn_struct.h"
#include "dp_types.h"
#include "dp_tx.h"
#include "dp_li_tx.h"
#include "dp_tx_desc.h"
#include <hal_li_api.h>
#include <hal_li_tx.h>
/*mapping between hal encrypt type and cdp_sec_type*/
#define MAX_CDP_SEC_TYPE 12
uint8_t sec_type_map[MAX_CDP_SEC_TYPE] = {HAL_TX_ENCRYPT_TYPE_NO_CIPHER,
HAL_TX_ENCRYPT_TYPE_WEP_128,
HAL_TX_ENCRYPT_TYPE_WEP_104,
HAL_TX_ENCRYPT_TYPE_WEP_40,
HAL_TX_ENCRYPT_TYPE_TKIP_WITH_MIC,
HAL_TX_ENCRYPT_TYPE_TKIP_NO_MIC,
HAL_TX_ENCRYPT_TYPE_AES_CCMP_128,
HAL_TX_ENCRYPT_TYPE_WAPI,
HAL_TX_ENCRYPT_TYPE_AES_CCMP_256,
HAL_TX_ENCRYPT_TYPE_AES_GCMP_128,
HAL_TX_ENCRYPT_TYPE_AES_GCMP_256,
HAL_TX_ENCRYPT_TYPE_WAPI_GCM_SM4};
void dp_tx_comp_get_params_from_hal_desc_li(struct dp_soc *soc,
void *tx_comp_hal_desc,
struct dp_tx_desc_s **r_tx_desc)
{
uint8_t pool_id;
uint32_t tx_desc_id;
tx_desc_id = hal_tx_comp_get_desc_id(tx_comp_hal_desc);
pool_id = (tx_desc_id & DP_TX_DESC_ID_POOL_MASK) >>
DP_TX_DESC_ID_POOL_OS;
/* Find Tx descriptor */
*r_tx_desc = dp_tx_desc_find(soc, pool_id,
(tx_desc_id & DP_TX_DESC_ID_PAGE_MASK) >>
DP_TX_DESC_ID_PAGE_OS,
(tx_desc_id & DP_TX_DESC_ID_OFFSET_MASK) >>
DP_TX_DESC_ID_OFFSET_OS);
/* Pool id is not matching. Error */
if ((*r_tx_desc)->pool_id != pool_id) {
dp_tx_comp_alert("Tx Comp pool id %d not matched %d",
pool_id, (*r_tx_desc)->pool_id);
qdf_assert_always(0);
}
}
QDF_STATUS
dp_tx_hw_enqueue_li(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc, uint16_t fw_metadata,
struct cdp_tx_exception_metadata *tx_exc_metadata,
struct dp_tx_msdu_info_s *msdu_info)
{
void *hal_tx_desc;
uint32_t *hal_tx_desc_cached;
int coalesce = 0;
struct dp_tx_queue *tx_q = &msdu_info->tx_queue;
uint8_t ring_id = tx_q->ring_id & DP_TX_QUEUE_MASK;
uint8_t tid = msdu_info->tid;
/*
* Setting it initialization statically here to avoid
* a memset call jump with qdf_mem_set call
*/
uint8_t cached_desc[HAL_TX_DESC_LEN_BYTES] = { 0 };
enum cdp_sec_type sec_type = ((tx_exc_metadata &&
tx_exc_metadata->sec_type != CDP_INVALID_SEC_TYPE) ?
tx_exc_metadata->sec_type : vdev->sec_type);
/* Return Buffer Manager ID */
uint8_t bm_id = dp_tx_get_rbm_id(soc, ring_id);
hal_ring_handle_t hal_ring_hdl = NULL;
QDF_STATUS status = QDF_STATUS_E_RESOURCES;
if (!dp_tx_is_desc_id_valid(soc, tx_desc->id)) {
dp_err_rl("Invalid tx desc id:%d", tx_desc->id);
return QDF_STATUS_E_RESOURCES;
}
hal_tx_desc_cached = (void *)cached_desc;
hal_tx_desc_set_buf_addr(soc->hal_soc, hal_tx_desc_cached,
tx_desc->dma_addr, bm_id, tx_desc->id,
(tx_desc->flags & DP_TX_DESC_FLAG_FRAG));
hal_tx_desc_set_lmac_id(soc->hal_soc, hal_tx_desc_cached,
vdev->lmac_id);
hal_tx_desc_set_search_type(soc->hal_soc, hal_tx_desc_cached,
vdev->search_type);
hal_tx_desc_set_search_index(soc->hal_soc, hal_tx_desc_cached,
vdev->bss_ast_idx);
hal_tx_desc_set_dscp_tid_table_id(soc->hal_soc, hal_tx_desc_cached,
vdev->dscp_tid_map_id);
hal_tx_desc_set_encrypt_type(hal_tx_desc_cached,
sec_type_map[sec_type]);
hal_tx_desc_set_cache_set_num(soc->hal_soc, hal_tx_desc_cached,
(vdev->bss_ast_hash & 0xF));
hal_tx_desc_set_fw_metadata(hal_tx_desc_cached, fw_metadata);
hal_tx_desc_set_buf_length(hal_tx_desc_cached, tx_desc->length);
hal_tx_desc_set_buf_offset(hal_tx_desc_cached, tx_desc->pkt_offset);
hal_tx_desc_set_encap_type(hal_tx_desc_cached, tx_desc->tx_encap_type);
hal_tx_desc_set_addr_search_flags(hal_tx_desc_cached,
vdev->hal_desc_addr_search_flags);
if (tx_desc->flags & DP_TX_DESC_FLAG_TO_FW)
hal_tx_desc_set_to_fw(hal_tx_desc_cached, 1);
/* verify checksum offload configuration*/
if (vdev->csum_enabled &&
((qdf_nbuf_get_tx_cksum(tx_desc->nbuf) ==
QDF_NBUF_TX_CKSUM_TCP_UDP) ||
qdf_nbuf_is_tso(tx_desc->nbuf))) {
hal_tx_desc_set_l3_checksum_en(hal_tx_desc_cached, 1);
hal_tx_desc_set_l4_checksum_en(hal_tx_desc_cached, 1);
}
if (tid != HTT_TX_EXT_TID_INVALID)
hal_tx_desc_set_hlos_tid(hal_tx_desc_cached, tid);
if (tx_desc->flags & DP_TX_DESC_FLAG_MESH)
hal_tx_desc_set_mesh_en(soc->hal_soc, hal_tx_desc_cached, 1);
if (qdf_unlikely(vdev->pdev->delay_stats_flag) ||
qdf_unlikely(wlan_cfg_is_peer_ext_stats_enabled(soc->wlan_cfg_ctx)))
tx_desc->timestamp = qdf_ktime_to_ms(qdf_ktime_real_get());
dp_verbose_debug("length:%d , type = %d, dma_addr %llx, offset %d desc id %u",
tx_desc->length,
(tx_desc->flags & DP_TX_DESC_FLAG_FRAG),
(uint64_t)tx_desc->dma_addr, tx_desc->pkt_offset,
tx_desc->id);
hal_ring_hdl = dp_tx_get_hal_ring_hdl(soc, ring_id);
if (qdf_unlikely(dp_tx_hal_ring_access_start(soc, hal_ring_hdl))) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s %d : HAL RING Access Failed -- %pK",
__func__, __LINE__, hal_ring_hdl);
DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1);
return status;
}
/* Sync cached descriptor with HW */
hal_tx_desc = hal_srng_src_get_next(soc->hal_soc, hal_ring_hdl);
if (qdf_unlikely(!hal_tx_desc)) {
dp_verbose_debug("TCL ring full ring_id:%d", ring_id);
DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1);
goto ring_access_fail;
}
tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX;
dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf);
hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc);
coalesce = dp_tx_attempt_coalescing(soc, vdev, tx_desc, tid);
DP_STATS_INC_PKT(vdev, tx_i.processed, 1, tx_desc->length);
dp_tx_update_stats(soc, tx_desc->nbuf);
status = QDF_STATUS_SUCCESS;
dp_tx_hw_desc_update_evt((uint8_t *)hal_tx_desc_cached,
hal_ring_hdl, soc);
ring_access_fail:
dp_tx_ring_access_end_wrapper(soc, hal_ring_hdl, coalesce);
return status;
}

55
dp/wifi3.0/li/dp_li_tx.h Normal file
View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
*
* 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.
*/
#ifndef __DP_LI_TX_H
#define __DP_LI_TX_H
#include <dp_types.h>
/**
* dp_tx_hw_enqueue_li() - Enqueue to TCL HW for transmit
* @soc: DP Soc Handle
* @vdev: DP vdev handle
* @tx_desc: Tx Descriptor Handle
* @tid: TID from HLOS for overriding default DSCP-TID mapping
* @fw_metadata: Metadata to send to Target Firmware along with frame
* @ring_id: Ring ID of H/W ring to which we enqueue the packet
* @tx_exc_metadata: Handle that holds exception path meta data
*
* Gets the next free TCL HW DMA descriptor and sets up required parameters
* from software Tx descriptor
*
* Return: QDF_STATUS_SUCCESS: success
* QDF_STATUS_E_RESOURCES: Error return
*/
QDF_STATUS
dp_tx_hw_enqueue_li(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc, uint16_t fw_metadata,
struct cdp_tx_exception_metadata *tx_exc_metadata,
struct dp_tx_msdu_info_s *msdu_info);
/**
* dp_tx_comp_get_params_from_hal_desc_li() - Get TX desc from HAL comp desc
* @soc: DP soc handle
* @tx_comp_hal_desc: HAL TX Comp Descriptor
* @r_tx_desc: SW Tx Descriptor retrieved from HAL desc.
*
* Return: None
*/
void dp_tx_comp_get_params_from_hal_desc_li(struct dp_soc *soc,
void *tx_comp_hal_desc,
struct dp_tx_desc_s **r_tx_desc);
#endif