From 4864c2459c2b98873bb393f857a2cd3ad25d0e62 Mon Sep 17 00:00:00 2001 From: Ashok Vuyyuru Date: Fri, 10 Jan 2020 16:38:34 +0530 Subject: [PATCH] msm: ipa4: Add changes to support PCIe addr for WDI2 over GSI Add changes to support PCIe addr for WDI2 over GSI Change-Id: I9084e735b5eb4a75cefc2daeaa22340a5014b2b4 Signed-off-by: Pooja Kumari Signed-off-by: Ashok Vuyyuru --- .../platform/msm/ipa/ipa_clients/ipa_wdi3.c | 16 ++ drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c | 159 +++++++++++++++++- include/linux/ipa.h | 18 +- 3 files changed, 188 insertions(+), 5 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c index b4f054f76434..31ef0ae6e5e9 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c @@ -558,6 +558,10 @@ int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in, in->u_rx.rx.event_ring_doorbell_pa; in_rx.u.ul.rdy_comp_ring_size = in->u_rx.rx.event_ring_size; + in_rx.u.ul.is_txr_rn_db_pcie_addr = + in->u_rx.rx.is_txr_rn_db_pcie_addr; + in_rx.u.ul.is_evt_rn_db_pcie_addr = + in->u_rx.rx.is_evt_rn_db_pcie_addr; if (ipa_connect_wdi_pipe(&in_rx, &out_rx)) { IPA_WDI_ERR("fail to setup rx pipe\n"); ret = -EFAULT; @@ -583,6 +587,10 @@ int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in, in->u_tx.tx.event_ring_size; in_tx.u.dl.num_tx_buffers = in->u_tx.tx.num_pkt_buffers; + in_tx.u.dl.is_txr_rn_db_pcie_addr = + in->u_tx.tx.is_txr_rn_db_pcie_addr; + in_tx.u.dl.is_evt_rn_db_pcie_addr = + in->u_tx.tx.is_evt_rn_db_pcie_addr; if (ipa_connect_wdi_pipe(&in_tx, &out_tx)) { IPA_WDI_ERR("fail to setup tx pipe\n"); ret = -EFAULT; @@ -610,6 +618,10 @@ int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in, in->u_rx.rx_smmu.event_ring_doorbell_pa; in_rx.u.ul_smmu.rdy_comp_ring_size = in->u_rx.rx_smmu.event_ring_size; + in_rx.u.ul_smmu.is_txr_rn_db_pcie_addr = + in->u_rx.rx_smmu.is_txr_rn_db_pcie_addr; + in_rx.u.ul_smmu.is_evt_rn_db_pcie_addr = + in->u_rx.rx_smmu.is_evt_rn_db_pcie_addr; if (ipa_connect_wdi_pipe(&in_rx, &out_rx)) { IPA_WDI_ERR("fail to setup rx pipe\n"); ret = -EFAULT; @@ -635,6 +647,10 @@ int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in, in->u_tx.tx_smmu.event_ring_size; in_tx.u.dl_smmu.num_tx_buffers = in->u_tx.tx_smmu.num_pkt_buffers; + in_tx.u.dl_smmu.is_txr_rn_db_pcie_addr = + in->u_tx.tx_smmu.is_txr_rn_db_pcie_addr; + in_tx.u.dl_smmu.is_evt_rn_db_pcie_addr = + in->u_tx.tx_smmu.is_evt_rn_db_pcie_addr; if (ipa_connect_wdi_pipe(&in_tx, &out_tx)) { IPA_WDI_ERR("fail to setup tx pipe\n"); ret = -EFAULT; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c index 24350131fe05..599cddd4bfa6 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c @@ -1184,6 +1184,8 @@ int ipa3_connect_gsi_wdi_pipe(struct ipa_wdi_in_params *in, unsigned long wifi_rx_ri_addr = 0; u32 gsi_db_reg_phs_addr_lsb; u32 gsi_db_reg_phs_addr_msb; + uint32_t addr_low, addr_high; + bool is_evt_rn_db_pcie_addr, is_txr_rn_db_pcie_addr; ipa_ep_idx = ipa3_get_ep_mapping(in->sys.client); if (ipa_ep_idx == -1) { @@ -1439,6 +1441,99 @@ int ipa3_connect_gsi_wdi_pipe(struct ipa_wdi_in_params *in, &ep->gsi_evt_ring_hdl); if (result) goto fail_alloc_evt_ring; + + is_evt_rn_db_pcie_addr = IPA_CLIENT_IS_CONS(in->sys.client) ? + in->u.dl.is_evt_rn_db_pcie_addr : + in->u.ul.is_evt_rn_db_pcie_addr; + + if (IPA_CLIENT_IS_CONS(in->sys.client)) { + is_evt_rn_db_pcie_addr = in->smmu_enabled ? + in->u.dl_smmu.is_evt_rn_db_pcie_addr : + in->u.dl.is_evt_rn_db_pcie_addr; + gsi_evt_ring_props.rp_update_addr = in->smmu_enabled ? + in->u.dl_smmu.ce_door_bell_pa : + in->u.dl.ce_door_bell_pa; + } else { + is_evt_rn_db_pcie_addr = in->smmu_enabled ? + in->u.ul_smmu.is_evt_rn_db_pcie_addr : + in->u.ul.is_evt_rn_db_pcie_addr; + gsi_evt_ring_props.rp_update_addr = in->smmu_enabled ? + in->u.ul_smmu.rdy_comp_ring_wp_pa : + in->u.ul.rdy_comp_ring_wp_pa; + } + if (!in->smmu_enabled) { + IPADBG("smmu disabled\n"); + if (is_evt_rn_db_pcie_addr == true) + IPADBG("is_evt_rn_db_pcie_addr is PCIE addr\n"); + else + IPADBG("is_evt_rn_db_pcie_addr is DDR addr\n"); + + addr_low = (u32)gsi_evt_ring_props.rp_update_addr; + addr_high = (u32)((u64)gsi_evt_ring_props.rp_update_addr >> 32); + } else { + IPADBG("smmu enabled\n"); + if (is_evt_rn_db_pcie_addr == true) + IPADBG("is_evt_rn_db_pcie_addr is PCIE addr\n"); + else + IPADBG("is_evt_rn_db_pcie_addr is DDR addr\n"); + + if (IPA_CLIENT_IS_CONS(in->sys.client)) { + if (ipa_create_gsi_smmu_mapping(IPA_WDI_CE_DB_RES, + true, gsi_evt_ring_props.rp_update_addr, + NULL, 4, true, &va)) { + IPAERR("failed to get smmu mapping\n"); + result = -EFAULT; + goto fail_alloc_evt_ring; + } + } else { + if (ipa_create_gsi_smmu_mapping( + IPA_WDI_RX_COMP_RING_WP_RES, + true, gsi_evt_ring_props.rp_update_addr, + NULL, 4, true, &va)) { + IPAERR("failed to get smmu mapping\n"); + result = -EFAULT; + goto fail_alloc_evt_ring; + } + } + addr_low = (u32)va; + addr_high = (u32)((u64)va >> 32); + + } + + /* + * Arch specific: + * pcie addr which are not via smmu, use pa directly! + * pcie and DDR via 2 different port + * assert bit 40 to indicate it is pcie addr + * WDI-3.0, MSM --> pcie via smmu + * WDI-3.0, MDM --> pcie not via smmu + dual port + * assert bit 40 in case + */ + if (!ipa3_is_msm_device() && + in->smmu_enabled) { + /* + * Ir-respective of smmu enabled don't use IOVA addr + * since pcie not via smmu in MDM's + */ + if (is_evt_rn_db_pcie_addr == true) { + addr_low = (u32)gsi_evt_ring_props.rp_update_addr; + addr_high = + (u32)((u64)gsi_evt_ring_props.rp_update_addr + >> 32); + } + } + + /* + * GSI recomendation to set bit-40 for (mdm targets && pcie addr) + * from wdi-3.0 interface document + */ + if (!ipa3_is_msm_device() && is_evt_rn_db_pcie_addr) + addr_high |= (1 << 8); + + gsi_wdi3_write_evt_ring_db(ep->gsi_evt_ring_hdl, addr_low, + addr_high); + + /*copy mem info */ ep->gsi_mem_info.evt_ring_len = gsi_evt_ring_props.ring_len; ep->gsi_mem_info.evt_ring_base_addr = gsi_evt_ring_props.ring_base_addr; @@ -1479,14 +1574,70 @@ int ipa3_connect_gsi_wdi_pipe(struct ipa_wdi_in_params *in, gsi_scratch.wdi.wdi_rx_tre_proc_in_progress = 0; } else { if (IPA_CLIENT_IS_PROD(in->sys.client)) { - gsi_scratch.wdi2_new.wifi_rx_ri_addr_low = - wifi_rx_ri_addr & 0xFFFFFFFF; - gsi_scratch.wdi2_new.wifi_rx_ri_addr_high = + is_txr_rn_db_pcie_addr = + in->smmu_enabled ? + in->u.ul_smmu.is_txr_rn_db_pcie_addr : + in->u.ul.is_txr_rn_db_pcie_addr; + if (!in->smmu_enabled) { + IPADBG("smmu disabled\n"); + gsi_scratch.wdi2_new.wifi_rx_ri_addr_low = + in->u.ul.rdy_ring_rp_pa & 0xFFFFFFFF; + gsi_scratch.wdi2_new.wifi_rx_ri_addr_high = + (in->u.ul.rdy_ring_rp_pa & + 0xFFFFF00000000) >> 32; + + } else { + IPADBG("smmu eabled\n"); + + gsi_scratch.wdi2_new.wifi_rx_ri_addr_low = + wifi_rx_ri_addr & 0xFFFFFFFF; + gsi_scratch.wdi2_new.wifi_rx_ri_addr_high = (wifi_rx_ri_addr & 0xFFFFF00000000) >> 32; + + } + + + /* + * Arch specific: + * pcie addr which are not via smmu, use pa directly! + * pcie and DDR via 2 different port + * assert bit 40 to indicate it is pcie addr + * WDI-3.0, MSM --> pcie via smmu + * WDI-3.0, MDM --> pcie not via smmu + dual port + * assert bit 40 in case + */ + if (!ipa3_is_msm_device() && + in->smmu_enabled) { + /* + * Ir-respective of smmu enabled don't use IOVA + * addr since pcie not via smmu in MDM's + */ + if (is_txr_rn_db_pcie_addr == true) { + gsi_scratch.wdi2_new.wifi_rx_ri_addr_low + = in->u.ul_smmu.rdy_ring_rp_pa + & 0xFFFFFFFF; + gsi_scratch.wdi2_new.wifi_rx_ri_addr_high = + (in->u.ul_smmu.rdy_ring_rp_pa & + 0xFFFFF00000000) >> 32; + } + } + + /* + * GSI recomendation to set bit-40 for + * (mdm targets && pcie addr) from wdi-3.0 + * interface document + */ + + if (!ipa3_is_msm_device() && is_txr_rn_db_pcie_addr) + gsi_scratch.wdi2_new.wifi_rx_ri_addr_high = + (u32)((u32) + gsi_scratch.wdi2_new.wifi_rx_ri_addr_high | + (1 << 8)); + gsi_scratch.wdi2_new.wdi_rx_vdev_id = 0xff; gsi_scratch.wdi2_new.wdi_rx_fw_desc = 0xff; gsi_scratch.wdi2_new.endp_metadatareg_offset = - ipahal_get_reg_mn_ofst( + ipahal_get_reg_mn_ofst( IPA_ENDP_INIT_HDR_METADATA_n, 0, ipa_ep_idx)/4; gsi_scratch.wdi2_new.qmap_id = 0; diff --git a/include/linux/ipa.h b/include/linux/ipa.h index a99cad2912c7..7ffb48990c5e 100644 --- a/include/linux/ipa.h +++ b/include/linux/ipa.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2020, 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 @@ -1051,6 +1051,8 @@ struct IpaHwStatsWDIInfoData_t { * uc is writing (WDI-2.0) * @rdy_comp_ring_size: size of the Rx_completion ring in bytes * expected to communicate about the Read pointer into the Rx Ring + * @is_txr_rn_db_pcie_addr: tx ring PCIE doorbell address + * @is_evt_rn_db_pcie_addr: event ring PCIE doorbell address */ struct ipa_wdi_ul_params { phys_addr_t rdy_ring_base_pa; @@ -1061,6 +1063,8 @@ struct ipa_wdi_ul_params { u32 rdy_comp_ring_size; u32 *rdy_ring_rp_va; u32 *rdy_comp_ring_wp_va; + bool is_txr_rn_db_pcie_addr; + bool is_evt_rn_db_pcie_addr; }; /** @@ -1069,6 +1073,8 @@ struct ipa_wdi_ul_params { * @rdy_ring_size: size of the Rx ring in bytes * @rdy_ring_rp_pa: physical address of the location through which IPA uc is * expected to communicate about the Read pointer into the Rx Ring + * @is_txr_rn_db_pcie_addr: tx ring PCIE doorbell address + * @is_evt_rn_db_pcie_addr: event ring PCIE doorbell address */ struct ipa_wdi_ul_params_smmu { struct sg_table rdy_ring; @@ -1079,6 +1085,8 @@ struct ipa_wdi_ul_params_smmu { u32 rdy_comp_ring_size; u32 *rdy_ring_rp_va; u32 *rdy_comp_ring_wp_va; + bool is_txr_rn_db_pcie_addr; + bool is_evt_rn_db_pcie_addr; }; /** @@ -1091,6 +1099,8 @@ struct ipa_wdi_ul_params_smmu { * write into to trigger the copy engine * @ce_ring_size: Copy Engine Ring size in bytes * @num_tx_buffers: Number of pkt buffers allocated + * @is_txr_rn_db_pcie_addr: tx ring PCIE doorbell address + * @is_evt_rn_db_pcie_addr: event ring PCIE doorbell address */ struct ipa_wdi_dl_params { phys_addr_t comp_ring_base_pa; @@ -1099,6 +1109,8 @@ struct ipa_wdi_dl_params { phys_addr_t ce_door_bell_pa; u32 ce_ring_size; u32 num_tx_buffers; + bool is_txr_rn_db_pcie_addr; + bool is_evt_rn_db_pcie_addr; }; /** @@ -1110,6 +1122,8 @@ struct ipa_wdi_dl_params { * write into to trigger the copy engine * @ce_ring_size: Copy Engine Ring size in bytes * @num_tx_buffers: Number of pkt buffers allocated + * @is_txr_rn_db_pcie_addr: tx ring PCIE doorbell address + * @is_evt_rn_db_pcie_addr: event ring PCIE doorbell address */ struct ipa_wdi_dl_params_smmu { struct sg_table comp_ring; @@ -1118,6 +1132,8 @@ struct ipa_wdi_dl_params_smmu { phys_addr_t ce_door_bell_pa; u32 ce_ring_size; u32 num_tx_buffers; + bool is_txr_rn_db_pcie_addr; + bool is_evt_rn_db_pcie_addr; }; /**