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:
11
Kbuild
11
Kbuild
@@ -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)
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
936
core/dp/txrx/ol_txrx_ipa.c
Normal 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
132
core/dp/txrx/ol_txrx_ipa.h
Normal 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_*/
|
@@ -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 {
|
||||||
|
@@ -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
@@ -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);
|
||||||
|
Reference in New Issue
Block a user