Commit 55c6eae7 authored by Alex Elder's avatar Alex Elder Committed by David S. Miller

net: ipa: add IPA v5.0 packet status support

Update ipa_status_extract() to support IPA v5.0 and beyond.  Because
the format of the IPA packet status depends on the version, pass an
IPA pointer to the function.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ebd2a82e
...@@ -122,8 +122,10 @@ enum ipa_status_field_id { ...@@ -122,8 +122,10 @@ enum ipa_status_field_id {
#define IPA_STATUS_SIZE sizeof(__le32[4]) #define IPA_STATUS_SIZE sizeof(__le32[4])
/* IPA status structure decoder; looks up field values for a structure */ /* IPA status structure decoder; looks up field values for a structure */
static u32 ipa_status_extract(const void *data, enum ipa_status_field_id field) static u32 ipa_status_extract(struct ipa *ipa, const void *data,
enum ipa_status_field_id field)
{ {
enum ipa_version version = ipa->version;
const __le32 *word = data; const __le32 *word = data;
switch (field) { switch (field) {
...@@ -136,10 +138,15 @@ static u32 ipa_status_extract(const void *data, enum ipa_status_field_id field) ...@@ -136,10 +138,15 @@ static u32 ipa_status_extract(const void *data, enum ipa_status_field_id field)
case STATUS_LENGTH: case STATUS_LENGTH:
return le32_get_bits(word[1], GENMASK(15, 0)); return le32_get_bits(word[1], GENMASK(15, 0));
case STATUS_SRC_ENDPOINT: case STATUS_SRC_ENDPOINT:
if (version < IPA_VERSION_5_0)
return le32_get_bits(word[1], GENMASK(20, 16)); return le32_get_bits(word[1], GENMASK(20, 16));
/* Status word 1, bits 21-23 are reserved */ return le32_get_bits(word[1], GENMASK(23, 16));
/* Status word 1, bits 21-23 are reserved (not IPA v5.0+) */
/* Status word 1, bits 24-26 are reserved (IPA v5.0+) */
case STATUS_DST_ENDPOINT: case STATUS_DST_ENDPOINT:
if (version < IPA_VERSION_5_0)
return le32_get_bits(word[1], GENMASK(28, 24)); return le32_get_bits(word[1], GENMASK(28, 24));
return le32_get_bits(word[7], GENMASK(23, 16));
/* Status word 1, bits 29-31 are reserved */ /* Status word 1, bits 29-31 are reserved */
case STATUS_METADATA: case STATUS_METADATA:
return le32_to_cpu(word[2]); return le32_to_cpu(word[2]);
...@@ -153,14 +160,23 @@ static u32 ipa_status_extract(const void *data, enum ipa_status_field_id field) ...@@ -153,14 +160,23 @@ static u32 ipa_status_extract(const void *data, enum ipa_status_field_id field)
return le32_get_bits(word[3], GENMASK(3, 3)); return le32_get_bits(word[3], GENMASK(3, 3));
case STATUS_FILTER_RULE_INDEX: case STATUS_FILTER_RULE_INDEX:
return le32_get_bits(word[3], GENMASK(13, 4)); return le32_get_bits(word[3], GENMASK(13, 4));
/* ROUTER_TABLE is in word 3, bits 14-21 (IPA v5.0+) */
case STATUS_ROUTER_LOCAL: case STATUS_ROUTER_LOCAL:
if (version < IPA_VERSION_5_0)
return le32_get_bits(word[3], GENMASK(14, 14)); return le32_get_bits(word[3], GENMASK(14, 14));
return le32_get_bits(word[1], GENMASK(27, 27));
case STATUS_ROUTER_HASH: case STATUS_ROUTER_HASH:
if (version < IPA_VERSION_5_0)
return le32_get_bits(word[3], GENMASK(15, 15)); return le32_get_bits(word[3], GENMASK(15, 15));
return le32_get_bits(word[1], GENMASK(28, 28));
case STATUS_UCP: case STATUS_UCP:
if (version < IPA_VERSION_5_0)
return le32_get_bits(word[3], GENMASK(16, 16)); return le32_get_bits(word[3], GENMASK(16, 16));
return le32_get_bits(word[7], GENMASK(31, 31));
case STATUS_ROUTER_TABLE: case STATUS_ROUTER_TABLE:
if (version < IPA_VERSION_5_0)
return le32_get_bits(word[3], GENMASK(21, 17)); return le32_get_bits(word[3], GENMASK(21, 17));
return le32_get_bits(word[3], GENMASK(21, 14));
case STATUS_ROUTER_RULE_INDEX: case STATUS_ROUTER_RULE_INDEX:
return le32_get_bits(word[3], GENMASK(31, 22)); return le32_get_bits(word[3], GENMASK(31, 22));
case STATUS_NAT_HIT: case STATUS_NAT_HIT:
...@@ -186,7 +202,8 @@ static u32 ipa_status_extract(const void *data, enum ipa_status_field_id field) ...@@ -186,7 +202,8 @@ static u32 ipa_status_extract(const void *data, enum ipa_status_field_id field)
return le32_get_bits(word[7], GENMASK(11, 11)); return le32_get_bits(word[7], GENMASK(11, 11));
case STATUS_FRAG_RULE_INDEX: case STATUS_FRAG_RULE_INDEX:
return le32_get_bits(word[7], GENMASK(15, 12)); return le32_get_bits(word[7], GENMASK(15, 12));
/* Status word 7, bits 16-31 are reserved */ /* Status word 7, bits 16-30 are reserved */
/* Status word 7, bit 31 is reserved (not IPA v5.0+) */
default: default:
WARN(true, "%s: bad field_id %u\n", __func__, field); WARN(true, "%s: bad field_id %u\n", __func__, field);
return 0; return 0;
...@@ -1444,14 +1461,15 @@ static bool ipa_status_format_packet(enum ipa_status_opcode opcode) ...@@ -1444,14 +1461,15 @@ static bool ipa_status_format_packet(enum ipa_status_opcode opcode)
static bool static bool
ipa_endpoint_status_skip(struct ipa_endpoint *endpoint, const void *data) ipa_endpoint_status_skip(struct ipa_endpoint *endpoint, const void *data)
{ {
struct ipa *ipa = endpoint->ipa;
enum ipa_status_opcode opcode; enum ipa_status_opcode opcode;
u32 endpoint_id; u32 endpoint_id;
opcode = ipa_status_extract(data, STATUS_OPCODE); opcode = ipa_status_extract(ipa, data, STATUS_OPCODE);
if (!ipa_status_format_packet(opcode)) if (!ipa_status_format_packet(opcode))
return true; return true;
endpoint_id = ipa_status_extract(data, STATUS_DST_ENDPOINT); endpoint_id = ipa_status_extract(ipa, data, STATUS_DST_ENDPOINT);
if (endpoint_id != endpoint->endpoint_id) if (endpoint_id != endpoint->endpoint_id)
return true; return true;
...@@ -1466,7 +1484,7 @@ ipa_endpoint_status_tag_valid(struct ipa_endpoint *endpoint, const void *data) ...@@ -1466,7 +1484,7 @@ ipa_endpoint_status_tag_valid(struct ipa_endpoint *endpoint, const void *data)
struct ipa *ipa = endpoint->ipa; struct ipa *ipa = endpoint->ipa;
u32 endpoint_id; u32 endpoint_id;
status_mask = ipa_status_extract(data, STATUS_MASK); status_mask = ipa_status_extract(ipa, data, STATUS_MASK);
if (!status_mask) if (!status_mask)
return false; /* No valid tag */ return false; /* No valid tag */
...@@ -1475,7 +1493,7 @@ ipa_endpoint_status_tag_valid(struct ipa_endpoint *endpoint, const void *data) ...@@ -1475,7 +1493,7 @@ ipa_endpoint_status_tag_valid(struct ipa_endpoint *endpoint, const void *data)
* If the packet came from the AP->command TX endpoint we know * If the packet came from the AP->command TX endpoint we know
* this packet was sent as part of the pipeline clear process. * this packet was sent as part of the pipeline clear process.
*/ */
endpoint_id = ipa_status_extract(data, STATUS_SRC_ENDPOINT); endpoint_id = ipa_status_extract(ipa, data, STATUS_SRC_ENDPOINT);
command_endpoint = ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX]; command_endpoint = ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX];
if (endpoint_id == command_endpoint->endpoint_id) { if (endpoint_id == command_endpoint->endpoint_id) {
complete(&ipa->completion); complete(&ipa->completion);
...@@ -1493,6 +1511,7 @@ static bool ...@@ -1493,6 +1511,7 @@ static bool
ipa_endpoint_status_drop(struct ipa_endpoint *endpoint, const void *data) ipa_endpoint_status_drop(struct ipa_endpoint *endpoint, const void *data)
{ {
enum ipa_status_exception exception; enum ipa_status_exception exception;
struct ipa *ipa = endpoint->ipa;
u32 rule; u32 rule;
/* If the status indicates a tagged transfer, we'll drop the packet */ /* If the status indicates a tagged transfer, we'll drop the packet */
...@@ -1500,12 +1519,12 @@ ipa_endpoint_status_drop(struct ipa_endpoint *endpoint, const void *data) ...@@ -1500,12 +1519,12 @@ ipa_endpoint_status_drop(struct ipa_endpoint *endpoint, const void *data)
return true; return true;
/* Deaggregation exceptions we drop; all other types we consume */ /* Deaggregation exceptions we drop; all other types we consume */
exception = ipa_status_extract(data, STATUS_EXCEPTION); exception = ipa_status_extract(ipa, data, STATUS_EXCEPTION);
if (exception) if (exception)
return exception == IPA_STATUS_EXCEPTION_DEAGGR; return exception == IPA_STATUS_EXCEPTION_DEAGGR;
/* Drop the packet if it fails to match a routing rule; otherwise no */ /* Drop the packet if it fails to match a routing rule; otherwise no */
rule = ipa_status_extract(data, STATUS_ROUTER_RULE_INDEX); rule = ipa_status_extract(ipa, data, STATUS_ROUTER_RULE_INDEX);
return rule == IPA_STATUS_RULE_MISS; return rule == IPA_STATUS_RULE_MISS;
} }
...@@ -1516,6 +1535,7 @@ static void ipa_endpoint_status_parse(struct ipa_endpoint *endpoint, ...@@ -1516,6 +1535,7 @@ static void ipa_endpoint_status_parse(struct ipa_endpoint *endpoint,
u32 buffer_size = endpoint->config.rx.buffer_size; u32 buffer_size = endpoint->config.rx.buffer_size;
void *data = page_address(page) + NET_SKB_PAD; void *data = page_address(page) + NET_SKB_PAD;
u32 unused = buffer_size - total_len; u32 unused = buffer_size - total_len;
struct ipa *ipa = endpoint->ipa;
u32 resid = total_len; u32 resid = total_len;
while (resid) { while (resid) {
...@@ -1531,7 +1551,7 @@ static void ipa_endpoint_status_parse(struct ipa_endpoint *endpoint, ...@@ -1531,7 +1551,7 @@ static void ipa_endpoint_status_parse(struct ipa_endpoint *endpoint,
} }
/* Skip over status packets that lack packet data */ /* Skip over status packets that lack packet data */
length = ipa_status_extract(data, STATUS_LENGTH); length = ipa_status_extract(ipa, data, STATUS_LENGTH);
if (!length || ipa_endpoint_status_skip(endpoint, data)) { if (!length || ipa_endpoint_status_skip(endpoint, data)) {
data += IPA_STATUS_SIZE; data += IPA_STATUS_SIZE;
resid -= IPA_STATUS_SIZE; resid -= IPA_STATUS_SIZE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment