mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 06:09:23 -04:00
Merge "msm: ipa: Add change to support wdi gsi db polling"
This commit is contained in:
commit
7e372e6a9d
7 changed files with 235 additions and 17 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue