2024-04-18 20:47:48

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 0/8] net: ipa: eight simple cleanups

This series contains a mix of cleanups, some dating back to
December, 2022.

The first two make it so the IPA SUSPEND interrupt only gets enabled
when necessary. That make it possible in the third patch to call
device_init_wakeup() during an earlier phase of initialization, and
remove two functions.

The next patch removes IPA register definitions that are never used.
The fifth patch makes ipa_table_hash_support() a real function, so
the IPA structure only needs to be declared rather than defined when
that file is parsed.

The sixth patch fixes improper argument names in two function
declarations. The seventh removes the declaration for a function
that does not exist, and makes ipa_cmd_init() actually get called.
And the last one eliminates ipa_version_supported(), in favor of
just deciding that if a device is probed because its compatible
matches, that device is assumed to be supported.

-Alex

Alex Elder (8):
net: ipa: maintain bitmap of suspend-enabled endpoints
net: ipa: only enable the SUSPEND IPA interrupt when needed
net: ipa: call device_init_wakeup() earlier
net: ipa: remove unneeded FILT_ROUT_HASH_EN definitions
net: ipa: make ipa_table_hash_support() a real function
net: ipa: fix two bogus argument names
net: ipa: fix two minor ipa_cmd problems
net: ipa: kill ipa_version_supported()

drivers/net/ipa/ipa_cmd.h | 8 ------
drivers/net/ipa/ipa_endpoint.h | 6 ++---
drivers/net/ipa/ipa_interrupt.c | 38 +++++++++++++++++++++++++---
drivers/net/ipa/ipa_main.c | 16 +++---------
drivers/net/ipa/ipa_power.c | 19 --------------
drivers/net/ipa/ipa_power.h | 14 ----------
drivers/net/ipa/ipa_table.c | 8 +++++-
drivers/net/ipa/ipa_table.h | 7 ++---
drivers/net/ipa/ipa_version.h | 18 -------------
drivers/net/ipa/reg/ipa_reg-v3.1.c | 14 ----------
drivers/net/ipa/reg/ipa_reg-v3.5.1.c | 14 ----------
drivers/net/ipa/reg/ipa_reg-v4.11.c | 14 ----------
drivers/net/ipa/reg/ipa_reg-v4.5.c | 14 ----------
drivers/net/ipa/reg/ipa_reg-v4.7.c | 14 ----------
drivers/net/ipa/reg/ipa_reg-v4.9.c | 14 ----------
15 files changed, 51 insertions(+), 167 deletions(-)

--
2.40.1



2024-04-18 20:48:05

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 1/8] net: ipa: maintain bitmap of suspend-enabled endpoints

Keep track of which endpoints have the SUSPEND IPA interrupt enabled
in a variable-length bitmap. This will be used in the next patch to
allow the SUSPEND interrupt type to be disabled except when needed.

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

diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c
index c44ec05f71e6f..0e8d4e43275ea 100644
--- a/drivers/net/ipa/ipa_interrupt.c
+++ b/drivers/net/ipa/ipa_interrupt.c
@@ -37,11 +37,13 @@
* @ipa: IPA pointer
* @irq: Linux IRQ number used for IPA interrupts
* @enabled: Mask indicating which interrupts are enabled
+ * @suspend_enabled: Bitmap of endpoints with the SUSPEND interrupt enabled
*/
struct ipa_interrupt {
struct ipa *ipa;
u32 irq;
u32 enabled;
+ unsigned long *suspend_enabled;
};

/* Clear the suspend interrupt for all endpoints that signaled it */
@@ -211,6 +213,7 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
val |= mask;
else
val &= ~mask;
+ __change_bit(endpoint_id, interrupt->suspend_enabled);

iowrite32(val, ipa->reg_virt + offset);
}
@@ -246,7 +249,16 @@ int ipa_interrupt_config(struct ipa *ipa)

interrupt->ipa = ipa;

- /* Disable all IPA interrupt types */
+ /* Initially all IPA interrupt types are disabled */
+ interrupt->enabled = 0;
+ interrupt->suspend_enabled = bitmap_zalloc(ipa->endpoint_count,
+ GFP_KERNEL);
+ if (!interrupt->suspend_enabled) {
+ ret = -ENOMEM;
+ goto err_kfree;
+ }
+
+ /* Disable IPA interrupt types */
reg = ipa_reg(ipa, IPA_IRQ_EN);
iowrite32(0, ipa->reg_virt + reg_offset(reg));

@@ -254,7 +266,7 @@ int ipa_interrupt_config(struct ipa *ipa)
"ipa", interrupt);
if (ret) {
dev_err(dev, "error %d requesting \"ipa\" IRQ\n", ret);
- goto err_kfree;
+ goto err_free_bitmap;
}

ret = dev_pm_set_wake_irq(dev, irq);
@@ -270,6 +282,8 @@ int ipa_interrupt_config(struct ipa *ipa)

err_free_irq:
free_irq(interrupt->irq, interrupt);
+err_free_bitmap:
+ bitmap_free(interrupt->suspend_enabled);
err_kfree:
kfree(interrupt);

@@ -286,6 +300,7 @@ void ipa_interrupt_deconfig(struct ipa *ipa)

dev_pm_clear_wake_irq(dev);
free_irq(interrupt->irq, interrupt);
+ bitmap_free(interrupt->suspend_enabled);
}

/* Initialize the IPA interrupt structure */
--
2.40.1


2024-04-18 20:49:47

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 4/8] net: ipa: remove unneeded FILT_ROUT_HASH_EN definitions

The FILT_ROUT_HASH_EN register is only used for IPA v4.2. There,
routing and filter table hashing are not supported, and so the
register must be written to disable the feature. No other version
uses this register, so its definition can be removed. If we need to
use these some day (for example, explicitly enable the feature) this
commit can be reverted.

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/reg/ipa_reg-v3.1.c | 14 --------------
drivers/net/ipa/reg/ipa_reg-v3.5.1.c | 14 --------------
drivers/net/ipa/reg/ipa_reg-v4.11.c | 14 --------------
drivers/net/ipa/reg/ipa_reg-v4.5.c | 14 --------------
drivers/net/ipa/reg/ipa_reg-v4.7.c | 14 --------------
drivers/net/ipa/reg/ipa_reg-v4.9.c | 14 --------------
6 files changed, 84 deletions(-)

diff --git a/drivers/net/ipa/reg/ipa_reg-v3.1.c b/drivers/net/ipa/reg/ipa_reg-v3.1.c
index 648dbfe1fce3a..df20f9194efb8 100644
--- a/drivers/net/ipa/reg/ipa_reg-v3.1.c
+++ b/drivers/net/ipa/reg/ipa_reg-v3.1.c
@@ -76,19 +76,6 @@ static const u32 reg_qsb_max_reads_fmask[] = {

REG_FIELDS(QSB_MAX_READS, qsb_max_reads, 0x00000078);

-static const u32 reg_filt_rout_hash_en_fmask[] = {
- [IPV6_ROUTER_HASH] = BIT(0),
- /* Bits 1-3 reserved */
- [IPV6_FILTER_HASH] = BIT(4),
- /* Bits 5-7 reserved */
- [IPV4_ROUTER_HASH] = BIT(8),
- /* Bits 9-11 reserved */
- [IPV4_FILTER_HASH] = BIT(12),
- /* Bits 13-31 reserved */
-};
-
-REG_FIELDS(FILT_ROUT_HASH_EN, filt_rout_hash_en, 0x000008c);
-
static const u32 reg_filt_rout_hash_flush_fmask[] = {
[IPV6_ROUTER_HASH] = BIT(0),
/* Bits 1-3 reserved */
@@ -403,7 +390,6 @@ static const struct reg *reg_array[] = {
[SHARED_MEM_SIZE] = &reg_shared_mem_size,
[QSB_MAX_WRITES] = &reg_qsb_max_writes,
[QSB_MAX_READS] = &reg_qsb_max_reads,
- [FILT_ROUT_HASH_EN] = &reg_filt_rout_hash_en,
[FILT_ROUT_HASH_FLUSH] = &reg_filt_rout_hash_flush,
[STATE_AGGR_ACTIVE] = &reg_state_aggr_active,
[IPA_BCR] = &reg_ipa_bcr,
diff --git a/drivers/net/ipa/reg/ipa_reg-v3.5.1.c b/drivers/net/ipa/reg/ipa_reg-v3.5.1.c
index 78b1bf60cd024..1f8c0457529e1 100644
--- a/drivers/net/ipa/reg/ipa_reg-v3.5.1.c
+++ b/drivers/net/ipa/reg/ipa_reg-v3.5.1.c
@@ -81,19 +81,6 @@ static const u32 reg_qsb_max_reads_fmask[] = {

REG_FIELDS(QSB_MAX_READS, qsb_max_reads, 0x00000078);

-static const u32 reg_filt_rout_hash_en_fmask[] = {
- [IPV6_ROUTER_HASH] = BIT(0),
- /* Bits 1-3 reserved */
- [IPV6_FILTER_HASH] = BIT(4),
- /* Bits 5-7 reserved */
- [IPV4_ROUTER_HASH] = BIT(8),
- /* Bits 9-11 reserved */
- [IPV4_FILTER_HASH] = BIT(12),
- /* Bits 13-31 reserved */
-};
-
-REG_FIELDS(FILT_ROUT_HASH_EN, filt_rout_hash_en, 0x000008c);
-
static const u32 reg_filt_rout_hash_flush_fmask[] = {
[IPV6_ROUTER_HASH] = BIT(0),
/* Bits 1-3 reserved */
@@ -414,7 +401,6 @@ static const struct reg *reg_array[] = {
[SHARED_MEM_SIZE] = &reg_shared_mem_size,
[QSB_MAX_WRITES] = &reg_qsb_max_writes,
[QSB_MAX_READS] = &reg_qsb_max_reads,
- [FILT_ROUT_HASH_EN] = &reg_filt_rout_hash_en,
[FILT_ROUT_HASH_FLUSH] = &reg_filt_rout_hash_flush,
[STATE_AGGR_ACTIVE] = &reg_state_aggr_active,
[IPA_BCR] = &reg_ipa_bcr,
diff --git a/drivers/net/ipa/reg/ipa_reg-v4.11.c b/drivers/net/ipa/reg/ipa_reg-v4.11.c
index 29e71cce4a843..ba21a6c655c88 100644
--- a/drivers/net/ipa/reg/ipa_reg-v4.11.c
+++ b/drivers/net/ipa/reg/ipa_reg-v4.11.c
@@ -113,19 +113,6 @@ static const u32 reg_qsb_max_reads_fmask[] = {

REG_FIELDS(QSB_MAX_READS, qsb_max_reads, 0x00000078);

-static const u32 reg_filt_rout_hash_en_fmask[] = {
- [IPV6_ROUTER_HASH] = BIT(0),
- /* Bits 1-3 reserved */
- [IPV6_FILTER_HASH] = BIT(4),
- /* Bits 5-7 reserved */
- [IPV4_ROUTER_HASH] = BIT(8),
- /* Bits 9-11 reserved */
- [IPV4_FILTER_HASH] = BIT(12),
- /* Bits 13-31 reserved */
-};
-
-REG_FIELDS(FILT_ROUT_HASH_EN, filt_rout_hash_en, 0x0000148);
-
static const u32 reg_filt_rout_hash_flush_fmask[] = {
[IPV6_ROUTER_HASH] = BIT(0),
/* Bits 1-3 reserved */
@@ -470,7 +457,6 @@ static const struct reg *reg_array[] = {
[SHARED_MEM_SIZE] = &reg_shared_mem_size,
[QSB_MAX_WRITES] = &reg_qsb_max_writes,
[QSB_MAX_READS] = &reg_qsb_max_reads,
- [FILT_ROUT_HASH_EN] = &reg_filt_rout_hash_en,
[FILT_ROUT_HASH_FLUSH] = &reg_filt_rout_hash_flush,
[STATE_AGGR_ACTIVE] = &reg_state_aggr_active,
[LOCAL_PKT_PROC_CNTXT] = &reg_local_pkt_proc_cntxt,
diff --git a/drivers/net/ipa/reg/ipa_reg-v4.5.c b/drivers/net/ipa/reg/ipa_reg-v4.5.c
index 1c58f78851c21..90fd749b43eba 100644
--- a/drivers/net/ipa/reg/ipa_reg-v4.5.c
+++ b/drivers/net/ipa/reg/ipa_reg-v4.5.c
@@ -107,19 +107,6 @@ static const u32 reg_qsb_max_reads_fmask[] = {

REG_FIELDS(QSB_MAX_READS, qsb_max_reads, 0x00000078);

-static const u32 reg_filt_rout_hash_en_fmask[] = {
- [IPV6_ROUTER_HASH] = BIT(0),
- /* Bits 1-3 reserved */
- [IPV6_FILTER_HASH] = BIT(4),
- /* Bits 5-7 reserved */
- [IPV4_ROUTER_HASH] = BIT(8),
- /* Bits 9-11 reserved */
- [IPV4_FILTER_HASH] = BIT(12),
- /* Bits 13-31 reserved */
-};
-
-REG_FIELDS(FILT_ROUT_HASH_EN, filt_rout_hash_en, 0x0000148);
-
static const u32 reg_filt_rout_hash_flush_fmask[] = {
[IPV6_ROUTER_HASH] = BIT(0),
/* Bits 1-3 reserved */
@@ -489,7 +476,6 @@ static const struct reg *reg_array[] = {
[SHARED_MEM_SIZE] = &reg_shared_mem_size,
[QSB_MAX_WRITES] = &reg_qsb_max_writes,
[QSB_MAX_READS] = &reg_qsb_max_reads,
- [FILT_ROUT_HASH_EN] = &reg_filt_rout_hash_en,
[FILT_ROUT_HASH_FLUSH] = &reg_filt_rout_hash_flush,
[STATE_AGGR_ACTIVE] = &reg_state_aggr_active,
[LOCAL_PKT_PROC_CNTXT] = &reg_local_pkt_proc_cntxt,
diff --git a/drivers/net/ipa/reg/ipa_reg-v4.7.c b/drivers/net/ipa/reg/ipa_reg-v4.7.c
index 731824fce1d4a..ebae61d10eadb 100644
--- a/drivers/net/ipa/reg/ipa_reg-v4.7.c
+++ b/drivers/net/ipa/reg/ipa_reg-v4.7.c
@@ -107,19 +107,6 @@ static const u32 reg_qsb_max_reads_fmask[] = {

REG_FIELDS(QSB_MAX_READS, qsb_max_reads, 0x00000078);

-static const u32 reg_filt_rout_hash_en_fmask[] = {
- [IPV6_ROUTER_HASH] = BIT(0),
- /* Bits 1-3 reserved */
- [IPV6_FILTER_HASH] = BIT(4),
- /* Bits 5-7 reserved */
- [IPV4_ROUTER_HASH] = BIT(8),
- /* Bits 9-11 reserved */
- [IPV4_FILTER_HASH] = BIT(12),
- /* Bits 13-31 reserved */
-};
-
-REG_FIELDS(FILT_ROUT_HASH_EN, filt_rout_hash_en, 0x0000148);
-
static const u32 reg_filt_rout_hash_flush_fmask[] = {
[IPV6_ROUTER_HASH] = BIT(0),
/* Bits 1-3 reserved */
@@ -462,7 +449,6 @@ static const struct reg *reg_array[] = {
[SHARED_MEM_SIZE] = &reg_shared_mem_size,
[QSB_MAX_WRITES] = &reg_qsb_max_writes,
[QSB_MAX_READS] = &reg_qsb_max_reads,
- [FILT_ROUT_HASH_EN] = &reg_filt_rout_hash_en,
[FILT_ROUT_HASH_FLUSH] = &reg_filt_rout_hash_flush,
[STATE_AGGR_ACTIVE] = &reg_state_aggr_active,
[LOCAL_PKT_PROC_CNTXT] = &reg_local_pkt_proc_cntxt,
diff --git a/drivers/net/ipa/reg/ipa_reg-v4.9.c b/drivers/net/ipa/reg/ipa_reg-v4.9.c
index 01f87b5290e01..f488f68603d07 100644
--- a/drivers/net/ipa/reg/ipa_reg-v4.9.c
+++ b/drivers/net/ipa/reg/ipa_reg-v4.9.c
@@ -112,19 +112,6 @@ static const u32 reg_qsb_max_reads_fmask[] = {

REG_FIELDS(QSB_MAX_READS, qsb_max_reads, 0x00000078);

-static const u32 reg_filt_rout_hash_en_fmask[] = {
- [IPV6_ROUTER_HASH] = BIT(0),
- /* Bits 1-3 reserved */
- [IPV6_FILTER_HASH] = BIT(4),
- /* Bits 5-7 reserved */
- [IPV4_ROUTER_HASH] = BIT(8),
- /* Bits 9-11 reserved */
- [IPV4_FILTER_HASH] = BIT(12),
- /* Bits 13-31 reserved */
-};
-
-REG_FIELDS(FILT_ROUT_HASH_EN, filt_rout_hash_en, 0x0000148);
-
static const u32 reg_filt_rout_hash_flush_fmask[] = {
[IPV6_ROUTER_HASH] = BIT(0),
/* Bits 1-3 reserved */
@@ -467,7 +454,6 @@ static const struct reg *reg_array[] = {
[SHARED_MEM_SIZE] = &reg_shared_mem_size,
[QSB_MAX_WRITES] = &reg_qsb_max_writes,
[QSB_MAX_READS] = &reg_qsb_max_reads,
- [FILT_ROUT_HASH_EN] = &reg_filt_rout_hash_en,
[FILT_ROUT_HASH_FLUSH] = &reg_filt_rout_hash_flush,
[STATE_AGGR_ACTIVE] = &reg_state_aggr_active,
[LOCAL_PKT_PROC_CNTXT] = &reg_local_pkt_proc_cntxt,
--
2.40.1


2024-04-18 20:50:13

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 6/8] net: ipa: fix two bogus argument names

In "ipa_endpoint.h", two function declarations have bogus argument
names. Fix these.

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/ipa_endpoint.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ipa/ipa_endpoint.h b/drivers/net/ipa/ipa_endpoint.h
index 3ad2e802040aa..b431e4e462114 100644
--- a/drivers/net/ipa/ipa_endpoint.h
+++ b/drivers/net/ipa/ipa_endpoint.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */

/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- * Copyright (C) 2019-2023 Linaro Ltd.
+ * Copyright (C) 2019-2024 Linaro Ltd.
*/
#ifndef _IPA_ENDPOINT_H_
#define _IPA_ENDPOINT_H_
@@ -199,9 +199,9 @@ int ipa_endpoint_init(struct ipa *ipa, u32 count,
const struct ipa_gsi_endpoint_data *data);
void ipa_endpoint_exit(struct ipa *ipa);

-void ipa_endpoint_trans_complete(struct ipa_endpoint *ipa,
+void ipa_endpoint_trans_complete(struct ipa_endpoint *endpoint,
struct gsi_trans *trans);
-void ipa_endpoint_trans_release(struct ipa_endpoint *ipa,
+void ipa_endpoint_trans_release(struct ipa_endpoint *endpoint,
struct gsi_trans *trans);

#endif /* _IPA_ENDPOINT_H_ */
--
2.40.1


2024-04-18 20:50:35

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 7/8] net: ipa: fix two minor ipa_cmd problems

In "ipa_cmd.h", ipa_cmd_data_valid() is declared, but that function
does not exist. So delete that declaration.

Also, for some reason ipa_cmd_init() never gets called. It isn't
really critical--it just validates that some memory offsets and a
size can be represented in some register fields, and they won't fail
with current data. Regardless, call the function in ipa_probe().

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/ipa_cmd.h | 8 --------
drivers/net/ipa/ipa_main.c | 4 ++++
2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ipa/ipa_cmd.h b/drivers/net/ipa/ipa_cmd.h
index e2cf1c2b0ef24..100a4e1133b5e 100644
--- a/drivers/net/ipa/ipa_cmd.h
+++ b/drivers/net/ipa/ipa_cmd.h
@@ -57,14 +57,6 @@ enum ipa_cmd_opcode {
bool ipa_cmd_table_init_valid(struct ipa *ipa, const struct ipa_mem *mem,
bool route);

-/**
- * ipa_cmd_data_valid() - Validate command-realted configuration is valid
- * @ipa: - IPA pointer
- *
- * Return: true if assumptions required for command are valid
- */
-bool ipa_cmd_data_valid(struct ipa *ipa);
-
/**
* ipa_cmd_pool_init() - initialize command channel pools
* @channel: AP->IPA command TX GSI channel pointer
diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c
index 59e7abb4a0d19..04dc0540ff7fb 100644
--- a/drivers/net/ipa/ipa_main.c
+++ b/drivers/net/ipa/ipa_main.c
@@ -866,6 +866,10 @@ static int ipa_probe(struct platform_device *pdev)
if (ret)
goto err_reg_exit;

+ ret = ipa_cmd_init(ipa);
+ if (ret)
+ goto err_mem_exit;
+
ret = gsi_init(&ipa->gsi, pdev, ipa->version, data->endpoint_count,
data->endpoint_data);
if (ret)
--
2.40.1


2024-04-18 20:51:00

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 8/8] net: ipa: kill ipa_version_supported()

The only place ipa_version_supported() is called is in the probe
function. The version comes from the match data. Rather than
checking the version validity separately, just consider anything
that has match data to be supported.

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/ipa_main.c | 5 -----
drivers/net/ipa/ipa_version.h | 18 ------------------
2 files changed, 23 deletions(-)

diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c
index 04dc0540ff7fb..08ec3581d1d27 100644
--- a/drivers/net/ipa/ipa_main.c
+++ b/drivers/net/ipa/ipa_main.c
@@ -811,11 +811,6 @@ static int ipa_probe(struct platform_device *pdev)
return -ENODEV;
}

- if (!ipa_version_supported(data->version)) {
- dev_err(dev, "unsupported IPA version %u\n", data->version);
- return -EINVAL;
- }
-
if (!data->modem_route_count) {
dev_err(dev, "modem_route_count cannot be zero\n");
return -EINVAL;
diff --git a/drivers/net/ipa/ipa_version.h b/drivers/net/ipa/ipa_version.h
index 38150345b607e..ae3396314acaf 100644
--- a/drivers/net/ipa/ipa_version.h
+++ b/drivers/net/ipa/ipa_version.h
@@ -45,24 +45,6 @@ enum ipa_version {
IPA_VERSION_COUNT, /* Last; not a version */
};

-static inline bool ipa_version_supported(enum ipa_version version)
-{
- switch (version) {
- case IPA_VERSION_3_1:
- case IPA_VERSION_3_5_1:
- case IPA_VERSION_4_2:
- case IPA_VERSION_4_5:
- case IPA_VERSION_4_7:
- case IPA_VERSION_4_9:
- case IPA_VERSION_4_11:
- case IPA_VERSION_5_0:
- case IPA_VERSION_5_5:
- return true;
- default:
- return false;
- }
-}
-
/* Execution environment IDs */
enum gsi_ee_id {
GSI_EE_AP = 0x0,
--
2.40.1


2024-04-18 21:00:39

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 2/8] net: ipa: only enable the SUSPEND IPA interrupt when needed

Only enable the SUSPEND IPA interrupt type when at least one
endpoint has that interrupt enabled.

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/ipa_interrupt.c | 8 ++++++++
drivers/net/ipa/ipa_power.c | 11 +----------
2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c
index 0e8d4e43275ea..e198712d46ebb 100644
--- a/drivers/net/ipa/ipa_interrupt.c
+++ b/drivers/net/ipa/ipa_interrupt.c
@@ -196,6 +196,7 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
u32 mask = BIT(endpoint_id % 32);
u32 unit = endpoint_id / 32;
const struct reg *reg;
+ unsigned long weight;
u32 offset;
u32 val;

@@ -205,6 +206,10 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
if (ipa->version == IPA_VERSION_3_0)
return;

+ weight = bitmap_weight(interrupt->suspend_enabled, ipa->endpoint_count);
+ if (weight == 1 && !enable)
+ ipa_interrupt_disable(ipa, IPA_IRQ_TX_SUSPEND);
+
reg = ipa_reg(ipa, IRQ_SUSPEND_EN);
offset = reg_n_offset(reg, unit);
val = ioread32(ipa->reg_virt + offset);
@@ -216,6 +221,9 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
__change_bit(endpoint_id, interrupt->suspend_enabled);

iowrite32(val, ipa->reg_virt + offset);
+
+ if (!weight && enable)
+ ipa_interrupt_enable(ipa, IPA_IRQ_TX_SUSPEND);
}

/* Enable TX_SUSPEND for an endpoint */
diff --git a/drivers/net/ipa/ipa_power.c b/drivers/net/ipa/ipa_power.c
index 41ca7ef5e20fc..bdbcf965d5a30 100644
--- a/drivers/net/ipa/ipa_power.c
+++ b/drivers/net/ipa/ipa_power.c
@@ -234,21 +234,12 @@ void ipa_power_retention(struct ipa *ipa, bool enable)

int ipa_power_setup(struct ipa *ipa)
{
- int ret;
-
- ipa_interrupt_enable(ipa, IPA_IRQ_TX_SUSPEND);
-
- ret = device_init_wakeup(ipa->dev, true);
- if (ret)
- ipa_interrupt_disable(ipa, IPA_IRQ_TX_SUSPEND);
-
- return ret;
+ return device_init_wakeup(ipa->dev, true);
}

void ipa_power_teardown(struct ipa *ipa)
{
(void)device_init_wakeup(ipa->dev, false);
- ipa_interrupt_disable(ipa, IPA_IRQ_TX_SUSPEND);
}

/* Initialize IPA power management */
--
2.40.1


2024-04-18 21:00:49

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 3/8] net: ipa: call device_init_wakeup() earlier

Currently, enabling wakeup for the IPA device doesn't occur until
the setup phase of initialization (in ipa_power_setup()).

There is no need to delay doing that, however. We can conveniently
do it during the config phase, in ipa_interrupt_config(), where we
enable power management wakeup mode for the IPA interrupt.

Moving the device_init_wakeup() out of ipa_power_setup() leaves that
function empty, so it can just be eliminated.

Similarly, rearrange all of the matching inverse calls, disabling
device wakeup in ipa_interrupt_deconfig() and removing that function
as well.

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/ipa_interrupt.c | 11 ++++++++++-
drivers/net/ipa/ipa_main.c | 7 -------
drivers/net/ipa/ipa_power.c | 10 ----------
drivers/net/ipa/ipa_power.h | 14 --------------
4 files changed, 10 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c
index e198712d46ebb..a9a2c34115b5b 100644
--- a/drivers/net/ipa/ipa_interrupt.c
+++ b/drivers/net/ipa/ipa_interrupt.c
@@ -277,17 +277,25 @@ int ipa_interrupt_config(struct ipa *ipa)
goto err_free_bitmap;
}

+ ret = device_init_wakeup(dev, true);
+ if (ret) {
+ dev_err(dev, "error %d enabling wakeup\n", ret);
+ goto err_free_irq;
+ }
+
ret = dev_pm_set_wake_irq(dev, irq);
if (ret) {
dev_err(dev, "error %d registering \"ipa\" IRQ as wakeirq\n",
ret);
- goto err_free_irq;
+ goto err_disable_wakeup;
}

ipa->interrupt = interrupt;

return 0;

+err_disable_wakeup:
+ (void)device_init_wakeup(dev, false);
err_free_irq:
free_irq(interrupt->irq, interrupt);
err_free_bitmap:
@@ -307,6 +315,7 @@ void ipa_interrupt_deconfig(struct ipa *ipa)
ipa->interrupt = NULL;

dev_pm_clear_wake_irq(dev);
+ (void)device_init_wakeup(dev, false);
free_irq(interrupt->irq, interrupt);
bitmap_free(interrupt->suspend_enabled);
}
diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c
index 57b241417e8cd..59e7abb4a0d19 100644
--- a/drivers/net/ipa/ipa_main.c
+++ b/drivers/net/ipa/ipa_main.c
@@ -120,10 +120,6 @@ int ipa_setup(struct ipa *ipa)
if (ret)
return ret;

- ret = ipa_power_setup(ipa);
- if (ret)
- goto err_gsi_teardown;
-
ipa_endpoint_setup(ipa);

/* We need to use the AP command TX endpoint to perform other
@@ -170,8 +166,6 @@ int ipa_setup(struct ipa *ipa)
ipa_endpoint_disable_one(command_endpoint);
err_endpoint_teardown:
ipa_endpoint_teardown(ipa);
- ipa_power_teardown(ipa);
-err_gsi_teardown:
gsi_teardown(&ipa->gsi);

return ret;
@@ -196,7 +190,6 @@ static void ipa_teardown(struct ipa *ipa)
command_endpoint = ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX];
ipa_endpoint_disable_one(command_endpoint);
ipa_endpoint_teardown(ipa);
- ipa_power_teardown(ipa);
gsi_teardown(&ipa->gsi);
}

diff --git a/drivers/net/ipa/ipa_power.c b/drivers/net/ipa/ipa_power.c
index bdbcf965d5a30..881bf9147b190 100644
--- a/drivers/net/ipa/ipa_power.c
+++ b/drivers/net/ipa/ipa_power.c
@@ -232,16 +232,6 @@ void ipa_power_retention(struct ipa *ipa, bool enable)
ret, enable ? "en" : "dis");
}

-int ipa_power_setup(struct ipa *ipa)
-{
- return device_init_wakeup(ipa->dev, true);
-}
-
-void ipa_power_teardown(struct ipa *ipa)
-{
- (void)device_init_wakeup(ipa->dev, false);
-}
-
/* Initialize IPA power management */
struct ipa_power *
ipa_power_init(struct device *dev, const struct ipa_power_data *data)
diff --git a/drivers/net/ipa/ipa_power.h b/drivers/net/ipa/ipa_power.h
index 227cc04bea806..df93b07415f2a 100644
--- a/drivers/net/ipa/ipa_power.h
+++ b/drivers/net/ipa/ipa_power.h
@@ -30,20 +30,6 @@ u32 ipa_core_clock_rate(struct ipa *ipa);
*/
void ipa_power_retention(struct ipa *ipa, bool enable);

-/**
- * ipa_power_setup() - Set up IPA power management
- * @ipa: IPA pointer
- *
- * Return: 0 if successful, or a negative error code
- */
-int ipa_power_setup(struct ipa *ipa);
-
-/**
- * ipa_power_teardown() - Inverse of ipa_power_setup()
- * @ipa: IPA pointer
- */
-void ipa_power_teardown(struct ipa *ipa);
-
/**
* ipa_power_init() - Initialize IPA power management
* @dev: IPA device
--
2.40.1


2024-04-18 21:01:31

by Alex Elder

[permalink] [raw]
Subject: [PATCH net-next 5/8] net: ipa: make ipa_table_hash_support() a real function

With the exception of ipa_table_hash_support(), nothing defined in
"ipa_table.h" requires the full definition of the IPA structure.

Change that function to be a "real" function rather than an inline,
to avoid requring the IPA structure to be defined.

Signed-off-by: Alex Elder <[email protected]>
---
drivers/net/ipa/ipa_table.c | 8 +++++++-
drivers/net/ipa/ipa_table.h | 7 ++-----
2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ipa/ipa_table.c b/drivers/net/ipa/ipa_table.c
index a24ac11b8893d..9b4bb6d3f152a 100644
--- a/drivers/net/ipa/ipa_table.c
+++ b/drivers/net/ipa/ipa_table.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0

/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- * Copyright (C) 2018-2023 Linaro Ltd.
+ * Copyright (C) 2018-2024 Linaro Ltd.
*/

#include <linux/types.h>
@@ -161,6 +161,12 @@ ipa_table_mem(struct ipa *ipa, bool filter, bool hashed, bool ipv6)
return ipa_mem_find(ipa, mem_id);
}

+/* Return true if hashed tables are supported */
+bool ipa_table_hash_support(struct ipa *ipa)
+{
+ return ipa->version != IPA_VERSION_4_2;
+}
+
bool ipa_filtered_valid(struct ipa *ipa, u64 filtered)
{
struct device *dev = ipa->dev;
diff --git a/drivers/net/ipa/ipa_table.h b/drivers/net/ipa/ipa_table.h
index 7cc951904bb48..16d4d15df9e9c 100644
--- a/drivers/net/ipa/ipa_table.h
+++ b/drivers/net/ipa/ipa_table.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */

/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- * Copyright (C) 2019-2022 Linaro Ltd.
+ * Copyright (C) 2019-2024 Linaro Ltd.
*/
#ifndef _IPA_TABLE_H_
#define _IPA_TABLE_H_
@@ -23,10 +23,7 @@ bool ipa_filtered_valid(struct ipa *ipa, u64 filtered);
* ipa_table_hash_support() - Return true if hashed tables are supported
* @ipa: IPA pointer
*/
-static inline bool ipa_table_hash_support(struct ipa *ipa)
-{
- return ipa->version != IPA_VERSION_4_2;
-}
+bool ipa_table_hash_support(struct ipa *ipa);

/**
* ipa_table_reset() - Reset filter and route tables entries to "none"
--
2.40.1


2024-04-18 23:53:15

by Bryan O'Donoghue

[permalink] [raw]
Subject: Re: [PATCH net-next 1/8] net: ipa: maintain bitmap of suspend-enabled endpoints

On 18/04/2024 21:47, Alex Elder wrote:
> Keep track of which endpoints have the SUSPEND IPA interrupt enabled
> in a variable-length bitmap. This will be used in the next patch to
> allow the SUSPEND interrupt type to be disabled except when needed.
>
> Signed-off-by: Alex Elder <[email protected]>
> ---
> drivers/net/ipa/ipa_interrupt.c | 19 +++++++++++++++++--
> 1 file changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c
> index c44ec05f71e6f..0e8d4e43275ea 100644
> --- a/drivers/net/ipa/ipa_interrupt.c
> +++ b/drivers/net/ipa/ipa_interrupt.c
> @@ -37,11 +37,13 @@
> * @ipa: IPA pointer
> * @irq: Linux IRQ number used for IPA interrupts
> * @enabled: Mask indicating which interrupts are enabled
> + * @suspend_enabled: Bitmap of endpoints with the SUSPEND interrupt enabled
> */
> struct ipa_interrupt {
> struct ipa *ipa;
> u32 irq;
> u32 enabled;
> + unsigned long *suspend_enabled;
> };
>
> /* Clear the suspend interrupt for all endpoints that signaled it */
> @@ -211,6 +213,7 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
> val |= mask;
> else
> val &= ~mask;
> + __change_bit(endpoint_id, interrupt->suspend_enabled);
>
> iowrite32(val, ipa->reg_virt + offset);
> }
> @@ -246,7 +249,16 @@ int ipa_interrupt_config(struct ipa *ipa)
>
> interrupt->ipa = ipa;
>
> - /* Disable all IPA interrupt types */
> + /* Initially all IPA interrupt types are disabled */
> + interrupt->enabled = 0;
> + interrupt->suspend_enabled = bitmap_zalloc(ipa->endpoint_count,
> + GFP_KERNEL);

why not use devm_bitmap_zalloc() instead and skip managing the cleanup ?

> + if (!interrupt->suspend_enabled) {
> + ret = -ENOMEM;
> + goto err_kfree;
> + }
> +
> + /* Disable IPA interrupt types */
> reg = ipa_reg(ipa, IPA_IRQ_EN);
> iowrite32(0, ipa->reg_virt + reg_offset(reg));
>
> @@ -254,7 +266,7 @@ int ipa_interrupt_config(struct ipa *ipa)
> "ipa", interrupt);
> if (ret) {
> dev_err(dev, "error %d requesting \"ipa\" IRQ\n", ret);
> - goto err_kfree;
> + goto err_free_bitmap;
> }
>
> ret = dev_pm_set_wake_irq(dev, irq);
> @@ -270,6 +282,8 @@ int ipa_interrupt_config(struct ipa *ipa)
>
> err_free_irq:
> free_irq(interrupt->irq, interrupt);
> +err_free_bitmap:
> + bitmap_free(interrupt->suspend_enabled);
> err_kfree:
> kfree(interrupt);

You could also use devm_kzalloc() and do away with the kfree()s you have
here on the probe path.

>
> @@ -286,6 +300,7 @@ void ipa_interrupt_deconfig(struct ipa *ipa)
>
> dev_pm_clear_wake_irq(dev);
> free_irq(interrupt->irq, interrupt);
> + bitmap_free(interrupt->suspend_enabled);
> }
>
> /* Initialize the IPA interrupt structure */

Just suggestions though.

Reviewed-by: Bryan O'Donoghue <[email protected]>

2024-04-19 00:46:58

by Alex Elder

[permalink] [raw]
Subject: Re: [PATCH net-next 1/8] net: ipa: maintain bitmap of suspend-enabled endpoints

On 4/18/24 6:52 PM, Bryan O'Donoghue wrote:
> On 18/04/2024 21:47, Alex Elder wrote:
>> Keep track of which endpoints have the SUSPEND IPA interrupt enabled
>> in a variable-length bitmap.  This will be used in the next patch to
>> allow the SUSPEND interrupt type to be disabled except when needed.
>>
>> Signed-off-by: Alex Elder <[email protected]>
>> ---
>>   drivers/net/ipa/ipa_interrupt.c | 19 +++++++++++++++++--
>>   1 file changed, 17 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/ipa/ipa_interrupt.c
>> b/drivers/net/ipa/ipa_interrupt.c
>> index c44ec05f71e6f..0e8d4e43275ea 100644
>> --- a/drivers/net/ipa/ipa_interrupt.c
>> +++ b/drivers/net/ipa/ipa_interrupt.c
>> @@ -37,11 +37,13 @@
>>    * @ipa:        IPA pointer
>>    * @irq:        Linux IRQ number used for IPA interrupts
>>    * @enabled:        Mask indicating which interrupts are enabled
>> + * @suspend_enabled:    Bitmap of endpoints with the SUSPEND
>> interrupt enabled
>>    */
>>   struct ipa_interrupt {
>>       struct ipa *ipa;
>>       u32 irq;
>>       u32 enabled;
>> +    unsigned long *suspend_enabled;
>>   };
>>   /* Clear the suspend interrupt for all endpoints that signaled it */
>> @@ -211,6 +213,7 @@ static void ipa_interrupt_suspend_control(struct
>> ipa_interrupt *interrupt,
>>           val |= mask;
>>       else
>>           val &= ~mask;
>> +    __change_bit(endpoint_id, interrupt->suspend_enabled);
>>       iowrite32(val, ipa->reg_virt + offset);
>>   }
>> @@ -246,7 +249,16 @@ int ipa_interrupt_config(struct ipa *ipa)
>>       interrupt->ipa = ipa;
>> -    /* Disable all IPA interrupt types */
>> +    /* Initially all IPA interrupt types are disabled */
>> +    interrupt->enabled = 0;
>> +    interrupt->suspend_enabled = bitmap_zalloc(ipa->endpoint_count,
>> +                           GFP_KERNEL);
>
> why not use devm_bitmap_zalloc() instead and skip managing the cleanup ?

I don't use the devm_*() variants in the IPA driver.

I know I can, but if I'm make the switch I want to
do it everywhere. Not now.

Thanks for the review.

-Alex

>> +    if (!interrupt->suspend_enabled) {
>> +        ret = -ENOMEM;
>> +        goto err_kfree;
>> +    }
>> +
>> +    /* Disable IPA interrupt types */
>>       reg = ipa_reg(ipa, IPA_IRQ_EN);
>>       iowrite32(0, ipa->reg_virt + reg_offset(reg));
>> @@ -254,7 +266,7 @@ int ipa_interrupt_config(struct ipa *ipa)
>>                      "ipa", interrupt);
>>       if (ret) {
>>           dev_err(dev, "error %d requesting \"ipa\" IRQ\n", ret);
>> -        goto err_kfree;
>> +        goto err_free_bitmap;
>>       }
>>       ret = dev_pm_set_wake_irq(dev, irq);
>> @@ -270,6 +282,8 @@ int ipa_interrupt_config(struct ipa *ipa)
>>   err_free_irq:
>>       free_irq(interrupt->irq, interrupt);
>> +err_free_bitmap:
>> +    bitmap_free(interrupt->suspend_enabled);
>>   err_kfree:
>>       kfree(interrupt);
>
> You could also use devm_kzalloc() and do away with the kfree()s you have
> here on the probe path.
>
>> @@ -286,6 +300,7 @@ void ipa_interrupt_deconfig(struct ipa *ipa)
>>       dev_pm_clear_wake_irq(dev);
>>       free_irq(interrupt->irq, interrupt);
>> +    bitmap_free(interrupt->suspend_enabled);
>>   }
>>   /* Initialize the IPA interrupt structure */
>
> Just suggestions though.
>
> Reviewed-by: Bryan O'Donoghue <[email protected]>