diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index df9f377adcac..4d86f9795948 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -454,6 +454,51 @@ int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt, } EXPORT_SYMBOL(ipa3_smmu_map_peer_buff); +int ipa3_smmu_map_ctg(u64 iova, u32 size, bool map, phys_addr_t pa, + enum ipa_smmu_cb_type cb_type) +{ + struct iommu_domain *smmu_domain; + int res; + phys_addr_t phys; + unsigned long va; + size_t len; + + if (cb_type >= IPA_SMMU_CB_MAX) { + IPAERR("invalid cb_type\n"); + return -EINVAL; + } + + if (ipa3_ctx->s1_bypass_arr[cb_type]) { + IPADBG("CB# %d is set to s1 bypass\n", cb_type); + return 0; + } + + smmu_domain = ipa3_get_smmu_domain_by_type(cb_type); + if (!smmu_domain) { + IPAERR("invalid smmu domain\n"); + return -EINVAL; + } + + if (map) { + va = rounddown(iova, PAGE_SIZE); + phys = rounddown(pa, PAGE_SIZE); + len = size + ((iova - va > pa - phys) ? + (iova-va) : (pa - phys)); + res = ipa3_iommu_map(smmu_domain, va, phys, + roundup(len, PAGE_SIZE), + IOMMU_READ | IOMMU_WRITE); + } else { + va = rounddown(iova, PAGE_SIZE); + phys = rounddown(pa, PAGE_SIZE); + len = size + ((iova - va > pa - phys) ? + (iova-va) : (pa - phys)); + res = iommu_unmap(smmu_domain, va, + roundup(len, PAGE_SIZE)); + } + IPADBG("ctg %s 0x%llx to 0x%llx\n", map ? "map" : "unmap", pa, iova); + return 0; +} + static enum ipa_client_cb_type ipa_get_client_cb_type( enum ipa_client_type client_type) { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index e0b43c7d6236..1e1e0bcd19f7 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -3084,6 +3084,8 @@ int ipa3_smmu_map_peer_reg(phys_addr_t phys_addr, bool map, enum ipa_smmu_cb_type cb_type); int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt, enum ipa_smmu_cb_type cb_type); +int ipa3_smmu_map_ctg(u64 iova, u32 size, bool map, phys_addr_t pa, + enum ipa_smmu_cb_type cb_type); void ipa3_reset_freeze_vote(void); int ipa3_ntn_init(void); int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c index 85a26d32c888..526f5246ffd8 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c @@ -7,6 +7,7 @@ #define IPA_UC_NTN_DB_PA_TX 0x79620DC #define IPA_UC_NTN_DB_PA_RX 0x79620D8 +#define IPA_UC_RING_ELEM_SZ 16 static void ipa3_uc_ntn_event_log_info_handler( struct IpaHwEventLogInfoData_t *uc_event_top_mmio) @@ -287,13 +288,31 @@ static int ipa3_smmu_map_uc_ntn_pipes(struct ipa_ntn_setup_info *params, } if (params->smmu_enabled) { IPADBG("smmu is enabled on EMAC\n"); - result = ipa3_smmu_map_peer_buff((u64)params->ring_base_iova, - params->ntn_ring_size, map, params->ring_base_sgt, - IPA_SMMU_CB_UC); - if (result) { - IPAERR("failed to %s ntn ring %d\n", - map ? "map" : "unmap", result); - goto fail_map_ring; + if (params->ring_base_sgt) { + result = ipa3_smmu_map_peer_buff( + (u64)params->ring_base_iova, + params->ntn_ring_size, map, + params->ring_base_sgt, + IPA_SMMU_CB_UC); + if (result) { + IPAERR("failed to %s ntn ring %d\n", + map ? "map" : "unmap", result); + goto fail_map_ring; + } + } else { + /* Eth driver passes # of elements instead of sz + * Calc & pass the ring size to map contigous mem + */ + result = ipa3_smmu_map_ctg( + (u64)params->ring_base_iova, + params->ntn_ring_size*IPA_UC_RING_ELEM_SZ, + map, params->ring_base_pa, + IPA_SMMU_CB_UC); + if (result) { + IPAERR("failed to %s ntn ring %d\n", + map ? "map" : "unmap", result); + goto fail_map_ring; + } } result = ipa3_smmu_map_peer_buff( (u64)params->buff_pool_base_iova, @@ -367,9 +386,15 @@ fail_map_data_buff_smmu_disabled: params->num_buffers * 4, !map, NULL, IPA_SMMU_CB_UC); goto fail_map_buffer_smmu_disabled; fail_map_buffer_smmu_enabled: - ipa3_smmu_map_peer_buff((u64)params->ring_base_iova, - params->ntn_ring_size, !map, params->ring_base_sgt, - IPA_SMMU_CB_UC); + if (params->ring_base_sgt) { + ipa3_smmu_map_peer_buff((u64)params->ring_base_iova, + params->ntn_ring_size, !map, params->ring_base_sgt, + IPA_SMMU_CB_UC); + } else { + ipa3_smmu_map_ctg((u64)params->ring_base_iova, + params->ntn_ring_size*IPA_UC_RING_ELEM_SZ, !map, + params->ring_base_pa, IPA_SMMU_CB_UC); + } goto fail_map_ring; fail_map_buffer_smmu_disabled: ipa3_smmu_map_peer_buff((u64)params->ring_base_pa, @@ -475,6 +500,8 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in, /* setup dl ep cfg */ ep_dl->valid = 1; ep_dl->client = in->dl.client; + ep_dl->client_notify = notify; + ep_dl->priv = priv; memset(&ep_dl->cfg, 0, sizeof(ep_ul->cfg)); ep_dl->cfg.nat.nat_en = IPA_BYPASS_NAT; ep_dl->cfg.hdr.hdr_len = hdr_len;