Loading drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c +131 −38 Original line number Original line Diff line number Diff line Loading @@ -132,7 +132,7 @@ struct ipa_gsb_iface_info { * struct ipa_gsb_context - GSB driver context information * struct ipa_gsb_context - GSB driver context information * @logbuf: buffer of ipc logging * @logbuf: buffer of ipc logging * @logbuf_low: buffer of ipc logging (low priority) * @logbuf_low: buffer of ipc logging (low priority) * @lock: mutex lock * @lock: global mutex lock for global variables * @prod_hdl: handle for prod pipe * @prod_hdl: handle for prod pipe * @cons_hdl: handle for cons pipe * @cons_hdl: handle for cons pipe * @ipa_sys_desc_size: sys pipe desc size * @ipa_sys_desc_size: sys pipe desc size Loading @@ -141,6 +141,8 @@ struct ipa_gsb_iface_info { * @num_connected_iface: number of connected interface * @num_connected_iface: number of connected interface * @num_resumed_iface: number of resumed interface * @num_resumed_iface: number of resumed interface * @iface: interface information * @iface: interface information * @iface_lock: interface mutex lock for control path * @iface_spinlock: interface spinlock for data path * @pm_hdl: IPA PM handle * @pm_hdl: IPA PM handle */ */ struct ipa_gsb_context { struct ipa_gsb_context { Loading @@ -155,6 +157,8 @@ struct ipa_gsb_context { int num_connected_iface; int num_connected_iface; int num_resumed_iface; int num_resumed_iface; struct ipa_gsb_iface_info *iface[MAX_SUPPORTED_IFACE]; struct ipa_gsb_iface_info *iface[MAX_SUPPORTED_IFACE]; struct mutex iface_lock[MAX_SUPPORTED_IFACE]; spinlock_t iface_spinlock[MAX_SUPPORTED_IFACE]; u32 pm_hdl; u32 pm_hdl; }; }; Loading Loading @@ -240,6 +244,7 @@ static void ipa_gsb_debugfs_destroy(void) static int ipa_gsb_driver_init(struct odu_bridge_params *params) static int ipa_gsb_driver_init(struct odu_bridge_params *params) { { int i; if (!ipa_is_ready()) { if (!ipa_is_ready()) { IPA_GSB_ERR("IPA is not ready\n"); IPA_GSB_ERR("IPA is not ready\n"); return -EFAULT; return -EFAULT; Loading @@ -252,6 +257,10 @@ static int ipa_gsb_driver_init(struct odu_bridge_params *params) return -ENOMEM; return -ENOMEM; mutex_init(&ipa_gsb_ctx->lock); mutex_init(&ipa_gsb_ctx->lock); for (i = 0; i < MAX_SUPPORTED_IFACE; i++) { mutex_init(&ipa_gsb_ctx->iface_lock[i]); spin_lock_init(&ipa_gsb_ctx->iface_spinlock[i]); } ipa_gsb_debugfs_init(); ipa_gsb_debugfs_init(); return 0; return 0; Loading Loading @@ -475,7 +484,7 @@ int ipa_bridge_init(struct ipa_bridge_init_params *params, u32 *hdl) if (!params || !params->wakeup_request || !hdl || if (!params || !params->wakeup_request || !hdl || !params->info.netdev_name || !params->info.tx_dp_notify || !params->info.netdev_name || !params->info.tx_dp_notify || !params->info.send_dl_skb) { !params->info.send_dl_skb) { IPA_GSB_ERR("NULL parameters\n"); IPA_GSB_ERR("Invalid parameters\n"); return -EINVAL; return -EINVAL; } } Loading Loading @@ -596,6 +605,7 @@ static void ipa_gsb_deregister_pm(void) int ipa_bridge_cleanup(u32 hdl) int ipa_bridge_cleanup(u32 hdl) { { int i; if (!ipa_gsb_ctx) { if (!ipa_gsb_ctx) { IPA_GSB_ERR("ipa_gsb_ctx was not initialized\n"); IPA_GSB_ERR("ipa_gsb_ctx was not initialized\n"); return -EFAULT; return -EFAULT; Loading @@ -606,39 +616,44 @@ int ipa_bridge_cleanup(u32 hdl) return -EINVAL; return -EINVAL; } } if (ipa_gsb_ctx->iface[hdl] == NULL) { mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); IPA_GSB_ERR("fail to find interface\n"); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } IPA_GSB_DBG("client hdl: %d\n", hdl); IPA_GSB_DBG("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->lock); if (ipa_gsb_ctx->iface[hdl]->is_connected) { if (ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_ERR("cannot cleanup when iface is connected\n"); IPA_GSB_ERR("cannot cleanup when iface is connected\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } ipa_gsb_dereg_intf_props(ipa_gsb_ctx->iface[hdl]); ipa_gsb_dereg_intf_props(ipa_gsb_ctx->iface[hdl]); ipa_gsb_delete_partial_hdr(ipa_gsb_ctx->iface[hdl]); ipa_gsb_delete_partial_hdr(ipa_gsb_ctx->iface[hdl]); spin_lock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); kfree(ipa_gsb_ctx->iface[hdl]); kfree(ipa_gsb_ctx->iface[hdl]); ipa_gsb_ctx->iface[hdl] = NULL; ipa_gsb_ctx->iface[hdl] = NULL; ipa_gsb_ctx->iface_hdl[hdl] = false; ipa_gsb_ctx->iface_hdl[hdl] = false; spin_unlock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); mutex_lock(&ipa_gsb_ctx->lock); ipa_gsb_ctx->num_iface--; ipa_gsb_ctx->num_iface--; IPA_GSB_DBG("num_iface %d\n", ipa_gsb_ctx->num_iface); IPA_GSB_DBG("num_iface %d\n", ipa_gsb_ctx->num_iface); if (ipa_gsb_ctx->num_iface == 0) { if (ipa_gsb_ctx->num_iface == 0) { ipa_gsb_deregister_pm(); ipa_gsb_deregister_pm(); ipa_gsb_debugfs_destroy(); ipa_gsb_debugfs_destroy(); ipc_log_context_destroy(ipa_gsb_ctx->logbuf); ipc_log_context_destroy(ipa_gsb_ctx->logbuf); ipc_log_context_destroy(ipa_gsb_ctx->logbuf_low); ipc_log_context_destroy(ipa_gsb_ctx->logbuf_low); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->lock); mutex_destroy(&ipa_gsb_ctx->lock); for (i = 0; i < MAX_SUPPORTED_IFACE; i++) mutex_destroy(&ipa_gsb_ctx->iface_lock[i]); kfree(ipa_gsb_ctx); kfree(ipa_gsb_ctx); ipa_gsb_ctx = NULL; ipa_gsb_ctx = NULL; return 0; return 0; } } mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->lock); return 0; return 0; } } Loading Loading @@ -670,6 +685,10 @@ static void ipa_gsb_cons_cb(void *priv, enum ipa_dp_evt_type evt, (pkt_size + sizeof(*mux_hdr) + (pkt_size + sizeof(*mux_hdr) + ETH_HLEN + IPA_GSB_SKB_DUMMY_HEADER); ETH_HLEN + IPA_GSB_SKB_DUMMY_HEADER); hdl = mux_hdr->iface_hdl; hdl = mux_hdr->iface_hdl; if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); break; } IPA_GSB_DBG_LOW("pkt_size: %d, pad_byte: %d, hdl: %d\n", IPA_GSB_DBG_LOW("pkt_size: %d, pad_byte: %d, hdl: %d\n", pkt_size, pad_byte, hdl); pkt_size, pad_byte, hdl); Loading @@ -683,11 +702,21 @@ static void ipa_gsb_cons_cb(void *priv, enum ipa_dp_evt_type evt, break; break; } } skb_trim(skb2, pkt_size + ETH_HLEN); skb_trim(skb2, pkt_size + ETH_HLEN); spin_lock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); if (ipa_gsb_ctx->iface[hdl] != NULL) { ipa_gsb_ctx->iface[hdl]->send_dl_skb( ipa_gsb_ctx->iface[hdl]->send_dl_skb( ipa_gsb_ctx->iface[hdl]->priv, skb2); ipa_gsb_ctx->iface[hdl]->priv, skb2); ipa_gsb_ctx->iface[hdl]->iface_stats.num_dl_packets++; ipa_gsb_ctx->iface[hdl]->iface_stats.num_dl_packets++; spin_unlock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); skb_pull(skb, pkt_size + ETH_HLEN + pad_byte); skb_pull(skb, pkt_size + ETH_HLEN + pad_byte); } else { IPA_GSB_ERR("Invalid hdl: %d, drop the skb\n", hdl); spin_unlock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); dev_kfree_skb_any(skb2); break; } } } if (skb) { if (skb) { dev_kfree_skb_any(skb); dev_kfree_skb_any(skb); skb = NULL; skb = NULL; Loading @@ -714,6 +743,11 @@ static void ipa_gsb_tx_dp_notify(void *priv, enum ipa_dp_evt_type evt, /* change to host order */ /* change to host order */ *(u32 *)mux_hdr = ntohl(*(u32 *)mux_hdr); *(u32 *)mux_hdr = ntohl(*(u32 *)mux_hdr); hdl = mux_hdr->iface_hdl; hdl = mux_hdr->iface_hdl; if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("invalid hdl: %d and cb, drop the skb\n", hdl); dev_kfree_skb_any(skb); return; } IPA_GSB_DBG_LOW("evt: %d, hdl in tx_dp_notify: %d\n", evt, hdl); IPA_GSB_DBG_LOW("evt: %d, hdl in tx_dp_notify: %d\n", evt, hdl); /* remove 4 byte mux header */ /* remove 4 byte mux header */ Loading Loading @@ -797,13 +831,23 @@ int ipa_bridge_connect(u32 hdl) return -EFAULT; return -EFAULT; } } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG("client hdl: %d\n", hdl); IPA_GSB_DBG("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->lock); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; } if (ipa_gsb_ctx->iface[hdl]->is_connected) { if (ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_DBG("iface was already connected\n"); IPA_GSB_DBG("iface was already connected\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } Loading @@ -811,13 +855,13 @@ int ipa_bridge_connect(u32 hdl) ret = ipa_pm_activate_sync(ipa_gsb_ctx->pm_hdl); ret = ipa_pm_activate_sync(ipa_gsb_ctx->pm_hdl); if (ret) { if (ret) { IPA_GSB_ERR("failed to activate ipa pm\n"); IPA_GSB_ERR("failed to activate ipa pm\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } ret = ipa_gsb_connect_sys_pipe(); ret = ipa_gsb_connect_sys_pipe(); if (ret) { if (ret) { IPA_GSB_ERR("fail to connect pipe\n"); IPA_GSB_ERR("fail to connect pipe\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } } } Loading @@ -833,7 +877,7 @@ int ipa_bridge_connect(u32 hdl) IPA_GSB_DBG("num resumed iface: %d\n", IPA_GSB_DBG("num resumed iface: %d\n", ipa_gsb_ctx->num_resumed_iface); ipa_gsb_ctx->num_resumed_iface); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } EXPORT_SYMBOL(ipa_bridge_connect); EXPORT_SYMBOL(ipa_bridge_connect); Loading Loading @@ -871,13 +915,23 @@ int ipa_bridge_disconnect(u32 hdl) return -EFAULT; return -EFAULT; } } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG("client hdl: %d\n", hdl); IPA_GSB_DBG("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->lock); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; } if (!ipa_gsb_ctx->iface[hdl]->is_connected) { if (!ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_DBG("iface was not connected\n"); IPA_GSB_DBG("iface was not connected\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } Loading @@ -885,14 +939,14 @@ int ipa_bridge_disconnect(u32 hdl) ret = ipa_gsb_disconnect_sys_pipe(); ret = ipa_gsb_disconnect_sys_pipe(); if (ret) { if (ret) { IPA_GSB_ERR("fail to discon pipes\n"); IPA_GSB_ERR("fail to discon pipes\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } ret = ipa_pm_deactivate_sync(ipa_gsb_ctx->pm_hdl); ret = ipa_pm_deactivate_sync(ipa_gsb_ctx->pm_hdl); if (ret) { if (ret) { IPA_GSB_ERR("failed to deactivate ipa pm\n"); IPA_GSB_ERR("failed to deactivate ipa pm\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } } } Loading @@ -910,7 +964,7 @@ int ipa_bridge_disconnect(u32 hdl) ipa_gsb_ctx->num_resumed_iface); ipa_gsb_ctx->num_resumed_iface); } } mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } EXPORT_SYMBOL(ipa_bridge_disconnect); EXPORT_SYMBOL(ipa_bridge_disconnect); Loading @@ -924,25 +978,37 @@ int ipa_bridge_resume(u32 hdl) return -EFAULT; return -EFAULT; } } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; } if (!ipa_gsb_ctx->iface[hdl]->is_connected) { if (!ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_ERR("iface is not connected\n"); IPA_GSB_ERR("iface is not connected\n"); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } if (ipa_gsb_ctx->iface[hdl]->is_resumed) { if (ipa_gsb_ctx->iface[hdl]->is_resumed) { IPA_GSB_DBG_LOW("iface was already resumed\n"); IPA_GSB_DBG_LOW("iface was already resumed\n"); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } mutex_lock(&ipa_gsb_ctx->lock); if (ipa_gsb_ctx->num_resumed_iface == 0) { if (ipa_gsb_ctx->num_resumed_iface == 0) { ret = ipa_pm_activate_sync(ipa_gsb_ctx->pm_hdl); ret = ipa_pm_activate_sync(ipa_gsb_ctx->pm_hdl); if (ret) { if (ret) { IPA_GSB_ERR("fail to activate ipa pm\n"); IPA_GSB_ERR("fail to activate ipa pm\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } Loading @@ -952,7 +1018,7 @@ int ipa_bridge_resume(u32 hdl) IPA_GSB_ERR( IPA_GSB_ERR( "fail to start con ep %d\n", "fail to start con ep %d\n", ret); ret); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } } } Loading @@ -962,7 +1028,7 @@ int ipa_bridge_resume(u32 hdl) IPA_GSB_DBG_LOW("num resumed iface: %d\n", IPA_GSB_DBG_LOW("num resumed iface: %d\n", ipa_gsb_ctx->num_resumed_iface); ipa_gsb_ctx->num_resumed_iface); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } EXPORT_SYMBOL(ipa_bridge_resume); EXPORT_SYMBOL(ipa_bridge_resume); Loading @@ -976,20 +1042,32 @@ int ipa_bridge_suspend(u32 hdl) return -EFAULT; return -EFAULT; } } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; } if (!ipa_gsb_ctx->iface[hdl]->is_connected) { if (!ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_ERR("iface is not connected\n"); IPA_GSB_ERR("iface is not connected\n"); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } if (!ipa_gsb_ctx->iface[hdl]->is_resumed) { if (!ipa_gsb_ctx->iface[hdl]->is_resumed) { IPA_GSB_DBG_LOW("iface was already suspended\n"); IPA_GSB_DBG_LOW("iface was already suspended\n"); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } mutex_lock(&ipa_gsb_ctx->lock); if (ipa_gsb_ctx->num_resumed_iface == 1) { if (ipa_gsb_ctx->num_resumed_iface == 1) { ret = ipa_stop_gsi_channel( ret = ipa_stop_gsi_channel( ipa_gsb_ctx->cons_hdl); ipa_gsb_ctx->cons_hdl); Loading @@ -997,7 +1075,7 @@ int ipa_bridge_suspend(u32 hdl) IPA_GSB_ERR( IPA_GSB_ERR( "fail to stop cons ep %d\n", "fail to stop cons ep %d\n", ret); ret); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } Loading @@ -1005,7 +1083,7 @@ int ipa_bridge_suspend(u32 hdl) if (ret) { if (ret) { IPA_GSB_ERR("fail to deactivate ipa pm\n"); IPA_GSB_ERR("fail to deactivate ipa pm\n"); ipa_start_gsi_channel(ipa_gsb_ctx->cons_hdl); ipa_start_gsi_channel(ipa_gsb_ctx->cons_hdl); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } } } Loading @@ -1015,7 +1093,7 @@ int ipa_bridge_suspend(u32 hdl) IPA_GSB_DBG_LOW("num resumed iface: %d\n", IPA_GSB_DBG_LOW("num resumed iface: %d\n", ipa_gsb_ctx->num_resumed_iface); ipa_gsb_ctx->num_resumed_iface); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } EXPORT_SYMBOL(ipa_bridge_suspend); EXPORT_SYMBOL(ipa_bridge_suspend); Loading @@ -1024,16 +1102,26 @@ int ipa_bridge_set_perf_profile(u32 hdl, u32 bandwidth) { { int ret; int ret; if (!ipa_gsb_ctx) { IPA_GSB_ERR("ipa_gsb_ctx was not initialized\n"); return -EFAULT; } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG("client hdl: %d, BW: %d\n", hdl, bandwidth); IPA_GSB_DBG("client hdl: %d, BW: %d\n", hdl, bandwidth); mutex_lock(&ipa_gsb_ctx->lock); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); ret = ipa_pm_set_perf_profile(ipa_gsb_ctx->pm_hdl, ret = ipa_pm_set_perf_profile(ipa_gsb_ctx->pm_hdl, bandwidth); bandwidth); if (ret) if (ret) IPA_GSB_ERR("fail to set perf profile\n"); IPA_GSB_ERR("fail to set perf profile\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } EXPORT_SYMBOL(ipa_bridge_set_perf_profile); EXPORT_SYMBOL(ipa_bridge_set_perf_profile); Loading @@ -1047,6 +1135,11 @@ int ipa_bridge_tx_dp(u32 hdl, struct sk_buff *skb, IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); return -EFAULT; } /* make sure skb has enough headroom */ /* make sure skb has enough headroom */ if (unlikely(skb_headroom(skb) < sizeof(struct ipa_gsb_mux_hdr))) { if (unlikely(skb_headroom(skb) < sizeof(struct ipa_gsb_mux_hdr))) { IPA_GSB_DBG_LOW("skb doesn't have enough headroom\n"); IPA_GSB_DBG_LOW("skb doesn't have enough headroom\n"); Loading Loading
drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c +131 −38 Original line number Original line Diff line number Diff line Loading @@ -132,7 +132,7 @@ struct ipa_gsb_iface_info { * struct ipa_gsb_context - GSB driver context information * struct ipa_gsb_context - GSB driver context information * @logbuf: buffer of ipc logging * @logbuf: buffer of ipc logging * @logbuf_low: buffer of ipc logging (low priority) * @logbuf_low: buffer of ipc logging (low priority) * @lock: mutex lock * @lock: global mutex lock for global variables * @prod_hdl: handle for prod pipe * @prod_hdl: handle for prod pipe * @cons_hdl: handle for cons pipe * @cons_hdl: handle for cons pipe * @ipa_sys_desc_size: sys pipe desc size * @ipa_sys_desc_size: sys pipe desc size Loading @@ -141,6 +141,8 @@ struct ipa_gsb_iface_info { * @num_connected_iface: number of connected interface * @num_connected_iface: number of connected interface * @num_resumed_iface: number of resumed interface * @num_resumed_iface: number of resumed interface * @iface: interface information * @iface: interface information * @iface_lock: interface mutex lock for control path * @iface_spinlock: interface spinlock for data path * @pm_hdl: IPA PM handle * @pm_hdl: IPA PM handle */ */ struct ipa_gsb_context { struct ipa_gsb_context { Loading @@ -155,6 +157,8 @@ struct ipa_gsb_context { int num_connected_iface; int num_connected_iface; int num_resumed_iface; int num_resumed_iface; struct ipa_gsb_iface_info *iface[MAX_SUPPORTED_IFACE]; struct ipa_gsb_iface_info *iface[MAX_SUPPORTED_IFACE]; struct mutex iface_lock[MAX_SUPPORTED_IFACE]; spinlock_t iface_spinlock[MAX_SUPPORTED_IFACE]; u32 pm_hdl; u32 pm_hdl; }; }; Loading Loading @@ -240,6 +244,7 @@ static void ipa_gsb_debugfs_destroy(void) static int ipa_gsb_driver_init(struct odu_bridge_params *params) static int ipa_gsb_driver_init(struct odu_bridge_params *params) { { int i; if (!ipa_is_ready()) { if (!ipa_is_ready()) { IPA_GSB_ERR("IPA is not ready\n"); IPA_GSB_ERR("IPA is not ready\n"); return -EFAULT; return -EFAULT; Loading @@ -252,6 +257,10 @@ static int ipa_gsb_driver_init(struct odu_bridge_params *params) return -ENOMEM; return -ENOMEM; mutex_init(&ipa_gsb_ctx->lock); mutex_init(&ipa_gsb_ctx->lock); for (i = 0; i < MAX_SUPPORTED_IFACE; i++) { mutex_init(&ipa_gsb_ctx->iface_lock[i]); spin_lock_init(&ipa_gsb_ctx->iface_spinlock[i]); } ipa_gsb_debugfs_init(); ipa_gsb_debugfs_init(); return 0; return 0; Loading Loading @@ -475,7 +484,7 @@ int ipa_bridge_init(struct ipa_bridge_init_params *params, u32 *hdl) if (!params || !params->wakeup_request || !hdl || if (!params || !params->wakeup_request || !hdl || !params->info.netdev_name || !params->info.tx_dp_notify || !params->info.netdev_name || !params->info.tx_dp_notify || !params->info.send_dl_skb) { !params->info.send_dl_skb) { IPA_GSB_ERR("NULL parameters\n"); IPA_GSB_ERR("Invalid parameters\n"); return -EINVAL; return -EINVAL; } } Loading Loading @@ -596,6 +605,7 @@ static void ipa_gsb_deregister_pm(void) int ipa_bridge_cleanup(u32 hdl) int ipa_bridge_cleanup(u32 hdl) { { int i; if (!ipa_gsb_ctx) { if (!ipa_gsb_ctx) { IPA_GSB_ERR("ipa_gsb_ctx was not initialized\n"); IPA_GSB_ERR("ipa_gsb_ctx was not initialized\n"); return -EFAULT; return -EFAULT; Loading @@ -606,39 +616,44 @@ int ipa_bridge_cleanup(u32 hdl) return -EINVAL; return -EINVAL; } } if (ipa_gsb_ctx->iface[hdl] == NULL) { mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); IPA_GSB_ERR("fail to find interface\n"); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } IPA_GSB_DBG("client hdl: %d\n", hdl); IPA_GSB_DBG("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->lock); if (ipa_gsb_ctx->iface[hdl]->is_connected) { if (ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_ERR("cannot cleanup when iface is connected\n"); IPA_GSB_ERR("cannot cleanup when iface is connected\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } ipa_gsb_dereg_intf_props(ipa_gsb_ctx->iface[hdl]); ipa_gsb_dereg_intf_props(ipa_gsb_ctx->iface[hdl]); ipa_gsb_delete_partial_hdr(ipa_gsb_ctx->iface[hdl]); ipa_gsb_delete_partial_hdr(ipa_gsb_ctx->iface[hdl]); spin_lock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); kfree(ipa_gsb_ctx->iface[hdl]); kfree(ipa_gsb_ctx->iface[hdl]); ipa_gsb_ctx->iface[hdl] = NULL; ipa_gsb_ctx->iface[hdl] = NULL; ipa_gsb_ctx->iface_hdl[hdl] = false; ipa_gsb_ctx->iface_hdl[hdl] = false; spin_unlock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); mutex_lock(&ipa_gsb_ctx->lock); ipa_gsb_ctx->num_iface--; ipa_gsb_ctx->num_iface--; IPA_GSB_DBG("num_iface %d\n", ipa_gsb_ctx->num_iface); IPA_GSB_DBG("num_iface %d\n", ipa_gsb_ctx->num_iface); if (ipa_gsb_ctx->num_iface == 0) { if (ipa_gsb_ctx->num_iface == 0) { ipa_gsb_deregister_pm(); ipa_gsb_deregister_pm(); ipa_gsb_debugfs_destroy(); ipa_gsb_debugfs_destroy(); ipc_log_context_destroy(ipa_gsb_ctx->logbuf); ipc_log_context_destroy(ipa_gsb_ctx->logbuf); ipc_log_context_destroy(ipa_gsb_ctx->logbuf_low); ipc_log_context_destroy(ipa_gsb_ctx->logbuf_low); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->lock); mutex_destroy(&ipa_gsb_ctx->lock); for (i = 0; i < MAX_SUPPORTED_IFACE; i++) mutex_destroy(&ipa_gsb_ctx->iface_lock[i]); kfree(ipa_gsb_ctx); kfree(ipa_gsb_ctx); ipa_gsb_ctx = NULL; ipa_gsb_ctx = NULL; return 0; return 0; } } mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->lock); return 0; return 0; } } Loading Loading @@ -670,6 +685,10 @@ static void ipa_gsb_cons_cb(void *priv, enum ipa_dp_evt_type evt, (pkt_size + sizeof(*mux_hdr) + (pkt_size + sizeof(*mux_hdr) + ETH_HLEN + IPA_GSB_SKB_DUMMY_HEADER); ETH_HLEN + IPA_GSB_SKB_DUMMY_HEADER); hdl = mux_hdr->iface_hdl; hdl = mux_hdr->iface_hdl; if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); break; } IPA_GSB_DBG_LOW("pkt_size: %d, pad_byte: %d, hdl: %d\n", IPA_GSB_DBG_LOW("pkt_size: %d, pad_byte: %d, hdl: %d\n", pkt_size, pad_byte, hdl); pkt_size, pad_byte, hdl); Loading @@ -683,11 +702,21 @@ static void ipa_gsb_cons_cb(void *priv, enum ipa_dp_evt_type evt, break; break; } } skb_trim(skb2, pkt_size + ETH_HLEN); skb_trim(skb2, pkt_size + ETH_HLEN); spin_lock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); if (ipa_gsb_ctx->iface[hdl] != NULL) { ipa_gsb_ctx->iface[hdl]->send_dl_skb( ipa_gsb_ctx->iface[hdl]->send_dl_skb( ipa_gsb_ctx->iface[hdl]->priv, skb2); ipa_gsb_ctx->iface[hdl]->priv, skb2); ipa_gsb_ctx->iface[hdl]->iface_stats.num_dl_packets++; ipa_gsb_ctx->iface[hdl]->iface_stats.num_dl_packets++; spin_unlock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); skb_pull(skb, pkt_size + ETH_HLEN + pad_byte); skb_pull(skb, pkt_size + ETH_HLEN + pad_byte); } else { IPA_GSB_ERR("Invalid hdl: %d, drop the skb\n", hdl); spin_unlock_bh(&ipa_gsb_ctx->iface_spinlock[hdl]); dev_kfree_skb_any(skb2); break; } } } if (skb) { if (skb) { dev_kfree_skb_any(skb); dev_kfree_skb_any(skb); skb = NULL; skb = NULL; Loading @@ -714,6 +743,11 @@ static void ipa_gsb_tx_dp_notify(void *priv, enum ipa_dp_evt_type evt, /* change to host order */ /* change to host order */ *(u32 *)mux_hdr = ntohl(*(u32 *)mux_hdr); *(u32 *)mux_hdr = ntohl(*(u32 *)mux_hdr); hdl = mux_hdr->iface_hdl; hdl = mux_hdr->iface_hdl; if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("invalid hdl: %d and cb, drop the skb\n", hdl); dev_kfree_skb_any(skb); return; } IPA_GSB_DBG_LOW("evt: %d, hdl in tx_dp_notify: %d\n", evt, hdl); IPA_GSB_DBG_LOW("evt: %d, hdl in tx_dp_notify: %d\n", evt, hdl); /* remove 4 byte mux header */ /* remove 4 byte mux header */ Loading Loading @@ -797,13 +831,23 @@ int ipa_bridge_connect(u32 hdl) return -EFAULT; return -EFAULT; } } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG("client hdl: %d\n", hdl); IPA_GSB_DBG("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->lock); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; } if (ipa_gsb_ctx->iface[hdl]->is_connected) { if (ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_DBG("iface was already connected\n"); IPA_GSB_DBG("iface was already connected\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } Loading @@ -811,13 +855,13 @@ int ipa_bridge_connect(u32 hdl) ret = ipa_pm_activate_sync(ipa_gsb_ctx->pm_hdl); ret = ipa_pm_activate_sync(ipa_gsb_ctx->pm_hdl); if (ret) { if (ret) { IPA_GSB_ERR("failed to activate ipa pm\n"); IPA_GSB_ERR("failed to activate ipa pm\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } ret = ipa_gsb_connect_sys_pipe(); ret = ipa_gsb_connect_sys_pipe(); if (ret) { if (ret) { IPA_GSB_ERR("fail to connect pipe\n"); IPA_GSB_ERR("fail to connect pipe\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } } } Loading @@ -833,7 +877,7 @@ int ipa_bridge_connect(u32 hdl) IPA_GSB_DBG("num resumed iface: %d\n", IPA_GSB_DBG("num resumed iface: %d\n", ipa_gsb_ctx->num_resumed_iface); ipa_gsb_ctx->num_resumed_iface); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } EXPORT_SYMBOL(ipa_bridge_connect); EXPORT_SYMBOL(ipa_bridge_connect); Loading Loading @@ -871,13 +915,23 @@ int ipa_bridge_disconnect(u32 hdl) return -EFAULT; return -EFAULT; } } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG("client hdl: %d\n", hdl); IPA_GSB_DBG("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->lock); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; } if (!ipa_gsb_ctx->iface[hdl]->is_connected) { if (!ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_DBG("iface was not connected\n"); IPA_GSB_DBG("iface was not connected\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } Loading @@ -885,14 +939,14 @@ int ipa_bridge_disconnect(u32 hdl) ret = ipa_gsb_disconnect_sys_pipe(); ret = ipa_gsb_disconnect_sys_pipe(); if (ret) { if (ret) { IPA_GSB_ERR("fail to discon pipes\n"); IPA_GSB_ERR("fail to discon pipes\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } ret = ipa_pm_deactivate_sync(ipa_gsb_ctx->pm_hdl); ret = ipa_pm_deactivate_sync(ipa_gsb_ctx->pm_hdl); if (ret) { if (ret) { IPA_GSB_ERR("failed to deactivate ipa pm\n"); IPA_GSB_ERR("failed to deactivate ipa pm\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } } } Loading @@ -910,7 +964,7 @@ int ipa_bridge_disconnect(u32 hdl) ipa_gsb_ctx->num_resumed_iface); ipa_gsb_ctx->num_resumed_iface); } } mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } EXPORT_SYMBOL(ipa_bridge_disconnect); EXPORT_SYMBOL(ipa_bridge_disconnect); Loading @@ -924,25 +978,37 @@ int ipa_bridge_resume(u32 hdl) return -EFAULT; return -EFAULT; } } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; } if (!ipa_gsb_ctx->iface[hdl]->is_connected) { if (!ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_ERR("iface is not connected\n"); IPA_GSB_ERR("iface is not connected\n"); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } if (ipa_gsb_ctx->iface[hdl]->is_resumed) { if (ipa_gsb_ctx->iface[hdl]->is_resumed) { IPA_GSB_DBG_LOW("iface was already resumed\n"); IPA_GSB_DBG_LOW("iface was already resumed\n"); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } mutex_lock(&ipa_gsb_ctx->lock); if (ipa_gsb_ctx->num_resumed_iface == 0) { if (ipa_gsb_ctx->num_resumed_iface == 0) { ret = ipa_pm_activate_sync(ipa_gsb_ctx->pm_hdl); ret = ipa_pm_activate_sync(ipa_gsb_ctx->pm_hdl); if (ret) { if (ret) { IPA_GSB_ERR("fail to activate ipa pm\n"); IPA_GSB_ERR("fail to activate ipa pm\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } Loading @@ -952,7 +1018,7 @@ int ipa_bridge_resume(u32 hdl) IPA_GSB_ERR( IPA_GSB_ERR( "fail to start con ep %d\n", "fail to start con ep %d\n", ret); ret); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } } } Loading @@ -962,7 +1028,7 @@ int ipa_bridge_resume(u32 hdl) IPA_GSB_DBG_LOW("num resumed iface: %d\n", IPA_GSB_DBG_LOW("num resumed iface: %d\n", ipa_gsb_ctx->num_resumed_iface); ipa_gsb_ctx->num_resumed_iface); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } EXPORT_SYMBOL(ipa_bridge_resume); EXPORT_SYMBOL(ipa_bridge_resume); Loading @@ -976,20 +1042,32 @@ int ipa_bridge_suspend(u32 hdl) return -EFAULT; return -EFAULT; } } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; } if (!ipa_gsb_ctx->iface[hdl]->is_connected) { if (!ipa_gsb_ctx->iface[hdl]->is_connected) { IPA_GSB_ERR("iface is not connected\n"); IPA_GSB_ERR("iface is not connected\n"); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return -EFAULT; return -EFAULT; } } if (!ipa_gsb_ctx->iface[hdl]->is_resumed) { if (!ipa_gsb_ctx->iface[hdl]->is_resumed) { IPA_GSB_DBG_LOW("iface was already suspended\n"); IPA_GSB_DBG_LOW("iface was already suspended\n"); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } mutex_lock(&ipa_gsb_ctx->lock); if (ipa_gsb_ctx->num_resumed_iface == 1) { if (ipa_gsb_ctx->num_resumed_iface == 1) { ret = ipa_stop_gsi_channel( ret = ipa_stop_gsi_channel( ipa_gsb_ctx->cons_hdl); ipa_gsb_ctx->cons_hdl); Loading @@ -997,7 +1075,7 @@ int ipa_bridge_suspend(u32 hdl) IPA_GSB_ERR( IPA_GSB_ERR( "fail to stop cons ep %d\n", "fail to stop cons ep %d\n", ret); ret); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } Loading @@ -1005,7 +1083,7 @@ int ipa_bridge_suspend(u32 hdl) if (ret) { if (ret) { IPA_GSB_ERR("fail to deactivate ipa pm\n"); IPA_GSB_ERR("fail to deactivate ipa pm\n"); ipa_start_gsi_channel(ipa_gsb_ctx->cons_hdl); ipa_start_gsi_channel(ipa_gsb_ctx->cons_hdl); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } } } Loading @@ -1015,7 +1093,7 @@ int ipa_bridge_suspend(u32 hdl) IPA_GSB_DBG_LOW("num resumed iface: %d\n", IPA_GSB_DBG_LOW("num resumed iface: %d\n", ipa_gsb_ctx->num_resumed_iface); ipa_gsb_ctx->num_resumed_iface); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return 0; return 0; } } EXPORT_SYMBOL(ipa_bridge_suspend); EXPORT_SYMBOL(ipa_bridge_suspend); Loading @@ -1024,16 +1102,26 @@ int ipa_bridge_set_perf_profile(u32 hdl, u32 bandwidth) { { int ret; int ret; if (!ipa_gsb_ctx) { IPA_GSB_ERR("ipa_gsb_ctx was not initialized\n"); return -EFAULT; } if (hdl >= MAX_SUPPORTED_IFACE) { IPA_GSB_ERR("invalid hdl: %d\n", hdl); return -EINVAL; } IPA_GSB_DBG("client hdl: %d, BW: %d\n", hdl, bandwidth); IPA_GSB_DBG("client hdl: %d, BW: %d\n", hdl, bandwidth); mutex_lock(&ipa_gsb_ctx->lock); mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]); ret = ipa_pm_set_perf_profile(ipa_gsb_ctx->pm_hdl, ret = ipa_pm_set_perf_profile(ipa_gsb_ctx->pm_hdl, bandwidth); bandwidth); if (ret) if (ret) IPA_GSB_ERR("fail to set perf profile\n"); IPA_GSB_ERR("fail to set perf profile\n"); mutex_unlock(&ipa_gsb_ctx->lock); mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]); return ret; return ret; } } EXPORT_SYMBOL(ipa_bridge_set_perf_profile); EXPORT_SYMBOL(ipa_bridge_set_perf_profile); Loading @@ -1047,6 +1135,11 @@ int ipa_bridge_tx_dp(u32 hdl, struct sk_buff *skb, IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); IPA_GSB_DBG_LOW("client hdl: %d\n", hdl); if (!ipa_gsb_ctx->iface[hdl]) { IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl); return -EFAULT; } /* make sure skb has enough headroom */ /* make sure skb has enough headroom */ if (unlikely(skb_headroom(skb) < sizeof(struct ipa_gsb_mux_hdr))) { if (unlikely(skb_headroom(skb) < sizeof(struct ipa_gsb_mux_hdr))) { IPA_GSB_DBG_LOW("skb doesn't have enough headroom\n"); IPA_GSB_DBG_LOW("skb doesn't have enough headroom\n"); Loading