summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSkylar Chang <chiaweic@codeaurora.org>2016-04-01 17:24:25 -0700
committerJeevan Shriram <jshriram@codeaurora.org>2016-04-13 11:07:58 -0700
commitc41f0385ee8d28857dc9bfea86f75380c0178bdc (patch)
tree8b3aebdab384b4de319b141fedd4a26a8edaa877
parent1d67a4738541b96fff6fdd7eb9f9ac7ae99f5bb1 (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.c40
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_i.h1
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_dp.c40
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_i.h1
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;