2021-03-26 23:11:11 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
|
|
|
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
|
2022-10-01 06:45:49 +08:00
|
|
|
* Copyright (C) 2018-2022 Linaro Ltd.
|
2021-03-26 23:11:11 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
|
|
|
|
#include "ipa.h"
|
|
|
|
#include "ipa_data.h"
|
|
|
|
#include "ipa_reg.h"
|
|
|
|
#include "ipa_resource.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DOC: IPA Resources
|
|
|
|
*
|
|
|
|
* The IPA manages a set of resources internally for various purposes.
|
|
|
|
* A given IPA version has a fixed number of resource types, and a fixed
|
|
|
|
* total number of resources of each type. "Source" resource types
|
|
|
|
* are separate from "destination" resource types.
|
|
|
|
*
|
|
|
|
* Each version of IPA also has some number of resource groups. Each
|
|
|
|
* endpoint is assigned to a resource group, and all endpoints in the
|
|
|
|
* same group share pools of each type of resource. A subset of the
|
|
|
|
* total resources of each type is assigned for use by each group.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool ipa_resource_limits_valid(struct ipa *ipa,
|
|
|
|
const struct ipa_resource_data *data)
|
|
|
|
{
|
|
|
|
u32 group_count;
|
|
|
|
u32 i;
|
|
|
|
u32 j;
|
|
|
|
|
2021-03-26 23:11:22 +08:00
|
|
|
/* We program at most 8 source or destination resource group limits */
|
|
|
|
BUILD_BUG_ON(IPA_RESOURCE_GROUP_MAX > 8);
|
2021-03-26 23:11:11 +08:00
|
|
|
|
2021-03-26 23:11:21 +08:00
|
|
|
group_count = data->rsrc_group_src_count;
|
2021-03-26 23:11:18 +08:00
|
|
|
if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX)
|
2021-03-26 23:11:11 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
/* 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++) {
|
2021-03-26 23:11:19 +08:00
|
|
|
const struct ipa_resource *resource;
|
2021-03-26 23:11:11 +08:00
|
|
|
|
|
|
|
resource = &data->resource_src[i];
|
2021-03-26 23:11:18 +08:00
|
|
|
for (j = group_count; j < IPA_RESOURCE_GROUP_MAX; j++)
|
2021-03-26 23:11:11 +08:00
|
|
|
if (resource->limits[j].min || resource->limits[j].max)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-11-12 02:37:24 +08:00
|
|
|
group_count = data->rsrc_group_dst_count;
|
2021-03-26 23:11:18 +08:00
|
|
|
if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX)
|
2021-03-26 23:11:11 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
for (i = 0; i < data->resource_dst_count; i++) {
|
2021-03-26 23:11:19 +08:00
|
|
|
const struct ipa_resource *resource;
|
2021-03-26 23:11:11 +08:00
|
|
|
|
|
|
|
resource = &data->resource_dst[i];
|
2021-03-26 23:11:18 +08:00
|
|
|
for (j = group_count; j < IPA_RESOURCE_GROUP_MAX; j++)
|
2021-03-26 23:11:11 +08:00
|
|
|
if (resource->limits[j].min || resource->limits[j].max)
|
|
|
|
return false;
|
|
|
|
}
|
2021-07-27 01:40:09 +08:00
|
|
|
|
2021-03-26 23:11:11 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-09-27 06:09:28 +08:00
|
|
|
ipa_resource_config_common(struct ipa *ipa, u32 resource_type,
|
net: ipa: start generalizing "ipa_reg"
IPA register definitions have evolved with each new version. The
changes required to support more than 32 endpoints in IPA v5.0 made
it best to define a unified mechanism for defining registers and
their fields.
GSI register definitions, meanwhile, have remained fairly stable.
And even as the total number of IPA endpoints goes beyond 32, the
number of GSI channels on a given EE that underly endpoints still
remains 32 or less.
Despite that, GSI v3.0 (which is used with IPA v5.0) extends the
number of channels (and events) it supports to be about 256, and as
a result, many GSI register definitions must change significantly.
To address this, we'll use the same "ipa_reg" mechanism to define
the GSI registers.
As a first step in generalizing the "ipa_reg" to also support GSI
registers, isolate the definitions of the "ipa_reg" and "ipa_regs"
structure types (and some supporting macros) into a new header file,
and remove the "ipa_" and "IPA_" from symbol names.
Separate the IPA register ID validity checking from the generic
check that a register ID is in range. Aside from that, this is
intended to have no functional effect on the code.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-09 04:56:51 +08:00
|
|
|
const struct reg *reg,
|
2021-03-26 23:11:11 +08:00
|
|
|
const struct ipa_resource_limits *xlimits,
|
|
|
|
const struct ipa_resource_limits *ylimits)
|
|
|
|
{
|
|
|
|
u32 val;
|
|
|
|
|
2023-02-09 04:56:53 +08:00
|
|
|
val = reg_encode(reg, X_MIN_LIM, xlimits->min);
|
|
|
|
val |= reg_encode(reg, X_MAX_LIM, xlimits->max);
|
2021-03-26 23:11:11 +08:00
|
|
|
if (ylimits) {
|
2023-02-09 04:56:53 +08:00
|
|
|
val |= reg_encode(reg, Y_MIN_LIM, ylimits->min);
|
|
|
|
val |= reg_encode(reg, Y_MAX_LIM, ylimits->max);
|
2021-03-26 23:11:11 +08:00
|
|
|
}
|
|
|
|
|
2023-02-09 04:56:52 +08:00
|
|
|
iowrite32(val, ipa->reg_virt + reg_n_offset(reg, resource_type));
|
2021-03-26 23:11:11 +08:00
|
|
|
}
|
|
|
|
|
2021-03-26 23:11:16 +08:00
|
|
|
static void ipa_resource_config_src(struct ipa *ipa, u32 resource_type,
|
2021-03-26 23:11:20 +08:00
|
|
|
const struct ipa_resource_data *data)
|
2021-03-26 23:11:11 +08:00
|
|
|
{
|
2021-03-26 23:11:21 +08:00
|
|
|
u32 group_count = data->rsrc_group_src_count;
|
2021-03-26 23:11:11 +08:00
|
|
|
const struct ipa_resource_limits *ylimits;
|
2021-03-26 23:11:20 +08:00
|
|
|
const struct ipa_resource *resource;
|
net: ipa: start generalizing "ipa_reg"
IPA register definitions have evolved with each new version. The
changes required to support more than 32 endpoints in IPA v5.0 made
it best to define a unified mechanism for defining registers and
their fields.
GSI register definitions, meanwhile, have remained fairly stable.
And even as the total number of IPA endpoints goes beyond 32, the
number of GSI channels on a given EE that underly endpoints still
remains 32 or less.
Despite that, GSI v3.0 (which is used with IPA v5.0) extends the
number of channels (and events) it supports to be about 256, and as
a result, many GSI register definitions must change significantly.
To address this, we'll use the same "ipa_reg" mechanism to define
the GSI registers.
As a first step in generalizing the "ipa_reg" to also support GSI
registers, isolate the definitions of the "ipa_reg" and "ipa_regs"
structure types (and some supporting macros) into a new header file,
and remove the "ipa_" and "IPA_" from symbol names.
Separate the IPA register ID validity checking from the generic
check that a register ID is in range. Aside from that, this is
intended to have no functional effect on the code.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-09 04:56:51 +08:00
|
|
|
const struct reg *reg;
|
2021-03-26 23:11:11 +08:00
|
|
|
|
2021-03-26 23:11:20 +08:00
|
|
|
resource = &data->resource_src[resource_type];
|
|
|
|
|
2022-09-27 06:09:21 +08:00
|
|
|
reg = ipa_reg(ipa, SRC_RSRC_GRP_01_RSRC_TYPE);
|
2021-03-26 23:11:11 +08:00
|
|
|
ylimits = group_count == 1 ? NULL : &resource->limits[1];
|
2022-09-27 06:09:28 +08:00
|
|
|
ipa_resource_config_common(ipa, resource_type, reg,
|
|
|
|
&resource->limits[0], ylimits);
|
2021-03-26 23:11:12 +08:00
|
|
|
if (group_count < 3)
|
2021-03-26 23:11:11 +08:00
|
|
|
return;
|
|
|
|
|
2022-09-27 06:09:21 +08:00
|
|
|
reg = ipa_reg(ipa, SRC_RSRC_GRP_23_RSRC_TYPE);
|
2021-03-26 23:11:11 +08:00
|
|
|
ylimits = group_count == 3 ? NULL : &resource->limits[3];
|
2022-09-27 06:09:28 +08:00
|
|
|
ipa_resource_config_common(ipa, resource_type, reg,
|
|
|
|
&resource->limits[2], ylimits);
|
2021-03-26 23:11:12 +08:00
|
|
|
if (group_count < 5)
|
2021-03-26 23:11:11 +08:00
|
|
|
return;
|
|
|
|
|
2022-09-27 06:09:21 +08:00
|
|
|
reg = ipa_reg(ipa, SRC_RSRC_GRP_45_RSRC_TYPE);
|
2021-03-26 23:11:11 +08:00
|
|
|
ylimits = group_count == 5 ? NULL : &resource->limits[5];
|
2022-09-27 06:09:28 +08:00
|
|
|
ipa_resource_config_common(ipa, resource_type, reg,
|
|
|
|
&resource->limits[4], ylimits);
|
2021-03-26 23:11:22 +08:00
|
|
|
if (group_count < 7)
|
|
|
|
return;
|
|
|
|
|
2022-09-27 06:09:21 +08:00
|
|
|
reg = ipa_reg(ipa, SRC_RSRC_GRP_67_RSRC_TYPE);
|
2021-03-26 23:11:22 +08:00
|
|
|
ylimits = group_count == 7 ? NULL : &resource->limits[7];
|
2022-09-27 06:09:28 +08:00
|
|
|
ipa_resource_config_common(ipa, resource_type, reg,
|
|
|
|
&resource->limits[6], ylimits);
|
2021-03-26 23:11:11 +08:00
|
|
|
}
|
|
|
|
|
2021-03-26 23:11:16 +08:00
|
|
|
static void ipa_resource_config_dst(struct ipa *ipa, u32 resource_type,
|
2021-03-26 23:11:20 +08:00
|
|
|
const struct ipa_resource_data *data)
|
2021-03-26 23:11:11 +08:00
|
|
|
{
|
2021-03-26 23:11:21 +08:00
|
|
|
u32 group_count = data->rsrc_group_dst_count;
|
2021-03-26 23:11:11 +08:00
|
|
|
const struct ipa_resource_limits *ylimits;
|
2021-03-26 23:11:20 +08:00
|
|
|
const struct ipa_resource *resource;
|
net: ipa: start generalizing "ipa_reg"
IPA register definitions have evolved with each new version. The
changes required to support more than 32 endpoints in IPA v5.0 made
it best to define a unified mechanism for defining registers and
their fields.
GSI register definitions, meanwhile, have remained fairly stable.
And even as the total number of IPA endpoints goes beyond 32, the
number of GSI channels on a given EE that underly endpoints still
remains 32 or less.
Despite that, GSI v3.0 (which is used with IPA v5.0) extends the
number of channels (and events) it supports to be about 256, and as
a result, many GSI register definitions must change significantly.
To address this, we'll use the same "ipa_reg" mechanism to define
the GSI registers.
As a first step in generalizing the "ipa_reg" to also support GSI
registers, isolate the definitions of the "ipa_reg" and "ipa_regs"
structure types (and some supporting macros) into a new header file,
and remove the "ipa_" and "IPA_" from symbol names.
Separate the IPA register ID validity checking from the generic
check that a register ID is in range. Aside from that, this is
intended to have no functional effect on the code.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-09 04:56:51 +08:00
|
|
|
const struct reg *reg;
|
2021-03-26 23:11:11 +08:00
|
|
|
|
2021-03-26 23:11:20 +08:00
|
|
|
resource = &data->resource_dst[resource_type];
|
|
|
|
|
2022-09-27 06:09:21 +08:00
|
|
|
reg = ipa_reg(ipa, DST_RSRC_GRP_01_RSRC_TYPE);
|
2021-03-26 23:11:11 +08:00
|
|
|
ylimits = group_count == 1 ? NULL : &resource->limits[1];
|
2022-09-27 06:09:28 +08:00
|
|
|
ipa_resource_config_common(ipa, resource_type, reg,
|
|
|
|
&resource->limits[0], ylimits);
|
2021-03-26 23:11:12 +08:00
|
|
|
if (group_count < 3)
|
2021-03-26 23:11:11 +08:00
|
|
|
return;
|
|
|
|
|
2022-09-27 06:09:21 +08:00
|
|
|
reg = ipa_reg(ipa, DST_RSRC_GRP_23_RSRC_TYPE);
|
2021-03-26 23:11:11 +08:00
|
|
|
ylimits = group_count == 3 ? NULL : &resource->limits[3];
|
2022-09-27 06:09:28 +08:00
|
|
|
ipa_resource_config_common(ipa, resource_type, reg,
|
|
|
|
&resource->limits[2], ylimits);
|
2021-03-26 23:11:12 +08:00
|
|
|
if (group_count < 5)
|
2021-03-26 23:11:11 +08:00
|
|
|
return;
|
|
|
|
|
2022-09-27 06:09:21 +08:00
|
|
|
reg = ipa_reg(ipa, DST_RSRC_GRP_45_RSRC_TYPE);
|
2021-03-26 23:11:11 +08:00
|
|
|
ylimits = group_count == 5 ? NULL : &resource->limits[5];
|
2022-09-27 06:09:28 +08:00
|
|
|
ipa_resource_config_common(ipa, resource_type, reg,
|
|
|
|
&resource->limits[4], ylimits);
|
2021-03-26 23:11:22 +08:00
|
|
|
if (group_count < 7)
|
|
|
|
return;
|
|
|
|
|
2022-09-27 06:09:21 +08:00
|
|
|
reg = ipa_reg(ipa, DST_RSRC_GRP_67_RSRC_TYPE);
|
2021-03-26 23:11:22 +08:00
|
|
|
ylimits = group_count == 7 ? NULL : &resource->limits[7];
|
2022-09-27 06:09:28 +08:00
|
|
|
ipa_resource_config_common(ipa, resource_type, reg,
|
|
|
|
&resource->limits[6], ylimits);
|
2021-03-26 23:11:11 +08:00
|
|
|
}
|
|
|
|
|
2021-04-10 02:07:20 +08:00
|
|
|
/* Configure resources; there is no ipa_resource_deconfig() */
|
2021-03-26 23:11:11 +08:00
|
|
|
int ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data)
|
|
|
|
{
|
|
|
|
u32 i;
|
|
|
|
|
|
|
|
if (!ipa_resource_limits_valid(ipa, data))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
for (i = 0; i < data->resource_src_count; i++)
|
2021-03-26 23:11:20 +08:00
|
|
|
ipa_resource_config_src(ipa, i, data);
|
2021-03-26 23:11:11 +08:00
|
|
|
|
|
|
|
for (i = 0; i < data->resource_dst_count; i++)
|
2021-03-26 23:11:20 +08:00
|
|
|
ipa_resource_config_dst(ipa, i, data);
|
2021-03-26 23:11:11 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|