From db2bd4325d32a1a9da9c3652b8ec9d3fb0590117 Mon Sep 17 00:00:00 2001 From: Ashok Vuyyuru Date: Wed, 4 Dec 2019 21:02:06 +0530 Subject: [PATCH] msm: ipa3: Fix to ignore frag status packet in lan consumer pipe Since lan payload is handler not handling the frag status packets, add changes to ignore frag status packet in lan payload handler. Change-Id: I6f93d29a009c023f0ab3966b2f73f49e82e2b585 Signed-off-by: Ashok Vuyyuru --- drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 8 +- .../platform/msm/ipa/ipa_v3/ipahal/ipahal.c | 135 +++++++++++------- .../platform/msm/ipa/ipa_v3/ipahal/ipahal.h | 17 +++ .../platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h | 65 ++++++++- 4 files changed, 174 insertions(+), 51 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 359ac0594f24..5ff788d213f0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -2804,8 +2804,14 @@ begin: case IPAHAL_PKT_STATUS_OPCODE_PACKET: case IPAHAL_PKT_STATUS_OPCODE_SUSPENDED_PACKET: case IPAHAL_PKT_STATUS_OPCODE_PACKET_2ND_PASS: - case IPAHAL_PKT_STATUS_OPCODE_NEW_FRAG_RULE: break; + case IPAHAL_PKT_STATUS_OPCODE_NEW_FRAG_RULE: + IPAERR_RL("Frag packets received on lan consumer\n"); + IPAERR_RL("STATUS opcode=%d src=%d dst=%d src ip=%x\n", + status.status_opcode, status.endp_src_idx, + status.endp_dest_idx, status.src_ip_addr); + skb_pull(skb, pkt_status_sz); + continue; default: IPAERR_RL("unsupported opcode(%d)\n", status.status_opcode); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c index 1cb1417fef87..8758360e34ae 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c @@ -861,7 +861,8 @@ struct ipahal_imm_cmd_pyld *ipahal_construct_nop_imm_cmd( #define IPA_PKT_STATUS_SET_MSK(__hw_bit_msk, __shft) \ (status->status_mask |= \ - ((hw_status->status_mask & (__hw_bit_msk) ? 1 : 0) << (__shft))) + ((hw_status->ipa_pkt.status_mask & (__hw_bit_msk) ? 1 : 0) \ + << (__shft))) static enum ipahal_pkt_status_exception pkt_status_parse_exception( bool is_ipv6, u64 exception) @@ -905,46 +906,81 @@ static enum ipahal_pkt_status_exception pkt_status_parse_exception( return exception_type; } +static void __ipa_parse_gen_pkt(struct ipahal_pkt_status *status, + const void *unparsed_status) +{ + bool is_ipv6; + union ipa_pkt_status_hw *hw_status = + (union ipa_pkt_status_hw *)unparsed_status; + + is_ipv6 = (hw_status->ipa_pkt.status_mask & 0x80) ? false : true; + status->pkt_len = hw_status->ipa_pkt.pkt_len; + status->endp_src_idx = hw_status->ipa_pkt.endp_src_idx; + status->endp_dest_idx = hw_status->ipa_pkt.endp_dest_idx; + status->metadata = hw_status->ipa_pkt.metadata; + status->flt_local = hw_status->ipa_pkt.flt_local; + status->flt_hash = hw_status->ipa_pkt.flt_hash; + status->flt_global = hw_status->ipa_pkt.flt_hash; + status->flt_ret_hdr = hw_status->ipa_pkt.flt_ret_hdr; + status->flt_miss = (hw_status->ipa_pkt.rt_rule_id == + IPAHAL_PKT_STATUS_FLTRT_RULE_MISS_ID); + status->flt_rule_id = hw_status->ipa_pkt.flt_rule_id; + status->rt_local = hw_status->ipa_pkt.rt_local; + status->rt_hash = hw_status->ipa_pkt.rt_hash; + status->ucp = hw_status->ipa_pkt.ucp; + status->rt_tbl_idx = hw_status->ipa_pkt.rt_tbl_idx; + status->rt_miss = (hw_status->ipa_pkt.rt_rule_id == + IPAHAL_PKT_STATUS_FLTRT_RULE_MISS_ID); + status->rt_rule_id = hw_status->ipa_pkt.rt_rule_id; + status->nat_hit = hw_status->ipa_pkt.nat_hit; + status->nat_entry_idx = hw_status->ipa_pkt.nat_entry_idx; + status->tag_info = hw_status->ipa_pkt.tag_info; + status->seq_num = hw_status->ipa_pkt.seq_num; + status->time_of_day_ctr = hw_status->ipa_pkt.time_of_day_ctr; + status->hdr_local = hw_status->ipa_pkt.hdr_local; + status->hdr_offset = hw_status->ipa_pkt.hdr_offset; + status->frag_hit = hw_status->ipa_pkt.frag_hit; + status->frag_rule = hw_status->ipa_pkt.frag_rule; + status->nat_type = hw_status->ipa_pkt.nat_type; + + status->exception = pkt_status_parse_exception(is_ipv6, + hw_status->ipa_pkt.exception); +} + +static void __ipa_parse_frag_pkt(struct ipahal_pkt_status *status, + const void *unparsed_status) +{ + union ipa_pkt_status_hw *hw_status = + (union ipa_pkt_status_hw *)unparsed_status; + + status->frag_rule_idx = hw_status->frag_pkt.frag_rule_idx; + status->tbl_idx = hw_status->frag_pkt.tbl_idx; + status->src_ip_addr = hw_status->frag_pkt.src_ip_addr; + status->dest_ip_addr = hw_status->frag_pkt.dest_ip_addr; + status->protocol = hw_status->frag_pkt.protocol; + status->ip_id = hw_status->frag_pkt.ip_id; + status->tlated_ip_addr = hw_status->frag_pkt.tlated_ip_addr; + status->ip_cksum_diff = hw_status->frag_pkt.ip_cksum_diff; + status->endp_src_idx = hw_status->frag_pkt.endp_src_idx; + status->endp_dest_idx = hw_status->frag_pkt.endp_dest_idx; + status->metadata = hw_status->frag_pkt.metadata; + status->seq_num = hw_status->frag_pkt.seq_num; + status->hdr_local = hw_status->frag_pkt.hdr_local; + status->hdr_offset = hw_status->frag_pkt.hdr_offset; + status->exception = hw_status->frag_pkt.exception; + status->nat_type = hw_status->frag_pkt.nat_type; +} + static void ipa_pkt_status_parse( const void *unparsed_status, struct ipahal_pkt_status *status) { enum ipahal_pkt_status_opcode opcode = 0; - bool is_ipv6; - struct ipa_pkt_status_hw *hw_status = - (struct ipa_pkt_status_hw *)unparsed_status; + union ipa_pkt_status_hw *hw_status = + (union ipa_pkt_status_hw *)unparsed_status; - is_ipv6 = (hw_status->status_mask & 0x80) ? false : true; - status->pkt_len = hw_status->pkt_len; - status->endp_src_idx = hw_status->endp_src_idx; - status->endp_dest_idx = hw_status->endp_dest_idx; - status->metadata = hw_status->metadata; - status->flt_local = hw_status->flt_local; - status->flt_hash = hw_status->flt_hash; - status->flt_global = hw_status->flt_hash; - status->flt_ret_hdr = hw_status->flt_ret_hdr; - status->flt_miss = (hw_status->rt_rule_id == - IPAHAL_PKT_STATUS_FLTRT_RULE_MISS_ID); - status->flt_rule_id = hw_status->flt_rule_id; - status->rt_local = hw_status->rt_local; - status->rt_hash = hw_status->rt_hash; - status->ucp = hw_status->ucp; - status->rt_tbl_idx = hw_status->rt_tbl_idx; - status->rt_miss = (hw_status->rt_rule_id == - IPAHAL_PKT_STATUS_FLTRT_RULE_MISS_ID); - status->rt_rule_id = hw_status->rt_rule_id; - status->nat_hit = hw_status->nat_hit; - status->nat_entry_idx = hw_status->nat_entry_idx; - status->tag_info = hw_status->tag_info; - status->seq_num = hw_status->seq_num; - status->time_of_day_ctr = hw_status->time_of_day_ctr; - status->hdr_local = hw_status->hdr_local; - status->hdr_offset = hw_status->hdr_offset; - status->frag_hit = hw_status->frag_hit; - status->frag_rule = hw_status->frag_rule; - - switch (hw_status->status_opcode) { + switch (hw_status->ipa_pkt.status_opcode) { case 0x1: opcode = IPAHAL_PKT_STATUS_OPCODE_PACKET; break; @@ -968,11 +1004,17 @@ static void ipa_pkt_status_parse( break; default: IPAHAL_ERR_RL("unsupported Status Opcode 0x%x\n", - hw_status->status_opcode); + hw_status->ipa_pkt.status_opcode); } + status->status_opcode = opcode; - switch (hw_status->nat_type) { + if (status->status_opcode == IPAHAL_PKT_STATUS_OPCODE_NEW_FRAG_RULE) + __ipa_parse_frag_pkt(status, unparsed_status); + else + __ipa_parse_gen_pkt(status, unparsed_status); + + switch (status->nat_type) { case 0: status->nat_type = IPAHAL_PKT_STATUS_NAT_NONE; break; @@ -984,12 +1026,9 @@ static void ipa_pkt_status_parse( break; default: IPAHAL_ERR_RL("unsupported Status NAT type 0x%x\n", - hw_status->nat_type); + status->nat_type); } - status->exception = pkt_status_parse_exception(is_ipv6, - hw_status->exception); - IPA_PKT_STATUS_SET_MSK(0x1, IPAHAL_PKT_STATUS_MASK_FRAG_PROCESS_SHFT); IPA_PKT_STATUS_SET_MSK(0x2, IPAHAL_PKT_STATUS_MASK_FILT_PROCESS_SHFT); IPA_PKT_STATUS_SET_MSK(0x4, IPAHAL_PKT_STATUS_MASK_NAT_PROCESS_SHFT); @@ -1023,11 +1062,11 @@ static void ipa_pkt_status_parse( static void ipa_pkt_status_parse_thin(const void *unparsed_status, struct ipahal_pkt_status_thin *status) { - struct ipa_pkt_status_hw *hw_status = - (struct ipa_pkt_status_hw *)unparsed_status; + union ipa_pkt_status_hw *hw_status = + (union ipa_pkt_status_hw *)unparsed_status; bool is_ipv6; - is_ipv6 = (hw_status->status_mask & 0x80) ? false : true; + is_ipv6 = (hw_status->ipa_pkt.status_mask & 0x80) ? false : true; if (!unparsed_status || !status) { IPAHAL_ERR("Input Error: unparsed_status=%pK status=%pK\n", unparsed_status, status); @@ -1035,11 +1074,11 @@ static void ipa_pkt_status_parse_thin(const void *unparsed_status, } IPAHAL_DBG_LOW("Parse Thin Status Packet\n"); - status->metadata = hw_status->metadata; - status->endp_src_idx = hw_status->endp_src_idx; - status->ucp = hw_status->ucp; + status->metadata = hw_status->ipa_pkt.metadata; + status->endp_src_idx = hw_status->ipa_pkt.endp_src_idx; + status->ucp = hw_status->ipa_pkt.ucp; status->exception = pkt_status_parse_exception(is_ipv6, - hw_status->exception); + hw_status->ipa_pkt.exception); } /* @@ -1102,7 +1141,7 @@ static int ipahal_pkt_status_init(enum ipa_hw_type ipa_hw_type) * add a compile time validty check for it like below (as well as * the new defines and/or the new strucutre in the internal header). */ - BUILD_BUG_ON(sizeof(struct ipa_pkt_status_hw) != + BUILD_BUG_ON(sizeof(union ipa_pkt_status_hw) != IPA3_0_PKT_STATUS_SIZE); memset(&zero_obj, 0, sizeof(zero_obj)); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h index d30e68756552..440c57036f19 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h @@ -555,6 +555,14 @@ enum ipahal_pkt_status_nat_type { * @rt_tbl_idx: Index of rt tbl that contains the rule on which was a match * @seq_num: Per source endp unique packet sequence number * @frag_rule: Frag rule index in H/W frag table in case of frag hit + * @frag_rule_idx: Frag rule index value. + * @tbl_idx: Table index valid or not. + * @src_ip_addr: Source packet IP address. + * @dest_ip_addr: Destination packet IP address. + * @protocol: Protocal number. + * @ip_id: IP packet IP ID number. + * @tlated_ip_addr: IP address. + * @ip_cksum_diff: IP packet checksum difference. */ struct ipahal_pkt_status { u64 tag_info; @@ -586,6 +594,15 @@ struct ipahal_pkt_status { u8 rt_tbl_idx; u8 seq_num; u8 frag_rule; + u8 frag_rule_idx; + bool tbl_idx; + u32 src_ip_addr; + u32 dest_ip_addr; + u8 protocol; + u16 ip_id; + u32 tlated_ip_addr; + u16 ip_cksum_diff; + }; /* diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h index c49ab093afbc..8ab85cba79d2 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h @@ -566,7 +566,7 @@ struct ipa_imm_cmd_hw_dma_task_32b_addr { * @frag_rule: Frag rule index in H/W frag table in case of frag hit * @hw_specific: H/W specific reserved value */ -struct ipa_pkt_status_hw { +struct ipa_gen_pkt_status_hw { u64 status_opcode:8; u64 exception:8; u64 status_mask:16; @@ -597,7 +597,68 @@ struct ipa_pkt_status_hw { u64 frag_hit:1; u64 frag_rule:4; u64 hw_specific:16; -}; +} __packed; + +/* + * struct ipa_frag_pkt_status_hw - IPA status packet payload in H/W format. + * This structure describes the frag status packet H/W structure for the + * following statuses: IPA_NEW_FRAG_RULE. + * @status_opcode: The Type of the status (Opcode). + * @frag_rule_idx: Frag rule index value. + * @rsvd1: reserved + * @tbl_idx: Table index valid or not. + * @endp_src_idx: Source end point index. + * @exception: (not bitmask) - the first exception that took place. + * In case of exception, src endp and pkt len are always valid. + * @rsvd2: reserved + * @seq_num: Packet sequence number. + * @src_ip_addr: Source packet IP address. + * @dest_ip_addr: Destination packet IP address. + * @rsvd3: reserved + * @nat_type: Defines the type of the NAT operation: + * 00: No NAT + * 01: Source NAT + * 10: Destination NAT + * 11: Reserved + * @protocol: Protocal number. + * @ip_id: IP packet IP ID number. + * @tlated_ip_addr: IP address. + * @hdr_local: Header table location flag: In header insertion, was the header + * taken from the table resides in local memory? (If no, then system mem) + * @hdr_offset: Offset of used header in the header table + * @endp_dest_idx: Destination end point index. + * @ip_cksum_diff: IP packet checksum difference. + * @metadata: meta data value used by packet + * @rsvd4: reserved + */ +struct ipa_frag_pkt_status_hw { + u64 status_opcode:8; + u64 frag_rule_idx:4; + u64 reserved_1:3; + u64 tbl_idx:1; + u64 endp_src_idx:5; + u64 exception:1; + u64 reserved_2:2; + u64 seq_num:8; + u64 src_ip_addr:32; + u64 dest_ip_addr:32; + u64 reserved_3:6; + u64 nat_type:2; + u64 protocol:8; + u64 ip_id:16; + u64 tlated_ip_addr:32; + u64 hdr_local:1; + u64 hdr_offset:10; + u64 endp_dest_idx:5; + u64 ip_cksum_diff:16; + u64 metadata:32; + u64 reserved_4:32; +} __packed; + +union ipa_pkt_status_hw { + struct ipa_gen_pkt_status_hw ipa_pkt; + struct ipa_frag_pkt_status_hw frag_pkt; +} __packed; /* Size of H/W Packet Status */ #define IPA3_0_PKT_STATUS_SIZE 32