Commit 1af15c2a authored by Alex Elder's avatar Alex Elder Committed by Jakub Kicinski
Browse files

net: ipa: add new most-significant bits to registers



IPA v4.5 adds a few fields to the endpoint header and extended
header configuration registers that represent new high-order bits
for certain offsets and sizes.  Add code to incorporate these upper
bits into the registers for IPA v4.5.

This includes creating ipa_header_size_encoded(), which handles
encoding the metadata offset field for use in the ENDP_INIT_HDR
register in a way appropriate for the hardware version.  This and
ipa_metadata_offset_encoded() ensure the mask argument passed to
u32_encode_bits() is constant.

Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 5b6cd69e
Loading
Loading
Loading
Loading
+30 −9
Original line number Diff line number Diff line
@@ -485,28 +485,34 @@ static void ipa_endpoint_init_cfg(struct ipa_endpoint *endpoint)
static void ipa_endpoint_init_hdr(struct ipa_endpoint *endpoint)
{
	u32 offset = IPA_REG_ENDP_INIT_HDR_N_OFFSET(endpoint->endpoint_id);
	struct ipa *ipa = endpoint->ipa;
	u32 val = 0;

	if (endpoint->data->qmap) {
		size_t header_size = sizeof(struct rmnet_map_header);
		enum ipa_version version = ipa->version;

		/* 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 |= u32_encode_bits(header_size, HDR_LEN_FMASK);
		val |= ipa_header_size_encoded(version, header_size);

		/* Define how to fill fields in a received QMAP header */
		if (!endpoint->toward_ipa) {
			u32 off;	/* Field offset within header */
			u32 offset;	/* Field offset within header */

			/* Where IPA will write the metadata value */
			off = offsetof(struct rmnet_map_header, mux_id);
			val |= u32_encode_bits(off, HDR_OFST_METADATA_FMASK);
			offset = offsetof(struct rmnet_map_header, mux_id);
			val |= ipa_metadata_offset_encoded(version, offset);

			/* Where IPA will write the length */
			off = offsetof(struct rmnet_map_header, pkt_len);
			offset = offsetof(struct rmnet_map_header, pkt_len);
			/* Upper bits are stored in HDR_EXT with IPA v4.5 */
			if (version == IPA_VERSION_4_5)
				offset &= field_mask(HDR_OFST_PKT_SIZE_FMASK);

			val |= HDR_OFST_PKT_SIZE_VALID_FMASK;
			val |= u32_encode_bits(off, HDR_OFST_PKT_SIZE_FMASK);
			val |= u32_encode_bits(offset, HDR_OFST_PKT_SIZE_FMASK);
		}
		/* For QMAP TX, metadata offset is 0 (modem assumes this) */
		val |= HDR_OFST_METADATA_VALID_FMASK;
@@ -517,13 +523,14 @@ static void ipa_endpoint_init_hdr(struct ipa_endpoint *endpoint)
		/* HDR_METADATA_REG_VALID is 0 (TX only) */
	}

	iowrite32(val, endpoint->ipa->reg_virt + offset);
	iowrite32(val, ipa->reg_virt + offset);
}

static void ipa_endpoint_init_hdr_ext(struct ipa_endpoint *endpoint)
{
	u32 offset = IPA_REG_ENDP_INIT_HDR_EXT_N_OFFSET(endpoint->endpoint_id);
	u32 pad_align = endpoint->data->rx.pad_align;
	struct ipa *ipa = endpoint->ipa;
	u32 val = 0;

	val |= HDR_ENDIANNESS_FMASK;		/* big endian */
@@ -545,9 +552,23 @@ static void ipa_endpoint_init_hdr_ext(struct ipa_endpoint *endpoint)
	if (!endpoint->toward_ipa)
		val |= u32_encode_bits(pad_align, HDR_PAD_TO_ALIGNMENT_FMASK);

	iowrite32(val, endpoint->ipa->reg_virt + offset);
}
	/* IPA v4.5 adds some most-significant bits to a few fields,
	 * two of which are defined in the HDR (not HDR_EXT) register.
	 */
	if (ipa->version == IPA_VERSION_4_5) {
		/* HDR_TOTAL_LEN_OR_PAD_OFFSET is 0, so MSB is 0 */
		if (endpoint->data->qmap && !endpoint->toward_ipa) {
			u32 offset;

			offset = offsetof(struct rmnet_map_header, pkt_len);
			offset >>= hweight32(HDR_OFST_PKT_SIZE_FMASK);
			val |= u32_encode_bits(offset,
					       HDR_OFST_PKT_SIZE_MSB_FMASK);
			/* HDR_ADDITIONAL_CONST_LEN is 0 so MSB is 0 */
		}
	}
	iowrite32(val, ipa->reg_virt + offset);
}

static void ipa_endpoint_init_hdr_metadata_mask(struct ipa_endpoint *endpoint)
{
+36 −2
Original line number Diff line number Diff line
@@ -367,6 +367,40 @@ enum ipa_cs_offload_en {
#define HDR_LEN_MSB_FMASK			GENMASK(29, 28)
#define HDR_OFST_METADATA_MSB_FMASK		GENMASK(31, 30)

/* Encoded value for ENDP_INIT_HDR register HDR_LEN* field(s) */
static inline u32 ipa_header_size_encoded(enum ipa_version version,
					  u32 header_size)
{
	u32 val;

	val = u32_encode_bits(header_size, HDR_LEN_FMASK);
	if (version < IPA_VERSION_4_5)
		return val;

	/* IPA v4.5 adds a few more most-significant bits */
	header_size >>= hweight32(HDR_LEN_FMASK);
	val |= u32_encode_bits(header_size, HDR_LEN_MSB_FMASK);

	return val;
}

/* Encoded value for ENDP_INIT_HDR register OFST_METADATA* field(s) */
static inline u32 ipa_metadata_offset_encoded(enum ipa_version version,
					      u32 offset)
{
	u32 val;

	val = u32_encode_bits(offset, HDR_OFST_METADATA_FMASK);
	if (version < IPA_VERSION_4_5)
		return val;

	/* IPA v4.5 adds a few more most-significant bits */
	offset >>= hweight32(HDR_OFST_METADATA_FMASK);
	val |= u32_encode_bits(offset, HDR_OFST_METADATA_MSB_FMASK);

	return val;
}

#define IPA_REG_ENDP_INIT_HDR_EXT_N_OFFSET(ep) \
					(0x00000814 + 0x0070 * (ep))
#define HDR_ENDIANNESS_FMASK			GENMASK(0, 0)
@@ -461,7 +495,7 @@ enum ipa_aggr_type {

#define IPA_REG_ENDP_INIT_RSRC_GRP_N_OFFSET(ep) \
					(0x00000838 + 0x0070 * (ep))
/* Encoded value for RSRC_GRP endpoint register RSRC_GRP field */
/* Encoded value for ENDP_INIT_RSRC_GRP register RSRC_GRP field */
static inline u32 rsrc_grp_encoded(enum ipa_version version, u32 rsrc_grp)
{
	switch (version) {
@@ -492,7 +526,7 @@ static inline u32 rsrc_grp_encoded(enum ipa_version version, u32 rsrc_grp)
 * @IPA_SEQ_INVALID:		invalid sequencer type
 *
 * The values defined here are broken into 4-bit nibbles that are written
 * into fields of the INIT_SEQ_N endpoint registers.
 * into fields of the ENDP_INIT_SEQ registers.
 */
enum ipa_seq_type {
	IPA_SEQ_DMA_ONLY			= 0x0000,