Merge "msm: ipa: Add change to support wdi gsi db polling"

This commit is contained in:
qctecmdr 2020-10-05 13:38:06 -07:00 • committed by Gerrit - the friendly Code Review server
commit 7e372e6a9d
7 changed files with 235 additions and 17 deletions

View file

@ -2768,6 +2768,44 @@ int gsi_write_channel_scratch2_reg(unsigned long chan_hdl,
}
EXPORT_SYMBOL(gsi_write_channel_scratch2_reg);
int gsi_write_wdi3_channel_scratch_6_7_reg(unsigned long chan_hdl,
union __packed gsi_wdi3_channel_scratch_6_7_reg val)
{
struct gsi_chan_ctx *ctx;
if (!gsi_ctx) {
pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
return -GSI_STATUS_NODEV;
}
if (chan_hdl >= gsi_ctx->max_ch) {
GSIERR("bad params chan_hdl=%lu\n", chan_hdl);
return -GSI_STATUS_INVALID_PARAMS;
}
ctx = &gsi_ctx->chan[chan_hdl];
mutex_lock(&ctx->mlock);
ctx->scratch.wdi3.db_addr_wp_lsb = val.wdi3.db_addr_wp_lsb;
ctx->scratch.wdi3.db_addr_wp_msb = val.wdi3.db_addr_wp_msb;
GSIDBG(" scratch value lsb 32 bit here %x0x & %x0x\n",val.wdi3.db_addr_wp_lsb,
ctx->scratch.wdi3.db_addr_wp_lsb );
GSIDBG(" scratch value here %x0x & %x0x\n",val.wdi3.db_addr_wp_msb,
ctx->scratch.wdi3.db_addr_wp_msb );
gsi_writel(val.data.word1, gsi_ctx->base +
GSI_EE_n_GSI_CH_k_SCRATCH_6_OFFS(chan_hdl,
gsi_ctx->per.ee));
gsi_writel(val.data.word2, gsi_ctx->base +
GSI_EE_n_GSI_CH_k_SCRATCH_7_OFFS(chan_hdl,
gsi_ctx->per.ee));
mutex_unlock(&ctx->mlock);
return GSI_STATUS_SUCCESS;
}
EXPORT_SYMBOL(gsi_write_wdi3_channel_scratch_6_7_reg);
static void __gsi_read_channel_scratch(unsigned long chan_hdl,
union __packed gsi_channel_scratch * val)
{

View file

@ -850,6 +850,7 @@ struct __packed gsi_11ad_tx_channel_scratch {
* be updated.
* @qmap_id: Rx only, used for setting metadata register in IPA. Read only field
* for MCS. Write for SW.
* @wdi_db_polling_enabled : set to true for cedros and lahaina WA
* @resv: reserved bits.
* @endp_metadata_reg_offset: Rx only, the offset of
* IPA_ENDP_INIT_HDR_METADATA_n of the
@ -858,16 +859,21 @@ struct __packed gsi_11ad_tx_channel_scratch {
* @rx_pkt_offset: Rx only, Since Rx header length is not fixed,
* WLAN host will pass this information to IPA.
* @resv: reserved bits.
* @db_addr_wp_lsb: used to store 32-bit lsb for wdi db polling
* @db_addr_wp_msb: used to store 32-bit msb for wdi db polling
*/
struct __packed gsi_wdi3_channel_scratch {
uint32_t wifi_rp_address_low;
uint32_t wifi_rp_address_high;
uint32_t update_rp_moderation_threshold : 5;
uint32_t qmap_id : 8;
uint32_t reserved1 : 3;
uint32_t wdi_db_polling_enabled : 1;
uint32_t reserved1 : 2;
uint32_t endp_metadata_reg_offset : 16;
uint32_t rx_pkt_offset : 16;
uint32_t reserved2 : 16;
uint32_t db_addr_wp_lsb;
uint32_t db_addr_wp_msb;
};
/**
@ -975,6 +981,19 @@ union __packed gsi_wdi2_channel_scratch2_reg {
} data;
};
struct __packed gsi_wdi3_channel_scratch_6_7 {
uint32_t db_addr_wp_lsb;
uint32_t db_addr_wp_msb;
};
union __packed gsi_wdi3_channel_scratch_6_7_reg {
struct __packed gsi_wdi3_channel_scratch_6_7 wdi3;
struct __packed {
uint32_t word1;
uint32_t word2;
} data;
};
/**
* gsi_mhi_evt_scratch - MHI protocol SW config area of
* event scratch
@ -1780,6 +1799,18 @@ int gsi_write_channel_scratch2_reg(unsigned long chan_hdl,
*/
int gsi_write_wdi3_channel_scratch2_reg(unsigned long chan_hdl,
union __packed gsi_wdi3_channel_scratch2_reg val);
/**
* gsi_write_channel_scratch_reg - Peripheral should call this function to
* write to the scratch 6, 7 reg area of the channel context
*
* @chan_hdl: Client handle previously obtained from
* gsi_alloc_channel
* @val: Value to write
*
* @Return gsi_status
*/
int gsi_write_wdi3_channel_scratch_6_7_reg(unsigned long chan_hdl,
union __packed gsi_wdi3_channel_scratch_6_7_reg val);
/**
* gsi_read_channel_scratch - Peripheral should call this function to

View file

@ -592,6 +592,17 @@
#define GSI_EE_n_GSI_CH_k_SCRATCH_3_SCRATCH_BMSK 0xffffffff
#define GSI_EE_n_GSI_CH_k_SCRATCH_3_SCRATCH_SHFT 0x0
#define GSI_EE_n_GSI_CH_k_SCRATCH_6_OFFS(k, n) \
(GSI_GSI_REG_BASE_OFFS + 0x0000f048 + 0x4000 * (n) + 0x80 * (k))
#define GSI_EE_n_GSI_CH_k_SCRATCH_3_SCRATCH_BMSK 0xffffffff
#define GSI_EE_n_GSI_CH_k_SCRATCH_3_SCRATCH_SHFT 0x0
#define GSI_EE_n_GSI_CH_k_SCRATCH_7_OFFS(k, n) \
(GSI_GSI_REG_BASE_OFFS + 0x0000f04c + 0x4000 * (n) + 0x80 * (k))
#define GSI_EE_n_GSI_CH_k_SCRATCH_3_SCRATCH_BMSK 0xffffffff
#define GSI_EE_n_GSI_CH_k_SCRATCH_3_SCRATCH_SHFT 0x0
#define GSI_EE_n_EV_CH_k_CNTXT_0_OFFS(k, n) \
(GSI_GSI_REG_BASE_OFFS + 0x00010000 + 0x4000 * (n) + 0x80 * (k))
#define GSI_EE_n_EV_CH_k_CNTXT_0_ELEMENT_SIZE_BMSK 0xff000000

View file

@ -7021,6 +7021,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
ipa3_ctx->rmnet_ctl_enable = resource_p->rmnet_ctl_enable;
ipa3_ctx->tx_wrapper_cache_max_size = get_tx_wrapper_cache_size(
resource_p->tx_wrapper_cache_max_size);
ipa3_ctx->gsi_wdi_db_polling = resource_p->gsi_wdi_db_polling;
if (resource_p->gsi_fw_file_name) {
ipa3_ctx->gsi_fw_file_name =
@ -7813,7 +7814,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
ipa_drv_res->ipa_endp_delay_wa = false;
ipa_drv_res->skip_ieob_mask_wa = false;
ipa_drv_res->ipa_gpi_event_rp_ddr = false;
ipa_drv_res->gsi_wdi_db_polling = false;
/* Get IPA HW Version */
result = of_property_read_u32(pdev->dev.of_node, "qcom,ipa-hw-ver",
&ipa_drv_res->ipa_hw_type);
@ -8062,6 +8063,12 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
ipa_drv_res->rmnet_ctl_enable
? "True" : "False");
ipa_drv_res->gsi_wdi_db_polling =
of_property_read_bool(pdev->dev.of_node,
"qcom,gsi_wdi_db_polling");
IPADBG(": gsi wdi db polling = %s\n",
ipa_drv_res->gsi_wdi_db_polling
? "True" : "False");
result = of_property_read_string(pdev->dev.of_node,
"qcom,use-gsi-ipa-fw", &ipa_drv_res->gsi_fw_file_name);
if (!result)

View file

@ -2716,6 +2716,38 @@ static ssize_t ipa3_enable_ipc_low(struct file *file,
return count;
}
static ssize_t ipa3_read_gsi_wdi3_db_polling(struct file *file,
char __user *buf, size_t count, loff_t *ppos) {
int nbytes;
nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
"gsi_wdi_db_polling = %d\n",
ipa3_ctx->gsi_wdi_db_polling);
return simple_read_from_buffer(buf, count, ppos, dbg_buff, nbytes);
}
static ssize_t ipa3_write_gsi_wdi3_db_polling(struct file *file,
const char __user *buf, size_t count, loff_t *ppos) {
int ret;
u32 gsi_wdi_db_polling =0;
if (count >= sizeof(dbg_buff))
return -EFAULT;
ret = kstrtou32_from_user(buf, count, 0, &gsi_wdi_db_polling);
if(ret)
return ret;
if(gsi_wdi_db_polling == 1)
ipa3_ctx->gsi_wdi_db_polling = true;
else if(gsi_wdi_db_polling == 0)
ipa3_ctx->gsi_wdi_db_polling = false;
else
IPAERR("Invalid value \n");
return count;
}
static const struct ipa3_debugfs_file debugfs_files[] = {
{
"gen_reg", IPA_READ_ONLY_MODE, NULL, {
@ -2889,6 +2921,11 @@ static const struct ipa3_debugfs_file debugfs_files[] = {
"app_clk_vote_cnt", IPA_READ_ONLY_MODE, NULL, {
.read = ipa3_read_app_clk_vote,
}
},{
"wdi3_db_polling_enable", IPA_READ_WRITE_MODE, NULL, {
.read = ipa3_read_gsi_wdi3_db_polling,
.write = ipa3_write_gsi_wdi3_db_polling,
}
},
};

View file

@ -491,6 +491,11 @@ enum ipa_icc_type {
#define IPA_ICC_MAX (IPA_ICC_PATH_MAX*IPA_ICC_TYPE_MAX)
enum ipa3_wdi_polling_mode {
IPA_WDI_DB_POLLING_DISABLED,
IPA_WDI_DB_POLLING_ENABLED,
};
/**
* struct ipa_rx_page_data - information needed
* to send to wlan driver on receiving data from ipa hw
@ -988,6 +993,8 @@ struct ipa3_ep_context {
u32 qmi_request_sent;
u32 eot_in_poll_err;
bool ep_delay_set;
void *tr_doorbel_va;
dma_addr_t tr_doorbel_phy;
/* sys MUST be the last element of this struct */
struct ipa3_sys_context *sys;
@ -2126,6 +2133,7 @@ struct ipa3_context {
bool rmnet_ctl_enable;
char *gsi_fw_file_name;
char *uc_fw_file_name;
bool gsi_wdi_db_polling;
};
struct ipa3_plat_drv_res {
@ -2189,6 +2197,7 @@ struct ipa3_plat_drv_res {
const char *gsi_fw_file_name;
const char *uc_fw_file_name;
u32 tx_wrapper_cache_max_size;
bool gsi_wdi_db_polling;
};
/**

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018 - 2020, The Linux Foundation. All rights reserved.
@ -428,6 +429,13 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
(1 << 8));
}
/* enable/disable wdi db polling mode based on dt value*/
if (ipa3_ctx->gsi_wdi_db_polling) {
ch_scratch.wdi3.wdi_db_polling_enabled = IPA_WDI_DB_POLLING_ENABLED;
} else {
ch_scratch.wdi3.wdi_db_polling_enabled = IPA_WDI_DB_POLLING_DISABLED;
}
result = gsi_write_channel_scratch(ep->gsi_chan_hdl, ch_scratch);
if (result != GSI_STATUS_SUCCESS) {
IPAERR("failed to write evt ring scratch\n");
@ -446,6 +454,53 @@ fail_smmu_mapping:
return result;
}
static int ipa3_wdi_gsi_db(phys_addr_t* db_addr, struct ipa3_ep_context *ep_ctx)
{
int result = 0;
struct ipa_mem_buffer mem;
union __packed gsi_wdi3_channel_scratch_6_7_reg gsi_ch_scratch;
mem.base = kzalloc(sizeof(int), GFP_KERNEL);
if (!mem.base)
{
IPAERR("failed to alloc memory mem.base\n");
return -ENOMEM;
}
memset(mem.base, 0, sizeof(int));
ep_ctx->tr_doorbel_va = mem.base;
*db_addr = virt_to_phys((void *) mem.base);
mem.phys_base = dma_map_single(ipa3_ctx->pdev, mem.base, sizeof(int), DMA_BIDIRECTIONAL);
ep_ctx->tr_doorbel_phy = mem.phys_base;
IPADBG("db_addr 0x%x, mem.base = 0x%x, mem.phys_base = 0x%x\n", (*db_addr), mem.base, mem.phys_base);
if (dma_mapping_error(ipa3_ctx->pdev, mem.phys_base)) {
IPAERR("failed to do dma mapping\n");
kfree(mem.base);
return -ENOMEM;
}
/* write channel scratch */
memset(&gsi_ch_scratch, 0, sizeof(gsi_ch_scratch));
gsi_ch_scratch.wdi3.db_addr_wp_lsb = (u32)mem.phys_base;
gsi_ch_scratch.wdi3.db_addr_wp_msb = (u32)(mem.phys_base >> 32);
IPADBG("gsi written lsb value 0x%x\n", gsi_ch_scratch.wdi3.db_addr_wp_lsb);
IPADBG("gsi written msb value 0x%x\n", gsi_ch_scratch.wdi3.db_addr_wp_msb);
result = gsi_write_wdi3_channel_scratch_6_7_reg(ep_ctx->gsi_chan_hdl, gsi_ch_scratch);
if (result != GSI_STATUS_SUCCESS) {
IPAERR("gsi_write_channel_scratch failed %d\n",
result);
dma_unmap_single(ipa3_ctx->pdev, ep_ctx->tr_doorbel_phy, sizeof(int), DMA_BIDIRECTIONAL);
kfree(mem.base);
return result;
}
return result;
}
int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
struct ipa_wdi_conn_out_params *out,
ipa_wdi_meter_notifier_cb wdi_notify)
@ -550,15 +605,27 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
result = -EFAULT;
goto fail;
}
if (gsi_query_channel_db_addr(ep_rx->gsi_chan_hdl,
&gsi_db_addr_low, &gsi_db_addr_high)) {
IPAERR("failed to query gsi rx db addr\n");
result = -EFAULT;
goto fail;
if (ipa3_ctx->gsi_wdi_db_polling) {
out->is_ddr_mapped = true;
result = ipa3_wdi_gsi_db(&(out->rx_uc_db_pa),ep_rx);
if(result){
IPAERR("fail to write db addr \n");
result = -EFAULT;
goto fail;
}
} else {
out->is_ddr_mapped = false;
if (gsi_query_channel_db_addr(ep_rx->gsi_chan_hdl,
&gsi_db_addr_low, &gsi_db_addr_high)) {
IPAERR("failed to query gsi rx db addr\n");
result = -EFAULT;
goto fail;
}
/* only 32 bit lsb is used */
out->rx_uc_db_pa = (phys_addr_t)(gsi_db_addr_low);
}
/* only 32 bit lsb is used */
out->rx_uc_db_pa = (phys_addr_t)(gsi_db_addr_low);
IPADBG("out->rx_uc_db_pa %llu\n", out->rx_uc_db_pa);
IPADBG("out->rx_uc_db_pa 0x%x\n", out->rx_uc_db_pa);
ipa3_install_dflt_flt_rules(ipa_ep_idx_rx);
IPADBG("client %d (ep: %d) connected\n", rx_client,
@ -601,14 +668,24 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
result = -EFAULT;
goto fail;
}
if (gsi_query_channel_db_addr(ep_tx->gsi_chan_hdl,
&gsi_db_addr_low, &gsi_db_addr_high)) {
IPAERR("failed to query gsi tx db addr\n");
result = -EFAULT;
goto fail;
if (ipa3_ctx->gsi_wdi_db_polling) {
result = ipa3_wdi_gsi_db(&(out->tx_uc_db_pa),ep_tx);
if(result){
IPAERR("fail to write db addr \n");
result = -EFAULT;
goto fail;
}
} else {
if (gsi_query_channel_db_addr(ep_tx->gsi_chan_hdl,
&gsi_db_addr_low, &gsi_db_addr_high)) {
IPAERR("failed to query gsi tx db addr\n");
result = -EFAULT;
goto fail;
}
/* only 32 bit lsb is used */
out->tx_uc_db_pa = (phys_addr_t)(gsi_db_addr_low);
}
/* only 32 bit lsb is used */
out->tx_uc_db_pa = (phys_addr_t)(gsi_db_addr_low);
IPADBG("out->tx_uc_db_pa %llu\n", out->tx_uc_db_pa);
IPADBG("client %d (ep: %d) connected\n", tx_client,
ipa_ep_idx_tx);
@ -690,6 +767,14 @@ int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
ep_rx = &ipa3_ctx->ep[ipa_ep_idx_rx];
IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(ipa_ep_idx_tx));
if (ipa3_ctx->gsi_wdi_db_polling) {
IPADBG("gsi_wdi_db_polling enabled, free and unmap ddr addr\n");
dma_unmap_single(ipa3_ctx->pdev, ep_tx->tr_doorbel_phy, sizeof(int), DMA_BIDIRECTIONAL);
dma_unmap_single(ipa3_ctx->pdev, ep_rx->tr_doorbel_phy, sizeof(int), DMA_BIDIRECTIONAL);
kfree(ep_tx->tr_doorbel_va);
kfree(ep_rx->tr_doorbel_va);
}
/* tear down tx pipe */
result = ipa3_reset_gsi_channel(ipa_ep_idx_tx);
if (result != GSI_STATUS_SUCCESS) {