Commit dc956588 authored by Jakub Kicinski's avatar Jakub Kicinski

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.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents c1181f42 4a0d7579
......@@ -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,
......
......@@ -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,
......
......@@ -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];
};
/**
......
......@@ -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);
}
......
......@@ -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);
val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK);
val |= u32_encode_bits(ylimits->max, Y_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,
const struct ipa_resource_src *resource)
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,
const struct ipa_resource_dst *resource)
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;
ipa_resource_config_common(ipa, offset,
&resource->limits[2], &resource->limits[3]);
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;
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;
}
......
......@@ -89,7 +89,7 @@ int ipa_mem_setup(struct ipa *ipa)
gsi_trans_commit_wait(trans);
/* Tell the hardware where the processing context area is located */
iowrite32(ipa->mem_offset + offset,
iowrite32(ipa->mem_offset + ipa->mem[IPA_MEM_MODEM_PROC_CTX].offset,
ipa->reg_virt + IPA_REG_LOCAL_PKT_PROC_CNTXT_BASE_OFFSET);
return 0;
......
......@@ -244,6 +244,43 @@ static inline u32 ipa_reg_idle_indication_cfg_offset(enum ipa_version version)
#define ENTER_IDLE_DEBOUNCE_THRESH_FMASK GENMASK(15, 0)
#define CONST_NON_IDLE_ENABLE_FMASK GENMASK(16, 16)
/* # IPA source resource groups available based on version */
static inline u32 ipa_resource_group_src_count(enum ipa_version version)
{
switch (version) {
case IPA_VERSION_3_5_1:
case IPA_VERSION_4_0:
case IPA_VERSION_4_1:
return 4;
case IPA_VERSION_4_2:
return 1;
default:
return 0;
}
}
/* # IPA destination resource groups available based on version */
static inline u32 ipa_resource_group_dst_count(enum ipa_version version)
{
switch (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;
}
}
/* Not all of the following are valid (depends on the count, above) */
#define IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(rt) \
(0x00000400 + 0x0020 * (rt))
#define IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(rt) \
......@@ -341,7 +378,16 @@ static inline u32 ipa_reg_idle_indication_cfg_offset(enum ipa_version version)
#define IPA_REG_ENDP_INIT_RSRC_GRP_N_OFFSET(ep) \
(0x00000838 + 0x0070 * (ep))
#define RSRC_GRP_FMASK GENMASK(1, 0)
/* Encoded value for RSRC_GRP endpoint register RSRC_GRP field */
static inline u32 rsrc_grp_encoded(enum ipa_version version, u32 rsrc_grp)
{
switch (version) {
case IPA_VERSION_4_2:
return u32_encode_bits(rsrc_grp, GENMASK(0, 0));
default:
return u32_encode_bits(rsrc_grp, GENMASK(1, 0));
}
}
/* Valid only for TX (IPA consumer) endpoints */
#define IPA_REG_ENDP_INIT_SEQ_N_OFFSET(txep) \
......
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