diff options
| author | Skylar Chang <chiaweic@codeaurora.org> | 2016-04-01 17:24:25 -0700 |
|---|---|---|
| committer | Jeevan Shriram <jshriram@codeaurora.org> | 2016-04-13 11:07:58 -0700 |
| commit | c41f0385ee8d28857dc9bfea86f75380c0178bdc (patch) | |
| tree | 8b3aebdab384b4de319b141fedd4a26a8edaa877 | |
| parent | 1d67a4738541b96fff6fdd7eb9f9ac7ae99f5bb1 (diff) | |
msm: ipa: fix to handle deaggr error
In case of deaggregation error in IPA, IPA HW will send
the deaggregation error frame as exception.
This change fixes a bug in this logic for large frames.
CRs-Fixed: 999351
Change-Id: I49ae94cea34dda039d03dbeeab2add2bdd1760bd
Acked-by: Ady Abraham <adya@qti.qualcomm.com>
Signed-off-by: Skylar Chang <chiaweic@codeaurora.org>
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v2/ipa_dp.c | 40 | ||||
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v2/ipa_i.h | 1 | ||||
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 40 | ||||
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 1 |
4 files changed, 58 insertions, 24 deletions
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c index 25b29cdb3e32..0a3f6795e92d 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c @@ -2115,7 +2115,6 @@ static int ipa_lan_rx_pyld_hdlr(struct sk_buff *skb, int pad_len_byte; int len; unsigned char *buf; - bool drop_packet; int src_pipe; unsigned int used = *(unsigned int *)skb->cb; unsigned int used_align = ALIGN(used, 32); @@ -2135,6 +2134,7 @@ static int ipa_lan_rx_pyld_hdlr(struct sk_buff *skb, memcpy(buf, sys->prev_skb->data, sys->len_partial); sys->len_partial = 0; sys->free_skb(sys->prev_skb); + sys->prev_skb = NULL; goto begin; } @@ -2154,9 +2154,13 @@ static int ipa_lan_rx_pyld_hdlr(struct sk_buff *skb, skb2->len - sys->len_pad); skb2->truesize = skb2->len + sizeof(struct sk_buff); - sys->ep->client_notify(sys->ep->priv, - IPA_RECEIVE, - (unsigned long)(skb2)); + if (sys->drop_packet) + dev_kfree_skb_any(skb2); + else + sys->ep->client_notify( + sys->ep->priv, + IPA_RECEIVE, + (unsigned long)(skb2)); } else { IPAERR("copy expand failed\n"); } @@ -2187,7 +2191,7 @@ static int ipa_lan_rx_pyld_hdlr(struct sk_buff *skb, begin: while (skb->len) { - drop_packet = false; + sys->drop_packet = false; IPADBG("LEN_REM %d\n", skb->len); if (skb->len < IPA_PKT_STATUS_SIZE) { @@ -2226,9 +2230,11 @@ begin: IPA_STATS_EXCP_CNT(status->exception, ipa_ctx->stats.rx_excp_pkts); if (status->endp_dest_idx >= ipa_ctx->ipa_num_pipes || - status->endp_src_idx >= ipa_ctx->ipa_num_pipes || - status->pkt_len > IPA_GENERIC_AGGR_BYTE_LIMIT * 1024) { + status->endp_src_idx >= ipa_ctx->ipa_num_pipes) { IPAERR("status fields invalid\n"); + IPAERR("STATUS opcode=%d src=%d dst=%d len=%d\n", + status->status_opcode, status->endp_src_idx, + status->endp_dest_idx, status->pkt_len); WARN_ON(1); BUG(); } @@ -2270,7 +2276,7 @@ begin: * there was no route match. */ if (!status->exception && !status->route_match) - drop_packet = true; + sys->drop_packet = true; if (skb->len == IPA_PKT_STATUS_SIZE && !status->exception) { @@ -2292,8 +2298,7 @@ begin: if (status->exception == IPA_HW_PKT_STATUS_EXCEPTION_DEAGGR) { IPADBG("Dropping packet on DeAggr Exception\n"); - skb_pull(skb, len + IPA_PKT_STATUS_SIZE); - continue; + sys->drop_packet = true; } skb2 = skb_clone(skb, GFP_KERNEL); @@ -2311,9 +2316,20 @@ begin: IPA_PKT_STATUS_SIZE); IPADBG("rx avail for %d\n", status->endp_dest_idx); - if (drop_packet) + if (sys->drop_packet) { dev_kfree_skb_any(skb2); - else { + } else if (status->pkt_len > + IPA_GENERIC_AGGR_BYTE_LIMIT * + 1024) { + IPAERR("packet size invalid\n"); + IPAERR("STATUS opcode=%d\n", + status->status_opcode); + IPAERR("src=%d dst=%d len=%d\n", + status->endp_src_idx, + status->endp_dest_idx, + status->pkt_len); + BUG(); + } else { skb2->truesize = skb2->len + sizeof(struct sk_buff) + (ALIGN(len + diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h index c243eaef37cc..50e30291bb0f 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h @@ -619,6 +619,7 @@ struct ipa_sys_context { unsigned int len_rem; unsigned int len_pad; unsigned int len_partial; + bool drop_packet; struct work_struct work; void (*sps_callback)(struct sps_event_notify *notify); enum sps_option sps_option; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index d545de10296d..d3f24b9403f0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -2225,7 +2225,6 @@ static int ipa3_lan_rx_pyld_hdlr(struct sk_buff *skb, int pad_len_byte; int len; unsigned char *buf; - bool drop_packet; int src_pipe; unsigned int used = *(unsigned int *)skb->cb; unsigned int used_align = ALIGN(used, 32); @@ -2247,6 +2246,7 @@ static int ipa3_lan_rx_pyld_hdlr(struct sk_buff *skb, memcpy(buf, sys->prev_skb->data, sys->len_partial); sys->len_partial = 0; sys->free_skb(sys->prev_skb); + sys->prev_skb = NULL; goto begin; } @@ -2266,9 +2266,13 @@ static int ipa3_lan_rx_pyld_hdlr(struct sk_buff *skb, skb2->len - sys->len_pad); skb2->truesize = skb2->len + sizeof(struct sk_buff); - sys->ep->client_notify(sys->ep->priv, - IPA_RECEIVE, - (unsigned long)(skb2)); + if (sys->drop_packet) + dev_kfree_skb_any(skb2); + else + sys->ep->client_notify( + sys->ep->priv, + IPA_RECEIVE, + (unsigned long)(skb2)); } else { IPAERR("copy expand failed\n"); } @@ -2300,7 +2304,7 @@ static int ipa3_lan_rx_pyld_hdlr(struct sk_buff *skb, begin: pkt_status_sz = ipahal_pkt_status_get_size(); while (skb->len) { - drop_packet = false; + sys->drop_packet = false; IPADBG_LOW("LEN_REM %d\n", skb->len); if (skb->len < pkt_status_sz) { @@ -2339,9 +2343,11 @@ begin: IPA_STATS_EXCP_CNT(status.exception, ipa3_ctx->stats.rx_excp_pkts); if (status.endp_dest_idx >= ipa3_ctx->ipa_num_pipes || - status.endp_src_idx >= ipa3_ctx->ipa_num_pipes || - status.pkt_len > IPA_GENERIC_AGGR_BYTE_LIMIT * 1024) { + status.endp_src_idx >= ipa3_ctx->ipa_num_pipes) { IPAERR("status fields invalid\n"); + IPAERR("STATUS opcode=%d src=%d dst=%d len=%d\n", + status.status_opcode, status.endp_src_idx, + status.endp_dest_idx, status.pkt_len); WARN_ON(1); BUG(); } @@ -2389,7 +2395,7 @@ begin: if (status.exception == IPAHAL_PKT_STATUS_EXCEPTION_NONE && status.rt_rule_id == IPA_RULE_ID_INVALID) - drop_packet = true; + sys->drop_packet = true; if (skb->len == pkt_status_sz && status.exception == @@ -2413,8 +2419,7 @@ begin: IPAHAL_PKT_STATUS_EXCEPTION_DEAGGR) { IPADBG_LOW( "Dropping packet on DeAggr Exception\n"); - skb_pull(skb, len + pkt_status_sz); - continue; + sys->drop_packet = true; } skb2 = ipa3_skb_copy_for_client(skb, @@ -2433,9 +2438,20 @@ begin: pkt_status_sz); IPADBG_LOW("rx avail for %d\n", status.endp_dest_idx); - if (drop_packet) + if (sys->drop_packet) { dev_kfree_skb_any(skb2); - else { + } else if (status.pkt_len > + IPA_GENERIC_AGGR_BYTE_LIMIT * + 1024) { + IPAERR("packet size invalid\n"); + IPAERR("STATUS opcode=%d\n", + status.status_opcode); + IPAERR("src=%d dst=%d len=%d\n", + status.endp_src_idx, + status.endp_dest_idx, + status.pkt_len); + BUG(); + } else { skb2->truesize = skb2->len + sizeof(struct sk_buff) + (ALIGN(len + diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index c2e93adb2a17..13639cf8491e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -714,6 +714,7 @@ struct ipa3_sys_context { unsigned int len_rem; unsigned int len_pad; unsigned int len_partial; + bool drop_packet; struct work_struct work; void (*sps_callback)(struct sps_event_notify *notify); enum sps_option sps_option; |
