* [PATCH v3 0/7] syscore: Pass context data to callbacks
@ 2025-10-29 16:33 Thierry Reding
2025-10-29 16:33 ` [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable Thierry Reding
` (6 more replies)
0 siblings, 7 replies; 16+ messages in thread
From: Thierry Reding @ 2025-10-29 16:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki
Cc: x86, linux-arm-kernel, linux-riscv, linux-mips, loongarch,
linuxppc-dev, linux-sh, linux-pci, linux-acpi, linux-kernel
From: Thierry Reding <treding@nvidia.com>
Hi Greg, Rafael,
sorry, this took a while to rework because I had to find a large enough
block of free time to push through. I played around a bit with different
ideas based on our discussion and ended up with a mix between Rafael's
and my proposal. struct syscore_ops is now split out and can be made
const. struct syscore is introduced to contain the variable data such
as the list head and the driver data. It also has a pointer to the ops
structure. Registration APIs are changed accordingly. I initially wanted
to avoid this churn, but then realized I was already touching all of the
files anyway, so might as well make it all consistent. As a result the
series is about twice as large in terms of LOC, but that's mostly due to
the structure split.
For anyone who hasn't seen this yet, here's the full cover letter:
Hi,
Something that's been bugging me over the years is how some drivers have
had to adopt file-scoped variables to pass data into something like the
syscore operations. This is often harmless, but usually leads to drivers
not being able to deal with multiple instances, or additional frameworks
or data structures needing to be created to handle multiple instances.
This series proposes to "objectify" struct syscore_ops by passing driver
specific data to the syscore callbacks. The contextual data is stored in
a new struct syscore before registering the structure with the framework
and the structure can be embedded in driver-specific data to make it per
instance.
Patch 1 contains the bulk of these changes. It's fairly intrusive
because it does the conversion of the function signature all in one
patch. An alternative would've been to introduce new callbacks such that
these changes could be staged in. However, the amount of changes here
are not quite numerous enough to justify that, in my opinion, and
syscore isn't very frequently used, so the risk of another user getting
added while this is merged is rather small. All in all I think merging
this in one go is the simplest way.
Patches 2-7 are conversions of some existing drivers to take advantage
of this new parameter and tie the code to per-instance data.
Given that the recipient list for this is huge, I'm limiting this to
Greg (because it's at the core a... core change) and a set of larger
lists for architectures and subsystems that are impacted.
Changes in v3:
- add separate syscore structure containing the modifiable fields,
including driver-specific data, as well as a pointer to the constified
syscore_ops structure
- change registration/unregistration API to make these changes more
obvious
Changes in v2:
- kerneldoc fixes
Thanks,
Thierry
Thierry Reding (7):
syscore: Pass context data to callbacks
MIPS: PCI: Use contextual data instead of global variable
bus: mvebu-mbus: Use contextual data instead of global variable
clk: ingenic: tcu: Use contextual data instead of global variable
clk: mvebu: Use contextual data instead of global variable
irqchip/irq-imx-gpcv2: Use contextual data instead of global variable
soc/tegra: pmc: Use contextual data instead of global variable
arch/arm/mach-exynos/mcpm-exynos.c | 12 ++--
arch/arm/mach-exynos/suspend.c | 48 +++++++------
arch/arm/mach-pxa/generic.h | 6 +-
arch/arm/mach-pxa/irq.c | 10 ++-
arch/arm/mach-pxa/mfp-pxa2xx.c | 10 ++-
arch/arm/mach-pxa/mfp-pxa3xx.c | 10 ++-
arch/arm/mach-pxa/pxa25x.c | 4 +-
arch/arm/mach-pxa/pxa27x.c | 4 +-
arch/arm/mach-pxa/pxa3xx.c | 4 +-
arch/arm/mach-pxa/smemc.c | 12 ++--
arch/arm/mach-s3c/irq-pm-s3c64xx.c | 12 ++--
arch/arm/mach-s5pv210/pm.c | 10 ++-
arch/arm/mach-versatile/integrator_ap.c | 12 ++--
arch/arm/mm/cache-b15-rac.c | 12 ++--
arch/loongarch/kernel/smp.c | 12 ++--
arch/mips/alchemy/common/dbdma.c | 12 ++--
arch/mips/alchemy/common/irq.c | 24 ++++---
arch/mips/alchemy/common/usb.c | 12 ++--
arch/mips/pci/pci-alchemy.c | 30 +++------
arch/powerpc/platforms/cell/spu_base.c | 10 ++-
arch/powerpc/platforms/powermac/pic.c | 12 ++--
arch/powerpc/sysdev/fsl_lbc.c | 12 ++--
arch/powerpc/sysdev/fsl_pci.c | 12 ++--
arch/powerpc/sysdev/ipic.c | 12 ++--
arch/powerpc/sysdev/mpic.c | 14 ++--
arch/powerpc/sysdev/mpic_timer.c | 10 ++-
arch/sh/mm/pmb.c | 10 ++-
arch/x86/events/amd/ibs.c | 12 ++--
arch/x86/hyperv/hv_init.c | 12 ++--
arch/x86/kernel/amd_gart_64.c | 10 ++-
arch/x86/kernel/apic/apic.c | 12 ++--
arch/x86/kernel/apic/io_apic.c | 17 +++--
arch/x86/kernel/cpu/aperfmperf.c | 20 +++---
arch/x86/kernel/cpu/intel_epb.c | 16 +++--
arch/x86/kernel/cpu/mce/core.c | 14 ++--
arch/x86/kernel/cpu/microcode/core.c | 15 ++++-
arch/x86/kernel/cpu/mtrr/legacy.c | 12 ++--
arch/x86/kernel/cpu/umwait.c | 10 ++-
arch/x86/kernel/i8237.c | 10 ++-
arch/x86/kernel/i8259.c | 14 ++--
arch/x86/kernel/kvm.c | 12 ++--
drivers/acpi/pci_link.c | 10 ++-
drivers/acpi/sleep.c | 12 ++--
drivers/base/firmware_loader/main.c | 12 ++--
drivers/base/syscore.c | 82 ++++++++++++-----------
drivers/bus/mvebu-mbus.c | 19 +++---
drivers/clk/at91/pmc.c | 12 ++--
drivers/clk/imx/clk-vf610.c | 12 ++--
drivers/clk/ingenic/jz4725b-cgu.c | 2 +-
drivers/clk/ingenic/jz4740-cgu.c | 2 +-
drivers/clk/ingenic/jz4755-cgu.c | 2 +-
drivers/clk/ingenic/jz4760-cgu.c | 2 +-
drivers/clk/ingenic/jz4770-cgu.c | 2 +-
drivers/clk/ingenic/jz4780-cgu.c | 2 +-
drivers/clk/ingenic/pm.c | 14 ++--
drivers/clk/ingenic/pm.h | 2 +-
drivers/clk/ingenic/tcu.c | 59 ++++++++--------
drivers/clk/ingenic/x1000-cgu.c | 2 +-
drivers/clk/ingenic/x1830-cgu.c | 2 +-
drivers/clk/mvebu/common.c | 19 ++++--
drivers/clk/rockchip/clk-rk3288.c | 12 ++--
drivers/clk/samsung/clk-s5pv210-audss.c | 12 ++--
drivers/clk/samsung/clk.c | 12 ++--
drivers/clk/tegra/clk-tegra210.c | 12 ++--
drivers/clocksource/timer-armada-370-xp.c | 12 ++--
drivers/cpuidle/cpuidle-psci.c | 12 ++--
drivers/gpio/gpio-mxc.c | 12 ++--
drivers/gpio/gpio-pxa.c | 12 ++--
drivers/gpio/gpio-sa1100.c | 12 ++--
drivers/hv/vmbus_drv.c | 14 ++--
drivers/iommu/amd/init.c | 12 ++--
drivers/iommu/intel/iommu.c | 12 ++--
drivers/irqchip/exynos-combiner.c | 14 ++--
drivers/irqchip/irq-armada-370-xp.c | 12 ++--
drivers/irqchip/irq-bcm7038-l1.c | 12 ++--
drivers/irqchip/irq-gic-v3-its.c | 12 ++--
drivers/irqchip/irq-i8259.c | 12 ++--
drivers/irqchip/irq-imx-gpcv2.c | 30 +++------
drivers/irqchip/irq-loongson-eiointc.c | 12 ++--
drivers/irqchip/irq-loongson-htpic.c | 10 ++-
drivers/irqchip/irq-loongson-htvec.c | 12 ++--
drivers/irqchip/irq-loongson-pch-lpc.c | 12 ++--
drivers/irqchip/irq-loongson-pch-pic.c | 12 ++--
drivers/irqchip/irq-mchp-eic.c | 12 ++--
drivers/irqchip/irq-mst-intc.c | 12 ++--
drivers/irqchip/irq-mtk-cirq.c | 12 ++--
drivers/irqchip/irq-renesas-rzg2l.c | 12 ++--
drivers/irqchip/irq-sa11x0.c | 12 ++--
drivers/irqchip/irq-sifive-plic.c | 12 ++--
drivers/irqchip/irq-sun6i-r.c | 18 +++--
drivers/irqchip/irq-tegra.c | 12 ++--
drivers/irqchip/irq-vic.c | 12 ++--
drivers/leds/trigger/ledtrig-cpu.c | 14 ++--
drivers/macintosh/via-pmu.c | 12 ++--
drivers/power/reset/sc27xx-poweroff.c | 10 ++-
drivers/sh/clk/core.c | 10 ++-
drivers/sh/intc/core.c | 12 ++--
drivers/soc/bcm/brcmstb/biuctrl.c | 12 ++--
drivers/soc/tegra/pmc.c | 21 ++++--
drivers/thermal/intel/intel_hfi.c | 12 ++--
drivers/xen/xen-acpi-processor.c | 12 ++--
include/linux/syscore_ops.h | 15 +++--
kernel/cpu_pm.c | 12 ++--
kernel/irq/generic-chip.c | 14 ++--
kernel/irq/pm.c | 11 ++-
kernel/printk/printk.c | 11 ++-
kernel/time/sched_clock.c | 22 ++++--
kernel/time/timekeeping.c | 22 ++++--
virt/kvm/kvm_main.c | 18 +++--
109 files changed, 930 insertions(+), 523 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable
2025-10-29 16:33 [PATCH v3 0/7] syscore: Pass context data to callbacks Thierry Reding
@ 2025-10-29 16:33 ` Thierry Reding
2025-10-29 17:46 ` Bjorn Helgaas
2025-10-29 16:33 ` [PATCH v3 3/7] bus: mvebu-mbus: " Thierry Reding
` (5 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Thierry Reding @ 2025-10-29 16:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki
Cc: x86, linux-arm-kernel, linux-riscv, linux-mips, loongarch,
linuxppc-dev, linux-sh, linux-pci, linux-acpi, linux-kernel
From: Thierry Reding <treding@nvidia.com>
Pass the driver-specific data via the syscore struct and use it in the
syscore ops.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v3:
- adjust for API changes and update commit message
Changes in v2:
- remove unused global variable
arch/mips/pci/pci-alchemy.c | 24 ++++++------------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c
index 6bfee0f71803..f73bf60bd069 100644
--- a/arch/mips/pci/pci-alchemy.c
+++ b/arch/mips/pci/pci-alchemy.c
@@ -33,6 +33,7 @@
struct alchemy_pci_context {
struct pci_controller alchemy_pci_ctrl; /* leave as first member! */
+ struct syscore syscore;
void __iomem *regs; /* ctrl base */
/* tools for wired entry for config space access */
unsigned long last_elo0;
@@ -46,12 +47,6 @@ struct alchemy_pci_context {
int (*board_pci_idsel)(unsigned int devsel, int assert);
};
-/* for syscore_ops. There's only one PCI controller on Alchemy chips, so this
- * should suffice for now.
- */
-static struct alchemy_pci_context *__alchemy_pci_ctx;
-
-
/* IO/MEM resources for PCI. Keep the memres in sync with fixup_bigphys_addr
* in arch/mips/alchemy/common/setup.c
*/
@@ -306,9 +301,7 @@ static int alchemy_pci_def_idsel(unsigned int devsel, int assert)
/* save PCI controller register contents. */
static int alchemy_pci_suspend(void *data)
{
- struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
- if (!ctx)
- return 0;
+ struct alchemy_pci_context *ctx = data;
ctx->pm[0] = __raw_readl(ctx->regs + PCI_REG_CMEM);
ctx->pm[1] = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009ffff;
@@ -328,9 +321,7 @@ static int alchemy_pci_suspend(void *data)
static void alchemy_pci_resume(void *data)
{
- struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
- if (!ctx)
- return;
+ struct alchemy_pci_context *ctx = data;
__raw_writel(ctx->pm[0], ctx->regs + PCI_REG_CMEM);
__raw_writel(ctx->pm[2], ctx->regs + PCI_REG_B2BMASK_CCH);
@@ -359,10 +350,6 @@ static const struct syscore_ops alchemy_pci_syscore_ops = {
.resume = alchemy_pci_resume,
};
-static struct syscore alchemy_pci_syscore = {
- .ops = &alchemy_pci_syscore_ops,
-};
-
static int alchemy_pci_probe(struct platform_device *pdev)
{
struct alchemy_pci_platdata *pd = pdev->dev.platform_data;
@@ -480,9 +467,10 @@ static int alchemy_pci_probe(struct platform_device *pdev)
__raw_writel(val, ctx->regs + PCI_REG_CONFIG);
wmb();
- __alchemy_pci_ctx = ctx;
platform_set_drvdata(pdev, ctx);
- register_syscore(&alchemy_pci_syscore);
+ ctx->syscore.ops = &alchemy_pci_syscore_ops;
+ ctx->syscore.data = ctx;
+ register_syscore(&ctx->syscore);
register_pci_controller(&ctx->alchemy_pci_ctrl);
dev_info(&pdev->dev, "PCI controller at %ld MHz\n",
--
2.51.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 3/7] bus: mvebu-mbus: Use contextual data instead of global variable
2025-10-29 16:33 [PATCH v3 0/7] syscore: Pass context data to callbacks Thierry Reding
2025-10-29 16:33 ` [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable Thierry Reding
@ 2025-10-29 16:33 ` Thierry Reding
2025-10-29 16:33 ` [PATCH v3 4/7] clk: ingenic: tcu: " Thierry Reding
` (4 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Thierry Reding @ 2025-10-29 16:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki
Cc: x86, linux-arm-kernel, linux-riscv, linux-mips, loongarch,
linuxppc-dev, linux-sh, linux-pci, linux-acpi, linux-kernel
From: Thierry Reding <treding@nvidia.com>
Pass the driver-specific data via the syscore struct and use it in the
syscore ops.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v3:
- adjust for API changes and update commit message
drivers/bus/mvebu-mbus.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index dd94145c9b22..d33c8e42e91c 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -130,6 +130,7 @@ struct mvebu_mbus_win_data {
};
struct mvebu_mbus_state {
+ struct syscore syscore;
void __iomem *mbuswins_base;
void __iomem *sdramwins_base;
void __iomem *mbusbridge_base;
@@ -1008,7 +1009,7 @@ fs_initcall(mvebu_mbus_debugfs_init);
static int mvebu_mbus_suspend(void *data)
{
- struct mvebu_mbus_state *s = &mbus_state;
+ struct mvebu_mbus_state *s = data;
int win;
if (!s->mbusbridge_base)
@@ -1042,7 +1043,7 @@ static int mvebu_mbus_suspend(void *data)
static void mvebu_mbus_resume(void *data)
{
- struct mvebu_mbus_state *s = &mbus_state;
+ struct mvebu_mbus_state *s = data;
int win;
writel(s->mbus_bridge_ctrl,
@@ -1074,10 +1075,6 @@ static const struct syscore_ops mvebu_mbus_syscore_ops = {
.resume = mvebu_mbus_resume,
};
-static struct syscore mvebu_mbus_syscore = {
- .ops = &mvebu_mbus_syscore_ops,
-};
-
static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
phys_addr_t mbuswins_phys_base,
size_t mbuswins_size,
@@ -1122,7 +1119,9 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
writel(UNIT_SYNC_BARRIER_ALL,
mbus->mbuswins_base + UNIT_SYNC_BARRIER_OFF);
- register_syscore(&mvebu_mbus_syscore);
+ mbus->syscore.ops = &mvebu_mbus_syscore_ops;
+ mbus->syscore.data = mbus;
+ register_syscore(&mbus->syscore);
return 0;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 4/7] clk: ingenic: tcu: Use contextual data instead of global variable
2025-10-29 16:33 [PATCH v3 0/7] syscore: Pass context data to callbacks Thierry Reding
2025-10-29 16:33 ` [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable Thierry Reding
2025-10-29 16:33 ` [PATCH v3 3/7] bus: mvebu-mbus: " Thierry Reding
@ 2025-10-29 16:33 ` Thierry Reding
2025-10-29 17:56 ` Bjorn Helgaas
2025-10-29 16:33 ` [PATCH v3 5/7] clk: mvebu: " Thierry Reding
` (3 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Thierry Reding @ 2025-10-29 16:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki
Cc: x86, linux-arm-kernel, linux-riscv, linux-mips, loongarch,
linuxppc-dev, linux-sh, linux-pci, linux-acpi, linux-kernel
From: Thierry Reding <treding@nvidia.com>
Pass the driver-specific data via the syscore struct and use it in the
syscore ops.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v3:
- adjust for API changes and update commit message
drivers/clk/ingenic/tcu.c | 63 +++++++++++++++++++--------------------
1 file changed, 30 insertions(+), 33 deletions(-)
diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c
index bc6a51da2072..8c6337d8e831 100644
--- a/drivers/clk/ingenic/tcu.c
+++ b/drivers/clk/ingenic/tcu.c
@@ -53,9 +53,9 @@ struct ingenic_tcu {
struct clk *clk;
struct clk_hw_onecell_data *clocks;
-};
-static struct ingenic_tcu *ingenic_tcu;
+ struct syscore syscore;
+};
static inline struct ingenic_tcu_clk *to_tcu_clk(struct clk_hw *hw)
{
@@ -332,6 +332,29 @@ static const struct of_device_id __maybe_unused ingenic_tcu_of_match[] __initcon
{ /* sentinel */ }
};
+static int __maybe_unused tcu_pm_suspend(void *data)
+{
+ struct ingenic_tcu *tcu = data;
+
+ if (tcu->clk)
+ clk_disable(tcu->clk);
+
+ return 0;
+}
+
+static void __maybe_unused tcu_pm_resume(void *data)
+{
+ struct ingenic_tcu *tcu = data;
+
+ if (tcu->clk)
+ clk_enable(tcu->clk);
+}
+
+static const struct syscore_ops tcu_pm_ops __maybe_unused = {
+ .suspend = tcu_pm_suspend,
+ .resume = tcu_pm_resume,
+};
+
static int __init ingenic_tcu_probe(struct device_node *np)
{
const struct of_device_id *id = of_match_node(ingenic_tcu_of_match, np);
@@ -430,7 +453,11 @@ static int __init ingenic_tcu_probe(struct device_node *np)
goto err_unregister_ost_clock;
}
- ingenic_tcu = tcu;
+ if (IS_ENABLED(CONFIG_PM_SLEEP)) {
+ tcu->syscore.ops = &tcu_pm_ops;
+ tcu->syscore.data = tcu;
+ register_syscore(&tcu->syscore);
+ }
return 0;
@@ -455,42 +482,12 @@ static int __init ingenic_tcu_probe(struct device_node *np)
return ret;
}
-static int __maybe_unused tcu_pm_suspend(void *data)
-{
- struct ingenic_tcu *tcu = ingenic_tcu;
-
- if (tcu->clk)
- clk_disable(tcu->clk);
-
- return 0;
-}
-
-static void __maybe_unused tcu_pm_resume(void *data)
-{
- struct ingenic_tcu *tcu = ingenic_tcu;
-
- if (tcu->clk)
- clk_enable(tcu->clk);
-}
-
-static const struct syscore_ops __maybe_unused tcu_pm_ops = {
- .suspend = tcu_pm_suspend,
- .resume = tcu_pm_resume,
-};
-
-static struct syscore __maybe_unused tcu_pm = {
- .ops = &tcu_pm_ops,
-};
-
static void __init ingenic_tcu_init(struct device_node *np)
{
int ret = ingenic_tcu_probe(np);
if (ret)
pr_crit("Failed to initialize TCU clocks: %d\n", ret);
-
- if (IS_ENABLED(CONFIG_PM_SLEEP))
- register_syscore(&tcu_pm);
}
CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-tcu", ingenic_tcu_init);
--
2.51.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 5/7] clk: mvebu: Use contextual data instead of global variable
2025-10-29 16:33 [PATCH v3 0/7] syscore: Pass context data to callbacks Thierry Reding
` (2 preceding siblings ...)
2025-10-29 16:33 ` [PATCH v3 4/7] clk: ingenic: tcu: " Thierry Reding
@ 2025-10-29 16:33 ` Thierry Reding
2025-10-29 16:33 ` [PATCH v3 6/7] irqchip/irq-imx-gpcv2: " Thierry Reding
` (2 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Thierry Reding @ 2025-10-29 16:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki
Cc: x86, linux-arm-kernel, linux-riscv, linux-mips, loongarch,
linuxppc-dev, linux-sh, linux-pci, linux-acpi, linux-kernel
From: Thierry Reding <treding@nvidia.com>
Pass the driver-specific data via the syscore struct and use it in the
syscore ops.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v3:
- adjust for API changes and update commit message
drivers/clk/mvebu/common.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index 5adbbd91a6db..8797de93472c 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -189,6 +189,7 @@ void __init mvebu_coreclk_setup(struct device_node *np,
DEFINE_SPINLOCK(ctrl_gating_lock);
struct clk_gating_ctrl {
+ struct syscore syscore;
spinlock_t *lock;
struct clk **gates;
int num_gates;
@@ -196,11 +197,10 @@ struct clk_gating_ctrl {
u32 saved_reg;
};
-static struct clk_gating_ctrl *ctrl;
-
static struct clk *clk_gating_get_src(
struct of_phandle_args *clkspec, void *data)
{
+ struct clk_gating_ctrl *ctrl = data;
int n;
if (clkspec->args_count < 1)
@@ -217,12 +217,16 @@ static struct clk *clk_gating_get_src(
static int mvebu_clk_gating_suspend(void *data)
{
+ struct clk_gating_ctrl *ctrl = data;
+
ctrl->saved_reg = readl(ctrl->base);
return 0;
}
static void mvebu_clk_gating_resume(void *data)
{
+ struct clk_gating_ctrl *ctrl = data;
+
writel(ctrl->saved_reg, ctrl->base);
}
@@ -231,13 +235,10 @@ static const struct syscore_ops clk_gate_syscore_ops = {
.resume = mvebu_clk_gating_resume,
};
-static struct syscore clk_gate_syscore = {
- .ops = &clk_gate_syscore_ops,
-};
-
void __init mvebu_clk_gating_setup(struct device_node *np,
const struct clk_gating_soc_desc *desc)
{
+ static struct clk_gating_ctrl *ctrl;
struct clk *clk;
void __iomem *base;
const char *default_parent = NULL;
@@ -288,7 +289,9 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
of_clk_add_provider(np, clk_gating_get_src, ctrl);
- register_syscore(&clk_gate_syscore);
+ ctrl->syscore.ops = &clk_gate_syscore_ops;
+ ctrl->syscore.data = ctrl;
+ register_syscore(&ctrl->syscore);
return;
gates_out:
--
2.51.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 6/7] irqchip/irq-imx-gpcv2: Use contextual data instead of global variable
2025-10-29 16:33 [PATCH v3 0/7] syscore: Pass context data to callbacks Thierry Reding
` (3 preceding siblings ...)
2025-10-29 16:33 ` [PATCH v3 5/7] clk: mvebu: " Thierry Reding
@ 2025-10-29 16:33 ` Thierry Reding
2025-10-29 16:33 ` [PATCH v3 7/7] soc/tegra: pmc: " Thierry Reding
[not found] ` <20251029163336.2785270-2-thierry.reding@gmail.com>
6 siblings, 0 replies; 16+ messages in thread
From: Thierry Reding @ 2025-10-29 16:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki
Cc: x86, linux-arm-kernel, linux-riscv, linux-mips, loongarch,
linuxppc-dev, linux-sh, linux-pci, linux-acpi, linux-kernel
From: Thierry Reding <treding@nvidia.com>
Pass the driver-specific data via the syscore struct and use it in the
syscore ops.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v3:
- adjust for API changes and update commit message
- remove unused global variable
drivers/irqchip/irq-imx-gpcv2.c | 24 ++++++------------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index 04f7ba0657be..ebfc659af385 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -19,6 +19,7 @@
struct gpcv2_irqchip_data {
+ struct syscore syscore;
struct raw_spinlock rlock;
void __iomem *gpc_base;
u32 wakeup_sources[IMR_NUM];
@@ -26,8 +27,6 @@ struct gpcv2_irqchip_data {
u32 cpu2wakeup;
};
-static struct gpcv2_irqchip_data *imx_gpcv2_instance __ro_after_init;
-
static void __iomem *gpcv2_idx_to_reg(struct gpcv2_irqchip_data *cd, int i)
{
return cd->gpc_base + cd->cpu2wakeup + i * 4;
@@ -35,14 +34,10 @@ static void __iomem *gpcv2_idx_to_reg(struct gpcv2_irqchip_data *cd, int i)
static int gpcv2_wakeup_source_save(void *data)
{
- struct gpcv2_irqchip_data *cd;
+ struct gpcv2_irqchip_data *cd = data;
void __iomem *reg;
int i;
- cd = imx_gpcv2_instance;
- if (!cd)
- return 0;
-
for (i = 0; i < IMR_NUM; i++) {
reg = gpcv2_idx_to_reg(cd, i);
cd->saved_irq_mask[i] = readl_relaxed(reg);
@@ -54,13 +49,9 @@ static int gpcv2_wakeup_source_save(void *data)
static void gpcv2_wakeup_source_restore(void *data)
{
- struct gpcv2_irqchip_data *cd;
+ struct gpcv2_irqchip_data *cd = data;
int i;
- cd = imx_gpcv2_instance;
- if (!cd)
- return;
-
for (i = 0; i < IMR_NUM; i++)
writel_relaxed(cd->saved_irq_mask[i], gpcv2_idx_to_reg(cd, i));
}
@@ -70,10 +61,6 @@ static const struct syscore_ops gpcv2_syscore_ops = {
.resume = gpcv2_wakeup_source_restore,
};
-static struct syscore gpcv2_syscore = {
- .ops = &gpcv2_syscore_ops,
-};
-
static int imx_gpcv2_irq_set_wake(struct irq_data *d, unsigned int on)
{
struct gpcv2_irqchip_data *cd = d->chip_data;
@@ -279,8 +266,9 @@ static int __init imx_gpcv2_irqchip_init(struct device_node *node,
*/
writel_relaxed(~0x1, cd->gpc_base + cd->cpu2wakeup);
- imx_gpcv2_instance = cd;
- register_syscore(&gpcv2_syscore);
+ cd->syscore.ops = &gpcv2_syscore_ops;
+ cd->syscore.data = cd;
+ register_syscore(&cd->syscore);
/*
* Clear the OF_POPULATED flag set in of_irq_init so that
--
2.51.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 7/7] soc/tegra: pmc: Use contextual data instead of global variable
2025-10-29 16:33 [PATCH v3 0/7] syscore: Pass context data to callbacks Thierry Reding
` (4 preceding siblings ...)
2025-10-29 16:33 ` [PATCH v3 6/7] irqchip/irq-imx-gpcv2: " Thierry Reding
@ 2025-10-29 16:33 ` Thierry Reding
[not found] ` <20251029163336.2785270-2-thierry.reding@gmail.com>
6 siblings, 0 replies; 16+ messages in thread
From: Thierry Reding @ 2025-10-29 16:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki
Cc: x86, linux-arm-kernel, linux-riscv, linux-mips, loongarch,
linuxppc-dev, linux-sh, linux-pci, linux-acpi, linux-kernel
From: Thierry Reding <treding@nvidia.com>
Pass the driver-specific data via the syscore struct and use it in the
syscore ops.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v3:
- adjust for API changes and update commit message
drivers/soc/tegra/pmc.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index f57e5a4b4d96..6e0ae0ede263 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -3150,6 +3150,7 @@ static void tegra186_pmc_process_wake_events(struct tegra_pmc *pmc, unsigned int
static void tegra186_pmc_wake_syscore_resume(void *data)
{
+ struct tegra_pmc *pmc = data;
u32 status, mask;
unsigned int i;
@@ -3163,6 +3164,8 @@ static void tegra186_pmc_wake_syscore_resume(void *data)
static int tegra186_pmc_wake_syscore_suspend(void *data)
{
+ struct tegra_pmc *pmc = data;
+
wke_read_sw_wake_status(pmc);
/* flip the wakeup trigger for dual-edge triggered pads
@@ -3836,6 +3839,7 @@ static const struct tegra_pmc_regs tegra186_pmc_regs = {
static void tegra186_pmc_init(struct tegra_pmc *pmc)
{
pmc->syscore.ops = &tegra186_pmc_wake_syscore_ops;
+ pmc->syscore.data = pmc;
register_syscore(&pmc->syscore);
}
--
2.51.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable
2025-10-29 16:33 ` [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable Thierry Reding
@ 2025-10-29 17:46 ` Bjorn Helgaas
2025-10-30 12:16 ` Thierry Reding
0 siblings, 1 reply; 16+ messages in thread
From: Bjorn Helgaas @ 2025-10-29 17:46 UTC (permalink / raw)
To: Thierry Reding
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, x86, linux-arm-kernel,
linux-riscv, linux-mips, loongarch, linuxppc-dev, linux-sh,
linux-pci, linux-acpi, linux-kernel
On Wed, Oct 29, 2025 at 05:33:31PM +0100, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Pass the driver-specific data via the syscore struct and use it in the
> syscore ops.
Would be nice to include the "instead of global variable" part here so
the commit log includes the benefit and can stand alone even without
the subject.
Awesome to get rid of another global variable! More comments below.
> +++ b/arch/mips/pci/pci-alchemy.c
> @@ -33,6 +33,7 @@
>
> struct alchemy_pci_context {
> struct pci_controller alchemy_pci_ctrl; /* leave as first member! */
> + struct syscore syscore;
> void __iomem *regs; /* ctrl base */
> /* tools for wired entry for config space access */
> unsigned long last_elo0;
> @@ -46,12 +47,6 @@ struct alchemy_pci_context {
> int (*board_pci_idsel)(unsigned int devsel, int assert);
> };
>
> -/* for syscore_ops. There's only one PCI controller on Alchemy chips, so this
> - * should suffice for now.
> - */
> -static struct alchemy_pci_context *__alchemy_pci_ctx;
> -
> -
> /* IO/MEM resources for PCI. Keep the memres in sync with fixup_bigphys_addr
> * in arch/mips/alchemy/common/setup.c
> */
> @@ -306,9 +301,7 @@ static int alchemy_pci_def_idsel(unsigned int devsel, int assert)
> /* save PCI controller register contents. */
> static int alchemy_pci_suspend(void *data)
> {
> - struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
> - if (!ctx)
> - return 0;
> + struct alchemy_pci_context *ctx = data;
>
> ctx->pm[0] = __raw_readl(ctx->regs + PCI_REG_CMEM);
> ctx->pm[1] = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009ffff;
> @@ -328,9 +321,7 @@ static int alchemy_pci_suspend(void *data)
>
> static void alchemy_pci_resume(void *data)
> {
> - struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
> - if (!ctx)
> - return;
> + struct alchemy_pci_context *ctx = data;
>
> __raw_writel(ctx->pm[0], ctx->regs + PCI_REG_CMEM);
> __raw_writel(ctx->pm[2], ctx->regs + PCI_REG_B2BMASK_CCH);
> @@ -359,10 +350,6 @@ static const struct syscore_ops alchemy_pci_syscore_ops = {
> .resume = alchemy_pci_resume,
> };
>
> -static struct syscore alchemy_pci_syscore = {
> - .ops = &alchemy_pci_syscore_ops,
> -};
> -
> static int alchemy_pci_probe(struct platform_device *pdev)
> {
> struct alchemy_pci_platdata *pd = pdev->dev.platform_data;
> @@ -480,9 +467,10 @@ static int alchemy_pci_probe(struct platform_device *pdev)
> __raw_writel(val, ctx->regs + PCI_REG_CONFIG);
> wmb();
>
> - __alchemy_pci_ctx = ctx;
> platform_set_drvdata(pdev, ctx);
> - register_syscore(&alchemy_pci_syscore);
> + ctx->syscore.ops = &alchemy_pci_syscore_ops;
> + ctx->syscore.data = ctx;
> + register_syscore(&ctx->syscore);
As far as I can tell, the only use of syscore in this driver is for
suspend/resume.
This is a regular platform_device driver, so instead of syscore, I
think it should use generic power management like other PCI host
controller drivers do, something like this:
static int alchemy_pci_suspend_noirq(struct device *dev)
...
static int alchemy_pci_resume_noirq(struct device *dev)
...
static DEFINE_NOIRQ_DEV_PM_OPS(alchemy_pci_pm_ops,
alchemy_pci_suspend_noirq,
alchemy_pci_resume_noirq);
static struct platform_driver alchemy_pcictl_driver = {
.probe = alchemy_pci_probe,
.driver = {
.name = "alchemy-pci",
.pm = pm_sleep_ptr(&alchemy_pci_pm_ops),
},
};
Here's a sample in another driver:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/controller/cadence/pci-j721e.c?id=v6.17#n663
> register_pci_controller(&ctx->alchemy_pci_ctrl);
>
> dev_info(&pdev->dev, "PCI controller at %ld MHz\n",
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 4/7] clk: ingenic: tcu: Use contextual data instead of global variable
2025-10-29 16:33 ` [PATCH v3 4/7] clk: ingenic: tcu: " Thierry Reding
@ 2025-10-29 17:56 ` Bjorn Helgaas
2025-10-30 12:28 ` Thierry Reding
0 siblings, 1 reply; 16+ messages in thread
From: Bjorn Helgaas @ 2025-10-29 17:56 UTC (permalink / raw)
To: Thierry Reding
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, x86, linux-arm-kernel,
linux-riscv, linux-mips, loongarch, linuxppc-dev, linux-sh,
linux-pci, linux-acpi, linux-kernel
On Wed, Oct 29, 2025 at 05:33:33PM +0100, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Pass the driver-specific data via the syscore struct and use it in the
> syscore ops.
Some of these things in drivers/clk/ are also platform_device drivers
(though not this one) and use generic power management, e.g.,
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clk/qcom/q6sstop-qcs404.c?id=v6.17#n209
I have no idea if that's desirable or practical here, but using the
platform_device model instead of syscore could have advantages in
terms of modeling device dependencies and ordering.
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> Changes in v3:
> - adjust for API changes and update commit message
>
> drivers/clk/ingenic/tcu.c | 63 +++++++++++++++++++--------------------
> 1 file changed, 30 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c
> index bc6a51da2072..8c6337d8e831 100644
> --- a/drivers/clk/ingenic/tcu.c
> +++ b/drivers/clk/ingenic/tcu.c
> @@ -53,9 +53,9 @@ struct ingenic_tcu {
> struct clk *clk;
>
> struct clk_hw_onecell_data *clocks;
> -};
>
> -static struct ingenic_tcu *ingenic_tcu;
> + struct syscore syscore;
> +};
>
> static inline struct ingenic_tcu_clk *to_tcu_clk(struct clk_hw *hw)
> {
> @@ -332,6 +332,29 @@ static const struct of_device_id __maybe_unused ingenic_tcu_of_match[] __initcon
> { /* sentinel */ }
> };
>
> +static int __maybe_unused tcu_pm_suspend(void *data)
> +{
> + struct ingenic_tcu *tcu = data;
> +
> + if (tcu->clk)
> + clk_disable(tcu->clk);
> +
> + return 0;
> +}
> +
> +static void __maybe_unused tcu_pm_resume(void *data)
> +{
> + struct ingenic_tcu *tcu = data;
> +
> + if (tcu->clk)
> + clk_enable(tcu->clk);
> +}
> +
> +static const struct syscore_ops tcu_pm_ops __maybe_unused = {
> + .suspend = tcu_pm_suspend,
> + .resume = tcu_pm_resume,
> +};
> +
> static int __init ingenic_tcu_probe(struct device_node *np)
> {
> const struct of_device_id *id = of_match_node(ingenic_tcu_of_match, np);
> @@ -430,7 +453,11 @@ static int __init ingenic_tcu_probe(struct device_node *np)
> goto err_unregister_ost_clock;
> }
>
> - ingenic_tcu = tcu;
> + if (IS_ENABLED(CONFIG_PM_SLEEP)) {
> + tcu->syscore.ops = &tcu_pm_ops;
> + tcu->syscore.data = tcu;
> + register_syscore(&tcu->syscore);
> + }
>
> return 0;
>
> @@ -455,42 +482,12 @@ static int __init ingenic_tcu_probe(struct device_node *np)
> return ret;
> }
>
> -static int __maybe_unused tcu_pm_suspend(void *data)
> -{
> - struct ingenic_tcu *tcu = ingenic_tcu;
> -
> - if (tcu->clk)
> - clk_disable(tcu->clk);
> -
> - return 0;
> -}
> -
> -static void __maybe_unused tcu_pm_resume(void *data)
> -{
> - struct ingenic_tcu *tcu = ingenic_tcu;
> -
> - if (tcu->clk)
> - clk_enable(tcu->clk);
> -}
> -
> -static const struct syscore_ops __maybe_unused tcu_pm_ops = {
> - .suspend = tcu_pm_suspend,
> - .resume = tcu_pm_resume,
> -};
> -
> -static struct syscore __maybe_unused tcu_pm = {
> - .ops = &tcu_pm_ops,
> -};
> -
> static void __init ingenic_tcu_init(struct device_node *np)
> {
> int ret = ingenic_tcu_probe(np);
>
> if (ret)
> pr_crit("Failed to initialize TCU clocks: %d\n", ret);
> -
> - if (IS_ENABLED(CONFIG_PM_SLEEP))
> - register_syscore(&tcu_pm);
> }
>
> CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-tcu", ingenic_tcu_init);
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable
2025-10-29 17:46 ` Bjorn Helgaas
@ 2025-10-30 12:16 ` Thierry Reding
2025-10-30 15:31 ` Bjorn Helgaas
0 siblings, 1 reply; 16+ messages in thread
From: Thierry Reding @ 2025-10-30 12:16 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, x86, linux-arm-kernel,
linux-riscv, linux-mips, loongarch, linuxppc-dev, linux-sh,
linux-pci, linux-acpi, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 5045 bytes --]
On Wed, Oct 29, 2025 at 12:46:54PM -0500, Bjorn Helgaas wrote:
> On Wed, Oct 29, 2025 at 05:33:31PM +0100, Thierry Reding wrote:
> > From: Thierry Reding <treding@nvidia.com>
> >
> > Pass the driver-specific data via the syscore struct and use it in the
> > syscore ops.
>
> Would be nice to include the "instead of global variable" part here so
> the commit log includes the benefit and can stand alone even without
> the subject.
Good point.
> Awesome to get rid of another global variable! More comments below.
\o/
> > +++ b/arch/mips/pci/pci-alchemy.c
> > @@ -33,6 +33,7 @@
> >
> > struct alchemy_pci_context {
> > struct pci_controller alchemy_pci_ctrl; /* leave as first member! */
> > + struct syscore syscore;
> > void __iomem *regs; /* ctrl base */
> > /* tools for wired entry for config space access */
> > unsigned long last_elo0;
> > @@ -46,12 +47,6 @@ struct alchemy_pci_context {
> > int (*board_pci_idsel)(unsigned int devsel, int assert);
> > };
> >
> > -/* for syscore_ops. There's only one PCI controller on Alchemy chips, so this
> > - * should suffice for now.
> > - */
> > -static struct alchemy_pci_context *__alchemy_pci_ctx;
> > -
> > -
> > /* IO/MEM resources for PCI. Keep the memres in sync with fixup_bigphys_addr
> > * in arch/mips/alchemy/common/setup.c
> > */
> > @@ -306,9 +301,7 @@ static int alchemy_pci_def_idsel(unsigned int devsel, int assert)
> > /* save PCI controller register contents. */
> > static int alchemy_pci_suspend(void *data)
> > {
> > - struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
> > - if (!ctx)
> > - return 0;
> > + struct alchemy_pci_context *ctx = data;
> >
> > ctx->pm[0] = __raw_readl(ctx->regs + PCI_REG_CMEM);
> > ctx->pm[1] = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009ffff;
> > @@ -328,9 +321,7 @@ static int alchemy_pci_suspend(void *data)
> >
> > static void alchemy_pci_resume(void *data)
> > {
> > - struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
> > - if (!ctx)
> > - return;
> > + struct alchemy_pci_context *ctx = data;
> >
> > __raw_writel(ctx->pm[0], ctx->regs + PCI_REG_CMEM);
> > __raw_writel(ctx->pm[2], ctx->regs + PCI_REG_B2BMASK_CCH);
> > @@ -359,10 +350,6 @@ static const struct syscore_ops alchemy_pci_syscore_ops = {
> > .resume = alchemy_pci_resume,
> > };
> >
> > -static struct syscore alchemy_pci_syscore = {
> > - .ops = &alchemy_pci_syscore_ops,
> > -};
> > -
> > static int alchemy_pci_probe(struct platform_device *pdev)
> > {
> > struct alchemy_pci_platdata *pd = pdev->dev.platform_data;
> > @@ -480,9 +467,10 @@ static int alchemy_pci_probe(struct platform_device *pdev)
> > __raw_writel(val, ctx->regs + PCI_REG_CONFIG);
> > wmb();
> >
> > - __alchemy_pci_ctx = ctx;
> > platform_set_drvdata(pdev, ctx);
> > - register_syscore(&alchemy_pci_syscore);
> > + ctx->syscore.ops = &alchemy_pci_syscore_ops;
> > + ctx->syscore.data = ctx;
> > + register_syscore(&ctx->syscore);
>
> As far as I can tell, the only use of syscore in this driver is for
> suspend/resume.
>
> This is a regular platform_device driver, so instead of syscore, I
> think it should use generic power management like other PCI host
> controller drivers do, something like this:
>
> static int alchemy_pci_suspend_noirq(struct device *dev)
> ...
>
> static int alchemy_pci_resume_noirq(struct device *dev)
> ...
>
> static DEFINE_NOIRQ_DEV_PM_OPS(alchemy_pci_pm_ops,
> alchemy_pci_suspend_noirq,
> alchemy_pci_resume_noirq);
>
> static struct platform_driver alchemy_pcictl_driver = {
> .probe = alchemy_pci_probe,
> .driver = {
> .name = "alchemy-pci",
> .pm = pm_sleep_ptr(&alchemy_pci_pm_ops),
> },
> };
>
> Here's a sample in another driver:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/controller/cadence/pci-j721e.c?id=v6.17#n663
I thought so too, but then I looked at the history and saw that it was
initially regular PM ops and then fixed by using syscore in this commit:
commit 864c6c22e9a5742b0f43c983b6c405d52817bacd
Author: Manuel Lauss <manuel.lauss@googlemail.com>
Date: Wed Nov 16 15:42:28 2011 +0100
MIPS: Alchemy: Fix PCI PM
Move PCI Controller PM to syscore_ops since the platform_driver PM methods
are called way too late on resume and far too early on suspend (after and
before PCI device resume/suspend).
This also allows to simplify wired entry management a bit.
Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3007/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
So unfortunately I don't think it'll work for this driver.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 4/7] clk: ingenic: tcu: Use contextual data instead of global variable
2025-10-29 17:56 ` Bjorn Helgaas
@ 2025-10-30 12:28 ` Thierry Reding
0 siblings, 0 replies; 16+ messages in thread
From: Thierry Reding @ 2025-10-30 12:28 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, x86, linux-arm-kernel,
linux-riscv, linux-mips, loongarch, linuxppc-dev, linux-sh,
linux-pci, linux-acpi, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 2041 bytes --]
On Wed, Oct 29, 2025 at 12:56:47PM -0500, Bjorn Helgaas wrote:
> On Wed, Oct 29, 2025 at 05:33:33PM +0100, Thierry Reding wrote:
> > From: Thierry Reding <treding@nvidia.com>
> >
> > Pass the driver-specific data via the syscore struct and use it in the
> > syscore ops.
>
> Some of these things in drivers/clk/ are also platform_device drivers
> (though not this one) and use generic power management, e.g.,
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clk/qcom/q6sstop-qcs404.c?id=v6.17#n209
>
> I have no idea if that's desirable or practical here, but using the
> platform_device model instead of syscore could have advantages in
> terms of modeling device dependencies and ordering.
Similar to the MIPS/Alchemy PCI driver, although there's no git log
reference in this case, I suspect this was not in driver PM on purpose.
The pattern I've seen quite often is very low-level device driver code
doing this using syscore_ops because they run very late/early during
suspend/resume, respectively, so the driver PM callbacks often aren't
sufficient.
In recent years, some of the issues have been alleviated by things such
as device links, so a conversion may work now.
However, often these are also exotic and/or old devices that are
difficult to find testers for, so I've been trying to keep the changes
in this series as minimal as possible, so that we can be reasonably sure
things will continue to work just by reviewing the code.
The most important bit in the series is patch 1, which lays the
groundwork for avoiding these global variables for new code. Also, in
particular I have a concrete case where the global variable approach
doesn't work because an IP block that used to be a guaranteed singleton
now no longer is.
I have looked at various drivers that I ended up not converting because
they use a global variable not only for syscore but also for other
things and fixing that up would've been way out of scope of this series.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable
2025-10-30 12:16 ` Thierry Reding
@ 2025-10-30 15:31 ` Bjorn Helgaas
2025-10-30 20:10 ` Maciej W. Rozycki
0 siblings, 1 reply; 16+ messages in thread
From: Bjorn Helgaas @ 2025-10-30 15:31 UTC (permalink / raw)
To: Thierry Reding
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, x86, linux-arm-kernel,
linux-riscv, linux-mips, loongarch, linuxppc-dev, linux-sh,
linux-pci, linux-acpi, linux-kernel
On Thu, Oct 30, 2025 at 01:16:12PM +0100, Thierry Reding wrote:
> On Wed, Oct 29, 2025 at 12:46:54PM -0500, Bjorn Helgaas wrote:
> > On Wed, Oct 29, 2025 at 05:33:31PM +0100, Thierry Reding wrote:
> > > From: Thierry Reding <treding@nvidia.com>
> > >
> > > Pass the driver-specific data via the syscore struct and use it in the
> > > syscore ops.
> > > +++ b/arch/mips/pci/pci-alchemy.c
> > > @@ -33,6 +33,7 @@
> > >
> > > struct alchemy_pci_context {
> > > struct pci_controller alchemy_pci_ctrl; /* leave as first member! */
> > > + struct syscore syscore;
> > > void __iomem *regs; /* ctrl base */
> > > /* tools for wired entry for config space access */
> > > unsigned long last_elo0;
> > > @@ -46,12 +47,6 @@ struct alchemy_pci_context {
> > > int (*board_pci_idsel)(unsigned int devsel, int assert);
> > > };
> > >
> > > -/* for syscore_ops. There's only one PCI controller on Alchemy chips, so this
> > > - * should suffice for now.
> > > - */
> > > -static struct alchemy_pci_context *__alchemy_pci_ctx;
> > > -
> > > -
> > > /* IO/MEM resources for PCI. Keep the memres in sync with fixup_bigphys_addr
> > > * in arch/mips/alchemy/common/setup.c
> > > */
> > > @@ -306,9 +301,7 @@ static int alchemy_pci_def_idsel(unsigned int devsel, int assert)
> > > /* save PCI controller register contents. */
> > > static int alchemy_pci_suspend(void *data)
> > > {
> > > - struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
> > > - if (!ctx)
> > > - return 0;
> > > + struct alchemy_pci_context *ctx = data;
> > >
> > > ctx->pm[0] = __raw_readl(ctx->regs + PCI_REG_CMEM);
> > > ctx->pm[1] = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009ffff;
> > > @@ -328,9 +321,7 @@ static int alchemy_pci_suspend(void *data)
> > >
> > > static void alchemy_pci_resume(void *data)
> > > {
> > > - struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
> > > - if (!ctx)
> > > - return;
> > > + struct alchemy_pci_context *ctx = data;
> > >
> > > __raw_writel(ctx->pm[0], ctx->regs + PCI_REG_CMEM);
> > > __raw_writel(ctx->pm[2], ctx->regs + PCI_REG_B2BMASK_CCH);
> > > @@ -359,10 +350,6 @@ static const struct syscore_ops alchemy_pci_syscore_ops = {
> > > .resume = alchemy_pci_resume,
> > > };
> > >
> > > -static struct syscore alchemy_pci_syscore = {
> > > - .ops = &alchemy_pci_syscore_ops,
> > > -};
> > > -
> > > static int alchemy_pci_probe(struct platform_device *pdev)
> > > {
> > > struct alchemy_pci_platdata *pd = pdev->dev.platform_data;
> > > @@ -480,9 +467,10 @@ static int alchemy_pci_probe(struct platform_device *pdev)
> > > __raw_writel(val, ctx->regs + PCI_REG_CONFIG);
> > > wmb();
> > >
> > > - __alchemy_pci_ctx = ctx;
> > > platform_set_drvdata(pdev, ctx);
> > > - register_syscore(&alchemy_pci_syscore);
> > > + ctx->syscore.ops = &alchemy_pci_syscore_ops;
> > > + ctx->syscore.data = ctx;
> > > + register_syscore(&ctx->syscore);
> >
> > As far as I can tell, the only use of syscore in this driver is for
> > suspend/resume.
> >
> > This is a regular platform_device driver, so instead of syscore, I
> > think it should use generic power management like other PCI host
> > controller drivers do, something like this:
> >
> > static int alchemy_pci_suspend_noirq(struct device *dev)
> > ...
> >
> > static int alchemy_pci_resume_noirq(struct device *dev)
> > ...
> >
> > static DEFINE_NOIRQ_DEV_PM_OPS(alchemy_pci_pm_ops,
> > alchemy_pci_suspend_noirq,
> > alchemy_pci_resume_noirq);
> >
> > static struct platform_driver alchemy_pcictl_driver = {
> > .probe = alchemy_pci_probe,
> > .driver = {
> > .name = "alchemy-pci",
> > .pm = pm_sleep_ptr(&alchemy_pci_pm_ops),
> > },
> > };
> >
> > Here's a sample in another driver:
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/controller/cadence/pci-j721e.c?id=v6.17#n663
>
> I thought so too, but then I looked at the history and saw that it was
> initially regular PM ops and then fixed by using syscore in this commit:
>
> commit 864c6c22e9a5742b0f43c983b6c405d52817bacd
> Author: Manuel Lauss <manuel.lauss@googlemail.com>
> Date: Wed Nov 16 15:42:28 2011 +0100
>
> MIPS: Alchemy: Fix PCI PM
>
> Move PCI Controller PM to syscore_ops since the platform_driver PM methods
> are called way too late on resume and far too early on suspend (after and
> before PCI device resume/suspend).
> This also allows to simplify wired entry management a bit.
>
> Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
> Cc: linux-mips@linux-mips.org
> Patchwork: https://patchwork.linux-mips.org/patch/3007/
> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
The alchemy PCI controller is a platform_device, and it must be
initialized before enumerating the PCI devices below it. The same
order should apply for suspend/resume (suspend PCI devices, then PCI
controller; resume PCI controller, then PCI devices).
So if this didn't work before, I think it means something is messed up
with the device hierarchy.
But I understand the difficulty of testing changes here, so syscore is
simplest from that point of view.
It does complicate maintenance though. I think all of mips ultimately
uses register_pci_controller() and pcibios_scanbus(). Neither really
contains anything mips-specific, so they duplicate a lot of the code
in pci_host_probe(). Oh well, I guess that's part of the burden of
supporting old platforms forever.
Bjorn
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable
2025-10-30 15:31 ` Bjorn Helgaas
@ 2025-10-30 20:10 ` Maciej W. Rozycki
0 siblings, 0 replies; 16+ messages in thread
From: Maciej W. Rozycki @ 2025-10-30 20:10 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Thomas Bogendoerfer, Thierry Reding, Greg Kroah-Hartman,
Rafael J. Wysocki, x86, linux-arm-kernel, linux-riscv, linux-mips,
loongarch, linuxppc-dev, linux-sh, linux-pci, linux-acpi,
linux-kernel
On Thu, 30 Oct 2025, Bjorn Helgaas wrote:
> It does complicate maintenance though. I think all of mips ultimately
> uses register_pci_controller() and pcibios_scanbus(). Neither really
> contains anything mips-specific, so they duplicate a lot of the code
> in pci_host_probe(). Oh well, I guess that's part of the burden of
> supporting old platforms forever.
FWIW new MIPS hardware continues being manufactured and if there is
anything needed to clean up in generic MIPS/PCI platform code, then that
can certainly be scheduled, subject to developers' resource availability.
Individual MIPS platforms may vary of course, and with the solely legacy
ones it will depend on the availability of hardware and engineers willing
to maintain it.
Maciej
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 1/7] syscore: Pass context data to callbacks
[not found] ` <CAJZ5v0igMJ12KoYCmrWauvOfdxaNP5-XVKoSxUroaKFN7S-rTQ@mail.gmail.com>
@ 2025-11-05 16:52 ` Thierry Reding
2025-11-13 18:32 ` Thierry Reding
0 siblings, 1 reply; 16+ messages in thread
From: Thierry Reding @ 2025-11-05 16:52 UTC (permalink / raw)
To: Rafael J. Wysocki, Greg Kroah-Hartman
Cc: x86, linux-arm-kernel, linux-riscv, linux-mips, loongarch,
linuxppc-dev, linux-sh, linux-pci, linux-acpi, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1264 bytes --]
On Mon, Nov 03, 2025 at 05:18:08PM +0100, Rafael J. Wysocki wrote:
> On Wed, Oct 29, 2025 at 5:33 PM Thierry Reding <thierry.reding@gmail.com> wrote:
> >
> > From: Thierry Reding <treding@nvidia.com>
> >
> > Several drivers can benefit from registering per-instance data along
> > with the syscore operations. To achieve this, move the modifiable fields
> > out of the syscore_ops structure and into a separate struct syscore that
> > can be registered with the framework. Add a void * driver data field for
> > drivers to store contextual data that will be passed to the syscore ops.
> >
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
>
> This change is fine with me, so I can apply it unless somebody has any
> specific heartburn related to it (Greg?), but in case you want to
> route it differently
>
> Acked-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
I have a few follow-up patches for the Tegra PMC driver that depend on
this. 6.19 is what I was targetting, so if we could put this into a
stable branch that'd be the best solution. I can set that up via the
Tegra tree if you and Greg are okay with it.
If that's all too complicated, I can probably wait until the next cycle
to merge the PMC changes.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 1/7] syscore: Pass context data to callbacks
2025-11-05 16:52 ` [PATCH v3 1/7] syscore: Pass context data to callbacks Thierry Reding
@ 2025-11-13 18:32 ` Thierry Reding
2025-11-13 19:18 ` Rafael J. Wysocki
0 siblings, 1 reply; 16+ messages in thread
From: Thierry Reding @ 2025-11-13 18:32 UTC (permalink / raw)
To: Rafael J. Wysocki, Greg Kroah-Hartman
Cc: x86, linux-arm-kernel, linux-riscv, linux-mips, loongarch,
linuxppc-dev, linux-sh, linux-pci, linux-acpi, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1739 bytes --]
On Wed, Nov 05, 2025 at 05:52:01PM +0100, Thierry Reding wrote:
> On Mon, Nov 03, 2025 at 05:18:08PM +0100, Rafael J. Wysocki wrote:
> > On Wed, Oct 29, 2025 at 5:33 PM Thierry Reding <thierry.reding@gmail.com> wrote:
> > >
> > > From: Thierry Reding <treding@nvidia.com>
> > >
> > > Several drivers can benefit from registering per-instance data along
> > > with the syscore operations. To achieve this, move the modifiable fields
> > > out of the syscore_ops structure and into a separate struct syscore that
> > > can be registered with the framework. Add a void * driver data field for
> > > drivers to store contextual data that will be passed to the syscore ops.
> > >
> > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> >
> > This change is fine with me, so I can apply it unless somebody has any
> > specific heartburn related to it (Greg?), but in case you want to
> > route it differently
> >
> > Acked-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
>
> I have a few follow-up patches for the Tegra PMC driver that depend on
> this. 6.19 is what I was targetting, so if we could put this into a
> stable branch that'd be the best solution. I can set that up via the
> Tegra tree if you and Greg are okay with it.
>
> If that's all too complicated, I can probably wait until the next cycle
> to merge the PMC changes.
I've added this single patch to a branch based off of v6.18-rc1 that I
plan to feed into linux-next so it can get some broader exposure.
I can keep that branch stable so it can go through multiple trees if
needed. If anyone's interested, the branch is here:
https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git/log/?h=for-6.19/syscore
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 1/7] syscore: Pass context data to callbacks
2025-11-13 18:32 ` Thierry Reding
@ 2025-11-13 19:18 ` Rafael J. Wysocki
0 siblings, 0 replies; 16+ messages in thread
From: Rafael J. Wysocki @ 2025-11-13 19:18 UTC (permalink / raw)
To: Thierry Reding
Cc: Rafael J. Wysocki, Greg Kroah-Hartman, x86, linux-arm-kernel,
linux-riscv, linux-mips, loongarch, linuxppc-dev, linux-sh,
linux-pci, linux-acpi, linux-kernel
On Thu, Nov 13, 2025 at 7:32 PM Thierry Reding <thierry.reding@gmail.com> wrote:
>
> On Wed, Nov 05, 2025 at 05:52:01PM +0100, Thierry Reding wrote:
> > On Mon, Nov 03, 2025 at 05:18:08PM +0100, Rafael J. Wysocki wrote:
> > > On Wed, Oct 29, 2025 at 5:33 PM Thierry Reding <thierry.reding@gmail.com> wrote:
> > > >
> > > > From: Thierry Reding <treding@nvidia.com>
> > > >
> > > > Several drivers can benefit from registering per-instance data along
> > > > with the syscore operations. To achieve this, move the modifiable fields
> > > > out of the syscore_ops structure and into a separate struct syscore that
> > > > can be registered with the framework. Add a void * driver data field for
> > > > drivers to store contextual data that will be passed to the syscore ops.
> > > >
> > > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > >
> > > This change is fine with me, so I can apply it unless somebody has any
> > > specific heartburn related to it (Greg?), but in case you want to
> > > route it differently
> > >
> > > Acked-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
> >
> > I have a few follow-up patches for the Tegra PMC driver that depend on
> > this. 6.19 is what I was targetting, so if we could put this into a
> > stable branch that'd be the best solution. I can set that up via the
> > Tegra tree if you and Greg are okay with it.
> >
> > If that's all too complicated, I can probably wait until the next cycle
> > to merge the PMC changes.
>
> I've added this single patch to a branch based off of v6.18-rc1 that I
> plan to feed into linux-next so it can get some broader exposure.
>
> I can keep that branch stable so it can go through multiple trees if
> needed. If anyone's interested, the branch is here:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git/log/?h=for-6.19/syscore
You beat me to this, sorry about the delay.
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-11-13 19:18 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-29 16:33 [PATCH v3 0/7] syscore: Pass context data to callbacks Thierry Reding
2025-10-29 16:33 ` [PATCH v3 2/7] MIPS: PCI: Use contextual data instead of global variable Thierry Reding
2025-10-29 17:46 ` Bjorn Helgaas
2025-10-30 12:16 ` Thierry Reding
2025-10-30 15:31 ` Bjorn Helgaas
2025-10-30 20:10 ` Maciej W. Rozycki
2025-10-29 16:33 ` [PATCH v3 3/7] bus: mvebu-mbus: " Thierry Reding
2025-10-29 16:33 ` [PATCH v3 4/7] clk: ingenic: tcu: " Thierry Reding
2025-10-29 17:56 ` Bjorn Helgaas
2025-10-30 12:28 ` Thierry Reding
2025-10-29 16:33 ` [PATCH v3 5/7] clk: mvebu: " Thierry Reding
2025-10-29 16:33 ` [PATCH v3 6/7] irqchip/irq-imx-gpcv2: " Thierry Reding
2025-10-29 16:33 ` [PATCH v3 7/7] soc/tegra: pmc: " Thierry Reding
[not found] ` <20251029163336.2785270-2-thierry.reding@gmail.com>
[not found] ` <CAJZ5v0igMJ12KoYCmrWauvOfdxaNP5-XVKoSxUroaKFN7S-rTQ@mail.gmail.com>
2025-11-05 16:52 ` [PATCH v3 1/7] syscore: Pass context data to callbacks Thierry Reding
2025-11-13 18:32 ` Thierry Reding
2025-11-13 19:18 ` Rafael J. Wysocki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).