2022-02-07 12:03:33

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 0/7] net: ipa: use bulk interconnect interfaces

The IPA code currently enables and disables interconnects by setting
the bandwidth of each to a non-zero value, or to zero. The
interconnect API now supports enable/disable functions, so we can
use those instead. In addition, the interconnect API provides bulk
interfaces that allow all interconnects to be operated on at once.

This series converts the IPA driver to use the bulk enable and
disable interfaces. In the process it uses some existing data
structures rather than defining new ones.

-Alex

Alex Elder (7):
net: ipa: kill struct ipa_interconnect
net: ipa: use icc_enable() and icc_disable()
net: ipa: use interconnect bulk enable/disable operations
net: ipa: use bulk operations to set up interconnects
net: ipa: use bulk interconnect initialization
net: ipa: embed interconnect array in the power structure
net: ipa: use IPA power device pointer

drivers/net/ipa/ipa_power.c | 178 +++++++++---------------------------
1 file changed, 42 insertions(+), 136 deletions(-)

--
2.32.0



2022-02-07 19:47:37

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 7/7] net: ipa: use IPA power device pointer

The ipa_power structure contains a copy of the IPA device pointer,
so there's no need to pass it to ipa_interconnect_init(). We can
also use that pointer for an error message in ipa_power_enable().

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/ipa_power.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ipa/ipa_power.c b/drivers/net/ipa/ipa_power.c
index 8a564d72799da..16ece27d14d7e 100644
--- a/drivers/net/ipa/ipa_power.c
+++ b/drivers/net/ipa/ipa_power.c
@@ -71,7 +71,7 @@ struct ipa_power {
};

/* Initialize interconnects required for IPA operation */
-static int ipa_interconnect_init(struct ipa_power *power, struct device *dev,
+static int ipa_interconnect_init(struct ipa_power *power,
const struct ipa_interconnect_data *data)
{
struct icc_bulk_data *interconnect;
@@ -89,7 +89,7 @@ static int ipa_interconnect_init(struct ipa_power *power, struct device *dev,
interconnect++;
}

- ret = of_icc_bulk_get(dev, power->interconnect_count,
+ ret = of_icc_bulk_get(power->dev, power->interconnect_count,
power->interconnect);
if (ret)
return ret;
@@ -123,7 +123,7 @@ static int ipa_power_enable(struct ipa *ipa)

ret = clk_prepare_enable(power->core);
if (ret) {
- dev_err(&ipa->pdev->dev, "error %d enabling core clock\n", ret);
+ dev_err(power->dev, "error %d enabling core clock\n", ret);
icc_bulk_disable(power->interconnect_count,
power->interconnect);
}
@@ -385,7 +385,7 @@ ipa_power_init(struct device *dev, const struct ipa_power_data *data)
spin_lock_init(&power->spinlock);
power->interconnect_count = data->interconnect_count;

- ret = ipa_interconnect_init(power, dev, data->interconnect_data);
+ ret = ipa_interconnect_init(power, data->interconnect_data);
if (ret)
goto err_kfree;

--
2.32.0


2022-02-07 19:47:38

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 6/7] net: ipa: embed interconnect array in the power structure

Rather than allocating the interconnect array dynamically, represent
the interconnects with a variable-length array at the end of the
ipa_power structure.

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/ipa_power.c | 31 +++++++++----------------------
1 file changed, 9 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ipa/ipa_power.c b/drivers/net/ipa/ipa_power.c
index b1f6978dddadb..8a564d72799da 100644
--- a/drivers/net/ipa/ipa_power.c
+++ b/drivers/net/ipa/ipa_power.c
@@ -67,7 +67,7 @@ struct ipa_power {
spinlock_t spinlock; /* used with STOPPED/STARTED power flags */
DECLARE_BITMAP(flags, IPA_POWER_FLAG_COUNT);
u32 interconnect_count;
- struct icc_bulk_data *interconnect;
+ struct icc_bulk_data interconnect[];
};

/* Initialize interconnects required for IPA operation */
@@ -75,17 +75,12 @@ static int ipa_interconnect_init(struct ipa_power *power, struct device *dev,
const struct ipa_interconnect_data *data)
{
struct icc_bulk_data *interconnect;
- u32 count;
int ret;
-
- count = power->interconnect_count;
- interconnect = kcalloc(count, sizeof(*interconnect), GFP_KERNEL);
- if (!interconnect)
- return -ENOMEM;
- power->interconnect = interconnect;
+ u32 i;

/* Initialize our interconnect data array for bulk operations */
- while (count--) {
+ interconnect = &power->interconnect[0];
+ for (i = 0; i < power->interconnect_count; i++) {
/* interconnect->path is filled in by of_icc_bulk_get() */
interconnect->name = data->name;
interconnect->avg_bw = data->average_bandwidth;
@@ -97,7 +92,7 @@ static int ipa_interconnect_init(struct ipa_power *power, struct device *dev,
ret = of_icc_bulk_get(dev, power->interconnect_count,
power->interconnect);
if (ret)
- goto err_free;
+ return ret;

/* All interconnects are initially disabled */
icc_bulk_disable(power->interconnect_count, power->interconnect);
@@ -105,15 +100,7 @@ static int ipa_interconnect_init(struct ipa_power *power, struct device *dev,
/* Set the bandwidth values to be used when enabled */
ret = icc_bulk_set_bw(power->interconnect_count, power->interconnect);
if (ret)
- goto err_bulk_put;
-
- return 0;
-
-err_bulk_put:
- icc_bulk_put(power->interconnect_count, power->interconnect);
-err_free:
- kfree(power->interconnect);
- power->interconnect = NULL;
+ icc_bulk_put(power->interconnect_count, power->interconnect);

return ret;
}
@@ -122,8 +109,6 @@ static int ipa_interconnect_init(struct ipa_power *power, struct device *dev,
static void ipa_interconnect_exit(struct ipa_power *power)
{
icc_bulk_put(power->interconnect_count, power->interconnect);
- kfree(power->interconnect);
- power->interconnect = NULL;
}

/* Enable IPA power, enabling interconnects and the core clock */
@@ -372,6 +357,7 @@ ipa_power_init(struct device *dev, const struct ipa_power_data *data)
{
struct ipa_power *power;
struct clk *clk;
+ size_t size;
int ret;

clk = clk_get(dev, "core");
@@ -388,7 +374,8 @@ ipa_power_init(struct device *dev, const struct ipa_power_data *data)
goto err_clk_put;
}

- power = kzalloc(sizeof(*power), GFP_KERNEL);
+ size = data->interconnect_count * sizeof(power->interconnect[0]);
+ power = kzalloc(sizeof(*power) + size, GFP_KERNEL);
if (!power) {
ret = -ENOMEM;
goto err_clk_put;
--
2.32.0


2022-02-08 15:59:35

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 4/7] net: ipa: use bulk operations to set up interconnects

Use of_icc_bulk_get() and icc_bulk_put(), icc_bulk_set_bw(), and
icc_bulk_enable() and icc_bulk_disable() to initialize individual
IPA interconnects. Those functions already log messages in the
event of error so we don't need to.

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/ipa_power.c | 40 ++++++++++++++-----------------------
1 file changed, 15 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ipa/ipa_power.c b/drivers/net/ipa/ipa_power.c
index 67f76e6a6ae59..c0da1274f5d67 100644
--- a/drivers/net/ipa/ipa_power.c
+++ b/drivers/net/ipa/ipa_power.c
@@ -74,41 +74,31 @@ static int ipa_interconnect_init_one(struct device *dev,
struct icc_bulk_data *interconnect,
const struct ipa_interconnect_data *data)
{
- struct icc_path *path;
int ret;

- path = of_icc_get(dev, data->name);
- if (IS_ERR(path)) {
- ret = PTR_ERR(path);
- dev_err_probe(dev, ret, "error getting %s interconnect\n",
- data->name);
-
- return ret;
- }
-
- /* All interconnects are initially disabled */
- (void)icc_disable(path);
-
- /* Set the bandwidth values to be used when enabled */
- ret = icc_set_bw(path, data->average_bandwidth, data->peak_bandwidth);
- if (ret) {
- dev_err(dev, "error %d setting %s interconnect bandwidths\n",
- ret, data->name);
-
- return ret;
- }
-
- interconnect->path = path;
+ /* interconnect->path is filled in by of_icc_bulk_get() */
interconnect->name = data->name;
interconnect->avg_bw = data->average_bandwidth;
interconnect->peak_bw = data->peak_bandwidth;

- return 0;
+ ret = of_icc_bulk_get(dev, 1, interconnect);
+ if (ret)
+ return ret;
+
+ /* All interconnects are initially disabled */
+ icc_bulk_disable(1, interconnect);
+
+ /* Set the bandwidth values to be used when enabled */
+ ret = icc_bulk_set_bw(1, interconnect);
+ if (ret)
+ icc_bulk_put(1, interconnect);
+
+ return ret;
}

static void ipa_interconnect_exit_one(struct icc_bulk_data *interconnect)
{
- icc_put(interconnect->path);
+ icc_bulk_put(1, interconnect);
memset(interconnect, 0, sizeof(*interconnect));
}

--
2.32.0