qcacld-3.0: Enable WLAN host data path support for IPA WDI3.0

Change to support WLAN Napier host autonomy data path architecture.

Change-Id: I80e8f609587d0df85d2da9fb0f41cb49e02a9d2f
CRs-Fixed: 2033368
This commit is contained in:
Yun Park
2017-03-29 15:51:01 -07:00
committed by snandini
parent 20747edb82
commit b4f591d8aa
11 changed files with 1416 additions and 1125 deletions

11
Kbuild
View File

@@ -9,6 +9,7 @@ endif
ifeq ($(CONFIG_CNSS_QCA6290), y) ifeq ($(CONFIG_CNSS_QCA6290), y)
CONFIG_LITHIUM := y CONFIG_LITHIUM := y
CONFIG_WLAN_FEATURE_11AX := y CONFIG_WLAN_FEATURE_11AX := y
CONFIG_IPA := n
endif endif
ifeq ($(CONFIG_CLD_HL_SDIO_CORE), y) ifeq ($(CONFIG_CLD_HL_SDIO_CORE), y)
@@ -1061,6 +1062,10 @@ ifeq ($(CONFIG_WLAN_TX_FLOW_CONTROL_V2), y)
TXRX_OBJS += $(TXRX_DIR)/ol_txrx_flow_control.o TXRX_OBJS += $(TXRX_DIR)/ol_txrx_flow_control.o
endif endif
ifeq ($(CONFIG_IPA_OFFLOAD), 1)
TXRX_OBJS += $(TXRX_DIR)/ol_txrx_ipa.o
endif
ifeq ($(CONFIG_LITHIUM), y) ifeq ($(CONFIG_LITHIUM), y)
############ DP 3.0 ############ ############ DP 3.0 ############
DP_INC := -I$(WLAN_COMMON_ROOT)/dp/inc \ DP_INC := -I$(WLAN_COMMON_ROOT)/dp/inc \
@@ -1085,6 +1090,10 @@ DP_OBJS += $(DP_SRC)/dp_tx_flow_control.o
endif endif
endif endif
ifeq ($(CONFIG_IPA_OFFLOAD), 1)
DP_OBJS += $(DP_SRC)/dp_ipa.o
endif
############ CFG ############ ############ CFG ############
WCFG_DIR := wlan_cfg WCFG_DIR := wlan_cfg
WCFG_INC := -I$(WLAN_COMMON_INC)/$(WCFG_DIR) WCFG_INC := -I$(WLAN_COMMON_INC)/$(WCFG_DIR)
@@ -1998,9 +2007,11 @@ CDEFINES += -DFEATURE_GREEN_AP
endif endif
#Stats & Quota Metering feature #Stats & Quota Metering feature
ifeq ($(CONFIG_IPA),y)
ifeq ($(CONFIG_QCACLD_FEATURE_METERING),y) ifeq ($(CONFIG_QCACLD_FEATURE_METERING),y)
CDEFINES += -DFEATURE_METERING CDEFINES += -DFEATURE_METERING
endif endif
endif
#Enable RX Full re-order OL feature only "LL and NON-MDM9630 platform" #Enable RX Full re-order OL feature only "LL and NON-MDM9630 platform"
ifneq ($(CONFIG_ARCH_MDM9630), y) ifneq ($(CONFIG_ARCH_MDM9630), y)

View File

@@ -151,6 +151,50 @@ static uint8_t *htt_t2h_mac_addr_deswizzle(uint8_t *tgt_mac_addr,
#endif #endif
} }
/**
* htt_ipa_op_response() - invoke an event handler from FW
* @pdev: Handle (pointer) to HTT pdev.
* @msg_word: htt msg
*
* Return: None
*/
#ifdef IPA_OFFLOAD
static void htt_ipa_op_response(struct htt_pdev_t *pdev, uint32_t *msg_word)
{
uint8_t op_code;
uint16_t len;
uint8_t *op_msg_buffer;
uint8_t *msg_start_ptr;
htc_pm_runtime_put(pdev->htc_pdev);
msg_start_ptr = (uint8_t *) msg_word;
op_code =
HTT_WDI_IPA_OP_RESPONSE_OP_CODE_GET(*msg_word);
msg_word++;
len = HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_GET(*msg_word);
op_msg_buffer =
qdf_mem_malloc(sizeof
(struct htt_wdi_ipa_op_response_t) +
len);
if (!op_msg_buffer) {
qdf_print("OPCODE messsage buffer alloc fail");
return;
}
qdf_mem_copy(op_msg_buffer,
msg_start_ptr,
sizeof(struct htt_wdi_ipa_op_response_t) +
len);
cdp_ipa_op_response(cds_get_context(QDF_MODULE_ID_SOC),
(struct cdp_pdev *)pdev->txrx_pdev,
op_msg_buffer);
}
#else
static void htt_ipa_op_response(struct htt_pdev_t *pdev, uint32_t *msg_word)
{
}
#endif
/* Target to host Msg/event handler for low priority messages*/ /* Target to host Msg/event handler for low priority messages*/
static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg, static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg,
bool free_msg_buf) bool free_msg_buf)
@@ -426,33 +470,7 @@ static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg,
case HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE: case HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE:
{ {
uint8_t op_code; htt_ipa_op_response(pdev, msg_word);
uint16_t len;
uint8_t *op_msg_buffer;
uint8_t *msg_start_ptr;
htc_pm_runtime_put(pdev->htc_pdev);
msg_start_ptr = (uint8_t *) msg_word;
op_code =
HTT_WDI_IPA_OP_RESPONSE_OP_CODE_GET(*msg_word);
msg_word++;
len = HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_GET(*msg_word);
op_msg_buffer =
qdf_mem_malloc(sizeof
(struct htt_wdi_ipa_op_response_t) +
len);
if (!op_msg_buffer) {
qdf_print("OPCODE messsage buffer alloc fail");
break;
}
qdf_mem_copy(op_msg_buffer,
msg_start_ptr,
sizeof(struct htt_wdi_ipa_op_response_t) +
len);
cdp_ipa_op_response(cds_get_context(QDF_MODULE_ID_SOC),
(struct cdp_pdev *)pdev->txrx_pdev,
op_msg_buffer);
break; break;
} }

View File

@@ -572,7 +572,7 @@ unsigned int ol_cfg_ipa_uc_rx_ind_ring_size(struct cdp_cfg *cfg_pdev);
*/ */
unsigned int ol_cfg_ipa_uc_tx_partition_base(struct cdp_cfg *cfg_pdev); unsigned int ol_cfg_ipa_uc_tx_partition_base(struct cdp_cfg *cfg_pdev);
void ol_cfg_set_ipa_uc_tx_partition_base(struct cdp_cfg *cfg_pdev, void ol_cfg_set_ipa_uc_tx_partition_base(struct cdp_cfg *cfg_pdev,
uint32_t value); uint32_t value);
#else #else
static inline unsigned int ol_cfg_ipa_uc_offload_enabled( static inline unsigned int ol_cfg_ipa_uc_offload_enabled(
struct cdp_cfg *cfg_pdev) struct cdp_cfg *cfg_pdev)
@@ -605,7 +605,7 @@ static inline unsigned int ol_cfg_ipa_uc_tx_partition_base(
} }
static inline void ol_cfg_set_ipa_uc_tx_partition_base( static inline void ol_cfg_set_ipa_uc_tx_partition_base(
struct cdp_cfg *cfg_pdev, uint32_t value) void *cfg_pdev, uint32_t value)
{ {
} }
#endif /* IPA_OFFLOAD */ #endif /* IPA_OFFLOAD */

View File

@@ -286,8 +286,7 @@ qdf_nbuf_t ol_tx_data(void *data_vdev, qdf_nbuf_t skb)
} }
#ifdef IPA_OFFLOAD #ifdef IPA_OFFLOAD
qdf_nbuf_t ol_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t ol_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t skb)
qdf_nbuf_t skb)
{ {
struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX); struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
qdf_nbuf_t ret; qdf_nbuf_t ret;

View File

@@ -86,6 +86,8 @@
#include <a_types.h> #include <a_types.h>
#include <cdp_txrx_handle.h> #include <cdp_txrx_handle.h>
#include <htt_internal.h> #include <htt_internal.h>
#include <ol_txrx_ipa.h>
#ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID #ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID
ol_txrx_peer_handle ol_txrx_peer_handle
ol_txrx_peer_find_by_local_id(struct cdp_pdev *pdev, ol_txrx_peer_find_by_local_id(struct cdp_pdev *pdev,
@@ -4519,159 +4521,7 @@ ol_txrx_ll_set_tx_pause_q_depth(uint8_t vdev_id, int pause_q_depth)
} }
#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
#ifdef IPA_OFFLOAD
/** /**
* ol_txrx_ipa_uc_get_resource() - Client request resource information
* @pdev: handle to the HTT instance
* @ce_sr_base_paddr: copy engine source ring base physical address
* @ce_sr_ring_size: copy engine source ring size
* @ce_reg_paddr: copy engine register physical address
* @tx_comp_ring_base_paddr: tx comp ring base physical address
* @tx_comp_ring_size: tx comp ring size
* @tx_num_alloc_buffer: number of allocated tx buffer
* @rx_rdy_ring_base_paddr: rx ready ring base physical address
* @rx_rdy_ring_size: rx ready ring size
* @rx_proc_done_idx_paddr: rx process done index physical address
* @rx_proc_done_idx_vaddr: rx process done index virtual address
* @rx2_rdy_ring_base_paddr: rx done ring base physical address
* @rx2_rdy_ring_size: rx done ring size
* @rx2_proc_done_idx_paddr: rx done index physical address
* @rx2_proc_done_idx_vaddr: rx done index virtual address
*
* OL client will reuqest IPA UC related resource information
* Resource information will be distributted to IPA module
* All of the required resources should be pre-allocated
*
* Return: none
*/
static void
ol_txrx_ipa_uc_get_resource(struct cdp_pdev *ppdev,
struct ol_txrx_ipa_resources *ipa_res)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
htt_ipa_uc_get_resource(pdev->htt_pdev,
&ipa_res->ce_sr_base_paddr,
&ipa_res->ce_sr_ring_size,
&ipa_res->ce_reg_paddr,
&ipa_res->tx_comp_ring_base_paddr,
&ipa_res->tx_comp_ring_size,
&ipa_res->tx_num_alloc_buffer,
&ipa_res->rx_rdy_ring_base_paddr,
&ipa_res->rx_rdy_ring_size,
&ipa_res->rx_proc_done_idx_paddr,
&ipa_res->rx_proc_done_idx_vaddr,
&ipa_res->rx2_rdy_ring_base_paddr,
&ipa_res->rx2_rdy_ring_size,
&ipa_res->rx2_proc_done_idx_paddr,
&ipa_res->rx2_proc_done_idx_vaddr);
}
/**
* ol_txrx_ipa_uc_set_doorbell_paddr() - Client set IPA UC doorbell register
* @pdev: handle to the HTT instance
* @ipa_uc_tx_doorbell_paddr: tx comp doorbell physical address
* @ipa_uc_rx_doorbell_paddr: rx ready doorbell physical address
*
* IPA UC let know doorbell register physical address
* WLAN firmware will use this physical address to notify IPA UC
*
* Return: none
*/
static void
ol_txrx_ipa_uc_set_doorbell_paddr(struct cdp_pdev *ppdev,
qdf_dma_addr_t ipa_tx_uc_doorbell_paddr,
qdf_dma_addr_t ipa_rx_uc_doorbell_paddr)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
htt_ipa_uc_set_doorbell_paddr(pdev->htt_pdev,
ipa_tx_uc_doorbell_paddr,
ipa_rx_uc_doorbell_paddr);
}
/**
* ol_txrx_ipa_uc_set_active() - Client notify IPA UC data path active or not
* @pdev: handle to the HTT instance
* @ipa_uc_tx_doorbell_paddr: tx comp doorbell physical address
* @ipa_uc_rx_doorbell_paddr: rx ready doorbell physical address
*
* IPA UC let know doorbell register physical address
* WLAN firmware will use this physical address to notify IPA UC
*
* Return: none
*/
static void
ol_txrx_ipa_uc_set_active(struct cdp_pdev *ppdev, bool uc_active, bool is_tx)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
htt_h2t_ipa_uc_set_active(pdev->htt_pdev, uc_active, is_tx);
}
/**
* ol_txrx_ipa_uc_op_response() - Handle OP command response from firmware
* @pdev: handle to the HTT instance
* @op_msg: op response message from firmware
*
* Return: none
*/
static void ol_txrx_ipa_uc_op_response(struct cdp_pdev *ppdev, uint8_t *op_msg)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
if (pdev->ipa_uc_op_cb) {
pdev->ipa_uc_op_cb(op_msg, pdev->osif_dev);
} else {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: IPA callback function is not registered", __func__);
qdf_mem_free(op_msg);
return;
}
}
/**
* ol_txrx_ipa_uc_register_op_cb() - Register OP handler function
* @pdev: handle to the HTT instance
* @op_cb: handler function pointer
* @osif_dev: register client context
*
* Return: none
*/
static void
ol_txrx_ipa_uc_register_op_cb(struct cdp_pdev *ppdev,
ipa_uc_op_cb_type op_cb, void *osif_dev)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
pdev->ipa_uc_op_cb = op_cb;
pdev->osif_dev = osif_dev;
}
/**
* ol_txrx_ipa_uc_get_stat() - Get firmware wdi status
* @pdev: handle to the HTT instance
*
* Return: none
*/
static void ol_txrx_ipa_uc_get_stat(struct cdp_pdev *ppdev)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
htt_h2t_ipa_uc_get_stats(pdev->htt_pdev);
}
static void ol_txrx_ipa_uc_get_share_stats(struct cdp_pdev *ppdev,
uint8_t reset_stats)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
htt_h2t_ipa_uc_get_share_stats(pdev->htt_pdev, reset_stats);
}
static void ol_txrx_ipa_uc_set_quota(struct cdp_pdev *ppdev,
uint64_t quota_bytes)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
htt_h2t_ipa_uc_set_quota(pdev->htt_pdev, quota_bytes);
}
#endif /* IPA_UC_OFFLOAD */
/*
* ol_txrx_display_stats() - Display OL TXRX display stats * ol_txrx_display_stats() - Display OL TXRX display stats
* @value: Module id for which stats needs to be displayed * @value: Module id for which stats needs to be displayed
* *
@@ -5566,8 +5416,8 @@ static struct cdp_lflowctl_ops ol_ops_l_flowctl = {
#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
}; };
static struct cdp_ipa_ops ol_ops_ipa = {
#ifdef IPA_OFFLOAD #ifdef IPA_OFFLOAD
static struct cdp_ipa_ops ol_ops_ipa = {
.ipa_get_resource = ol_txrx_ipa_uc_get_resource, .ipa_get_resource = ol_txrx_ipa_uc_get_resource,
.ipa_set_doorbell_paddr = ol_txrx_ipa_uc_set_doorbell_paddr, .ipa_set_doorbell_paddr = ol_txrx_ipa_uc_set_doorbell_paddr,
.ipa_set_active = ol_txrx_ipa_uc_set_active, .ipa_set_active = ol_txrx_ipa_uc_set_active,
@@ -5576,10 +5426,21 @@ static struct cdp_ipa_ops ol_ops_ipa = {
.ipa_get_stat = ol_txrx_ipa_uc_get_stat, .ipa_get_stat = ol_txrx_ipa_uc_get_stat,
.ipa_tx_data_frame = ol_tx_send_ipa_data_frame, .ipa_tx_data_frame = ol_tx_send_ipa_data_frame,
.ipa_set_uc_tx_partition_base = ol_cfg_set_ipa_uc_tx_partition_base, .ipa_set_uc_tx_partition_base = ol_cfg_set_ipa_uc_tx_partition_base,
.ipa_enable_autonomy = ol_txrx_ipa_enable_autonomy,
.ipa_disable_autonomy = ol_txrx_ipa_disable_autonomy,
.ipa_setup = ol_txrx_ipa_setup,
.ipa_cleanup = ol_txrx_ipa_cleanup,
.ipa_setup_iface = ol_txrx_ipa_setup_iface,
.ipa_cleanup_iface = ol_txrx_ipa_cleanup_iface,
.ipa_enable_pipes = ol_txrx_ipa_enable_pipes,
.ipa_disable_pipes = ol_txrx_ipa_disable_pipes,
.ipa_set_perf_level = ol_txrx_ipa_set_perf_level,
#ifdef FEATURE_METERING
.ipa_uc_get_share_stats = ol_txrx_ipa_uc_get_share_stats, .ipa_uc_get_share_stats = ol_txrx_ipa_uc_get_share_stats,
.ipa_uc_set_quota = ol_txrx_ipa_uc_set_quota .ipa_uc_set_quota = ol_txrx_ipa_uc_set_quota
#endif /* IPA_OFFLOAD */ #endif
}; };
#endif
static struct cdp_bus_ops ol_ops_bus = { static struct cdp_bus_ops ol_ops_bus = {
.bus_suspend = ol_txrx_bus_suspend, .bus_suspend = ol_txrx_bus_suspend,
@@ -5696,7 +5557,9 @@ static struct cdp_ops ol_txrx_ops = {
.cfg_ops = &ol_ops_cfg, .cfg_ops = &ol_ops_cfg,
.flowctl_ops = &ol_ops_flowctl, .flowctl_ops = &ol_ops_flowctl,
.l_flowctl_ops = &ol_ops_l_flowctl, .l_flowctl_ops = &ol_ops_l_flowctl,
#ifdef IPA_OFFLOAD
.ipa_ops = &ol_ops_ipa, .ipa_ops = &ol_ops_ipa,
#endif
.bus_ops = &ol_ops_bus, .bus_ops = &ol_ops_bus,
.ocb_ops = &ol_ops_ocb, .ocb_ops = &ol_ops_ocb,
.peer_ops = &ol_ops_peer, .peer_ops = &ol_ops_peer,

936
core/dp/txrx/ol_txrx_ipa.c Normal file
View File

@@ -0,0 +1,936 @@
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*=== includes ===*/
/* header files for OS primitives */
#include <osdep.h> /* uint32_t, etc. */
#include <qdf_mem.h> /* qdf_mem_malloc,free */
#include <qdf_types.h> /* qdf_device_t, qdf_print */
#include <qdf_lock.h> /* qdf_spinlock */
#include <qdf_atomic.h> /* qdf_atomic_read */
#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB)
/* Required for WLAN_FEATURE_FASTPATH */
#include <ce_api.h>
#endif
/* header files for utilities */
#include <cds_queue.h> /* TAILQ */
/* header files for configuration API */
#include <ol_cfg.h> /* ol_cfg_is_high_latency */
#include <ol_if_athvar.h>
/* header files for HTT API */
#include <ol_htt_api.h>
#include <ol_htt_tx_api.h>
/* header files for our own APIs */
#include <ol_txrx_api.h>
#include <ol_txrx_dbg.h>
#include <cdp_txrx_ocb.h>
#include <ol_txrx_ctrl_api.h>
#include <cdp_txrx_stats.h>
#include <ol_txrx_osif_api.h>
/* header files for our internal definitions */
#include <ol_txrx_internal.h> /* TXRX_ASSERT, etc. */
#include <wdi_event.h> /* WDI events */
#include <ol_tx.h> /* ol_tx_ll */
#include <ol_rx.h> /* ol_rx_deliver */
#include <ol_txrx_peer_find.h> /* ol_txrx_peer_find_attach, etc. */
#include <ol_rx_pn.h> /* ol_rx_pn_check, etc. */
#include <ol_rx_fwd.h> /* ol_rx_fwd_check, etc. */
#include <ol_rx_reorder_timeout.h> /* OL_RX_REORDER_TIMEOUT_INIT, etc. */
#include <ol_rx_reorder.h>
#include <ol_tx_send.h> /* ol_tx_discard_target_frms */
#include <ol_tx_desc.h> /* ol_tx_desc_frame_free */
#include <ol_tx_queue.h>
#include <ol_tx_sched.h> /* ol_tx_sched_attach, etc. */
#include <ol_txrx.h>
#include <ol_txrx_types.h>
#include <cdp_txrx_flow_ctrl_legacy.h>
#include <cdp_txrx_bus.h>
#include <cdp_txrx_ipa.h>
#include <cdp_txrx_pmf.h>
#include "wma.h"
#include "hif.h"
#include <cdp_txrx_peer_ops.h>
#ifndef REMOVE_PKT_LOG
#include "pktlog_ac.h"
#endif
#include "epping_main.h"
#include <a_types.h>
#ifdef IPA_OFFLOAD
#include <ol_txrx_ipa.h>
/* For Tx pipes, use Ethernet-II Header format */
struct ol_txrx_ipa_uc_tx_hdr ipa_uc_tx_hdr = {
{
0x0000,
0x00000000,
0x00000000
},
{
0x00000000
},
{
{0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc},
{0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff},
0x0008
}
};
/**
* ol_txrx_ipa_uc_get_resource() - Client request resource information
* @pdev: handle to the HTT instance
*
* OL client will reuqest IPA UC related resource information
* Resource information will be distributted to IPA module
* All of the required resources should be pre-allocated
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_uc_get_resource(struct cdp_pdev *ppdev)
{
ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev;
struct ol_txrx_ipa_resources *ipa_res = &pdev->ipa_resource;
htt_ipa_uc_get_resource(pdev->htt_pdev,
&ipa_res->ce_sr_base_paddr,
&ipa_res->ce_sr_ring_size,
&ipa_res->ce_reg_paddr,
&ipa_res->tx_comp_ring_base_paddr,
&ipa_res->tx_comp_ring_size,
&ipa_res->tx_num_alloc_buffer,
&ipa_res->rx_rdy_ring_base_paddr,
&ipa_res->rx_rdy_ring_size,
&ipa_res->rx_proc_done_idx_paddr,
&ipa_res->rx_proc_done_idx_vaddr,
&ipa_res->rx2_rdy_ring_base_paddr,
&ipa_res->rx2_rdy_ring_size,
&ipa_res->rx2_proc_done_idx_paddr,
&ipa_res->rx2_proc_done_idx_vaddr);
if ((0 == ipa_res->ce_sr_base_paddr) ||
(0 == ipa_res->tx_comp_ring_base_paddr) ||
(0 == ipa_res->rx_rdy_ring_base_paddr)
#if defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)
|| (0 == ipa_res->rx2_rdy_ring_base_paddr)
#endif
)
return QDF_STATUS_E_FAILURE;
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_uc_set_doorbell_paddr() - Client set IPA UC doorbell register
* @pdev: handle to the HTT instance
*
* IPA UC let know doorbell register physical address
* WLAN firmware will use this physical address to notify IPA UC
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_uc_set_doorbell_paddr(struct cdp_pdev *ppdev)
{
ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev;
struct ol_txrx_ipa_resources *ipa_res = &pdev->ipa_resource;
int ret;
ret = htt_ipa_uc_set_doorbell_paddr(pdev->htt_pdev,
ipa_res->tx_comp_doorbell_paddr,
ipa_res->rx_ready_doorbell_paddr);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"htt_ipa_uc_set_doorbell_paddr fail: %d", ret);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_uc_set_active() - Client notify IPA UC data path active or not
* @pdev: handle to the HTT instance
* @uc_active: WDI UC path enable or not
* @is_tx: TX path or RX path
*
* IPA UC let know doorbell register physical address
* WLAN firmware will use this physical address to notify IPA UC
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_uc_set_active(struct cdp_pdev *ppdev, bool uc_active,
bool is_tx)
{
ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev;
int ret;
ret = htt_h2t_ipa_uc_set_active(pdev->htt_pdev, uc_active, is_tx);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"htt_h2t_ipa_uc_set_active fail: %d", ret);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_uc_op_response() - Handle OP command response from firmware
* @pdev: handle to the device instance
* @op_msg: op response message from firmware
*
* Return: none
*/
QDF_STATUS ol_txrx_ipa_uc_op_response(struct cdp_pdev *ppdev, uint8_t *op_msg)
{
ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev;
if (pdev->ipa_uc_op_cb) {
pdev->ipa_uc_op_cb(op_msg, pdev->usr_ctxt);
} else {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: IPA callback function is not registered", __func__);
qdf_mem_free(op_msg);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_uc_register_op_cb() - Register OP handler function
* @pdev: handle to the device instance
* @op_cb: handler function pointer
*
* Return: none
*/
QDF_STATUS ol_txrx_ipa_uc_register_op_cb(struct cdp_pdev *ppdev,
ipa_uc_op_cb_type op_cb, void *usr_ctxt)
{
ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev;
pdev->ipa_uc_op_cb = op_cb;
pdev->usr_ctxt = usr_ctxt;
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_uc_get_stat() - Get firmware wdi status
* @pdev: handle to the HTT instance
*
* Return: none
*/
QDF_STATUS ol_txrx_ipa_uc_get_stat(struct cdp_pdev *ppdev)
{
ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev;
int ret;
ret = htt_h2t_ipa_uc_get_stats(pdev->htt_pdev);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"htt_h2t_ipa_uc_get_stats fail: %d", ret);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_enable_autonomy() - Enable autonomy RX path
* @pdev: handle to the device instance
*
* Set all RX packet route to IPA
* Return: none
*/
QDF_STATUS ol_txrx_ipa_enable_autonomy(struct cdp_pdev *ppdev)
{
/* TBD */
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_disable_autonomy() - Disable autonomy RX path
* @pdev: handle to the device instance
*
* Disable RX packet route to host
* Return: none
*/
QDF_STATUS ol_txrx_ipa_disable_autonomy(struct cdp_pdev *ppdev)
{
/* TBD */
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_setup() - Setup and connect IPA pipes
* @pdev: handle to the device instance
* @ipa_i2w_cb: IPA to WLAN callback
* @ipa_w2i_cb: WLAN to IPA callback
* @ipa_wdi_meter_notifier_cb: IPA WDI metering callback
* @ipa_desc_size: IPA descriptor size
* @ipa_priv: handle to the HTT instance
* @is_rm_enabled: Is IPA RM enabled or not
* @p_tx_pipe_handle: pointer to Tx pipe handle
* @p_rx_pipe_handle: pointer to Rx pipe handle
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb,
void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb,
uint32_t ipa_desc_size, void *ipa_priv,
bool is_rm_enabled, uint32_t *p_tx_pipe_handle,
uint32_t *p_rx_pipe_handle)
{
ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev;
struct ol_txrx_ipa_resources *ipa_res = &pdev->ipa_resource;
struct ipa_wdi_in_params pipe_in;
struct ipa_wdi_out_params pipe_out;
int ret;
qdf_mem_zero(&pipe_in, sizeof(struct ipa_wdi_in_params));
qdf_mem_zero(&pipe_out, sizeof(struct ipa_wdi_out_params));
/* TX PIPE */
pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
pipe_in.sys.ipa_ep_cfg.hdr.hdr_len = OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
pipe_in.sys.ipa_ep_cfg.hdr.hdr_additional_const_len =
OL_TXRX_IPA_UC_WLAN_8023_HDR_SIZE;
pipe_in.sys.ipa_ep_cfg.mode.mode = IPA_BASIC;
pipe_in.sys.client = IPA_CLIENT_WLAN1_CONS;
pipe_in.sys.desc_fifo_sz = ipa_desc_size;
pipe_in.sys.priv = ipa_priv;
pipe_in.sys.ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
pipe_in.sys.notify = ipa_i2w_cb;
if (!is_rm_enabled) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: IPA RM DISABLED, IPA AWAKE", __func__);
pipe_in.sys.keep_ipa_awake = true;
}
pipe_in.u.dl.comp_ring_base_pa = ipa_res->tx_comp_ring_base_paddr;
pipe_in.u.dl.comp_ring_size = ipa_res->tx_comp_ring_size *
sizeof(qdf_dma_addr_t);
pipe_in.u.dl.ce_ring_base_pa = ipa_res->ce_sr_base_paddr;
pipe_in.u.dl.ce_door_bell_pa = ipa_res->ce_reg_paddr;
pipe_in.u.dl.ce_ring_size = ipa_res->ce_sr_ring_size;
pipe_in.u.dl.num_tx_buffers = ipa_res->tx_num_alloc_buffer;
/* Connect WDI IPA PIPE */
ret = ipa_connect_wdi_pipe(&pipe_in, &pipe_out);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"ipa_connect_wdi_pipe: Tx pipe setup failed: ret=%d", ret);
return QDF_STATUS_E_FAILURE;
}
/* Micro Controller Doorbell register */
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s CONS DB pipe out 0x%x TX PIPE Handle 0x%x",
__func__, (unsigned int)pipe_out.uc_door_bell_pa,
pipe_out.clnt_hdl);
ipa_res->tx_comp_doorbell_paddr = pipe_out.uc_door_bell_pa;
/* WLAN TX PIPE Handle */
ipa_res->tx_pipe_handle = pipe_out.clnt_hdl;
*p_tx_pipe_handle = pipe_out.clnt_hdl;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"TX: %s 0x%x, %s %d, %s 0x%x, %s 0x%x, %s %d, %sNB %d, %s 0x%x",
"comp_ring_base_pa",
(unsigned int)pipe_in.u.dl.comp_ring_base_pa,
"comp_ring_size",
pipe_in.u.dl.comp_ring_size,
"ce_ring_base_pa",
(unsigned int)pipe_in.u.dl.ce_ring_base_pa,
"ce_door_bell_pa",
(unsigned int)pipe_in.u.dl.ce_door_bell_pa,
"ce_ring_size",
pipe_in.u.dl.ce_ring_size,
"num_tx_buffers",
pipe_in.u.dl.num_tx_buffers,
"tx_comp_doorbell_paddr",
(unsigned int)ipa_res->tx_comp_doorbell_paddr);
/* RX PIPE */
pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
pipe_in.sys.ipa_ep_cfg.hdr.hdr_len = OL_TXRX_IPA_UC_WLAN_RX_HDR_LEN;
pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 0;
pipe_in.sys.ipa_ep_cfg.hdr.hdr_metadata_reg_valid = 1;
pipe_in.sys.ipa_ep_cfg.mode.mode = IPA_BASIC;
pipe_in.sys.client = IPA_CLIENT_WLAN1_PROD;
pipe_in.sys.desc_fifo_sz = ipa_desc_size + sizeof(struct sps_iovec);
pipe_in.sys.notify = ipa_w2i_cb;
if (!is_rm_enabled) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: IPA RM DISABLED, IPA AWAKE", __func__);
pipe_in.sys.keep_ipa_awake = true;
}
pipe_in.u.ul.rdy_ring_base_pa = ipa_res->rx_rdy_ring_base_paddr;
pipe_in.u.ul.rdy_ring_size = ipa_res->rx_rdy_ring_size;
pipe_in.u.ul.rdy_ring_rp_pa = ipa_res->rx_proc_done_idx_paddr;
OL_TXRX_IPA_WDI2_SET(pipe_in, ipa_res);
#ifdef FEATURE_METERING
pipe_in.wdi_notify = ipa_wdi_meter_notifier_cb;
#endif
ret = ipa_connect_wdi_pipe(&pipe_in, &pipe_out);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"ipa_connect_wdi_pipe: Rx pipe setup failed: ret=%d", ret);
return QDF_STATUS_E_FAILURE;
}
ipa_res->rx_ready_doorbell_paddr = pipe_out.uc_door_bell_pa;
ipa_res->rx_pipe_handle = pipe_out.clnt_hdl;
*p_rx_pipe_handle = pipe_out.clnt_hdl;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"RX: %s 0x%x, %s %d, %s 0x%x, %s 0x%x",
"rdy_ring_base_pa",
(unsigned int)pipe_in.u.ul.rdy_ring_base_pa,
"rdy_ring_size",
pipe_in.u.ul.rdy_ring_size,
"rdy_ring_rp_pa",
(unsigned int)pipe_in.u.ul.rdy_ring_rp_pa,
"rx_ready_doorbell_paddr",
(unsigned int)ipa_res->rx_ready_doorbell_paddr);
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_cleanup() - Disconnect IPA pipes
* @tx_pipe_handle: Tx pipe handle
* @rx_pipe_handle: Rx pipe handle
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_cleanup(uint32_t tx_pipe_handle, uint32_t rx_pipe_handle)
{
int ret;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: Disconnect TX PIPE tx_pipe_handle=0x%x",
__func__, tx_pipe_handle);
ret = ipa_disconnect_wdi_pipe(tx_pipe_handle);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"ipa_disconnect_wdi_pipe: Tx pipe cleanup failed: ret=%d",
ret);
return QDF_STATUS_E_FAILURE;
}
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: Disconnect RX PIPE rx_pipe_handle=0x%x",
__func__, rx_pipe_handle);
ret = ipa_disconnect_wdi_pipe(rx_pipe_handle);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"ipa_disconnect_wdi_pipe: Rx pipe cleanup failed: ret=%d",
ret);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_remove_ipa_header() - Remove a specific header from IPA
* @name: Name of the header to be removed
*
* Return: QDF_STATUS
*/
static QDF_STATUS ol_txrx_ipa_remove_header(char *name)
{
struct ipa_ioc_get_hdr hdrlookup;
int ret = 0, len;
struct ipa_ioc_del_hdr *ipa_hdr;
qdf_mem_zero(&hdrlookup, sizeof(hdrlookup));
strlcpy(hdrlookup.name, name, sizeof(hdrlookup.name));
ret = ipa_get_hdr(&hdrlookup);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"Hdr deleted already %s, %d", name, ret);
return QDF_STATUS_E_FAILURE;
}
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "hdl: 0x%x",
hdrlookup.hdl);
len = sizeof(struct ipa_ioc_del_hdr) + sizeof(struct ipa_hdr_del) * 1;
ipa_hdr = (struct ipa_ioc_del_hdr *)qdf_mem_malloc(len);
if (ipa_hdr == NULL) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"ipa_hdr allocation failed");
return QDF_STATUS_E_FAILURE;
}
ipa_hdr->num_hdls = 1;
ipa_hdr->commit = 0;
ipa_hdr->hdl[0].hdl = hdrlookup.hdl;
ipa_hdr->hdl[0].status = -1;
ret = ipa_del_hdr(ipa_hdr);
if (ret != 0) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Delete header failed: %d", ret);
qdf_mem_free(ipa_hdr);
return QDF_STATUS_E_FAILURE;
}
qdf_mem_free(ipa_hdr);
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_add_header_info() - Add IPA header for a given interface
* @ifname: Interface name
* @mac_addr: Interface MAC address
* @is_ipv6_enabled: Is IPV6 enabled or not
*
* Return: 0 on success, negativer errno value on error
*/
static int ol_txrx_ipa_add_header_info(char *ifname, uint8_t *mac_addr,
uint8_t session_id, bool is_ipv6_enabled)
{
struct ipa_ioc_add_hdr *ipa_hdr = NULL;
int ret = -EINVAL;
struct ol_txrx_ipa_uc_tx_hdr *uc_tx_hdr = NULL;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"Add Partial hdr: %s, %pM", ifname, mac_addr);
/* dynamically allocate the memory to add the hdrs */
ipa_hdr = qdf_mem_malloc(sizeof(struct ipa_ioc_add_hdr)
+ sizeof(struct ipa_hdr_add));
if (!ipa_hdr) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: ipa_hdr allocation failed", ifname);
ret = -ENOMEM;
goto end;
}
ipa_hdr->commit = 0;
ipa_hdr->num_hdrs = 1;
uc_tx_hdr = (struct ol_txrx_ipa_uc_tx_hdr *)ipa_hdr->hdr[0].hdr;
memcpy(uc_tx_hdr, &ipa_uc_tx_hdr, OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN);
memcpy(uc_tx_hdr->eth.h_source, mac_addr, ETH_ALEN);
uc_tx_hdr->ipa_hd.vdev_id = session_id;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"ifname=%s, vdev_id=%d",
ifname, uc_tx_hdr->ipa_hd.vdev_id);
snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
ipa_hdr->hdr[0].hdr_len = OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
ipa_hdr->hdr[0].type = IPA_HDR_L2_ETHERNET_II;
ipa_hdr->hdr[0].is_partial = 1;
ipa_hdr->hdr[0].hdr_hdl = 0;
ipa_hdr->hdr[0].is_eth2_ofst_valid = 1;
ipa_hdr->hdr[0].eth2_ofst = OL_TXRX_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
ret = ipa_add_hdr(ipa_hdr);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s IPv4 add hdr failed: %d", ifname, ret);
goto end;
}
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: IPv4 hdr_hdl: 0x%x",
ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl);
if (is_ipv6_enabled) {
snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, OL_TXRX_IPA_IPV6_NAME_EXT);
uc_tx_hdr = (struct ol_txrx_ipa_uc_tx_hdr *)ipa_hdr->hdr[0].hdr;
uc_tx_hdr->eth.h_proto = cpu_to_be16(ETH_P_IPV6);
ret = ipa_add_hdr(ipa_hdr);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: IPv6 add hdr failed: %d", ifname, ret);
goto clean_ipv4_hdr;
}
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: IPv6 hdr_hdl: 0x%x",
ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl);
}
qdf_mem_free(ipa_hdr);
return ret;
clean_ipv4_hdr:
snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
ol_txrx_ipa_remove_header(ipa_hdr->hdr[0].name);
end:
if (ipa_hdr)
qdf_mem_free(ipa_hdr);
return ret;
}
/**
* ol_txrx_ipa_register_interface() - register IPA interface
* @ifname: Interface name
* @prod_client: IPA prod client type
* @cons_client: IPA cons client type
* @session_id: Session ID
* @is_ipv6_enabled: Is IPV6 enabled or not
*
* Return: 0 on success, negative errno on error
*/
static int ol_txrx_ipa_register_interface(char *ifname,
enum ipa_client_type prod_client,
enum ipa_client_type cons_client,
uint8_t session_id,
bool is_ipv6_enabled)
{
struct ipa_tx_intf tx_intf;
struct ipa_rx_intf rx_intf;
struct ipa_ioc_tx_intf_prop *tx_prop = NULL;
struct ipa_ioc_rx_intf_prop *rx_prop = NULL;
char ipv4_hdr_name[IPA_RESOURCE_NAME_MAX];
char ipv6_hdr_name[IPA_RESOURCE_NAME_MAX];
int num_prop = 1;
int ret = 0;
if (is_ipv6_enabled)
num_prop++;
/* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */
tx_prop =
qdf_mem_malloc(sizeof(struct ipa_ioc_tx_intf_prop) * num_prop);
if (!tx_prop) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"tx_prop allocation failed");
goto register_interface_fail;
}
/* Allocate RX properties, 1 each for IPv4 & IPv6 */
rx_prop =
qdf_mem_malloc(sizeof(struct ipa_ioc_rx_intf_prop) * num_prop);
if (!rx_prop) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"rx_prop allocation failed");
goto register_interface_fail;
}
qdf_mem_zero(&tx_intf, sizeof(tx_intf));
qdf_mem_zero(&rx_intf, sizeof(rx_intf));
snprintf(ipv4_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, OL_TXRX_IPA_IPV6_NAME_EXT);
rx_prop[IPA_IP_v4].ip = IPA_IP_v4;
rx_prop[IPA_IP_v4].src_pipe = prod_client;
rx_prop[IPA_IP_v4].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA;
/*
* Interface ID is 3rd byte in the CLD header. Add the meta data and
* mask to identify the interface in IPA hardware
*/
rx_prop[IPA_IP_v4].attrib.meta_data =
htonl(session_id << 16);
rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000);
rx_intf.num_props++;
if (is_ipv6_enabled) {
rx_prop[IPA_IP_v6].ip = IPA_IP_v6;
rx_prop[IPA_IP_v6].src_pipe = prod_client;
rx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
rx_prop[IPA_IP_v6].attrib.attrib_mask = IPA_FLT_META_DATA;
rx_prop[IPA_IP_v6].attrib.meta_data =
htonl(session_id << 16);
rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000);
rx_intf.num_props++;
}
tx_prop[IPA_IP_v4].ip = IPA_IP_v4;
tx_prop[IPA_IP_v4].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
tx_prop[IPA_IP_v4].dst_pipe = IPA_CLIENT_WLAN1_CONS;
tx_prop[IPA_IP_v4].alt_dst_pipe = cons_client;
strlcpy(tx_prop[IPA_IP_v4].hdr_name, ipv4_hdr_name,
IPA_RESOURCE_NAME_MAX);
tx_intf.num_props++;
if (is_ipv6_enabled) {
tx_prop[IPA_IP_v6].ip = IPA_IP_v6;
tx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
tx_prop[IPA_IP_v6].dst_pipe = IPA_CLIENT_WLAN1_CONS;
tx_prop[IPA_IP_v6].alt_dst_pipe = cons_client;
strlcpy(tx_prop[IPA_IP_v6].hdr_name, ipv6_hdr_name,
IPA_RESOURCE_NAME_MAX);
tx_intf.num_props++;
}
tx_intf.prop = tx_prop;
rx_intf.prop = rx_prop;
/* Call the ipa api to register interface */
ret = ipa_register_intf(ifname, &tx_intf, &rx_intf);
register_interface_fail:
qdf_mem_free(tx_prop);
qdf_mem_free(rx_prop);
return ret;
}
/**
* ol_txrx_ipa_setup_iface() - Setup IPA header and register interface
* @ifname: Interface name
* @mac_addr: Interface MAC address
* @prod_client: IPA prod client type
* @cons_client: IPA cons client type
* @session_id: Session ID
* @is_ipv6_enabled: Is IPV6 enabled or not
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
enum ipa_client_type prod_client,
enum ipa_client_type cons_client,
uint8_t session_id, bool is_ipv6_enabled)
{
int ret;
ret = ol_txrx_ipa_add_header_info(ifname, mac_addr, session_id,
is_ipv6_enabled);
if (ret)
return QDF_STATUS_E_FAILURE;
/* Configure the TX and RX pipes filter rules */
ret = ol_txrx_ipa_register_interface(ifname, prod_client, cons_client,
session_id, is_ipv6_enabled);
if (ret)
return QDF_STATUS_E_FAILURE;
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_cleanup_iface() - Cleanup IPA header and deregister interface
* @ifname: Interface name
* @is_ipv6_enabled: Is IPV6 enabled or not
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled)
{
char name_ipa[IPA_RESOURCE_NAME_MAX];
int ret;
/* Remove the headers */
snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
ol_txrx_ipa_remove_header(name_ipa);
if (is_ipv6_enabled) {
snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, OL_TXRX_IPA_IPV6_NAME_EXT);
ol_txrx_ipa_remove_header(name_ipa);
}
/* unregister the interface with IPA */
ret = ipa_deregister_intf(ifname);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: ipa_deregister_intf fail: %d",
ifname, ret);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_uc_enable_pipes() - Enable and resume traffic on Tx/Rx pipes
* @pdev: handle to the device instance
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_pdev *ppdev)
{
ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev;
struct ol_txrx_ipa_resources *ipa_res = &pdev->ipa_resource;
int result;
/* ACTIVATE TX PIPE */
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: Enable TX PIPE(tx_pipe_handle=%d)",
__func__, ipa_res->tx_pipe_handle);
result = ipa_enable_wdi_pipe(ipa_res->tx_pipe_handle);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Enable TX PIPE fail, code %d",
__func__, result);
return QDF_STATUS_E_FAILURE;
}
result = ipa_resume_wdi_pipe(ipa_res->tx_pipe_handle);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Resume TX PIPE fail, code %d",
__func__, result);
return QDF_STATUS_E_FAILURE;
}
ol_txrx_ipa_uc_set_active((struct cdp_pdev *)pdev, true, true);
/* ACTIVATE RX PIPE */
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: Enable RX PIPE(rx_pipe_handle=%d)",
__func__, ipa_res->rx_pipe_handle);
result = ipa_enable_wdi_pipe(ipa_res->rx_pipe_handle);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Enable RX PIPE fail, code %d",
__func__, result);
return QDF_STATUS_E_FAILURE;
}
result = ipa_resume_wdi_pipe(ipa_res->rx_pipe_handle);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Resume RX PIPE fail, code %d",
__func__, result);
return QDF_STATUS_E_FAILURE;
}
ol_txrx_ipa_uc_set_active((struct cdp_pdev *)pdev, true, false);
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_uc_disable_pipes() Suspend traffic and disable Tx/Rx pipes
* @pdev: handle to the device instance
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_pdev *ppdev)
{
ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev;
struct ol_txrx_ipa_resources *ipa_res = &pdev->ipa_resource;
int result;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: Disable RX PIPE", __func__);
result = ipa_suspend_wdi_pipe(ipa_res->rx_pipe_handle);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Suspend RX PIPE fail, code %d",
__func__, result);
return QDF_STATUS_E_FAILURE;
}
result = ipa_disable_wdi_pipe(ipa_res->rx_pipe_handle);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Disable RX PIPE fail, code %d",
__func__, result);
return QDF_STATUS_E_FAILURE;
}
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
"%s: Disable TX PIPE", __func__);
result = ipa_suspend_wdi_pipe(ipa_res->tx_pipe_handle);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Suspend TX PIPE fail, code %d",
__func__, result);
return QDF_STATUS_E_FAILURE;
}
result = ipa_disable_wdi_pipe(ipa_res->tx_pipe_handle);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Disable TX PIPE fail, code %d",
__func__, result);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* ol_txrx_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates
* @client: Client type
* @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps)
*
* Return: QDF_STATUS
*/
QDF_STATUS ol_txrx_ipa_set_perf_level(int client,
uint32_t max_supported_bw_mbps)
{
struct ipa_rm_perf_profile profile;
int result;
profile.max_supported_bandwidth_mbps = max_supported_bw_mbps;
result = ipa_rm_set_perf_profile(client, &profile);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Set perf profile failed, code %d", result);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
#ifdef FEATURE_METERING
QDF_STATUS ol_txrx_ipa_uc_get_share_stats(struct cdp_pdev *ppdev,
uint8_t reset_stats)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
int result;
result = htt_h2t_ipa_uc_get_share_stats(pdev->htt_pdev, reset_stats);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Get IPA sharing stats failed, code %d", result);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ol_txrx_ipa_uc_set_quota(struct cdp_pdev *ppdev,
uint64_t quota_bytes)
{
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
int result;
result = htt_h2t_ipa_uc_set_quota(pdev->htt_pdev, quota_bytes);
if (result) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Set IPA quota failed, code %d", result);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
#endif
#endif /* IPA_UC_OFFLOAD */

132
core/dp/txrx/ol_txrx_ipa.h Normal file
View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _OL_TXRX_IPA_H_
#define _OL_TXRX_IPA_H_
#ifdef IPA_OFFLOAD
#include <cdp_txrx_cmn.h> /* ol_txrx_vdev_t, etc. */
#include <ol_txrx_types.h>
/**
* struct frag_header - fragment header type registered to IPA hardware
* @length: fragment length
* @reserved1: Reserved not used
* @reserved2: Reserved not used
*
*/
struct frag_header {
uint16_t length;
uint32_t reserved1;
uint32_t reserved2;
} __packed;
/**
* struct ipa_header - ipa header type registered to IPA hardware
* @vdev_id: vdev id
* @reserved: Reserved not used
*
*/
struct ipa_header {
uint32_t
vdev_id:8, /* vdev_id field is LSB of IPA DESC */
reserved:24;
} __packed;
/**
* struct ol_txrx_ipa_uc_tx_hdr - full tx header registered to IPA hardware
* @frag_hd: fragment header
* @ipa_hd: ipa header
* @eth: ether II header
*
*/
struct ol_txrx_ipa_uc_tx_hdr {
struct frag_header frag_hd;
struct ipa_header ipa_hd;
struct ethhdr eth;
} __packed;
/**
* struct ol_txrx_ipa_uc_rx_hdr - full rx header registered to IPA hardware
* @eth: ether II header
*
*/
struct ol_txrx_ipa_uc_rx_hdr {
struct ethhdr eth;
} __packed;
#define OL_TXRX_IPA_UC_WLAN_8023_HDR_SIZE 14
#define OL_TXRX_IPA_IPV4_NAME_EXT "_ipv4"
#define OL_TXRX_IPA_IPV6_NAME_EXT "_ipv6"
#define OL_TXRX_IPA_WLAN_FRAG_HEADER sizeof(struct frag_header)
#define OL_TXRX_IPA_WLAN_IPA_HEADER sizeof(struct ipa_header)
#define OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN sizeof(struct ol_txrx_ipa_uc_tx_hdr)
#define OL_TXRX_IPA_UC_WLAN_RX_HDR_LEN sizeof(struct ol_txrx_ipa_uc_rx_hdr)
#define OL_TXRX_IPA_UC_WLAN_HDR_DES_MAC_OFFSET \
(OL_TXRX_IPA_WLAN_FRAG_HEADER + OL_TXRX_IPA_WLAN_IPA_HEADER)
#if defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)
#define OL_TXRX_IPA_WDI2_SET(pipe_in, ipa_res) \
do { \
pipe_in.u.ul.rdy_ring_rp_va = \
ipa_res->rx_proc_done_idx_vaddr; \
pipe_in.u.ul.rdy_comp_ring_base_pa = \
ipa_res->rx2_rdy_ring_base_paddr;\
pipe_in.u.ul.rdy_comp_ring_size = \
ipa_res->rx2_rdy_ring_size; \
pipe_in.u.ul.rdy_comp_ring_wp_pa = \
ipa_res->rx2_proc_done_idx_paddr; \
pipe_in.u.ul.rdy_comp_ring_wp_va = \
ipa_res->rx2_proc_done_idx_vaddr; \
} while (0)
#else
/* Do nothing */
#define OL_TXRX_IPA_WDI2_SET(pipe_in, ipa_res)
#endif /* IPA3 */
QDF_STATUS ol_txrx_ipa_uc_get_resource(struct cdp_pdev *pdev);
QDF_STATUS ol_txrx_ipa_uc_set_doorbell_paddr(struct cdp_pdev *pdev);
QDF_STATUS ol_txrx_ipa_uc_set_active(struct cdp_pdev *pdev, bool uc_active,
bool is_tx);
QDF_STATUS ol_txrx_ipa_uc_op_response(struct cdp_pdev *pdev, uint8_t *op_msg);
QDF_STATUS ol_txrx_ipa_uc_register_op_cb(struct cdp_pdev *pdev,
ipa_uc_op_cb_type op_cb, void *usr_ctxt);
QDF_STATUS ol_txrx_ipa_uc_get_stat(struct cdp_pdev *pdev);
QDF_STATUS ol_txrx_ipa_enable_autonomy(struct cdp_pdev *pdev);
QDF_STATUS ol_txrx_ipa_disable_autonomy(struct cdp_pdev *pdev);
QDF_STATUS ol_txrx_ipa_setup(struct cdp_pdev *pdev, void *ipa_i2w_cb,
void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb,
uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled,
uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle);
QDF_STATUS ol_txrx_ipa_cleanup(uint32_t tx_pipe_handle,
uint32_t rx_pipe_handle);
QDF_STATUS ol_txrx_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
enum ipa_client_type prod_client,
enum ipa_client_type cons_client,
uint8_t session_id, bool is_ipv6_enabled);
QDF_STATUS ol_txrx_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled);
QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_pdev *pdev);
QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_pdev *pdev);
QDF_STATUS ol_txrx_ipa_set_perf_level(int client,
uint32_t max_supported_bw_mbps);
#ifdef FEATURE_METERING
QDF_STATUS ol_txrx_ipa_uc_get_share_stats(struct cdp_pdev *pdev,
uint8_t reset_stats);
QDF_STATUS ol_txrx_ipa_uc_set_quota(struct cdp_pdev *pdev,
uint64_t quota_bytes);
#endif
#endif
#endif /* _OL_TXRX_IPA_H_*/

View File

@@ -406,7 +406,7 @@ enum throttle_phase {
#define THROTTLE_TX_THRESHOLD (100) #define THROTTLE_TX_THRESHOLD (100)
typedef void (*ipa_uc_op_cb_type)(uint8_t *op_msg, void *osif_ctxt); typedef void (*ipa_uc_op_cb_type)(uint8_t *op_msg, void *usr_ctxt);
struct ol_tx_queue_group_t { struct ol_tx_queue_group_t {
qdf_atomic_t credit; qdf_atomic_t credit;
@@ -918,11 +918,6 @@ struct ol_txrx_pdev_t {
bool is_paused; bool is_paused;
} tx_throttle; } tx_throttle;
#ifdef IPA_OFFLOAD
ipa_uc_op_cb_type ipa_uc_op_cb;
void *osif_dev;
#endif /* IPA_UC_OFFLOAD */
#if defined(FEATURE_TSO) #if defined(FEATURE_TSO)
struct { struct {
uint16_t pool_size; uint16_t pool_size;
@@ -979,6 +974,12 @@ struct ol_txrx_pdev_t {
} lro_info; } lro_info;
struct ol_txrx_peer_t *self_peer; struct ol_txrx_peer_t *self_peer;
qdf_work_t peer_unmap_timer_work; qdf_work_t peer_unmap_timer_work;
#ifdef IPA_OFFLOAD
ipa_uc_op_cb_type ipa_uc_op_cb;
void *usr_ctxt;
struct ol_txrx_ipa_resources ipa_resource;
#endif /* IPA_UC_OFFLOAD */
}; };
struct ol_txrx_vdev_t { struct ol_txrx_vdev_t {

View File

@@ -269,7 +269,7 @@ static inline void hdd_ipa_set_tx_flow_info(void)
* *
* Return: 0 on success, negativer errno on error * Return: 0 on success, negativer errno on error
*/ */
static int hdd_ipa_uc_ol_deinit(hdd_context_t *hdd_ctx) static inline int hdd_ipa_uc_ol_deinit(hdd_context_t *hdd_ctx)
{ {
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -605,6 +605,99 @@ int wma_cli_set_command(int vdev_id, int param_id, int sval, int vpdev)
} }
/**
* wma_ipa_get_stat() - get IPA data path stats from FW
*
* Return: 0 on success, errno on failure
*/
#ifdef IPA_OFFLOAD
static int wma_ipa_get_stat(void)
{
struct cdp_pdev *pdev;
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
if (!pdev) {
WMA_LOGE("pdev NULL for uc stat");
return -EINVAL;
}
cdp_ipa_get_stat(cds_get_context(QDF_MODULE_ID_SOC), pdev);
return 0;
}
#else
static int wma_ipa_get_stat(void)
{
return 0;
}
#endif
/**
* wma_ipa_uc_get_share_stats() - get Tx/Rx byte stats from FW
* @privcmd: private command
*
* Return: 0 on success, errno on failure
*/
#if defined(IPA_OFFLOAD) && defined(FEATURE_METERING)
static int wma_ipa_uc_get_share_stats(wma_cli_set_cmd_t *privcmd)
{
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
struct cdp_pdev *pdev;
uint8_t reset_stats = privcmd->param_value;
WMA_LOGD("%s: reset_stats=%d",
"WMA_VDEV_TXRX_GET_IPA_UC_SHARING_STATS_CMDID",
reset_stats);
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
if (!pdev) {
WMA_LOGE("pdev NULL for uc get share stats");
return -EINVAL;
}
cdp_ipa_uc_get_share_stats(soc, pdev, reset_stats);
return 0;
}
#else
static int wma_ipa_uc_get_share_stats(wma_cli_set_cmd_t *privcmd)
{
return 0;
}
#endif
/**
* wma_ipa_uc_set_quota() - set quota limit to FW
* @privcmd: private command
*
* Return: 0 on success, errno on failure
*/
#if defined(IPA_OFFLOAD) && defined(FEATURE_METERING)
static int wma_ipa_uc_set_quota(wma_cli_set_cmd_t *privcmd)
{
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
struct cdp_pdev *pdev;
uint64_t quota_bytes = privcmd->param_sec_value;
quota_bytes <<= 32;
quota_bytes |= privcmd->param_value;
WMA_LOGD("%s: quota_bytes=%llu",
"WMA_VDEV_TXRX_SET_IPA_UC_QUOTA_CMDID",
quota_bytes);
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
if (!pdev) {
WMA_LOGE("pdev NULL for uc set quota");
return -EINVAL;
}
cdp_ipa_uc_set_quota(soc, pdev, quota_bytes);
return 0;
}
#else
static int wma_ipa_uc_set_quota(wma_cli_set_cmd_t *privcmd)
{
return 0;
}
#endif
/** /**
* wma_set_priv_cfg() - set private config parameters * wma_set_priv_cfg() - set private config parameters
* @wma_handle: wma handle * @wma_handle: wma handle
@@ -751,54 +844,20 @@ static int32_t wma_set_priv_cfg(tp_wma_handle wma_handle,
case WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID: case WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID:
{ {
void *soc = cds_get_context(QDF_MODULE_ID_SOC); wma_ipa_get_stat();
struct cdp_pdev *pdev;
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
if (!pdev) {
WMA_LOGE("pdev NULL for uc stat");
return -EINVAL;
}
cdp_ipa_get_stat(soc, pdev);
} }
break; break;
case WMA_VDEV_TXRX_GET_IPA_UC_SHARING_STATS_CMDID: case WMA_VDEV_TXRX_GET_IPA_UC_SHARING_STATS_CMDID:
{ {
void *soc = cds_get_context(QDF_MODULE_ID_SOC); wma_ipa_uc_get_share_stats(privcmd);
struct cdp_pdev *pdev;
uint8_t reset_stats = privcmd->param_value;
WMA_LOGE("%s: reset_stats=%d",
"WMA_VDEV_TXRX_GET_IPA_UC_SHARING_STATS_CMDID",
reset_stats);
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
if (!pdev) {
WMA_LOGE("pdev NULL for uc stat");
return -EINVAL;
}
cdp_ipa_uc_get_share_stats(soc, pdev, reset_stats);
} }
break; break;
case WMA_VDEV_TXRX_SET_IPA_UC_QUOTA_CMDID: case WMA_VDEV_TXRX_SET_IPA_UC_QUOTA_CMDID:
{ {
void *soc = cds_get_context(QDF_MODULE_ID_SOC); wma_ipa_uc_set_quota(privcmd);
struct cdp_pdev *pdev;
uint64_t quota_bytes = privcmd->param_sec_value;
quota_bytes <<= 32;
quota_bytes |= privcmd->param_value;
WMA_LOGE("%s: quota_bytes=%llu",
"WMA_VDEV_TXRX_SET_IPA_UC_QUOTA_CMDID",
quota_bytes);
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
if (!pdev) {
WMA_LOGE("pdev NULL for uc stat");
return -EINVAL;
}
cdp_ipa_uc_set_quota(soc, pdev, quota_bytes);
} }
break; break;
@@ -3826,6 +3885,28 @@ static void wma_alloc_host_mem(tp_wma_handle wma_handle, uint32_t req_id,
wma_handle->num_mem_chunks = idx; wma_handle->num_mem_chunks = idx;
} }
/**
* wma_set_tx_partition_base() - set TX MSDU ID partition base for IPA
* @value: TX MSDU ID partition base
*
* Return: none
*/
#ifdef IPA_OFFLOAD
static void wma_set_tx_partition_base(uint32_t value)
{
cdp_ipa_set_uc_tx_partition_base(
cds_get_context(QDF_MODULE_ID_SOC),
(struct cdp_cfg *)cds_get_context(QDF_MODULE_ID_CFG),
value);
WMA_LOGD("%s: TX_MSDU_ID_PARTITION=%d", __func__,
value);
}
#else
static void wma_set_tx_partition_base(uint32_t value)
{
}
#endif
/** /**
* wma_update_target_services() - update target services from wma handle * wma_update_target_services() - update target services from wma handle
* @wh: wma handle * @wh: wma handle
@@ -3920,19 +4001,9 @@ static inline void wma_update_target_services(tp_wma_handle wh,
if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap,
WMI_SERVICE_TX_MSDU_ID_NEW_PARTITION_SUPPORT)) { WMI_SERVICE_TX_MSDU_ID_NEW_PARTITION_SUPPORT)) {
cdp_ipa_set_uc_tx_partition_base( wma_set_tx_partition_base(HTT_TX_IPA_NEW_MSDU_ID_SPACE_BEGIN);
cds_get_context(QDF_MODULE_ID_SOC),
(struct cdp_cfg *)cds_get_context(QDF_MODULE_ID_CFG),
HTT_TX_IPA_NEW_MSDU_ID_SPACE_BEGIN);
WMA_LOGD("%s: TX_MSDU_ID_NEW_PARTITION=%d", __func__,
HTT_TX_IPA_NEW_MSDU_ID_SPACE_BEGIN);
} else { } else {
cdp_ipa_set_uc_tx_partition_base( wma_set_tx_partition_base(HTT_TX_IPA_MSDU_ID_SPACE_BEGIN);
cds_get_context(QDF_MODULE_ID_SOC),
(struct cdp_cfg *)cds_get_context(QDF_MODULE_ID_CFG),
HTT_TX_IPA_MSDU_ID_SPACE_BEGIN);
WMA_LOGD("%s: TX_MSDU_ID_OLD_PARTITION=%d", __func__,
HTT_TX_IPA_MSDU_ID_SPACE_BEGIN);
} }
wma_he_update_tgt_services(wh, cfg); wma_he_update_tgt_services(wh, cfg);