Commit dc956588 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-ipa-minor-bug-fixes'

Alex Elder says:

====================
net: ipa: minor bug fixes

This series fixes several bugs.  They are minor, in that the code
currently works on supported platforms even without these patches
applied, but they're bugs nevertheless and should be fixed.

Version 2 improves the commit message for the fourth patch.  It also
fixes a bug in two spots in the last patch.  Both of these changes
were suggested by Willem de Bruijn.
====================

Link: https://lore.kernel.org/r/20201028194148.6659-1-elder@linaro.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents c1181f42 4a0d7579
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
		.endpoint = {
			.seq_type	= IPA_SEQ_DMA_ONLY,
			.config = {
				.resource_group	= 0,
				.dma_mode	= true,
				.dma_endpoint	= IPA_ENDPOINT_AP_LAN_RX,
			},
@@ -42,6 +43,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
		.endpoint = {
			.seq_type	= IPA_SEQ_INVALID,
			.config = {
				.resource_group	= 0,
				.aggregation	= true,
				.status_enable	= true,
				.rx = {
@@ -65,6 +67,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
			.seq_type	=
				IPA_SEQ_PKT_PROCESS_NO_DEC_NO_UCP_DMAP,
			.config = {
				.resource_group	= 0,
				.checksum	= true,
				.qmap		= true,
				.status_enable	= true,
@@ -88,6 +91,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
		.endpoint = {
			.seq_type	= IPA_SEQ_INVALID,
			.config = {
				.resource_group	= 0,
				.checksum	= true,
				.qmap		= true,
				.aggregation	= true,
+4 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
		.endpoint = {
			.seq_type	= IPA_SEQ_DMA_ONLY,
			.config = {
				.resource_group	= 1,
				.dma_mode	= true,
				.dma_endpoint	= IPA_ENDPOINT_AP_LAN_RX,
			},
@@ -44,6 +45,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
		.endpoint = {
			.seq_type	= IPA_SEQ_INVALID,
			.config = {
				.resource_group	= 1,
				.aggregation	= true,
				.status_enable	= true,
				.rx = {
@@ -67,6 +69,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
			.seq_type	=
				IPA_SEQ_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
			.config = {
				.resource_group	= 1,
				.checksum	= true,
				.qmap		= true,
				.status_enable	= true,
@@ -90,6 +93,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
		.endpoint = {
			.seq_type	= IPA_SEQ_INVALID,
			.config = {
				.resource_group	= 1,
				.checksum	= true,
				.qmap		= true,
				.aggregation	= true,
+7 −5
Original line number Diff line number Diff line
@@ -45,10 +45,10 @@
 * the IPA endpoint.
 */

/* The maximum value returned by ipa_resource_group_count() */
#define IPA_RESOURCE_GROUP_COUNT	4
/* The maximum value returned by ipa_resource_group_{src,dst}_count() */
#define IPA_RESOURCE_GROUP_SRC_MAX	4
#define IPA_RESOURCE_GROUP_DST_MAX	4

/** enum ipa_resource_type_src - source resource types */
/**
 * struct gsi_channel_data - GSI channel configuration data
 * @tre_count:		number of TREs in the channel ring
@@ -109,6 +109,7 @@ struct ipa_endpoint_rx_data {

/**
 * struct ipa_endpoint_config_data - IPA endpoint hardware configuration
 * @resource_group:	resource group to assign endpoint to
 * @checksum:		whether checksum offload is enabled
 * @qmap:		whether endpoint uses QMAP protocol
 * @aggregation:	whether endpoint supports aggregation
@@ -119,6 +120,7 @@ struct ipa_endpoint_rx_data {
 * @rx:			RX-specific endpoint information (see above)
 */
struct ipa_endpoint_config_data {
	u32 resource_group;
	bool checksum;
	bool qmap;
	bool aggregation;
@@ -206,7 +208,7 @@ struct ipa_resource_limits {
 */
struct ipa_resource_src {
	enum ipa_resource_type_src type;
	struct ipa_resource_limits limits[IPA_RESOURCE_GROUP_COUNT];
	struct ipa_resource_limits limits[IPA_RESOURCE_GROUP_SRC_MAX];
};

/**
@@ -216,7 +218,7 @@ struct ipa_resource_src {
 */
struct ipa_resource_dst {
	enum ipa_resource_type_dst type;
	struct ipa_resource_limits limits[IPA_RESOURCE_GROUP_COUNT];
	struct ipa_resource_limits limits[IPA_RESOURCE_GROUP_DST_MAX];
};

/**
+11 −0
Original line number Diff line number Diff line
@@ -751,6 +751,16 @@ static void ipa_endpoint_init_deaggr(struct ipa_endpoint *endpoint)
	iowrite32(val, endpoint->ipa->reg_virt + offset);
}

static void ipa_endpoint_init_rsrc_grp(struct ipa_endpoint *endpoint)
{
	u32 offset = IPA_REG_ENDP_INIT_RSRC_GRP_N_OFFSET(endpoint->endpoint_id);
	struct ipa *ipa = endpoint->ipa;
	u32 val;

	val = rsrc_grp_encoded(ipa->version, endpoint->data->resource_group);
	iowrite32(val, ipa->reg_virt + offset);
}

static void ipa_endpoint_init_seq(struct ipa_endpoint *endpoint)
{
	u32 offset = IPA_REG_ENDP_INIT_SEQ_N_OFFSET(endpoint->endpoint_id);
@@ -1328,6 +1338,7 @@ static void ipa_endpoint_program(struct ipa_endpoint *endpoint)
	ipa_endpoint_init_mode(endpoint);
	ipa_endpoint_init_aggr(endpoint);
	ipa_endpoint_init_deaggr(endpoint);
	ipa_endpoint_init_rsrc_grp(endpoint);
	ipa_endpoint_init_seq(endpoint);
	ipa_endpoint_status(endpoint);
}
+62 −59
Original line number Diff line number Diff line
@@ -363,52 +363,41 @@ static void ipa_hardware_deconfig(struct ipa *ipa)

#ifdef IPA_VALIDATION

/* # IPA resources used based on version (see IPA_RESOURCE_GROUP_COUNT) */
static int ipa_resource_group_count(struct ipa *ipa)
{
	switch (ipa->version) {
	case IPA_VERSION_3_5_1:
		return 3;

	case IPA_VERSION_4_0:
	case IPA_VERSION_4_1:
		return 4;

	case IPA_VERSION_4_2:
		return 1;

	default:
		return 0;
	}
}

static bool ipa_resource_limits_valid(struct ipa *ipa,
				      const struct ipa_resource_data *data)
{
	u32 group_count = ipa_resource_group_count(ipa);
	u32 group_count;
	u32 i;
	u32 j;

	if (!group_count)
	/* We program at most 6 source or destination resource group limits */
	BUILD_BUG_ON(IPA_RESOURCE_GROUP_SRC_MAX > 6);

	group_count = ipa_resource_group_src_count(ipa->version);
	if (!group_count || group_count > IPA_RESOURCE_GROUP_SRC_MAX)
		return false;

	/* Return an error if a non-zero resource group limit is specified
	 * for a resource not supported by hardware.
	/* Return an error if a non-zero resource limit is specified
	 * for a resource group not supported by hardware.
	 */
	for (i = 0; i < data->resource_src_count; i++) {
		const struct ipa_resource_src *resource;

		resource = &data->resource_src[i];
		for (j = group_count; j < IPA_RESOURCE_GROUP_COUNT; j++)
		for (j = group_count; j < IPA_RESOURCE_GROUP_SRC_MAX; j++)
			if (resource->limits[j].min || resource->limits[j].max)
				return false;
	}

	group_count = ipa_resource_group_dst_count(ipa->version);
	if (!group_count || group_count > IPA_RESOURCE_GROUP_DST_MAX)
		return false;

	for (i = 0; i < data->resource_dst_count; i++) {
		const struct ipa_resource_dst *resource;

		resource = &data->resource_dst[i];
		for (j = group_count; j < IPA_RESOURCE_GROUP_COUNT; j++)
		for (j = group_count; j < IPA_RESOURCE_GROUP_DST_MAX; j++)
			if (resource->limits[j].min || resource->limits[j].max)
				return false;
	}
@@ -435,46 +424,64 @@ ipa_resource_config_common(struct ipa *ipa, u32 offset,

	val = u32_encode_bits(xlimits->min, X_MIN_LIM_FMASK);
	val |= u32_encode_bits(xlimits->max, X_MAX_LIM_FMASK);
	if (ylimits) {
		val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK);
		val |= u32_encode_bits(ylimits->max, Y_MAX_LIM_FMASK);
	}

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

static void ipa_resource_config_src_01(struct ipa *ipa,
static void ipa_resource_config_src(struct ipa *ipa,
				    const struct ipa_resource_src *resource)
{
	u32 offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
	u32 group_count = ipa_resource_group_src_count(ipa->version);
	const struct ipa_resource_limits *ylimits;
	u32 offset;

	ipa_resource_config_common(ipa, offset,
				   &resource->limits[0], &resource->limits[1]);
}
	offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
	ylimits = group_count == 1 ? NULL : &resource->limits[1];
	ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);

static void ipa_resource_config_src_23(struct ipa *ipa,
				       const struct ipa_resource_src *resource)
{
	u32 offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
	if (group_count < 2)
		return;

	ipa_resource_config_common(ipa, offset,
				   &resource->limits[2], &resource->limits[3]);
}
	offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
	ylimits = group_count == 3 ? NULL : &resource->limits[3];
	ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);

static void ipa_resource_config_dst_01(struct ipa *ipa,
				       const struct ipa_resource_dst *resource)
{
	u32 offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
	if (group_count < 4)
		return;

	ipa_resource_config_common(ipa, offset,
				   &resource->limits[0], &resource->limits[1]);
	offset = IPA_REG_SRC_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource->type);
	ylimits = group_count == 5 ? NULL : &resource->limits[5];
	ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
}

static void ipa_resource_config_dst_23(struct ipa *ipa,
static void ipa_resource_config_dst(struct ipa *ipa,
				    const struct ipa_resource_dst *resource)
{
	u32 offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
	u32 group_count = ipa_resource_group_dst_count(ipa->version);
	const struct ipa_resource_limits *ylimits;
	u32 offset;

	offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
	ylimits = group_count == 1 ? NULL : &resource->limits[1];
	ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);

	if (group_count < 2)
		return;

	offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
	ylimits = group_count == 3 ? NULL : &resource->limits[3];
	ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);

	if (group_count < 4)
		return;

	ipa_resource_config_common(ipa, offset,
				   &resource->limits[2], &resource->limits[3]);
	offset = IPA_REG_DST_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource->type);
	ylimits = group_count == 5 ? NULL : &resource->limits[5];
	ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
}

static int
@@ -485,15 +492,11 @@ ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data)
	if (!ipa_resource_limits_valid(ipa, data))
		return -EINVAL;

	for (i = 0; i < data->resource_src_count; i++) {
		ipa_resource_config_src_01(ipa, &data->resource_src[i]);
		ipa_resource_config_src_23(ipa, &data->resource_src[i]);
	}
	for (i = 0; i < data->resource_src_count; i++)
		ipa_resource_config_src(ipa, data->resource_src);

	for (i = 0; i < data->resource_dst_count; i++) {
		ipa_resource_config_dst_01(ipa, &data->resource_dst[i]);
		ipa_resource_config_dst_23(ipa, &data->resource_dst[i]);
	}
	for (i = 0; i < data->resource_dst_count; i++)
		ipa_resource_config_dst(ipa, data->resource_dst);

	return 0;
}
Loading