diff --git a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c index 8dfe1920c56b..0c319f951e5a 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c +++ b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c @@ -659,13 +659,21 @@ static void ecm_ipa_packet_receive_notify packet_len = skb->len; ECM_IPA_DEBUG("packet RX, len=%d\n", skb->len); + if (unlikely(ecm_ipa_ctx == NULL)) { + ECM_IPA_DEBUG("Private context is NULL. Drop SKB.\n"); + dev_kfree_skb_any(skb); + return; + } + if (unlikely(ecm_ipa_ctx->state != ECM_IPA_CONNECTED_AND_UP)) { ECM_IPA_DEBUG("Missing pipe connected and/or iface up\n"); + dev_kfree_skb_any(skb); return; } if (unlikely(evt != IPA_RECEIVE)) { ECM_IPA_ERROR("A none IPA_RECEIVE event in ecm_ipa_receive\n"); + dev_kfree_skb_any(skb); return; } diff --git a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c index c201aa342084..8b93ee9b0e35 100644 --- a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c +++ b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c @@ -1135,6 +1135,12 @@ static void rndis_ipa_packet_receive_notify( ("packet Rx, len=%d\n", skb->len); + if (unlikely(rndis_ipa_ctx == NULL)) { + RNDIS_IPA_DEBUG("Private context is NULL. Drop SKB.\n"); + dev_kfree_skb_any(skb); + return; + } + if (unlikely(rndis_ipa_ctx->rx_dump_enable)) rndis_ipa_dump_skb(skb); @@ -1142,11 +1148,15 @@ static void rndis_ipa_packet_receive_notify( RNDIS_IPA_DEBUG("use connect()/up() before receive()\n"); RNDIS_IPA_DEBUG("packet dropped (length=%d)\n", skb->len); + rndis_ipa_ctx->rx_dropped++; + dev_kfree_skb_any(skb); return; } if (evt != IPA_RECEIVE) { RNDIS_IPA_ERROR_RL("a none IPA_RECEIVE event in driver RX\n"); + rndis_ipa_ctx->rx_dropped++; + dev_kfree_skb_any(skb); return; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 2b36491a5c5d..f4b4b24da406 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -1524,7 +1524,10 @@ int ipa3_release_gsi_channel(u32 clnt_hdl) IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl)); /* Set the disconnect in progress flag to avoid calling cb.*/ + spin_lock(&ipa3_ctx->disconnect_lock); atomic_set(&ep->disconnect_in_progress, 1); + spin_unlock(&ipa3_ctx->disconnect_lock); + gsi_res = gsi_dealloc_channel(ep->gsi_chan_hdl); if (gsi_res != GSI_STATUS_SUCCESS) { @@ -1544,7 +1547,9 @@ int ipa3_release_gsi_channel(u32 clnt_hdl) if (!ep->keep_ipa_awake) IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); + spin_lock(&ipa3_ctx->disconnect_lock); memset(&ipa3_ctx->ep[clnt_hdl], 0, sizeof(struct ipa3_ep_context)); + spin_unlock(&ipa3_ctx->disconnect_lock); IPADBG("exit\n"); return 0; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index dd341697d6ea..298f4343ea4c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -3402,14 +3402,18 @@ void ipa3_lan_rx_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) unsigned int src_pipe; u32 metadata; u8 ucp; + void (*client_notify)(void *client_priv, enum ipa_dp_evt_type evt, + unsigned long data); + void *client_priv; ipahal_pkt_status_parse_thin(rx_skb->data, &status); src_pipe = status.endp_src_idx; metadata = status.metadata; ucp = status.ucp; ep = &ipa3_ctx->ep[src_pipe]; - if (unlikely(src_pipe >= ipa3_ctx->ipa_num_pipes)) { - IPAERR_RL("drop pipe=%d\n", src_pipe); + if (unlikely(src_pipe >= ipa3_ctx->ipa_num_pipes) || + unlikely(atomic_read(&ep->disconnect_in_progress))) { + IPAERR("drop pipe=%d\n", src_pipe); dev_kfree_skb_any(rx_skb); return; } @@ -3431,12 +3435,19 @@ void ipa3_lan_rx_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) metadata, *(u32 *)rx_skb->cb); IPADBG_LOW("ucp: %d\n", *(u8 *)(rx_skb->cb + 4)); + spin_lock(&ipa3_ctx->disconnect_lock); if (likely((!atomic_read(&ep->disconnect_in_progress)) && - ep->valid && ep->client_notify)) - ep->client_notify(ep->priv, IPA_RECEIVE, + ep->valid && ep->client_notify)) { + client_notify = ep->client_notify; + client_priv = ep->priv; + spin_unlock(&ipa3_ctx->disconnect_lock); + client_notify(client_priv, IPA_RECEIVE, (unsigned long)(rx_skb)); - else + } else { + spin_unlock(&ipa3_ctx->disconnect_lock); dev_kfree_skb_any(rx_skb); + } + } static void ipa3_recycle_rx_wrapper(struct ipa3_rx_pkt_wrapper *rx_pkt)