Loading drivers/platform/msm/ipa/ipa_api.c +42 −2 Original line number Diff line number Diff line Loading @@ -294,6 +294,46 @@ u8 *ipa_pad_to_32(u8 *dest) return dest; } int ipa_smmu_store_sgt(struct sg_table **out_ch_ptr, struct sg_table *in_sgt_ptr) { unsigned int nents; if (in_sgt_ptr != NULL) { *out_ch_ptr = kzalloc(sizeof(struct sg_table), GFP_KERNEL); if (*out_ch_ptr == NULL) return -ENOMEM; nents = in_sgt_ptr->nents; (*out_ch_ptr)->sgl = kcalloc(nents, sizeof(struct scatterlist), GFP_KERNEL); if ((*out_ch_ptr)->sgl == NULL) { kfree(*out_ch_ptr); *out_ch_ptr = NULL; return -ENOMEM; } memcpy((*out_ch_ptr)->sgl, in_sgt_ptr->sgl, nents*sizeof((*out_ch_ptr)->sgl)); (*out_ch_ptr)->nents = nents; (*out_ch_ptr)->orig_nents = in_sgt_ptr->orig_nents; } return 0; } int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr) { if (*out_sgt_ptr != NULL) { kfree((*out_sgt_ptr)->sgl); (*out_sgt_ptr)->sgl = NULL; kfree(*out_sgt_ptr); *out_sgt_ptr = NULL; } return 0; } /** * ipa_connect() - low-level IPA client connect * @in: [in] input parameters from client Loading Loading @@ -3111,12 +3151,12 @@ int ipa_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *inp, * ipa_tear_down_uc_offload_pipes() - tear down uc offload pipes */ int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl) int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params) { int ret; IPA_API_DISPATCH_RETURN(ipa_tear_down_uc_offload_pipes, ipa_ep_idx_ul, ipa_ep_idx_dl); ipa_ep_idx_dl, params); return ret; } Loading drivers/platform/msm/ipa/ipa_api.h +1 −1 Original line number Diff line number Diff line Loading @@ -394,7 +394,7 @@ struct ipa_api_controller { struct ipa_ntn_conn_out_params *); int (*ipa_tear_down_uc_offload_pipes)(int ipa_ep_idx_ul, int ipa_ep_idx_dl); int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params); struct device *(*ipa_get_pdev)(void); Loading drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c +77 −3 Original line number Diff line number Diff line /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018 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 Loading Loading @@ -73,6 +73,7 @@ struct ipa_uc_offload_ctx { ipa_notify_cb notify; struct completion ntn_completion; u32 pm_hdl; struct ipa_ntn_conn_in_params conn; }; static struct ipa_uc_offload_ctx *ipa_uc_offload_ctx[IPA_UC_MAX_PROT_SIZE]; Loading Loading @@ -403,6 +404,51 @@ static void ipa_uc_offload_rm_notify(void *user_data, enum ipa_rm_event event, } } static int ipa_uc_ntn_alloc_conn_smmu_info(struct ipa_ntn_setup_info *dest, struct ipa_ntn_setup_info *source) { int result; IPA_UC_OFFLOAD_DBG("Allocating smmu info\n"); memcpy(dest, source, sizeof(struct ipa_ntn_setup_info)); dest->data_buff_list = kcalloc(dest->num_buffers, sizeof(struct ntn_buff_smmu_map), GFP_KERNEL); if (dest->data_buff_list == NULL) { IPA_UC_OFFLOAD_ERR("failed to alloc smmu info\n"); return -ENOMEM; } memcpy(dest->data_buff_list, source->data_buff_list, sizeof(struct ntn_buff_smmu_map) * dest->num_buffers); result = ipa_smmu_store_sgt(&dest->buff_pool_base_sgt, source->buff_pool_base_sgt); if (result) { kfree(dest->data_buff_list); return result; } result = ipa_smmu_store_sgt(&dest->ring_base_sgt, source->ring_base_sgt); if (result) { kfree(dest->data_buff_list); ipa_smmu_free_sgt(&dest->buff_pool_base_sgt); return result; } return 0; } static void ipa_uc_ntn_free_conn_smmu_info(struct ipa_ntn_setup_info *params) { kfree(params->data_buff_list); ipa_smmu_free_sgt(¶ms->buff_pool_base_sgt); ipa_smmu_free_sgt(¶ms->ring_base_sgt); } int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp, struct ipa_ntn_conn_out_params *outp, struct ipa_uc_offload_ctx *ntn_ctx) Loading @@ -410,6 +456,11 @@ int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp, int result = 0; enum ipa_uc_offload_state prev_state; if (ntn_ctx->conn.dl.smmu_enabled != ntn_ctx->conn.ul.smmu_enabled) { IPA_UC_OFFLOAD_ERR("ul and dl smmu enablement do not match\n"); return -EINVAL; } prev_state = ntn_ctx->state; if (inp->dl.ring_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT || inp->dl.buff_pool_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT) { Loading Loading @@ -467,7 +518,21 @@ int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp, goto fail; } return 0; if (ntn_ctx->conn.dl.smmu_enabled) { result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.dl, &inp->dl); if (result) { IPA_UC_OFFLOAD_ERR("alloc failure on TX\n"); goto fail; } result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.ul, &inp->ul); if (result) { ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.dl); IPA_UC_OFFLOAD_ERR("alloc failure on RX\n"); goto fail; } } fail: if (!ipa_pm_is_used()) Loading Loading @@ -563,6 +628,11 @@ static int ipa_uc_ntn_disconn_pipes(struct ipa_uc_offload_ctx *ntn_ctx) int ipa_ep_idx_ul, ipa_ep_idx_dl; int ret = 0; if (ntn_ctx->conn.dl.smmu_enabled != ntn_ctx->conn.ul.smmu_enabled) { IPA_UC_OFFLOAD_ERR("ul and dl smmu enablement do not match\n"); return -EINVAL; } ntn_ctx->state = IPA_UC_OFFLOAD_STATE_INITIALIZED; #ifdef CONFIG_IPA3 Loading Loading @@ -594,12 +664,16 @@ static int ipa_uc_ntn_disconn_pipes(struct ipa_uc_offload_ctx *ntn_ctx) ipa_ep_idx_ul = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_PROD); ipa_ep_idx_dl = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_CONS); ret = ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl); ret = ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl, &ntn_ctx->conn); if (ret) { IPA_UC_OFFLOAD_ERR("fail to tear down ntn offload pipes, %d\n", ret); return -EFAULT; } if (ntn_ctx->conn.dl.smmu_enabled) ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.dl); ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.ul); return ret; } Loading drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +15 −49 Original line number Diff line number Diff line Loading @@ -1149,7 +1149,8 @@ static int ipa3_usb_smmu_map_xdci_channel( if (ipa3_usb_ctx->smmu_reg_map.cnt == 0) { ipa3_usb_ctx->smmu_reg_map.addr = gevntcount_r; result = ipa3_smmu_map_peer_reg( ipa3_usb_ctx->smmu_reg_map.addr, true); ipa3_usb_ctx->smmu_reg_map.addr, true, IPA_SMMU_CB_AP); if (result) { IPA_USB_ERR("failed to map USB regs %d\n", result); Loading @@ -1172,7 +1173,8 @@ static int ipa3_usb_smmu_map_xdci_channel( if (ipa3_usb_ctx->smmu_reg_map.cnt == 1) { result = ipa3_smmu_map_peer_reg( ipa3_usb_ctx->smmu_reg_map.addr, false); ipa3_usb_ctx->smmu_reg_map.addr, false, IPA_SMMU_CB_AP); if (result) { IPA_USB_ERR("failed to unmap USB regs %d\n", result); Loading @@ -1184,14 +1186,16 @@ static int ipa3_usb_smmu_map_xdci_channel( result = ipa3_smmu_map_peer_buff(params->xfer_ring_base_addr_iova, params->xfer_ring_len, map, params->sgt_xfer_rings); params->xfer_ring_len, map, params->sgt_xfer_rings, IPA_SMMU_CB_AP); if (result) { IPA_USB_ERR("failed to map Xfer ring %d\n", result); return result; } result = ipa3_smmu_map_peer_buff(params->data_buff_base_addr_iova, params->data_buff_base_len, map, params->sgt_data_buff); params->data_buff_base_len, map, params->sgt_data_buff, IPA_SMMU_CB_AP); if (result) { IPA_USB_ERR("failed to map TRBs buff %d\n", result); return result; Loading @@ -1200,43 +1204,6 @@ static int ipa3_usb_smmu_map_xdci_channel( return 0; } static int ipa3_usb_smmu_store_sgt(struct sg_table **out_ch_ptr, struct sg_table *in_sgt_ptr) { unsigned int nents; if (in_sgt_ptr != NULL) { *out_ch_ptr = kzalloc(sizeof(struct sg_table), GFP_KERNEL); if (*out_ch_ptr == NULL) return -ENOMEM; nents = in_sgt_ptr->nents; (*out_ch_ptr)->sgl = kcalloc(nents, sizeof(struct scatterlist), GFP_KERNEL); if ((*out_ch_ptr)->sgl == NULL) return -ENOMEM; memcpy((*out_ch_ptr)->sgl, in_sgt_ptr->sgl, nents*sizeof((*out_ch_ptr)->sgl)); (*out_ch_ptr)->nents = nents; (*out_ch_ptr)->orig_nents = in_sgt_ptr->orig_nents; } return 0; } static int ipa3_usb_smmu_free_sgt(struct sg_table **out_sgt_ptr) { if (*out_sgt_ptr != NULL) { kfree((*out_sgt_ptr)->sgl); (*out_sgt_ptr)->sgl = NULL; kfree(*out_sgt_ptr); *out_sgt_ptr = NULL; } return 0; } static int ipa3_usb_request_xdci_channel( struct ipa_usb_xdci_chan_params *params, enum ipa_usb_direction dir, Loading Loading @@ -1327,18 +1294,17 @@ static int ipa3_usb_request_xdci_channel( xdci_ch_params = &ipa3_usb_ctx->ttype_ctx[ttype].dl_ch_params; *xdci_ch_params = *params; result = ipa3_usb_smmu_store_sgt( result = ipa_smmu_store_sgt( &xdci_ch_params->sgt_xfer_rings, params->sgt_xfer_rings); if (result) { ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings); if (result) return result; } result = ipa3_usb_smmu_store_sgt( result = ipa_smmu_store_sgt( &xdci_ch_params->sgt_data_buff, params->sgt_data_buff); if (result) { ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_data_buff); ipa_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings); return result; } chan_params.keep_ipa_awake = params->keep_ipa_awake; Loading Loading @@ -1443,9 +1409,9 @@ static int ipa3_usb_release_xdci_channel(u32 clnt_hdl, result = ipa3_usb_smmu_map_xdci_channel(xdci_ch_params, false); if (xdci_ch_params->sgt_xfer_rings != NULL) ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings); ipa_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings); if (xdci_ch_params->sgt_data_buff != NULL) ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_data_buff); ipa_smmu_free_sgt(&xdci_ch_params->sgt_data_buff); /* Change ipa_usb state to INITIALIZED */ if (!ipa3_usb_set_state(IPA_USB_INITIALIZED, false, ttype)) Loading drivers/platform/msm/ipa/ipa_common_i.h +6 −1 Original line number Diff line number Diff line Loading @@ -408,7 +408,8 @@ int ipa_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in, ipa_notify_cb notify, void *priv, u8 hdr_len, struct ipa_ntn_conn_out_params *outp); int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl); int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params); u8 *ipa_write_64(u64 w, u8 *dest); u8 *ipa_write_32(u32 w, u8 *dest); u8 *ipa_write_16(u16 hw, u8 *dest); Loading @@ -434,4 +435,8 @@ int ipa_start_gsi_channel(u32 clnt_hdl); bool ipa_pm_is_used(void); int ipa_smmu_store_sgt(struct sg_table **out_ch_ptr, struct sg_table *in_sgt_ptr); int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr); #endif /* _IPA_COMMON_I_H_ */ Loading
drivers/platform/msm/ipa/ipa_api.c +42 −2 Original line number Diff line number Diff line Loading @@ -294,6 +294,46 @@ u8 *ipa_pad_to_32(u8 *dest) return dest; } int ipa_smmu_store_sgt(struct sg_table **out_ch_ptr, struct sg_table *in_sgt_ptr) { unsigned int nents; if (in_sgt_ptr != NULL) { *out_ch_ptr = kzalloc(sizeof(struct sg_table), GFP_KERNEL); if (*out_ch_ptr == NULL) return -ENOMEM; nents = in_sgt_ptr->nents; (*out_ch_ptr)->sgl = kcalloc(nents, sizeof(struct scatterlist), GFP_KERNEL); if ((*out_ch_ptr)->sgl == NULL) { kfree(*out_ch_ptr); *out_ch_ptr = NULL; return -ENOMEM; } memcpy((*out_ch_ptr)->sgl, in_sgt_ptr->sgl, nents*sizeof((*out_ch_ptr)->sgl)); (*out_ch_ptr)->nents = nents; (*out_ch_ptr)->orig_nents = in_sgt_ptr->orig_nents; } return 0; } int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr) { if (*out_sgt_ptr != NULL) { kfree((*out_sgt_ptr)->sgl); (*out_sgt_ptr)->sgl = NULL; kfree(*out_sgt_ptr); *out_sgt_ptr = NULL; } return 0; } /** * ipa_connect() - low-level IPA client connect * @in: [in] input parameters from client Loading Loading @@ -3111,12 +3151,12 @@ int ipa_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *inp, * ipa_tear_down_uc_offload_pipes() - tear down uc offload pipes */ int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl) int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params) { int ret; IPA_API_DISPATCH_RETURN(ipa_tear_down_uc_offload_pipes, ipa_ep_idx_ul, ipa_ep_idx_dl); ipa_ep_idx_dl, params); return ret; } Loading
drivers/platform/msm/ipa/ipa_api.h +1 −1 Original line number Diff line number Diff line Loading @@ -394,7 +394,7 @@ struct ipa_api_controller { struct ipa_ntn_conn_out_params *); int (*ipa_tear_down_uc_offload_pipes)(int ipa_ep_idx_ul, int ipa_ep_idx_dl); int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params); struct device *(*ipa_get_pdev)(void); Loading
drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c +77 −3 Original line number Diff line number Diff line /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018 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 Loading Loading @@ -73,6 +73,7 @@ struct ipa_uc_offload_ctx { ipa_notify_cb notify; struct completion ntn_completion; u32 pm_hdl; struct ipa_ntn_conn_in_params conn; }; static struct ipa_uc_offload_ctx *ipa_uc_offload_ctx[IPA_UC_MAX_PROT_SIZE]; Loading Loading @@ -403,6 +404,51 @@ static void ipa_uc_offload_rm_notify(void *user_data, enum ipa_rm_event event, } } static int ipa_uc_ntn_alloc_conn_smmu_info(struct ipa_ntn_setup_info *dest, struct ipa_ntn_setup_info *source) { int result; IPA_UC_OFFLOAD_DBG("Allocating smmu info\n"); memcpy(dest, source, sizeof(struct ipa_ntn_setup_info)); dest->data_buff_list = kcalloc(dest->num_buffers, sizeof(struct ntn_buff_smmu_map), GFP_KERNEL); if (dest->data_buff_list == NULL) { IPA_UC_OFFLOAD_ERR("failed to alloc smmu info\n"); return -ENOMEM; } memcpy(dest->data_buff_list, source->data_buff_list, sizeof(struct ntn_buff_smmu_map) * dest->num_buffers); result = ipa_smmu_store_sgt(&dest->buff_pool_base_sgt, source->buff_pool_base_sgt); if (result) { kfree(dest->data_buff_list); return result; } result = ipa_smmu_store_sgt(&dest->ring_base_sgt, source->ring_base_sgt); if (result) { kfree(dest->data_buff_list); ipa_smmu_free_sgt(&dest->buff_pool_base_sgt); return result; } return 0; } static void ipa_uc_ntn_free_conn_smmu_info(struct ipa_ntn_setup_info *params) { kfree(params->data_buff_list); ipa_smmu_free_sgt(¶ms->buff_pool_base_sgt); ipa_smmu_free_sgt(¶ms->ring_base_sgt); } int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp, struct ipa_ntn_conn_out_params *outp, struct ipa_uc_offload_ctx *ntn_ctx) Loading @@ -410,6 +456,11 @@ int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp, int result = 0; enum ipa_uc_offload_state prev_state; if (ntn_ctx->conn.dl.smmu_enabled != ntn_ctx->conn.ul.smmu_enabled) { IPA_UC_OFFLOAD_ERR("ul and dl smmu enablement do not match\n"); return -EINVAL; } prev_state = ntn_ctx->state; if (inp->dl.ring_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT || inp->dl.buff_pool_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT) { Loading Loading @@ -467,7 +518,21 @@ int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp, goto fail; } return 0; if (ntn_ctx->conn.dl.smmu_enabled) { result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.dl, &inp->dl); if (result) { IPA_UC_OFFLOAD_ERR("alloc failure on TX\n"); goto fail; } result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.ul, &inp->ul); if (result) { ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.dl); IPA_UC_OFFLOAD_ERR("alloc failure on RX\n"); goto fail; } } fail: if (!ipa_pm_is_used()) Loading Loading @@ -563,6 +628,11 @@ static int ipa_uc_ntn_disconn_pipes(struct ipa_uc_offload_ctx *ntn_ctx) int ipa_ep_idx_ul, ipa_ep_idx_dl; int ret = 0; if (ntn_ctx->conn.dl.smmu_enabled != ntn_ctx->conn.ul.smmu_enabled) { IPA_UC_OFFLOAD_ERR("ul and dl smmu enablement do not match\n"); return -EINVAL; } ntn_ctx->state = IPA_UC_OFFLOAD_STATE_INITIALIZED; #ifdef CONFIG_IPA3 Loading Loading @@ -594,12 +664,16 @@ static int ipa_uc_ntn_disconn_pipes(struct ipa_uc_offload_ctx *ntn_ctx) ipa_ep_idx_ul = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_PROD); ipa_ep_idx_dl = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_CONS); ret = ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl); ret = ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl, &ntn_ctx->conn); if (ret) { IPA_UC_OFFLOAD_ERR("fail to tear down ntn offload pipes, %d\n", ret); return -EFAULT; } if (ntn_ctx->conn.dl.smmu_enabled) ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.dl); ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.ul); return ret; } Loading
drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +15 −49 Original line number Diff line number Diff line Loading @@ -1149,7 +1149,8 @@ static int ipa3_usb_smmu_map_xdci_channel( if (ipa3_usb_ctx->smmu_reg_map.cnt == 0) { ipa3_usb_ctx->smmu_reg_map.addr = gevntcount_r; result = ipa3_smmu_map_peer_reg( ipa3_usb_ctx->smmu_reg_map.addr, true); ipa3_usb_ctx->smmu_reg_map.addr, true, IPA_SMMU_CB_AP); if (result) { IPA_USB_ERR("failed to map USB regs %d\n", result); Loading @@ -1172,7 +1173,8 @@ static int ipa3_usb_smmu_map_xdci_channel( if (ipa3_usb_ctx->smmu_reg_map.cnt == 1) { result = ipa3_smmu_map_peer_reg( ipa3_usb_ctx->smmu_reg_map.addr, false); ipa3_usb_ctx->smmu_reg_map.addr, false, IPA_SMMU_CB_AP); if (result) { IPA_USB_ERR("failed to unmap USB regs %d\n", result); Loading @@ -1184,14 +1186,16 @@ static int ipa3_usb_smmu_map_xdci_channel( result = ipa3_smmu_map_peer_buff(params->xfer_ring_base_addr_iova, params->xfer_ring_len, map, params->sgt_xfer_rings); params->xfer_ring_len, map, params->sgt_xfer_rings, IPA_SMMU_CB_AP); if (result) { IPA_USB_ERR("failed to map Xfer ring %d\n", result); return result; } result = ipa3_smmu_map_peer_buff(params->data_buff_base_addr_iova, params->data_buff_base_len, map, params->sgt_data_buff); params->data_buff_base_len, map, params->sgt_data_buff, IPA_SMMU_CB_AP); if (result) { IPA_USB_ERR("failed to map TRBs buff %d\n", result); return result; Loading @@ -1200,43 +1204,6 @@ static int ipa3_usb_smmu_map_xdci_channel( return 0; } static int ipa3_usb_smmu_store_sgt(struct sg_table **out_ch_ptr, struct sg_table *in_sgt_ptr) { unsigned int nents; if (in_sgt_ptr != NULL) { *out_ch_ptr = kzalloc(sizeof(struct sg_table), GFP_KERNEL); if (*out_ch_ptr == NULL) return -ENOMEM; nents = in_sgt_ptr->nents; (*out_ch_ptr)->sgl = kcalloc(nents, sizeof(struct scatterlist), GFP_KERNEL); if ((*out_ch_ptr)->sgl == NULL) return -ENOMEM; memcpy((*out_ch_ptr)->sgl, in_sgt_ptr->sgl, nents*sizeof((*out_ch_ptr)->sgl)); (*out_ch_ptr)->nents = nents; (*out_ch_ptr)->orig_nents = in_sgt_ptr->orig_nents; } return 0; } static int ipa3_usb_smmu_free_sgt(struct sg_table **out_sgt_ptr) { if (*out_sgt_ptr != NULL) { kfree((*out_sgt_ptr)->sgl); (*out_sgt_ptr)->sgl = NULL; kfree(*out_sgt_ptr); *out_sgt_ptr = NULL; } return 0; } static int ipa3_usb_request_xdci_channel( struct ipa_usb_xdci_chan_params *params, enum ipa_usb_direction dir, Loading Loading @@ -1327,18 +1294,17 @@ static int ipa3_usb_request_xdci_channel( xdci_ch_params = &ipa3_usb_ctx->ttype_ctx[ttype].dl_ch_params; *xdci_ch_params = *params; result = ipa3_usb_smmu_store_sgt( result = ipa_smmu_store_sgt( &xdci_ch_params->sgt_xfer_rings, params->sgt_xfer_rings); if (result) { ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings); if (result) return result; } result = ipa3_usb_smmu_store_sgt( result = ipa_smmu_store_sgt( &xdci_ch_params->sgt_data_buff, params->sgt_data_buff); if (result) { ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_data_buff); ipa_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings); return result; } chan_params.keep_ipa_awake = params->keep_ipa_awake; Loading Loading @@ -1443,9 +1409,9 @@ static int ipa3_usb_release_xdci_channel(u32 clnt_hdl, result = ipa3_usb_smmu_map_xdci_channel(xdci_ch_params, false); if (xdci_ch_params->sgt_xfer_rings != NULL) ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings); ipa_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings); if (xdci_ch_params->sgt_data_buff != NULL) ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_data_buff); ipa_smmu_free_sgt(&xdci_ch_params->sgt_data_buff); /* Change ipa_usb state to INITIALIZED */ if (!ipa3_usb_set_state(IPA_USB_INITIALIZED, false, ttype)) Loading
drivers/platform/msm/ipa/ipa_common_i.h +6 −1 Original line number Diff line number Diff line Loading @@ -408,7 +408,8 @@ int ipa_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in, ipa_notify_cb notify, void *priv, u8 hdr_len, struct ipa_ntn_conn_out_params *outp); int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl); int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params); u8 *ipa_write_64(u64 w, u8 *dest); u8 *ipa_write_32(u32 w, u8 *dest); u8 *ipa_write_16(u16 hw, u8 *dest); Loading @@ -434,4 +435,8 @@ int ipa_start_gsi_channel(u32 clnt_hdl); bool ipa_pm_is_used(void); int ipa_smmu_store_sgt(struct sg_table **out_ch_ptr, struct sg_table *in_sgt_ptr); int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr); #endif /* _IPA_COMMON_I_H_ */