Merge "msm: ipa: add a thin parsing option for status packets"

This commit is contained in:
qctecmdr 2019-11-18 14:16:17 -08:00 • committed by Gerrit - the friendly Code Review server
commit 31d355bad1
3 changed files with 135 additions and 36 deletions

View file

@ -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;

View file

@ -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

View file

@ -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