diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 4332f2920522..72b2df6a8dbf 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -3203,13 +3203,13 @@ static void ipa3_free_skb_rx(struct sk_buff *skb) void ipa3_lan_rx_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) { struct sk_buff *rx_skb = (struct sk_buff *)data; - struct ipahal_pkt_status status; + struct ipahal_pkt_status_thin status; struct ipa3_ep_context *ep; unsigned int src_pipe; u32 metadata; u8 ucp; - ipahal_pkt_status_parse(rx_skb->data, &status); + ipahal_pkt_status_parse_thin(rx_skb->data, &status); src_pipe = status.endp_src_idx; metadata = status.metadata; ucp = status.ucp; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c index 799308f2deaa..1cb1417fef87 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c @@ -863,11 +863,52 @@ struct ipahal_imm_cmd_pyld *ipahal_construct_nop_imm_cmd( (status->status_mask |= \ ((hw_status->status_mask & (__hw_bit_msk) ? 1 : 0) << (__shft))) +static enum ipahal_pkt_status_exception pkt_status_parse_exception( + bool is_ipv6, u64 exception) +{ + enum ipahal_pkt_status_exception exception_type = 0; + + switch (exception) { + case 0: + exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NONE; + break; + case 1: + exception_type = IPAHAL_PKT_STATUS_EXCEPTION_DEAGGR; + break; + case 4: + exception_type = IPAHAL_PKT_STATUS_EXCEPTION_IPTYPE; + break; + case 8: + exception_type = IPAHAL_PKT_STATUS_EXCEPTION_PACKET_LENGTH; + break; + case 16: + exception_type = IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS; + break; + case 32: + exception_type = IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT; + break; + case 64: + if (is_ipv6) + exception_type = IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT; + else + exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NAT; + break; + case 229: + exception_type = IPAHAL_PKT_STATUS_EXCEPTION_CSUM; + break; + default: + IPAHAL_ERR("unsupported Status Exception type 0x%x\n", + exception); + WARN_ON(1); + } + + return exception_type; +} + static void ipa_pkt_status_parse( const void *unparsed_status, struct ipahal_pkt_status *status) { enum ipahal_pkt_status_opcode opcode = 0; - enum ipahal_pkt_status_exception exception_type = 0; bool is_ipv6; struct ipa_pkt_status_hw *hw_status = @@ -946,39 +987,8 @@ static void ipa_pkt_status_parse( hw_status->nat_type); } - switch (hw_status->exception) { - case 0: - exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NONE; - break; - case 1: - exception_type = IPAHAL_PKT_STATUS_EXCEPTION_DEAGGR; - break; - case 4: - exception_type = IPAHAL_PKT_STATUS_EXCEPTION_IPTYPE; - break; - case 8: - exception_type = IPAHAL_PKT_STATUS_EXCEPTION_PACKET_LENGTH; - break; - case 16: - exception_type = IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS; - break; - case 32: - exception_type = IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT; - break; - case 64: - if (is_ipv6) - exception_type = IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT; - else - exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NAT; - break; - case 229: - exception_type = IPAHAL_PKT_STATUS_EXCEPTION_CSUM; - break; - default: - IPAHAL_ERR_RL("unsupported Status Exception type 0x%x\n", - hw_status->exception); - } - status->exception = exception_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); @@ -1002,16 +1012,50 @@ static void ipa_pkt_status_parse( status->status_mask &= 0xFFFF; } +/* + * ipa_pkt_status_parse_thin() - Parse some of the packet status fields + * for specific usage in the LAN rx data path where parsing needs to be done + * but only for specific fields. + * @unparsed_status: Pointer to H/W format of the packet status as read from HW + * @status: Pointer to pre-allocated buffer where the parsed info will be + * stored + */ +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; + bool is_ipv6; + + is_ipv6 = (hw_status->status_mask & 0x80) ? false : true; + if (!unparsed_status || !status) { + IPAHAL_ERR("Input Error: unparsed_status=%pK status=%pK\n", + unparsed_status, status); + return; + } + + 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->exception = pkt_status_parse_exception(is_ipv6, + hw_status->exception); +} + /* * struct ipahal_pkt_status_obj - Pakcet Status H/W information for * specific IPA version * @size: H/W size of the status packet * @parse: CB that parses the H/W packet status into the abstracted structure + * @parse_thin: light weight CB that parses only some of the fields for + * data path optimization */ struct ipahal_pkt_status_obj { u32 size; void (*parse)(const void *unparsed_status, struct ipahal_pkt_status *status); + void (*parse_thin)(const void *unparsed_status, + struct ipahal_pkt_status_thin *status); }; /* @@ -1027,6 +1071,7 @@ static struct ipahal_pkt_status_obj ipahal_pkt_status_objs[IPA_HW_MAX] = { [IPA_HW_v3_0] = { IPA3_0_PKT_STATUS_SIZE, ipa_pkt_status_parse, + ipa_pkt_status_parse_thin, }, }; @@ -1050,6 +1095,8 @@ static int ipahal_pkt_status_init(enum ipa_hw_type ipa_hw_type) /* * Since structure alignment is implementation dependent, * add test to avoid different and incompatible data layouts. + * If test fails it also means that ipahal_pkt_status_parse_thin + * need to be checked. * * In case new H/W has different size or structure of status packet, * add a compile time validty check for it like below (as well as @@ -1082,6 +1129,12 @@ static int ipahal_pkt_status_init(enum ipa_hw_type ipa_hw_type) i+1); WARN_ON(1); } + if (!ipahal_pkt_status_objs[i+1].parse_thin) { + IPAHAL_ERR( + "Packet Status without Parse_thin func ipa_ver=%d\n", + i+1); + WARN_ON(1); + } } } @@ -1116,6 +1169,26 @@ void ipahal_pkt_status_parse(const void *unparsed_status, status); } +/* + * ipahal_pkt_status_parse_thin() - Similar to ipahal_pkt_status_parse, + * the difference is it only parses some of the status packet fields + * used for TP optimization. + * @unparsed_status: Pointer to H/W format of the packet status as read from H/W + * @status: Pointer to pre-allocated buffer where the parsed info will be stored + */ +void ipahal_pkt_status_parse_thin(const void *unparsed_status, + struct ipahal_pkt_status_thin *status) +{ + if (!unparsed_status || !status) { + IPAHAL_ERR("Input Error: unparsed_status=%pK status=%pK\n", + unparsed_status, status); + return; + } + IPAHAL_DBG_LOW("Parse_thin Status Packet\n"); + ipahal_pkt_status_objs[ipahal_ctx->hw_type].parse_thin(unparsed_status, + status); +} + /* * ipahal_pkt_status_exception_str() - returns string represents exception type * @exception: [in] The exception type diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h index bab01e2a42e0..d30e68756552 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h @@ -588,6 +588,21 @@ struct ipahal_pkt_status { u8 frag_rule; }; +/* + * struct ipahal_pkt_status_thin - this struct is used to parse only + * a few fields from the status packet, needed for LAN optimization. + * @exception: The first exception that took place. + * @metadata: meta data value used by packet + * @endp_src_idx: Source end point index. + * @ucp: UC Processing flag + */ +struct ipahal_pkt_status_thin { + enum ipahal_pkt_status_exception exception; + u32 metadata; + u8 endp_src_idx; + bool ucp; +}; + /* * ipahal_pkt_status_get_size() - Get H/W size of packet status */ @@ -601,6 +616,17 @@ u32 ipahal_pkt_status_get_size(void); void ipahal_pkt_status_parse(const void *unparsed_status, struct ipahal_pkt_status *status); +/* + * ipahal_pkt_status_parse_thin() - Parse some of the packet status fields + * for specific usage in the LAN rx data path where parsing needs to be done + * but only for specific fields. + * @unparsed_status: Pointer to H/W format of the packet status as read from HW + * @status: Pointer to pre-allocated buffer where the parsed info will be + * stored + */ +void ipahal_pkt_status_parse_thin(const void *unparsed_status, + struct ipahal_pkt_status_thin *status); + /* * ipahal_pkt_status_exception_str() - returns string represents exception type * @exception: [in] The exception type