diff options
author | Alex Elder <elder@linaro.org> | 2021-06-02 07:41:30 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-06-03 15:09:40 -0700 |
commit | 5567d4d9e7381230462a564d4f466177f3ba9dd5 (patch) | |
tree | 0102afcf7689e9172a1d2a31c56e2940d7efb238 /drivers/net/ipa/ipa_endpoint.c | |
parent | fcd1a53064cf44ef912c354859027ef291147848 (diff) |
net: ipa: add support for inline checksum offload
Starting with IPA v4.5, IP payload checksum offload is implemented
differently.
Prior to v4.5, the IPA hardware appends an rmnet_map_dl_csum_trailer
structure to each packet if checksum offload is enabled in the
download direction (modem->AP). In the upload direction (AP->modem)
a rmnet_map_ul_csum_header structure is prepended before each sent
packet.
Starting with IPA v4.5, checksum offload is implemented using a
single new rmnet_map_v5_csum_header structure which sits between
the QMAP header and the packet data. The same header structure
is used in both directions.
The new header contains a header type (CSUM_OFFLOAD); a checksum
flag; and a flag indicating whether any other headers follow this
one. The checksum flag indicates whether the hardware should
compute (and insert) the checksum on a sent packet. On a received
packet the checksum flag indicates whether the hardware confirms the
checksum value in the payload is correct.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ipa/ipa_endpoint.c')
-rw-r--r-- | drivers/net/ipa/ipa_endpoint.c | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c index ccc99ad983eb..03719fb6a15a 100644 --- a/drivers/net/ipa/ipa_endpoint.c +++ b/drivers/net/ipa/ipa_endpoint.c @@ -457,28 +457,34 @@ int ipa_endpoint_modem_exception_reset_all(struct ipa *ipa) static void ipa_endpoint_init_cfg(struct ipa_endpoint *endpoint) { u32 offset = IPA_REG_ENDP_INIT_CFG_N_OFFSET(endpoint->endpoint_id); + enum ipa_cs_offload_en enabled; u32 val = 0; /* FRAG_OFFLOAD_EN is 0 */ if (endpoint->data->checksum) { + enum ipa_version version = endpoint->ipa->version; + if (endpoint->toward_ipa) { u32 checksum_offset; - val |= u32_encode_bits(IPA_CS_OFFLOAD_UL, - CS_OFFLOAD_EN_FMASK); /* Checksum header offset is in 4-byte units */ checksum_offset = sizeof(struct rmnet_map_header); checksum_offset /= sizeof(u32); val |= u32_encode_bits(checksum_offset, CS_METADATA_HDR_OFFSET_FMASK); + + enabled = version < IPA_VERSION_4_5 + ? IPA_CS_OFFLOAD_UL + : IPA_CS_OFFLOAD_INLINE; } else { - val |= u32_encode_bits(IPA_CS_OFFLOAD_DL, - CS_OFFLOAD_EN_FMASK); + enabled = version < IPA_VERSION_4_5 + ? IPA_CS_OFFLOAD_DL + : IPA_CS_OFFLOAD_INLINE; } } else { - val |= u32_encode_bits(IPA_CS_OFFLOAD_NONE, - CS_OFFLOAD_EN_FMASK); + enabled = IPA_CS_OFFLOAD_NONE; } + val |= u32_encode_bits(enabled, CS_OFFLOAD_EN_FMASK); /* CS_GEN_QMB_MASTER_SEL is 0 */ iowrite32(val, endpoint->ipa->reg_virt + offset); @@ -498,6 +504,27 @@ static void ipa_endpoint_init_nat(struct ipa_endpoint *endpoint) iowrite32(val, endpoint->ipa->reg_virt + offset); } +static u32 +ipa_qmap_header_size(enum ipa_version version, struct ipa_endpoint *endpoint) +{ + u32 header_size = sizeof(struct rmnet_map_header); + + /* Without checksum offload, we just have the MAP header */ + if (!endpoint->data->checksum) + return header_size; + + if (version < IPA_VERSION_4_5) { + /* Checksum header inserted for AP TX endpoints only */ + if (endpoint->toward_ipa) + header_size += sizeof(struct rmnet_map_ul_csum_header); + } else { + /* Checksum header is used in both directions */ + header_size += sizeof(struct rmnet_map_v5_csum_header); + } + + return header_size; +} + /** * ipa_endpoint_init_hdr() - Initialize HDR endpoint configuration register * @endpoint: Endpoint pointer @@ -526,13 +553,11 @@ static void ipa_endpoint_init_hdr(struct ipa_endpoint *endpoint) u32 val = 0; if (endpoint->data->qmap) { - size_t header_size = sizeof(struct rmnet_map_header); enum ipa_version version = ipa->version; + size_t header_size; - /* We might supply a checksum header after the QMAP header */ - if (endpoint->toward_ipa && endpoint->data->checksum) - header_size += sizeof(struct rmnet_map_ul_csum_header); - val |= ipa_header_size_encoded(version, header_size); + header_size = ipa_qmap_header_size(version, endpoint); + val = ipa_header_size_encoded(version, header_size); /* Define how to fill fields in a received QMAP header */ if (!endpoint->toward_ipa) { |