From 9acc9ed2d916c0c4121f5987abbabb64161280bd Mon Sep 17 00:00:00 2001 From: Michael Adisumarta Date: Mon, 24 May 2021 12:06:56 -0700 Subject: [PATCH] msm: ipa3: Send actual DL flt rule to Q6 Currently max length size of DL flt rule is sent to Q6. But 64K memory allocation is not always guaranteed. Send actual size of DL flt rule to Q6 to avoid memory error and install flt rule. Change-Id: Id5f7bbb616c23feb6efbacd288f790432156630b Signed-off-by: Michael Adisumarta --- .../platform/msm/ipa/ipa_v3/ipa_qmi_service.c | 43 +++++++++- .../msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c | 82 +++++++++++++++++++ 2 files changed, 123 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c index 46f93e7a5f..992431fe75 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c @@ -796,6 +796,44 @@ int ipa3_qmi_filter_request_send(struct ipa_install_fltr_rule_req_msg_v01 *req) resp.resp.error, "ipa_install_filter"); } +static int ipa3_qmi_filter_request_ex_calc_length( + struct ipa_install_fltr_rule_req_ex_msg_v01 *req) +{ + int len = 0; + + /* caller should validate and send the req */ + /* instead of sending max length,the approximate length is calculated */ + len += ((sizeof(struct ipa_install_fltr_rule_req_ex_msg_v01)) - + (QMI_IPA_MAX_FILTERS_EX_V01 * + sizeof(struct ipa_filter_spec_ex_type_v01) - + QMI_IPA_MAX_FILTERS_EX_V01 * sizeof(uint32_t)) - + (QMI_IPA_MAX_FILTERS_V01 * + sizeof(struct ipa_filter_spec_ex2_type_v01))); + + if (req->filter_spec_ex_list_valid && + req->filter_spec_ex_list_len > 0) { + len += sizeof(struct ipa_filter_spec_ex_type_v01)* + req->filter_spec_ex_list_len; + } + if (req->xlat_filter_indices_list_valid && + req->xlat_filter_indices_list_len > 0) { + len += sizeof(uint32_t)*req->xlat_filter_indices_list_len; + } + + if (req->filter_spec_ex2_list_valid && + req->filter_spec_ex2_list_len > 0) { + len += sizeof(struct ipa_filter_spec_ex2_type_v01)* + req->filter_spec_ex2_list_len; + } + + if (req->ul_firewall_indices_list_valid && + req->ul_firewall_indices_list_len > 0) { + len += sizeof(uint32_t)*req->ul_firewall_indices_list_len; + } + + return len; +} + /* sending filter-install-request to modem*/ int ipa3_qmi_filter_request_ex_send( struct ipa_install_fltr_rule_req_ex_msg_v01 *req) @@ -861,8 +899,9 @@ int ipa3_qmi_filter_request_ex_send( } mutex_unlock(&ipa3_qmi_lock); - req_desc.max_msg_len = - QMI_IPA_INSTALL_FILTER_RULE_EX_REQ_MAX_MSG_LEN_V01; + req_desc.max_msg_len = ipa3_qmi_filter_request_ex_calc_length(req); + IPAWANDBG("QMI send request length = %d\n", req_desc.max_msg_len); + req_desc.msg_id = QMI_IPA_INSTALL_FILTER_RULE_EX_REQ_V01; req_desc.ei_array = ipa3_install_fltr_rule_req_ex_msg_data_v01_ei; diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c index 536551ec45..35a5c17f9e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "ipa_qmi_service.h" #include "ipa_i.h" @@ -96,7 +97,11 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct ipa_install_fltr_rule_req_msg_v01); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -117,7 +122,11 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE_EX :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct ipa_install_fltr_rule_req_ex_msg_v01); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -138,7 +147,11 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_ADD_OFFLOAD_CONNECTION :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct ipa_add_offload_connection_req_msg_v01); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -160,7 +173,11 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_RMV_OFFLOAD_CONNECTION :>>>\n", DRIVER_NAME); pyld_sz = rmv_offload_req__msg_size; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -183,7 +200,11 @@ static long ipa3_wan_ioctl(struct file *filp, DRIVER_NAME); pyld_sz = sizeof(struct ipa_configure_ul_firewall_rules_req_msg_v01); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -205,7 +226,11 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE_INDEX :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct ipa_fltr_installed_notif_req_msg_v01); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -226,7 +251,11 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_VOTE_FOR_BW_MBPS :>>>\n", DRIVER_NAME); pyld_sz = sizeof(uint32_t); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -245,7 +274,11 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_POLL_TETHERING_STATS: IPAWANDBG_LOW("got WAN_IOCTL_POLL_TETHERING_STATS :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_poll_tethering_stats); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -266,7 +299,11 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG_LOW("device %s got WAN_IOCTL_SET_DATA_QUOTA :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct wan_ioctl_set_data_quota); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -322,7 +359,11 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_SET_TETHER_CLIENT_PIPE: IPAWANDBG_LOW("got WAN_IOC_SET_TETHER_CLIENT_PIPE :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_set_tether_client_pipe); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -338,7 +379,11 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_QUERY_TETHER_STATS: IPAWANDBG_LOW("got WAN_IOC_QUERY_TETHER_STATS :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_query_tether_stats); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -360,7 +405,11 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_QUERY_TETHER_STATS_ALL: IPAWANDBG_LOW("got WAN_IOC_QUERY_TETHER_STATS_ALL :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_query_tether_stats_all); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -383,7 +432,11 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG_LOW("device %s got WAN_IOC_RESET_TETHER_STATS :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct wan_ioctl_reset_tether_stats); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -401,7 +454,11 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG_LOW("device %s got WAN_IOC_NOTIFY_WAN_STATE :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct wan_ioctl_notify_wan_state); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -423,7 +480,11 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_ENABLE_PER_CLIENT_STATS: IPAWANDBG_LOW("got WAN_IOC_ENABLE_PER_CLIENT_STATS :>>>\n"); pyld_sz = sizeof(bool); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -438,7 +499,11 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_QUERY_PER_CLIENT_STATS: IPAWANDBG_LOW("got WAN_IOC_QUERY_PER_CLIENT_STATS :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_query_per_client_stats); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -463,7 +528,11 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_SET_LAN_CLIENT_INFO: IPAWANDBG_LOW("got WAN_IOC_SET_LAN_CLIENT_INFO :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_lan_client_info); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -479,7 +548,11 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_CLEAR_LAN_CLIENT_INFO: IPAWANDBG_LOW("got WAN_IOC_CLEAR_LAN_CLIENT_INFO :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_lan_client_info); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -496,7 +569,11 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_SEND_LAN_CLIENT_MSG: IPAWANDBG_LOW("got WAN_IOC_SEND_LAN_CLIENT_MSG :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_send_lan_client_msg); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) param = memdup_user((const void __user *)arg, pyld_sz); +#else + param = vmemdup_user((const void __user *)arg, pyld_sz); +#endif if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -536,7 +613,12 @@ static long ipa3_wan_ioctl(struct file *filp, retval = -ENOTTY; } if (!IS_ERR(param)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) kfree(param); +#else + kvfree(param); +#endif + return retval; }