Loading drivers/platform/msm/ipa/ipa_v2/ipa.c +45 −0 Original line number Diff line number Diff line Loading @@ -278,6 +278,51 @@ static int ipa_open(struct inode *inode, struct file *filp) return 0; } /** * ipa_flow_control() - Enable/Disable flow control on a particular client. * Return codes: * None */ void ipa_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id) { struct ipa_ep_cfg_ctrl ep_ctrl = {0}; int ep_idx; struct ipa_ep_context *ep; /* Check if ep is valid. */ ep_idx = ipa2_get_ep_mapping(ipa_client); if (ep_idx == -1) { IPAERR("Invalid IPA client\n"); return; } ep = &ipa_ctx->ep[ep_idx]; if (!ep->valid) { IPAERR("EP not valid.\n"); return; } /* Check if the QMAP_ID matches. */ if (ep->cfg.meta.qmap_id != qmap_id) { IPADBG("Flow control indication not for the same flow: %u %u\n", ep->cfg.meta.qmap_id, qmap_id); return; } if (enable) { IPADBG("Enabling Flow\n"); ep_ctrl.ipa_ep_delay = false; IPA_STATS_INC_CNT(ipa_ctx->stats.flow_enable); } else { IPADBG("Disabling Flow\n"); ep_ctrl.ipa_ep_delay = true; IPA_STATS_INC_CNT(ipa_ctx->stats.flow_disable); } ep_ctrl.ipa_ep_suspend = false; ipa2_cfg_ep_ctrl(ep_idx, &ep_ctrl); } static void ipa_wan_msg_free_cb(void *buff, u32 len, u32 type) { if (!buff) { Loading drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c +6 −2 Original line number Diff line number Diff line Loading @@ -866,7 +866,9 @@ static ssize_t ipa_read_stats(struct file *file, char __user *ubuf, "wan_rx_empty=%u\n" "wan_repl_rx_empty=%u\n" "lan_rx_empty=%u\n" "lan_repl_rx_empty=%u\n", "lan_repl_rx_empty=%u\n" "flow_enable=%u\n" "flow_disable=%u\n", ipa_ctx->stats.tx_sw_pkts, ipa_ctx->stats.tx_hw_pkts, ipa_ctx->stats.tx_pkts_compl, Loading @@ -879,7 +881,9 @@ static ssize_t ipa_read_stats(struct file *file, char __user *ubuf, ipa_ctx->stats.wan_rx_empty, ipa_ctx->stats.wan_repl_rx_empty, ipa_ctx->stats.lan_rx_empty, ipa_ctx->stats.lan_repl_rx_empty); ipa_ctx->stats.lan_repl_rx_empty, ipa_ctx->stats.flow_enable, ipa_ctx->stats.flow_disable); cnt += nbytes; for (i = 0; i < MAX_NUM_EXCP; i++) { Loading drivers/platform/msm/ipa/ipa_v2/ipa_i.h +4 −0 Original line number Diff line number Diff line Loading @@ -763,6 +763,8 @@ struct ipa_stats { u32 wan_repl_rx_empty; u32 lan_rx_empty; u32 lan_repl_rx_empty; u32 flow_enable; u32 flow_disable; }; struct ipa_active_clients { Loading Loading @@ -1961,4 +1963,6 @@ int ipa2_release_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info); int ipa2_create_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info); void ipa_suspend_apps_pipes(bool suspend); void ipa_update_repl_threshold(enum ipa_client_type ipa_client); void ipa_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id); #endif /* _IPA_I_H_ */ drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +16 −0 Original line number Diff line number Diff line Loading @@ -1220,9 +1220,25 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; /* Flow enable */ case RMNET_IOCTL_FLOW_ENABLE: IPAWANDBG("Received flow enable\n"); if (copy_from_user(&ioctl_data, ifr->ifr_ifru.ifru_data, sizeof(struct rmnet_ioctl_data_s))) { rc = -EFAULT; break; } ipa_flow_control(IPA_CLIENT_USB_PROD, true, ioctl_data.u.tcm_handle); break; /* Flow disable */ case RMNET_IOCTL_FLOW_DISABLE: IPAWANDBG("Received flow disable\n"); if (copy_from_user(&ioctl_data, ifr->ifr_ifru.ifru_data, sizeof(struct rmnet_ioctl_data_s))) { rc = -EFAULT; break; } ipa_flow_control(IPA_CLIENT_USB_PROD, false, ioctl_data.u.tcm_handle); break; /* Set flow handle */ case RMNET_IOCTL_FLOW_SET_HNDL: Loading drivers/platform/msm/ipa/ipa_v3/ipa.c +45 −0 Original line number Diff line number Diff line Loading @@ -277,6 +277,51 @@ static int ipa3_open(struct inode *inode, struct file *filp) return 0; } /** * ipa3_flow_control() - Enable/Disable flow control on a particular client. * Return codes: * None */ void ipa3_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id) { struct ipa_ep_cfg_ctrl ep_ctrl = {0}; int ep_idx; struct ipa3_ep_context *ep; /* Check if ep is valid. */ ep_idx = ipa3_get_ep_mapping(ipa_client); if (ep_idx == -1) { IPAERR("Invalid IPA client\n"); return; } ep = &ipa3_ctx->ep[ep_idx]; if (!ep->valid) { IPAERR("EP not valid.\n"); return; } /* Check if the QMAP_ID matches. */ if (ep->cfg.meta.qmap_id != qmap_id) { IPADBG("Flow control indication not for the same flow: %u %u\n", ep->cfg.meta.qmap_id, qmap_id); return; } if (enable) { IPADBG("Enabling Flow\n"); ep_ctrl.ipa_ep_delay = false; IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_enable); } else { IPADBG("Disabling Flow\n"); ep_ctrl.ipa_ep_delay = true; IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_disable); } ep_ctrl.ipa_ep_suspend = false; ipa3_cfg_ep_ctrl(ep_idx, &ep_ctrl); } static void ipa3_wan_msg_free_cb(void *buff, u32 len, u32 type) { if (!buff) { Loading Loading
drivers/platform/msm/ipa/ipa_v2/ipa.c +45 −0 Original line number Diff line number Diff line Loading @@ -278,6 +278,51 @@ static int ipa_open(struct inode *inode, struct file *filp) return 0; } /** * ipa_flow_control() - Enable/Disable flow control on a particular client. * Return codes: * None */ void ipa_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id) { struct ipa_ep_cfg_ctrl ep_ctrl = {0}; int ep_idx; struct ipa_ep_context *ep; /* Check if ep is valid. */ ep_idx = ipa2_get_ep_mapping(ipa_client); if (ep_idx == -1) { IPAERR("Invalid IPA client\n"); return; } ep = &ipa_ctx->ep[ep_idx]; if (!ep->valid) { IPAERR("EP not valid.\n"); return; } /* Check if the QMAP_ID matches. */ if (ep->cfg.meta.qmap_id != qmap_id) { IPADBG("Flow control indication not for the same flow: %u %u\n", ep->cfg.meta.qmap_id, qmap_id); return; } if (enable) { IPADBG("Enabling Flow\n"); ep_ctrl.ipa_ep_delay = false; IPA_STATS_INC_CNT(ipa_ctx->stats.flow_enable); } else { IPADBG("Disabling Flow\n"); ep_ctrl.ipa_ep_delay = true; IPA_STATS_INC_CNT(ipa_ctx->stats.flow_disable); } ep_ctrl.ipa_ep_suspend = false; ipa2_cfg_ep_ctrl(ep_idx, &ep_ctrl); } static void ipa_wan_msg_free_cb(void *buff, u32 len, u32 type) { if (!buff) { Loading
drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c +6 −2 Original line number Diff line number Diff line Loading @@ -866,7 +866,9 @@ static ssize_t ipa_read_stats(struct file *file, char __user *ubuf, "wan_rx_empty=%u\n" "wan_repl_rx_empty=%u\n" "lan_rx_empty=%u\n" "lan_repl_rx_empty=%u\n", "lan_repl_rx_empty=%u\n" "flow_enable=%u\n" "flow_disable=%u\n", ipa_ctx->stats.tx_sw_pkts, ipa_ctx->stats.tx_hw_pkts, ipa_ctx->stats.tx_pkts_compl, Loading @@ -879,7 +881,9 @@ static ssize_t ipa_read_stats(struct file *file, char __user *ubuf, ipa_ctx->stats.wan_rx_empty, ipa_ctx->stats.wan_repl_rx_empty, ipa_ctx->stats.lan_rx_empty, ipa_ctx->stats.lan_repl_rx_empty); ipa_ctx->stats.lan_repl_rx_empty, ipa_ctx->stats.flow_enable, ipa_ctx->stats.flow_disable); cnt += nbytes; for (i = 0; i < MAX_NUM_EXCP; i++) { Loading
drivers/platform/msm/ipa/ipa_v2/ipa_i.h +4 −0 Original line number Diff line number Diff line Loading @@ -763,6 +763,8 @@ struct ipa_stats { u32 wan_repl_rx_empty; u32 lan_rx_empty; u32 lan_repl_rx_empty; u32 flow_enable; u32 flow_disable; }; struct ipa_active_clients { Loading Loading @@ -1961,4 +1963,6 @@ int ipa2_release_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info); int ipa2_create_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info); void ipa_suspend_apps_pipes(bool suspend); void ipa_update_repl_threshold(enum ipa_client_type ipa_client); void ipa_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id); #endif /* _IPA_I_H_ */
drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +16 −0 Original line number Diff line number Diff line Loading @@ -1220,9 +1220,25 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; /* Flow enable */ case RMNET_IOCTL_FLOW_ENABLE: IPAWANDBG("Received flow enable\n"); if (copy_from_user(&ioctl_data, ifr->ifr_ifru.ifru_data, sizeof(struct rmnet_ioctl_data_s))) { rc = -EFAULT; break; } ipa_flow_control(IPA_CLIENT_USB_PROD, true, ioctl_data.u.tcm_handle); break; /* Flow disable */ case RMNET_IOCTL_FLOW_DISABLE: IPAWANDBG("Received flow disable\n"); if (copy_from_user(&ioctl_data, ifr->ifr_ifru.ifru_data, sizeof(struct rmnet_ioctl_data_s))) { rc = -EFAULT; break; } ipa_flow_control(IPA_CLIENT_USB_PROD, false, ioctl_data.u.tcm_handle); break; /* Set flow handle */ case RMNET_IOCTL_FLOW_SET_HNDL: Loading
drivers/platform/msm/ipa/ipa_v3/ipa.c +45 −0 Original line number Diff line number Diff line Loading @@ -277,6 +277,51 @@ static int ipa3_open(struct inode *inode, struct file *filp) return 0; } /** * ipa3_flow_control() - Enable/Disable flow control on a particular client. * Return codes: * None */ void ipa3_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id) { struct ipa_ep_cfg_ctrl ep_ctrl = {0}; int ep_idx; struct ipa3_ep_context *ep; /* Check if ep is valid. */ ep_idx = ipa3_get_ep_mapping(ipa_client); if (ep_idx == -1) { IPAERR("Invalid IPA client\n"); return; } ep = &ipa3_ctx->ep[ep_idx]; if (!ep->valid) { IPAERR("EP not valid.\n"); return; } /* Check if the QMAP_ID matches. */ if (ep->cfg.meta.qmap_id != qmap_id) { IPADBG("Flow control indication not for the same flow: %u %u\n", ep->cfg.meta.qmap_id, qmap_id); return; } if (enable) { IPADBG("Enabling Flow\n"); ep_ctrl.ipa_ep_delay = false; IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_enable); } else { IPADBG("Disabling Flow\n"); ep_ctrl.ipa_ep_delay = true; IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_disable); } ep_ctrl.ipa_ep_suspend = false; ipa3_cfg_ep_ctrl(ep_idx, &ep_ctrl); } static void ipa3_wan_msg_free_cb(void *buff, u32 len, u32 type) { if (!buff) { Loading