Commit e5118f57 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ipa-inline-csum'

Alex Elder says:

====================
net: ipa: support inline checksum offload

Inline offload--required for checksum offload support on IPA version
4.5 and above--is now supported by the RMNet driver:
  https://lore.kernel.org/netdev/162259440606.2786.10278242816453240434.git-patchwork-notify@kernel.org/



Add support for it in the IPA driver, and revert the commit that
disabled it pending acceptance of the RMNet code.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents fcd1a530 d15ec193
Loading
Loading
Loading
Loading
+36 −27
Original line number Diff line number Diff line
@@ -88,11 +88,6 @@ static bool ipa_endpoint_data_valid_one(struct ipa *ipa, u32 count,
	if (ipa_gsi_endpoint_data_empty(data))
		return true;

	/* IPA v4.5+ uses checksum offload, not yet supported by RMNet */
	if (ipa->version >= IPA_VERSION_4_5)
		if (data->endpoint.config.checksum)
			return false;

	if (!data->toward_ipa) {
		if (data->endpoint.filter_support) {
			dev_err(dev, "filtering not supported for "
@@ -235,17 +230,6 @@ static bool ipa_endpoint_data_valid(struct ipa *ipa, u32 count,
static bool ipa_endpoint_data_valid(struct ipa *ipa, u32 count,
				    const struct ipa_gsi_endpoint_data *data)
{
	const struct ipa_gsi_endpoint_data *dp = data;
	enum ipa_endpoint_name name;

	if (ipa->version < IPA_VERSION_4_5)
		return true;

	/* IPA v4.5+ uses checksum offload, not yet supported by RMNet */
	for (name = 0; name < count; name++, dp++)
		if (data->endpoint.config.checksum)
			return false;

	return true;
}

@@ -457,28 +441,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 +488,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 +537,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) {
+1 −0
Original line number Diff line number Diff line
@@ -368,6 +368,7 @@ enum ipa_cs_offload_en {
	IPA_CS_OFFLOAD_NONE		= 0x0,
	IPA_CS_OFFLOAD_UL		= 0x1,	/* Before IPA v4.5 (TX) */
	IPA_CS_OFFLOAD_DL		= 0x2,	/* Before IPA v4.5 (RX) */
	IPA_CS_OFFLOAD_INLINE		= 0x1,	/* IPA v4.5 (TX and RX) */
};

/* Valid only for TX (IPA consumer) endpoints */