LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [BUG] sched/cache: "Make LLC id continuous" causes NULL cpumask
From: Shrikanth Hegde @ 2026-05-27 18:07 UTC (permalink / raw)
  To: Chen, Yu C, kprateek.nayak
  Cc: srikar, venkat88, maddy, riteshh, chleroy, tim.c.chen, peterz,
	linux-kernel, linuxppc-dev, linux-sched
In-Reply-To: <912676bc-230e-410f-a5fe-153b0f304aee@intel.com>

Hi Chen, Prateek.

On 5/27/26 9:35 PM, Chen, Yu C wrote:
> Hi Shrikanth,
> 
> On 5/27/2026 3:01 PM, Shrikanth Hegde wrote:
>> Hi Chen, Prateek.
>>
>> I got back to work today, sorry for delay.
>> I am trying to go through the mails.
>> Apologies in case i have missed any bits.
>>
> 
> Thanks for taking a look at this!
> 
>> On 5/26/26 7:38 PM, Chen Yu wrote:
>>> Hi Prateek,
>>>
>>> On Tue, 26 May 2026 11:23:59 +0530, K Prateek Nayak 
>>> <kprateek.nayak@amd.com> wrote:
>>>> Hello Srikar,
>>>>
>>>> On 5/26/2026 10:28 AM, Srikar Dronamraju wrote:
>>>>> L2 Cache reported here is for SMT8 Core aka CACHE domain.
>>>>
>>>> Apart for the scheduler, nothing in tree currently cares about
>>>> cpu_coregroup_mask() except for drivers/base/arch_topology.c but
>>>> Power doesn't select GENERIC_ARCH_TOPOLOGY.
>>>>
>>>> Why can't Power have an internal mask for MC domain (tl_mc_mask) and
>>>> the scheduler can use cpu_coregroup_mask() for the actual LLc? (The L2
>>>> mask in this case.)
>>
>> This seems wrong. there is no notion that coregroup_mask
>> (MC domain) has to point at LLC domain.
>>
>> For example, on Shared LPAR, there is no MC domain and LLC is at SMT 
>> core level.
>> In that case coregroup_mask has point at SMT mask is wrong.
>>
> 
> On Shared LPAR, highest_flag_domain(SD_SHARE_LLC) selected the
> SMT domain(L2 shared)prior to commit b5ea300a17e3.
> Prateek suggested changing cpu_coregroup_mask() to use
> cpu_l2_cache_mask(), which makes the LLC mask cover the same range.
> sd_llc, size and grouping remain unchanged. Only sd_llc_id becomes
> contiguous, which aligns with the intent of this commit.
> 
> But yes, the naming is confusing. cpu_coregroup_mask suggests a
> "group of cores", but after the change, it only covers threads
> within a single SMT core.
> 

Yes. Though it might achieve the same effect, keeping it explicit may
help in maintaining it better.

On PowerPC, there are these subtleties of Shared LPAR where MC domain
per se doesn't exit etc, and on power9 and earlier has different 
topologies. Maybe one could figure it all out and simplifies them into
a few masks. But yes, it is slightly different as of today.

>> If we need a mask to point to the LLC mask which arch has to return, 
>> then we would
>> need a new api say cpu_llc_mask ? that can point accordingly.
>>
> 
> Do you mean something like this?
> https://lore.kernel.org/lkml/8d14c844-b4a8-4af6- 
> acab-2cfdd42225be@intel.com/

Yes. This is something i prefer, but not to make it point to l2 mask 
always. See below diff which now make it boot on Shared Processor LPAR
where i see panic without it.

Need to add proper comments where appropriate.

diff --git a/arch/powerpc/include/asm/topology.h 
b/arch/powerpc/include/asm/topology.h
index 66ed5fe1b718..bd1db3b1dbb0 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -131,6 +131,9 @@ static inline int cpu_to_coregroup_id(int cpu)
  #ifdef CONFIG_SMP
  #include <asm/cputable.h>

+const struct cpumask *arch_llc_mask(int cpu);
+#define arch_llc_mask  arch_llc_mask
+
  struct cpumask *cpu_coregroup_mask(int cpu);
  const struct cpumask *cpu_die_mask(int cpu);
  int cpu_die_id(int cpu);
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 3467f86fd78f..26c15c786c55 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -1101,6 +1101,13 @@ const struct cpumask *cpu_die_mask(int cpu)
  }
  EXPORT_SYMBOL_GPL(cpu_die_mask);

+const struct cpumask *arch_llc_mask(int cpu)
+{
+       if (has_coregroup_support())
+               return cpu_coregroup_mask(cpu);
+       return cpu_smallcore_mask(cpu);
+}
+
  int cpu_die_id(int cpu)
  {
         if (has_coregroup_support())
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index df2ceb54c970..3b5155121276 100644
--- a/kernel/sched/topology.c
+++ b/kernel/sched/topology.c
@@ -2063,7 +2063,11 @@ const struct cpumask *tl_mc_mask(struct 
sched_domain_topology_level *tl, int cpu
         return cpu_coregroup_mask(cpu);
  }

+#ifndef arch_llc_mask
  #define llc_mask(cpu) cpu_coregroup_mask(cpu)
+#else
+#define llc_mask(cpu) arch_llc_mask(cpu)
+#endif

  #else
  #define llc_mask(cpu) cpumask_of(cpu)

(One more subtlety; crash would be seen only with NR_CPUS=8192 as 
CPUMASK_OFFSTACK=y, but that's a different concern altogether.)


> 
>> I don't like mixing MC domain and LLC into one bit.
>>
> 
> [ ... ]
> 
>>>   struct cpumask *cpu_coregroup_mask(int cpu)
>>>   {
>>> -    return per_cpu(cpu_coregroup_map, cpu);
>>> +    return cpu_l2_cache_mask(cpu);
>>> +}
>>
>> This looks wrong to me too. In different hardware topologies
>> there maybe distinction between coregroup and l2 mask.
>>
>> Let me go through the code and see if there is better way.
>>
> 
> Sure, please go ahead - I'm on board with the direction
> you settle on.
> 
> thanks,
> Chenyu
> 



^ permalink raw reply related

* [PATCH v2 0/3] ppc/pnv: Fix panics and refactor pnv_php.c
From: Aditya Gupta @ 2026-05-27 18:08 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev, Madhavan Srinivasan, Timothy Pearson,
	Bjorn Helgaas, Shawn Anastasio
  Cc: sashiko-bot, linux-pci, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP)

Overview
========

Since below upstream commit, powernv systems get a panic during boot when an
OpenCAPI hotplug slot is detected:

  commit 80f9fc2362797538ebd4fd70a1dfa838cc2c2cdb
  Date:   Tue Jul 15 16:36:55 2025 -0500
  
      PCI: pnv_php: Work around switches with broken presence detection

The panic log is present in patch #1

Patch #1: Adds null checks around null pointer dereferences
Patch #2: Rework the driver code to separate PCIe-specific and common code
Patch #3 (optional): Group PCIe functionality together, only code movements

Note: Patch 1 is important and independent of the other patches

Note2: Patch 2 & 3 can be squashed into 1 commit. Intentionally kept patch #2 as
small as possible for ease of review.

Changelog
=========
v1 -> v2:
* Sashiko pointed out various null pointer dereferences including a kernel panic triggered by userspace, fixed them
* Add rework patches, so that PCIe-specific and common code can be separated
  cleanly

Aditya Gupta (3):
  ppc/pnv: Add null checks for OpenCapi PHBs
  ppc/pnv: Refactor PNV PCI hotplug driver
  ppc/pnv: Refactor PNV PCI Hotplug to group PCIe functions

 arch/powerpc/include/asm/pnv-pci.h |  16 +
 drivers/pci/hotplug/pnv_php.c      | 554 ++++++++++++++++-------------
 2 files changed, 328 insertions(+), 242 deletions(-)

-- 
2.54.0



^ permalink raw reply

* [PATCH v2 1/3] ppc/pnv: Add null checks for OpenCapi PHBs
From: Aditya Gupta @ 2026-05-27 18:08 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev, Madhavan Srinivasan, Timothy Pearson,
	Bjorn Helgaas, Shawn Anastasio
  Cc: sashiko-bot, linux-pci, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), stable
In-Reply-To: <20260527180816.2749186-1-adityag@linux.ibm.com>

For opencapi phb direct slots, the .pdev for php_slots will be NULL

Various sections of the code in pnv_php can do a null dereference and
crash the kernel.

Originally, the issue was hit during boot:

    [    1.568588] PowerPC PowerNV PCI Hotplug Driver version: 0.1
    [    1.569722] BUG: Kernel NULL pointer dereference at 0x00000074
    [    1.569811] Faulting instruction address: 0xc000000000b75fd0
    [    1.569890] Oops: Kernel access of bad area, sig: 11 [#1]
    [    1.569963] LE PAGE_SIZE=64K MMU=Hash  SMP NR_CPUS=2048 NUMA PowerNV
    ...
    [    1.571492] NIP [c000000000b75fd0] pnv_php_get_adapter_state+0x60/0x154
    [    1.571604] LR [c000000000b75fbc] pnv_php_get_adapter_state+0x4c/0x154
    [    1.571690] Call Trace:
    [    1.571725] [c000c0000688f990] [c000000000b75fbc] pnv_php_get_adapter_state+0x4c/0x154 (unreliable)
    [    1.571783] [c000c0000688fa20] [c000000000b78bd0] pnv_php_enable+0x94/0x378
    [    1.571951] [c000c0000688fac0] [c000000000b7912c] pnv_php_register_one.isra.0+0x11c/0x1e0

This occurs for hotplug slots on root buses where bus->self == NULL,
such as OpenCAPI PHB direct slots. An added debug print (not part of
this patch) confirmed it was opencapi:

    [    1.617227] pnv_php: slot 'OPENCAPI-0009' has NULL pdev (bus 0009:00, parent=NO (root bus))
    [    1.617308] pnv_php: slot 'OPENCAPI-0009' dn->full_name='pciex@603a000000000', compatible='ibm,power10-pau-opencapi-pciex'

This only required null check in 'pnv_php_get_adapter_state', which
caused the kernel to boot.

Even with 'pnv_php_get_adapter_state' null check, there are more
possible null dereferences pointed by sashiko, including cases where
userspace crashes the kernel, such as:

    $ cat /sys/bus/pci/slots/*/attention
    ...
    [  557.036295] Kernel attempted to read user page (6e) - exploit attempt? (uid: 0)
    [  557.036354] BUG: Kernel NULL pointer dereference on read at 0x0000006e
    [  557.036383] Faulting instruction address: 0xc000000000a83334
    [  557.036413] Oops: Kernel access of bad area, sig: 11 [#1]
    [  557.036449] LE PAGE_SIZE=64K MMU=Hash  SMP NR_CPUS=2048 NUMA PowerNV
    ...
    [  557.037749] [c000000046707a20] [c000000046707b90] 0xc000000046707b90 (unreliable)
    [  557.037795] [c000000046707a70] [0000000000000001] 0x1
    [  557.037850] [c000000046707ab0] [c000000000acb00c] attention_read_file+0x54/0xa8
    [  557.037910] [c000000046707b30] [c000000000abfbfc] pci_slot_attr_show+0x3c/0x58
    [  557.037977] [c000000046707b50] [c0000000008181ec] sysfs_kf_seq_show+0xd4/0x204
    [  557.038022] [c000000046707be0] [c000000000815004] kernfs_seq_show+0x44/0x58

Add null checks to prevent the null dereferences.

Cc: stable@vger.kernel.org
Fixes: 80f9fc236279 ("PCI: pnv_php: Work around switches with broken presence detection")
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
---
 drivers/pci/hotplug/pnv_php.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c
index ff92a5c301b8..d0f5e8ad1f71 100644
--- a/drivers/pci/hotplug/pnv_php.c
+++ b/drivers/pci/hotplug/pnv_php.c
@@ -47,6 +47,9 @@ static void pnv_php_disable_irq(struct pnv_php_slot *php_slot,
 	struct pci_dev *pdev = php_slot->pdev;
 	u16 ctrl;
 
+	if (!pdev)
+		return;
+
 	if (php_slot->irq > 0) {
 		pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl);
 		ctrl &= ~(PCI_EXP_SLTCTL_HPIE |
@@ -414,7 +417,8 @@ static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)
 	 */
 	ret = pnv_pci_get_presence_state(php_slot->id, &presence);
 	if (ret >= 0) {
-		if (pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM &&
+		if (php_slot->pdev &&
+			pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM &&
 			presence == OPAL_PCI_SLOT_EMPTY) {
 			/*
 			 * Similar to pciehp_hpc, check whether the Link Active
@@ -442,6 +446,11 @@ static int pnv_php_get_raw_indicator_status(struct hotplug_slot *slot, u8 *state
 	struct pci_dev *bridge = php_slot->pdev;
 	u16 status;
 
+	if (!bridge) {
+		*state = 0;
+		return 0;
+	}
+
 	pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status);
 	*state = (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6;
 	return 0;
@@ -514,11 +523,13 @@ static int pnv_php_activate_slot(struct pnv_php_slot *php_slot,
 			 * fence / freeze.
 			 */
 			SLOT_WARN(php_slot, "Try %d...\n", i + 1);
-			pci_set_pcie_reset_state(php_slot->pdev,
-						 pcie_warm_reset);
-			msleep(250);
-			pci_set_pcie_reset_state(php_slot->pdev,
-						 pcie_deassert_reset);
+			if (php_slot->pdev) {
+				pci_set_pcie_reset_state(php_slot->pdev,
+							 pcie_warm_reset);
+				msleep(250);
+				pci_set_pcie_reset_state(php_slot->pdev,
+							 pcie_deassert_reset);
+			}
 
 			ret = pnv_php_set_slot_power_state(
 				slot, OPAL_PCI_SLOT_POWER_ON);
@@ -911,6 +922,9 @@ pnv_php_detect_clear_suprise_removal_freeze(struct pnv_php_slot *php_slot)
 	struct eeh_pe *pe;
 	int i, rc;
 
+	if (!pdev)
+		return;
+
 	/*
 	 * When a device is surprise removed from a downstream bridge slot,
 	 * the upstream bridge port can still end up frozen due to related EEH
@@ -1093,6 +1107,9 @@ static void pnv_php_enable_irq(struct pnv_php_slot *php_slot)
 	struct pci_dev *pdev = php_slot->pdev;
 	int irq, ret;
 
+	if (!pdev)
+		return;
+
 	/*
 	 * The MSI/MSIx interrupt might have been occupied by other
 	 * drivers. Don't populate the surprise hotplug capability
-- 
2.54.0



^ permalink raw reply related

* [PATCH v2 2/3] ppc/pnv: Refactor PNV PCI hotplug driver
From: Aditya Gupta @ 2026-05-27 18:08 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev, Madhavan Srinivasan, Timothy Pearson,
	Bjorn Helgaas, Shawn Anastasio
  Cc: sashiko-bot, linux-pci, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP)
In-Reply-To: <20260527180816.2749186-1-adityag@linux.ibm.com>

Currently the pnv_php driver handles both PCIe and OpenCAPI slots.

The slots has many common functionality, but many operations are pcie
specific, and assume the slot having a parent device, which isn't the
case with opencapi slots

This requires handling the case of parent device being NULL, at many
places, which can be hard to maintain and add code to.

Instead, have PCIe/OpenCAPI operations as .backend_ops in pnv_php_slot,
so that PCIe code is cleanly separated.
With this, future patches can just edit the PCIe/OpenCAPI specific ops,
instead of editing the common code.

No functional change is intended other than reset_slot for OpenCAPI
slots returning -ENODEV when not probing.

Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
---
 arch/powerpc/include/asm/pnv-pci.h |  16 +++
 drivers/pci/hotplug/pnv_php.c      | 160 +++++++++++++++++++----------
 2 files changed, 123 insertions(+), 53 deletions(-)

diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h
index 7e9a479951a3..f1020f1e61cd 100644
--- a/arch/powerpc/include/asm/pnv-pci.h
+++ b/arch/powerpc/include/asm/pnv-pci.h
@@ -27,6 +27,9 @@ extern int pnv_pci_set_power_state(uint64_t id, uint8_t state,
 int64_t pnv_opal_pci_msi_eoi(struct irq_data *d);
 bool is_pnv_opal_msi(struct irq_chip *chip);
 
+/* To be set for hotplug operations for PCIe/OpenCAPI */
+struct pnv_php_backend_ops;
+
 struct pnv_php_slot {
 	struct hotplug_slot		slot;
 	uint64_t			id;
@@ -50,10 +53,23 @@ struct pnv_php_slot {
 	void				*fdt;
 	void				*dt;
 	struct of_changeset		ocs;
+	const struct pnv_php_backend_ops *backend_ops;
 	struct pnv_php_slot		*parent;
 	struct list_head		children;
 	struct list_head		link;
 };
+
+struct pnv_php_backend_ops {
+	void (*enable_irq)(struct pnv_php_slot *slot);
+	void (*disable_irq)(struct pnv_php_slot *slot, bool disable_device, bool disable_msi);
+	void (*fixup_presence_state)(struct pnv_php_slot *slot, u8 *presence);
+	void  (*get_attention_state)(struct pnv_php_slot *slot, u8 *state);
+	void  (*set_attention_state)(struct pnv_php_slot *slot, u8 state);
+	void (*fundamental_reset)(struct pnv_php_slot *slot);
+	void (*detect_surprise_removal)(struct pnv_php_slot *slot);
+	int  (*reset_slot)(struct pnv_php_slot *slot, bool probe);
+};
+
 extern struct pnv_php_slot *pnv_php_find_slot(struct device_node *dn);
 extern int pnv_php_set_slot_power_state(struct hotplug_slot *slot,
 					uint8_t state);
diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c
index d0f5e8ad1f71..997412eea486 100644
--- a/drivers/pci/hotplug/pnv_php.c
+++ b/drivers/pci/hotplug/pnv_php.c
@@ -39,17 +39,53 @@ static void pnv_php_register(struct device_node *dn);
 static void pnv_php_unregister_one(struct device_node *dn);
 static void pnv_php_unregister(struct device_node *dn);
 
-static void pnv_php_enable_irq(struct pnv_php_slot *php_slot);
+static void pcie_enable_irq(struct pnv_php_slot *php_slot);
+static int pcie_check_link_active(struct pci_dev *pdev);
+static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot);
+
+static void pcie_fixup_presence_state(struct pnv_php_slot *php_slot, u8 *presence)
+{
+	if (pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM &&
+	    *presence == OPAL_PCI_SLOT_EMPTY) {
+		/*
+		 * Similar to pciehp_hpc, check whether the Link Active
+		 * bit is set to account for broken downstream bridges
+		 * that don't properly assert Presence Detect State, as
+		 * was observed on the Microsemi Switchtec PM8533 PFX
+		 * [11f8:8533].
+		 */
+		if (pcie_check_link_active(php_slot->pdev) > 0)
+			*presence = OPAL_PCI_SLOT_PRESENT;
+	}
+}
+
+static void pcie_fundamental_reset(struct pnv_php_slot *php_slot)
+{
+	pci_set_pcie_reset_state(php_slot->pdev, pcie_warm_reset);
+	msleep(250);
+	pci_set_pcie_reset_state(php_slot->pdev, pcie_deassert_reset);
+}
+
+static void pnv_php_enable_irq(struct pnv_php_slot *php_slot)
+{
+	if (php_slot->backend_ops->enable_irq)
+		php_slot->backend_ops->enable_irq(php_slot);
+}
 
 static void pnv_php_disable_irq(struct pnv_php_slot *php_slot,
 				bool disable_device, bool disable_msi)
+{
+	if (php_slot->backend_ops->disable_irq)
+		php_slot->backend_ops->disable_irq(php_slot, disable_device,
+				disable_msi);
+}
+
+static void pcie_disable_irq(struct pnv_php_slot *php_slot,
+				bool disable_device, bool disable_msi)
 {
 	struct pci_dev *pdev = php_slot->pdev;
 	u16 ctrl;
 
-	if (!pdev)
-		return;
-
 	if (php_slot->irq > 0) {
 		pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl);
 		ctrl &= ~(PCI_EXP_SLTCTL_HPIE |
@@ -417,19 +453,8 @@ static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)
 	 */
 	ret = pnv_pci_get_presence_state(php_slot->id, &presence);
 	if (ret >= 0) {
-		if (php_slot->pdev &&
-			pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM &&
-			presence == OPAL_PCI_SLOT_EMPTY) {
-			/*
-			 * Similar to pciehp_hpc, check whether the Link Active
-			 * bit is set to account for broken downstream bridges
-			 * that don't properly assert Presence Detect State, as
-			 * was observed on the Microsemi Switchtec PM8533 PFX
-			 * [11f8:8533].
-			 */
-			if (pcie_check_link_active(php_slot->pdev) > 0)
-				presence = OPAL_PCI_SLOT_PRESENT;
-		}
+		if (php_slot->backend_ops->fixup_presence_state)
+			php_slot->backend_ops->fixup_presence_state(php_slot, &presence);
 
 		*state = presence;
 		ret = 0;
@@ -440,28 +465,24 @@ static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)
 	return ret;
 }
 
-static int pnv_php_get_raw_indicator_status(struct hotplug_slot *slot, u8 *state)
+static void pcie_get_attention_state(struct pnv_php_slot *php_slot, u8 *state)
 {
-	struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
 	struct pci_dev *bridge = php_slot->pdev;
 	u16 status;
 
-	if (!bridge) {
-		*state = 0;
-		return 0;
-	}
-
 	pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status);
 	*state = (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6;
-	return 0;
 }
 
-
 static int pnv_php_get_attention_state(struct hotplug_slot *slot, u8 *state)
 {
 	struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
 
-	pnv_php_get_raw_indicator_status(slot, &php_slot->attention_state);
+	if (php_slot->backend_ops->get_attention_state)
+		php_slot->backend_ops->get_attention_state(php_slot, &php_slot->attention_state);
+	else
+		php_slot->attention_state = 0;
+
 	*state = php_slot->attention_state;
 	return 0;
 }
@@ -469,13 +490,19 @@ static int pnv_php_get_attention_state(struct hotplug_slot *slot, u8 *state)
 static int pnv_php_set_attention_state(struct hotplug_slot *slot, u8 state)
 {
 	struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
+
+	if (php_slot->backend_ops->set_attention_state)
+		php_slot->backend_ops->set_attention_state(php_slot, state);
+
+	return 0;
+}
+
+static void pcie_set_attention_state(struct pnv_php_slot *php_slot, u8 state)
+{
 	struct pci_dev *bridge = php_slot->pdev;
 	u16 new, mask;
 
 	php_slot->attention_state = state;
-	if (!bridge)
-		return 0;
-
 	mask = PCI_EXP_SLTCTL_AIC;
 
 	if (state)
@@ -484,8 +511,6 @@ static int pnv_php_set_attention_state(struct hotplug_slot *slot, u8 state)
 		new = PCI_EXP_SLTCTL_ATTN_IND_OFF;
 
 	pcie_capability_clear_and_set_word(bridge, PCI_EXP_SLTCTL, mask, new);
-
-	return 0;
 }
 
 static int pnv_php_activate_slot(struct pnv_php_slot *php_slot,
@@ -523,13 +548,8 @@ static int pnv_php_activate_slot(struct pnv_php_slot *php_slot,
 			 * fence / freeze.
 			 */
 			SLOT_WARN(php_slot, "Try %d...\n", i + 1);
-			if (php_slot->pdev) {
-				pci_set_pcie_reset_state(php_slot->pdev,
-							 pcie_warm_reset);
-				msleep(250);
-				pci_set_pcie_reset_state(php_slot->pdev,
-							 pcie_deassert_reset);
-			}
+			if (php_slot->backend_ops->fundamental_reset)
+				php_slot->backend_ops->fundamental_reset(php_slot);
 
 			ret = pnv_php_set_slot_power_state(
 				slot, OPAL_PCI_SLOT_POWER_ON);
@@ -633,16 +653,18 @@ static int pnv_php_enable(struct pnv_php_slot *php_slot, bool rescan)
 static int pnv_php_reset_slot(struct hotplug_slot *slot, bool probe)
 {
 	struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
+	if (php_slot->backend_ops->reset_slot)
+		return php_slot->backend_ops->reset_slot(php_slot, probe);
+	return probe ? 0 : -ENODEV;
+}
+
+static int pcie_reset_slot(struct pnv_php_slot *php_slot, bool probe)
+{
 	struct pci_dev *bridge = php_slot->pdev;
 	uint16_t sts;
 
-	/*
-	 * The CAPI folks want pnv_php to drive OpenCAPI slots
-	 * which don't have a bridge. Only claim to support
-	 * reset_slot() if we have a bridge device (for now...)
-	 */
 	if (probe)
-		return !bridge;
+		return 0;
 
 	/* mask our interrupt while resetting the bridge */
 	if (php_slot->irq > 0)
@@ -778,6 +800,26 @@ static void pnv_php_release(struct pnv_php_slot *php_slot)
 	pnv_php_put_slot(php_slot->parent);
 }
 
+static const struct pnv_php_backend_ops pnv_php_pcie_ops = {
+	.enable_irq              = pcie_enable_irq,
+	.disable_irq             = pcie_disable_irq,
+	.get_attention_state     = pcie_get_attention_state,
+	.set_attention_state     = pcie_set_attention_state,
+	.fixup_presence_state    = pcie_fixup_presence_state,
+	.fundamental_reset       = pcie_fundamental_reset,
+	.detect_surprise_removal = pcie_detect_surprise_removal,
+	.reset_slot              = pcie_reset_slot,
+};
+
+static int opencapi_reset_slot(struct pnv_php_slot *slot, bool probe)
+{
+	return probe ? 1 : -ENODEV;
+}
+
+static const struct pnv_php_backend_ops pnv_php_opencapi_ops = {
+	.reset_slot              = opencapi_reset_slot,
+};
+
 static struct pnv_php_slot *pnv_php_alloc_slot(struct device_node *dn)
 {
 	struct pnv_php_slot *php_slot;
@@ -830,6 +872,12 @@ static struct pnv_php_slot *pnv_php_alloc_slot(struct device_node *dn)
 	php_slot->power_state_check     = false;
 	php_slot->slot.ops              = &php_slot_ops;
 
+	/* OpenCAPI slots don't have a parent bridge */
+	if (php_slot->pdev)
+		php_slot->backend_ops = &pnv_php_pcie_ops;
+	else
+		php_slot->backend_ops = &pnv_php_opencapi_ops;
+
 	INIT_LIST_HEAD(&php_slot->children);
 	INIT_LIST_HEAD(&php_slot->link);
 
@@ -886,7 +934,7 @@ static int pnv_php_register_slot(struct pnv_php_slot *php_slot)
 	return 0;
 }
 
-static int pnv_php_enable_msix(struct pnv_php_slot *php_slot)
+static int pcie_enable_msix(struct pnv_php_slot *php_slot)
 {
 	struct pci_dev *pdev = php_slot->pdev;
 	struct msix_entry entry;
@@ -915,7 +963,13 @@ static int pnv_php_enable_msix(struct pnv_php_slot *php_slot)
 }
 
 static void
-pnv_php_detect_clear_suprise_removal_freeze(struct pnv_php_slot *php_slot)
+pnv_php_detect_clear_surprise_removal_freeze(struct pnv_php_slot *php_slot)
+{
+	if (php_slot->backend_ops->detect_surprise_removal)
+		php_slot->backend_ops->detect_surprise_removal(php_slot);
+}
+
+static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot)
 {
 	struct pci_dev *pdev = php_slot->pdev;
 	struct eeh_dev *edev;
@@ -972,7 +1026,7 @@ static void pnv_php_event_handler(struct work_struct *work)
 		pnv_php_enable_slot(&php_slot->slot);
 	} else {
 		pnv_php_disable_slot(&php_slot->slot);
-		pnv_php_detect_clear_suprise_removal_freeze(php_slot);
+		pnv_php_detect_clear_surprise_removal_freeze(php_slot);
 	}
 
 	kfree(event);
@@ -1055,7 +1109,7 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq)
+static void pcie_init_irq(struct pnv_php_slot *php_slot, int irq)
 {
 	struct pci_dev *pdev = php_slot->pdev;
 	u32 broken_pdc = 0;
@@ -1102,7 +1156,7 @@ static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq)
 	php_slot->irq = irq;
 }
 
-static void pnv_php_enable_irq(struct pnv_php_slot *php_slot)
+static void pcie_enable_irq(struct pnv_php_slot *php_slot)
 {
 	struct pci_dev *pdev = php_slot->pdev;
 	int irq, ret;
@@ -1127,9 +1181,9 @@ static void pnv_php_enable_irq(struct pnv_php_slot *php_slot)
 	pci_set_master(pdev);
 
 	/* Enable MSIx interrupt */
-	irq = pnv_php_enable_msix(php_slot);
+	irq = pcie_enable_msix(php_slot);
 	if (irq > 0) {
-		pnv_php_init_irq(php_slot, irq);
+		pcie_init_irq(php_slot, irq);
 		return;
 	}
 
@@ -1140,7 +1194,7 @@ static void pnv_php_enable_irq(struct pnv_php_slot *php_slot)
 	ret = pci_enable_msi(pdev);
 	if (!ret || pdev->irq) {
 		irq = pdev->irq;
-		pnv_php_init_irq(php_slot, irq);
+		pcie_init_irq(php_slot, irq);
 	}
 }
 
-- 
2.54.0



^ permalink raw reply related

* [PATCH v2 3/3] ppc/pnv: Refactor PNV PCI Hotplug to group PCIe functions
From: Aditya Gupta @ 2026-05-27 18:08 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev, Madhavan Srinivasan, Timothy Pearson,
	Bjorn Helgaas, Shawn Anastasio
  Cc: sashiko-bot, linux-pci, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP)
In-Reply-To: <20260527180816.2749186-1-adityag@linux.ibm.com>

With the refactor change to pnv_php.c, pnv_php_* and pcie_* are mixed
up.

Move and group pcie, opencapi, and pnv_php*.

No functional change. Only moves code, and no logic has been modified.

Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
---
 drivers/pci/hotplug/pnv_php.c | 559 +++++++++++++++++-----------------
 1 file changed, 279 insertions(+), 280 deletions(-)

diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c
index 997412eea486..dd8e00b879e1 100644
--- a/drivers/pci/hotplug/pnv_php.c
+++ b/drivers/pci/hotplug/pnv_php.c
@@ -38,46 +38,125 @@ static DEFINE_SPINLOCK(pnv_php_lock);
 static void pnv_php_register(struct device_node *dn);
 static void pnv_php_unregister_one(struct device_node *dn);
 static void pnv_php_unregister(struct device_node *dn);
+static irqreturn_t pnv_php_interrupt(int irq, void *data);
+static void pnv_php_disable_irq(struct pnv_php_slot *php_slot,
+				bool disable_device, bool disable_msi);
 
-static void pcie_enable_irq(struct pnv_php_slot *php_slot);
-static int pcie_check_link_active(struct pci_dev *pdev);
-static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot);
-
-static void pcie_fixup_presence_state(struct pnv_php_slot *php_slot, u8 *presence)
+static void pcie_init_irq(struct pnv_php_slot *php_slot, int irq)
 {
-	if (pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM &&
-	    *presence == OPAL_PCI_SLOT_EMPTY) {
-		/*
-		 * Similar to pciehp_hpc, check whether the Link Active
-		 * bit is set to account for broken downstream bridges
-		 * that don't properly assert Presence Detect State, as
-		 * was observed on the Microsemi Switchtec PM8533 PFX
-		 * [11f8:8533].
-		 */
-		if (pcie_check_link_active(php_slot->pdev) > 0)
-			*presence = OPAL_PCI_SLOT_PRESENT;
+	struct pci_dev *pdev = php_slot->pdev;
+	u32 broken_pdc = 0;
+	u16 sts, ctrl;
+	int ret;
+
+	/* Check PDC (Presence Detection Change) is broken or not */
+	ret = of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc",
+				   &broken_pdc);
+	if (!ret && broken_pdc)
+		php_slot->flags |= PNV_PHP_FLAG_BROKEN_PDC;
+
+	/* Clear pending interrupts */
+	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts);
+	if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC)
+		sts |= PCI_EXP_SLTSTA_DLLSC;
+	else
+		sts |= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
+	pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts);
+
+	/* Request the interrupt */
+	ret = request_irq(irq, pnv_php_interrupt, IRQF_SHARED,
+			  php_slot->name, php_slot);
+	if (ret) {
+		pnv_php_disable_irq(php_slot, true, true);
+		SLOT_WARN(php_slot, "Error %d enabling IRQ %d\n", ret, irq);
+		return;
 	}
-}
 
-static void pcie_fundamental_reset(struct pnv_php_slot *php_slot)
-{
-	pci_set_pcie_reset_state(php_slot->pdev, pcie_warm_reset);
-	msleep(250);
-	pci_set_pcie_reset_state(php_slot->pdev, pcie_deassert_reset);
+	/* Enable the interrupts */
+	pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl);
+	if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) {
+		ctrl &= ~PCI_EXP_SLTCTL_PDCE;
+		ctrl |= (PCI_EXP_SLTCTL_HPIE |
+			 PCI_EXP_SLTCTL_DLLSCE);
+	} else {
+		ctrl |= (PCI_EXP_SLTCTL_HPIE |
+			 PCI_EXP_SLTCTL_PDCE |
+			 PCI_EXP_SLTCTL_DLLSCE);
+	}
+	pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl);
+
+	/* The interrupt is initialized successfully when @irq is valid */
+	php_slot->irq = irq;
 }
 
-static void pnv_php_enable_irq(struct pnv_php_slot *php_slot)
+static int pcie_enable_msix(struct pnv_php_slot *php_slot)
 {
-	if (php_slot->backend_ops->enable_irq)
-		php_slot->backend_ops->enable_irq(php_slot);
+	struct pci_dev *pdev = php_slot->pdev;
+	struct msix_entry entry;
+	int nr_entries, ret;
+	u16 pcie_flag;
+
+	/* Get total number of MSIx entries */
+	nr_entries = pci_msix_vec_count(pdev);
+	if (nr_entries < 0)
+		return nr_entries;
+
+	/* Check hotplug MSIx entry is in range */
+	pcie_capability_read_word(pdev, PCI_EXP_FLAGS, &pcie_flag);
+	entry.entry = FIELD_GET(PCI_EXP_FLAGS_IRQ, pcie_flag);
+	if (entry.entry >= nr_entries)
+		return -ERANGE;
+
+	/* Enable MSIx */
+	ret = pci_enable_msix_exact(pdev, &entry, 1);
+	if (ret) {
+		SLOT_WARN(php_slot, "Error %d enabling MSIx\n", ret);
+		return ret;
+	}
+
+	return entry.vector;
 }
 
-static void pnv_php_disable_irq(struct pnv_php_slot *php_slot,
-				bool disable_device, bool disable_msi)
+static void pcie_enable_irq(struct pnv_php_slot *php_slot)
 {
-	if (php_slot->backend_ops->disable_irq)
-		php_slot->backend_ops->disable_irq(php_slot, disable_device,
-				disable_msi);
+	struct pci_dev *pdev = php_slot->pdev;
+	int irq, ret;
+
+	if (!pdev)
+		return;
+
+	/*
+	 * The MSI/MSIx interrupt might have been occupied by other
+	 * drivers. Don't populate the surprise hotplug capability
+	 * in that case.
+	 */
+	if (pci_dev_msi_enabled(pdev))
+		return;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		SLOT_WARN(php_slot, "Error %d enabling device\n", ret);
+		return;
+	}
+
+	pci_set_master(pdev);
+
+	/* Enable MSIx interrupt */
+	irq = pcie_enable_msix(php_slot);
+	if (irq > 0) {
+		pcie_init_irq(php_slot, irq);
+		return;
+	}
+
+	/*
+	 * Use MSI if MSIx doesn't work. Fail back to legacy INTx
+	 * if MSI doesn't work either
+	 */
+	ret = pci_enable_msi(pdev);
+	if (!ret || pdev->irq) {
+		irq = pdev->irq;
+		pcie_init_irq(php_slot, irq);
+	}
 }
 
 static void pcie_disable_irq(struct pnv_php_slot *php_slot,
@@ -104,8 +183,176 @@ static void pcie_disable_irq(struct pnv_php_slot *php_slot,
 			pci_disable_msi(pdev);
 	}
 
-	if (disable_device)
-		pci_disable_device(pdev);
+	if (disable_device)
+		pci_disable_device(pdev);
+}
+
+static void pcie_get_attention_state(struct pnv_php_slot *php_slot, u8 *state)
+{
+	struct pci_dev *bridge = php_slot->pdev;
+	u16 status;
+
+	pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status);
+	*state = (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6;
+}
+
+static void pcie_set_attention_state(struct pnv_php_slot *php_slot, u8 state)
+{
+	struct pci_dev *bridge = php_slot->pdev;
+	u16 new, mask;
+
+	php_slot->attention_state = state;
+	mask = PCI_EXP_SLTCTL_AIC;
+
+	if (state)
+		new = FIELD_PREP(PCI_EXP_SLTCTL_AIC, state);
+	else
+		new = PCI_EXP_SLTCTL_ATTN_IND_OFF;
+
+	pcie_capability_clear_and_set_word(bridge, PCI_EXP_SLTCTL, mask, new);
+}
+
+static int pcie_check_link_active(struct pci_dev *pdev)
+{
+	u16 lnk_status;
+	int ret;
+
+	ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
+	if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status))
+		return -ENODEV;
+
+	ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
+
+	return ret;
+}
+
+static void pcie_fixup_presence_state(struct pnv_php_slot *php_slot, u8 *presence)
+{
+	if (pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM &&
+	    *presence == OPAL_PCI_SLOT_EMPTY) {
+		/*
+		 * Similar to pciehp_hpc, check whether the Link Active
+		 * bit is set to account for broken downstream bridges
+		 * that don't properly assert Presence Detect State, as
+		 * was observed on the Microsemi Switchtec PM8533 PFX
+		 * [11f8:8533].
+		 */
+		if (pcie_check_link_active(php_slot->pdev) > 0)
+			*presence = OPAL_PCI_SLOT_PRESENT;
+	}
+}
+
+static void pcie_fundamental_reset(struct pnv_php_slot *php_slot)
+{
+	pci_set_pcie_reset_state(php_slot->pdev, pcie_warm_reset);
+	msleep(250);
+	pci_set_pcie_reset_state(php_slot->pdev, pcie_deassert_reset);
+}
+
+static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot)
+{
+	struct pci_dev *pdev = php_slot->pdev;
+	struct eeh_dev *edev;
+	struct eeh_pe *pe;
+	int i, rc;
+
+	if (!pdev)
+		return;
+
+	/*
+	 * When a device is surprise removed from a downstream bridge slot,
+	 * the upstream bridge port can still end up frozen due to related EEH
+	 * events, which will in turn block the MSI interrupts for slot hotplug
+	 * detection.
+	 *
+	 * Detect and thaw any frozen upstream PE after slot deactivation.
+	 */
+	edev = pci_dev_to_eeh_dev(pdev);
+	pe = edev ? edev->pe : NULL;
+	rc = eeh_pe_get_state(pe);
+	if ((rc == -ENODEV) || (rc == -ENOENT)) {
+		SLOT_WARN(
+			php_slot,
+			"Upstream bridge PE state unknown, hotplug detect may fail\n");
+	} else {
+		if (pe->state & EEH_PE_ISOLATED) {
+			SLOT_WARN(
+				php_slot,
+				"Upstream bridge PE %02x frozen, thawing...\n",
+				pe->addr);
+			for (i = 0; i < 3; i++)
+				if (!eeh_unfreeze_pe(pe))
+					break;
+			if (i >= 3)
+				SLOT_WARN(
+					php_slot,
+					"Unable to thaw PE %02x, hotplug detect will fail!\n",
+					pe->addr);
+			else
+				SLOT_WARN(php_slot,
+					  "PE %02x thawed successfully\n",
+					  pe->addr);
+		}
+	}
+}
+
+static int pcie_reset_slot(struct pnv_php_slot *php_slot, bool probe)
+{
+	struct pci_dev *bridge = php_slot->pdev;
+	uint16_t sts;
+
+	if (probe)
+		return 0;
+
+	/* mask our interrupt while resetting the bridge */
+	if (php_slot->irq > 0)
+		disable_irq(php_slot->irq);
+
+	pci_bridge_secondary_bus_reset(bridge);
+
+	/* clear any state changes that happened due to the reset */
+	pcie_capability_read_word(php_slot->pdev, PCI_EXP_SLTSTA, &sts);
+	sts &= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
+	pcie_capability_write_word(php_slot->pdev, PCI_EXP_SLTSTA, sts);
+
+	if (php_slot->irq > 0)
+		enable_irq(php_slot->irq);
+
+	return 0;
+}
+
+static const struct pnv_php_backend_ops pnv_php_pcie_ops = {
+	.enable_irq              = pcie_enable_irq,
+	.disable_irq             = pcie_disable_irq,
+	.get_attention_state     = pcie_get_attention_state,
+	.set_attention_state     = pcie_set_attention_state,
+	.fixup_presence_state    = pcie_fixup_presence_state,
+	.fundamental_reset       = pcie_fundamental_reset,
+	.detect_surprise_removal = pcie_detect_surprise_removal,
+	.reset_slot              = pcie_reset_slot,
+};
+
+static int opencapi_reset_slot(struct pnv_php_slot *slot, bool probe)
+{
+	return probe ? 1 : -ENODEV;
+}
+
+static const struct pnv_php_backend_ops pnv_php_opencapi_ops = {
+	.reset_slot              = opencapi_reset_slot,
+};
+
+static void pnv_php_enable_irq(struct pnv_php_slot *php_slot)
+{
+	if (php_slot->backend_ops->enable_irq)
+		php_slot->backend_ops->enable_irq(php_slot);
+}
+
+static void pnv_php_disable_irq(struct pnv_php_slot *php_slot,
+				bool disable_device, bool disable_msi)
+{
+	if (php_slot->backend_ops->disable_irq)
+		php_slot->backend_ops->disable_irq(php_slot, disable_device,
+				disable_msi);
 }
 
 static void pnv_php_free_slot(struct kref *kref)
@@ -427,20 +674,6 @@ static int pnv_php_get_power_state(struct hotplug_slot *slot, u8 *state)
 	return 0;
 }
 
-static int pcie_check_link_active(struct pci_dev *pdev)
-{
-	u16 lnk_status;
-	int ret;
-
-	ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
-	if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status))
-		return -ENODEV;
-
-	ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
-
-	return ret;
-}
-
 static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)
 {
 	struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
@@ -465,15 +698,6 @@ static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)
 	return ret;
 }
 
-static void pcie_get_attention_state(struct pnv_php_slot *php_slot, u8 *state)
-{
-	struct pci_dev *bridge = php_slot->pdev;
-	u16 status;
-
-	pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status);
-	*state = (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6;
-}
-
 static int pnv_php_get_attention_state(struct hotplug_slot *slot, u8 *state)
 {
 	struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
@@ -497,22 +721,6 @@ static int pnv_php_set_attention_state(struct hotplug_slot *slot, u8 state)
 	return 0;
 }
 
-static void pcie_set_attention_state(struct pnv_php_slot *php_slot, u8 state)
-{
-	struct pci_dev *bridge = php_slot->pdev;
-	u16 new, mask;
-
-	php_slot->attention_state = state;
-	mask = PCI_EXP_SLTCTL_AIC;
-
-	if (state)
-		new = FIELD_PREP(PCI_EXP_SLTCTL_AIC, state);
-	else
-		new = PCI_EXP_SLTCTL_ATTN_IND_OFF;
-
-	pcie_capability_clear_and_set_word(bridge, PCI_EXP_SLTCTL, mask, new);
-}
-
 static int pnv_php_activate_slot(struct pnv_php_slot *php_slot,
 				 struct hotplug_slot *slot)
 {
@@ -658,31 +866,6 @@ static int pnv_php_reset_slot(struct hotplug_slot *slot, bool probe)
 	return probe ? 0 : -ENODEV;
 }
 
-static int pcie_reset_slot(struct pnv_php_slot *php_slot, bool probe)
-{
-	struct pci_dev *bridge = php_slot->pdev;
-	uint16_t sts;
-
-	if (probe)
-		return 0;
-
-	/* mask our interrupt while resetting the bridge */
-	if (php_slot->irq > 0)
-		disable_irq(php_slot->irq);
-
-	pci_bridge_secondary_bus_reset(bridge);
-
-	/* clear any state changes that happened due to the reset */
-	pcie_capability_read_word(php_slot->pdev, PCI_EXP_SLTSTA, &sts);
-	sts &= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
-	pcie_capability_write_word(php_slot->pdev, PCI_EXP_SLTSTA, sts);
-
-	if (php_slot->irq > 0)
-		enable_irq(php_slot->irq);
-
-	return 0;
-}
-
 static int pnv_php_enable_slot(struct hotplug_slot *slot)
 {
 	struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
@@ -800,26 +983,6 @@ static void pnv_php_release(struct pnv_php_slot *php_slot)
 	pnv_php_put_slot(php_slot->parent);
 }
 
-static const struct pnv_php_backend_ops pnv_php_pcie_ops = {
-	.enable_irq              = pcie_enable_irq,
-	.disable_irq             = pcie_disable_irq,
-	.get_attention_state     = pcie_get_attention_state,
-	.set_attention_state     = pcie_set_attention_state,
-	.fixup_presence_state    = pcie_fixup_presence_state,
-	.fundamental_reset       = pcie_fundamental_reset,
-	.detect_surprise_removal = pcie_detect_surprise_removal,
-	.reset_slot              = pcie_reset_slot,
-};
-
-static int opencapi_reset_slot(struct pnv_php_slot *slot, bool probe)
-{
-	return probe ? 1 : -ENODEV;
-}
-
-static const struct pnv_php_backend_ops pnv_php_opencapi_ops = {
-	.reset_slot              = opencapi_reset_slot,
-};
-
 static struct pnv_php_slot *pnv_php_alloc_slot(struct device_node *dn)
 {
 	struct pnv_php_slot *php_slot;
@@ -934,34 +1097,6 @@ static int pnv_php_register_slot(struct pnv_php_slot *php_slot)
 	return 0;
 }
 
-static int pcie_enable_msix(struct pnv_php_slot *php_slot)
-{
-	struct pci_dev *pdev = php_slot->pdev;
-	struct msix_entry entry;
-	int nr_entries, ret;
-	u16 pcie_flag;
-
-	/* Get total number of MSIx entries */
-	nr_entries = pci_msix_vec_count(pdev);
-	if (nr_entries < 0)
-		return nr_entries;
-
-	/* Check hotplug MSIx entry is in range */
-	pcie_capability_read_word(pdev, PCI_EXP_FLAGS, &pcie_flag);
-	entry.entry = FIELD_GET(PCI_EXP_FLAGS_IRQ, pcie_flag);
-	if (entry.entry >= nr_entries)
-		return -ERANGE;
-
-	/* Enable MSIx */
-	ret = pci_enable_msix_exact(pdev, &entry, 1);
-	if (ret) {
-		SLOT_WARN(php_slot, "Error %d enabling MSIx\n", ret);
-		return ret;
-	}
-
-	return entry.vector;
-}
-
 static void
 pnv_php_detect_clear_surprise_removal_freeze(struct pnv_php_slot *php_slot)
 {
@@ -969,53 +1104,6 @@ pnv_php_detect_clear_surprise_removal_freeze(struct pnv_php_slot *php_slot)
 		php_slot->backend_ops->detect_surprise_removal(php_slot);
 }
 
-static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot)
-{
-	struct pci_dev *pdev = php_slot->pdev;
-	struct eeh_dev *edev;
-	struct eeh_pe *pe;
-	int i, rc;
-
-	if (!pdev)
-		return;
-
-	/*
-	 * When a device is surprise removed from a downstream bridge slot,
-	 * the upstream bridge port can still end up frozen due to related EEH
-	 * events, which will in turn block the MSI interrupts for slot hotplug
-	 * detection.
-	 *
-	 * Detect and thaw any frozen upstream PE after slot deactivation.
-	 */
-	edev = pci_dev_to_eeh_dev(pdev);
-	pe = edev ? edev->pe : NULL;
-	rc = eeh_pe_get_state(pe);
-	if ((rc == -ENODEV) || (rc == -ENOENT)) {
-		SLOT_WARN(
-			php_slot,
-			"Upstream bridge PE state unknown, hotplug detect may fail\n");
-	} else {
-		if (pe->state & EEH_PE_ISOLATED) {
-			SLOT_WARN(
-				php_slot,
-				"Upstream bridge PE %02x frozen, thawing...\n",
-				pe->addr);
-			for (i = 0; i < 3; i++)
-				if (!eeh_unfreeze_pe(pe))
-					break;
-			if (i >= 3)
-				SLOT_WARN(
-					php_slot,
-					"Unable to thaw PE %02x, hotplug detect will fail!\n",
-					pe->addr);
-			else
-				SLOT_WARN(php_slot,
-					  "PE %02x thawed successfully\n",
-					  pe->addr);
-		}
-	}
-}
-
 static void pnv_php_event_handler(struct work_struct *work)
 {
 	struct pnv_php_event *event =
@@ -1109,95 +1197,6 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static void pcie_init_irq(struct pnv_php_slot *php_slot, int irq)
-{
-	struct pci_dev *pdev = php_slot->pdev;
-	u32 broken_pdc = 0;
-	u16 sts, ctrl;
-	int ret;
-
-	/* Check PDC (Presence Detection Change) is broken or not */
-	ret = of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc",
-				   &broken_pdc);
-	if (!ret && broken_pdc)
-		php_slot->flags |= PNV_PHP_FLAG_BROKEN_PDC;
-
-	/* Clear pending interrupts */
-	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts);
-	if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC)
-		sts |= PCI_EXP_SLTSTA_DLLSC;
-	else
-		sts |= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
-	pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts);
-
-	/* Request the interrupt */
-	ret = request_irq(irq, pnv_php_interrupt, IRQF_SHARED,
-			  php_slot->name, php_slot);
-	if (ret) {
-		pnv_php_disable_irq(php_slot, true, true);
-		SLOT_WARN(php_slot, "Error %d enabling IRQ %d\n", ret, irq);
-		return;
-	}
-
-	/* Enable the interrupts */
-	pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl);
-	if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) {
-		ctrl &= ~PCI_EXP_SLTCTL_PDCE;
-		ctrl |= (PCI_EXP_SLTCTL_HPIE |
-			 PCI_EXP_SLTCTL_DLLSCE);
-	} else {
-		ctrl |= (PCI_EXP_SLTCTL_HPIE |
-			 PCI_EXP_SLTCTL_PDCE |
-			 PCI_EXP_SLTCTL_DLLSCE);
-	}
-	pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl);
-
-	/* The interrupt is initialized successfully when @irq is valid */
-	php_slot->irq = irq;
-}
-
-static void pcie_enable_irq(struct pnv_php_slot *php_slot)
-{
-	struct pci_dev *pdev = php_slot->pdev;
-	int irq, ret;
-
-	if (!pdev)
-		return;
-
-	/*
-	 * The MSI/MSIx interrupt might have been occupied by other
-	 * drivers. Don't populate the surprise hotplug capability
-	 * in that case.
-	 */
-	if (pci_dev_msi_enabled(pdev))
-		return;
-
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		SLOT_WARN(php_slot, "Error %d enabling device\n", ret);
-		return;
-	}
-
-	pci_set_master(pdev);
-
-	/* Enable MSIx interrupt */
-	irq = pcie_enable_msix(php_slot);
-	if (irq > 0) {
-		pcie_init_irq(php_slot, irq);
-		return;
-	}
-
-	/*
-	 * Use MSI if MSIx doesn't work. Fail back to legacy INTx
-	 * if MSI doesn't work either
-	 */
-	ret = pci_enable_msi(pdev);
-	if (!ret || pdev->irq) {
-		irq = pdev->irq;
-		pcie_init_irq(php_slot, irq);
-	}
-}
-
 static int pnv_php_register_one(struct device_node *dn)
 {
 	struct pnv_php_slot *php_slot;
-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH] powerpc: Export set_memory_encrypted and set_memory_decrypted
From: Borislav Petkov @ 2026-05-27 18:15 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Christoph Hellwig, T.J. Mercier, maddy, mpe, npiggin, chleroy,
	linuxppc-dev, mripard, sumit.semwal, lkp, linux-kernel, iommu,
	linux-mm, agordeev, gerald.schaefer, linux-s390, Dan Williams,
	Tom Lendacky, x86
In-Reply-To: <20260527160716.GN2487554@ziepe.ca>

On Wed, May 27, 2026 at 01:07:16PM -0300, Jason Gunthorpe wrote:
> > Setting memory decrypted is a dangerous operations and should only
> > be available to core code.  We should have various allocators for
> > decrypted code, but not export the functionality to random code.
> 
> At the very least an EXPORT_SYMBOL_NS.
> 
> Looks like there are about 3 modules using it already..

Looks like more to me...

In any case, we exported them back then for some framebuffer things:

95cf9264d5f3 ("x86, drm, fbdev: Do not specify encrypted memory for video mappings")

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette


^ permalink raw reply

* Re: [PATCH mm-unstable RFC v4 4/7] mm/huge_memory: refactor copy_huge_pmd()
From: Dev Jain @ 2026-05-27 12:24 UTC (permalink / raw)
  To: Yin Tirui, Andrew Morton, Matthew Wilcox, David Hildenbrand,
	Lorenzo Stoakes, Juergen Gross, Jonathan Cameron, Will Deacon
  Cc: Catalin Marinas, Peter Xu, Luiz Capitulino, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H . Peter Anvin,
	Andy Lutomirski, Peter Zijlstra, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Christophe Leroy,
	Liam R . Howlett, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
	Barry Song, Lance Yang, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Anshuman Khandual, Rohan McLure,
	Kevin Brodsky, Alistair Popple, Andrew Donnellan, Pasha Tatashin,
	Baoquan He, Thomas Huth, Coiby Xu, Dan Williams, Yu-cheng Yu,
	Lu Baolu, Conor Dooley, Rik van Riel, wangkefeng.wang, chenjun102,
	linux-mm, linux-kernel, x86, linux-arm-kernel, linuxppc-dev,
	linux-pm
In-Reply-To: <20260526145003.88445-5-yintirui@huawei.com>



On 26/05/26 8:20 pm, Yin Tirui wrote:
> Classify the source PMD via pmd_present() and vm_normal_folio_pmd(),
> matching the way the PTE path uses pte_present() and vm_normal_page().
> This moves the present-PMD decision from VMA identity checks to the
> actual PMD/folio state.
> 
> Drop the defensive "if (!pmd_trans_huge(pmd)) goto out_unlock" branch:
> with mmap_write_lock held during fork, it should not occur.

Split this from this patch? This is a functional change so will be better
to review it separately.

> 
> Extract the present-PMD side of copy_huge_pmd() into
> copy_present_huge_pmd(). The helper owns the child pgtable passed by the
> caller: it either deposits the pgtable when installing a copied PMD, or
> frees it on paths that do not install one.
> 
> The child pgtable is now allocated once up front and freed on every skip
> path. This makes file/shmem and PFNMAP/special skip paths take the PMD
> locks and free the preallocated pgtable before returning. These are not
> expected to be hot paths, and the PFNMAP case is reused by the follow-up
> PMD PFNMAP copy support.
> 
> Signed-off-by: Yin Tirui <yintirui@huawei.com>
> ---

Since the series is still marked RFC, I think it would be better to send
the refactor patches separately?

>  mm/huge_memory.c | 175 +++++++++++++++++++++++++----------------------
>  1 file changed, 95 insertions(+), 80 deletions(-)
> 
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 9832ee910d5e..3964258ff91d 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -1879,6 +1879,82 @@ bool touch_pmd(struct vm_area_struct *vma, unsigned long addr,
>  	return false;
>  }
>  
> +static int copy_present_huge_pmd(
> +		struct mm_struct *dst_mm, struct mm_struct *src_mm,
> +		pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
> +		struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma,
> +		pmd_t pmd, pgtable_t pgtable, bool *need_split)
> +{
> +	struct folio *src_folio;
> +	bool wrprotect = true;
> +
> +	src_folio = vm_normal_folio_pmd(src_vma, addr, pmd);
> +	if (!src_folio) {
> +		/*
> +		 * When page table lock is held, the huge zero pmd should not be
> +		 * under splitting since we don't split the page itself, only pmd to
> +		 * a page table.
> +		 */
> +		if (is_huge_zero_pmd(pmd)) {
> +			/*
> +			 * mm_get_huge_zero_folio() will never allocate a new
> +			 * folio here, since we already have a zero page to
> +			 * copy. It just takes a reference.
> +			 */
> +			mm_get_huge_zero_folio(dst_mm);
> +			goto set_pmd;
> +		}
> +
> +		/*
> +		 * Making sure it's not a CoW VMA with writable
> +		 * mapping, otherwise it means either the anon page wrongly
> +		 * applied special bit, or we made the PRIVATE mapping be
> +		 * able to wrongly write to the backend MMIO.
> +		 */
> +		VM_WARN_ON_ONCE(is_cow_mapping(src_vma->vm_flags) && pmd_write(pmd));
> +		pte_free(dst_mm, pgtable);
> +		pgtable = NULL;
> +		wrprotect = false;
> +		goto set_pmd;
> +	}
> +
> +	/* File THPs are copied lazily by refaulting. */
> +	if (!folio_test_anon(src_folio)) {
> +		pte_free(dst_mm, pgtable);
> +		return 0;
> +	}


You removed !vma_is_anonymous to condense it into !folio_test_anon.
For private-file mappings that is not true, but okay since PMD mapping
is not supported.

> +
> +	folio_get(src_folio);
> +	if (unlikely(folio_try_dup_anon_rmap_pmd(src_folio,
> +							&src_folio->page,
> +							dst_vma, src_vma))) {
> +		/* Page maybe pinned: split and retry the fault on PTEs. */
> +		folio_put(src_folio);
> +		pte_free(dst_mm, pgtable);
> +		*need_split = true;
> +		return -EAGAIN;
> +	}
> +	add_mm_counter(dst_mm, MM_ANONPAGES, HPAGE_PMD_NR);
> +
> +set_pmd:
> +	if (pgtable) {
> +		mm_inc_nr_ptes(dst_mm);
> +		pgtable_trans_huge_deposit(dst_mm, dst_pmd, pgtable);
> +	}
> +
> +	if (wrprotect) {
> +		pmdp_set_wrprotect(src_mm, addr, src_pmd);
> +		if (!userfaultfd_wp(dst_vma))
> +			pmd = pmd_clear_uffd_wp(pmd);
> +		pmd = pmd_wrprotect(pmd);
> +	}
> +
> +	pmd = pmd_mkold(pmd);
> +	set_pmd_at(dst_mm, addr, dst_pmd, pmd);
> +
> +	return 0;
> +}
> +
>  static void copy_huge_non_present_pmd(
>  		struct mm_struct *dst_mm, struct mm_struct *src_mm,
>  		pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
> @@ -1940,104 +2016,43 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
>  		  struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma)
>  {
>  	spinlock_t *dst_ptl, *src_ptl;
> -	struct page *src_page;
> -	struct folio *src_folio;
> -	pmd_t pmd;
>  	pgtable_t pgtable = NULL;
> -	int ret = -ENOMEM;
> -
> -	pmd = pmdp_get_lockless(src_pmd);
> -	if (unlikely(pmd_present(pmd) && pmd_special(pmd) &&
> -		     !is_huge_zero_pmd(pmd))) {
> -		dst_ptl = pmd_lock(dst_mm, dst_pmd);
> -		src_ptl = pmd_lockptr(src_mm, src_pmd);
> -		spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
> -		/*
> -		 * No need to recheck the pmd, it can't change with write
> -		 * mmap lock held here.
> -		 *
> -		 * Meanwhile, making sure it's not a CoW VMA with writable
> -		 * mapping, otherwise it means either the anon page wrongly
> -		 * applied special bit, or we made the PRIVATE mapping be
> -		 * able to wrongly write to the backend MMIO.
> -		 */
> -		VM_WARN_ON_ONCE(is_cow_mapping(src_vma->vm_flags) && pmd_write(pmd));
> -		goto set_pmd;
> -	}
> -
> -	/* Skip if can be re-fill on fault */
> -	if (!vma_is_anonymous(dst_vma))
> -		return 0;
> +	bool need_split = false;
> +	int ret = 0;
> +	pmd_t pmd;
>  
>  	pgtable = pte_alloc_one(dst_mm);
>  	if (unlikely(!pgtable))
> -		goto out;
> +		return -ENOMEM;
>  
>  	dst_ptl = pmd_lock(dst_mm, dst_pmd);
>  	src_ptl = pmd_lockptr(src_mm, src_pmd);
>  	spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
>  
> -	ret = -EAGAIN;
>  	pmd = *src_pmd;
>  
> -	if (unlikely(thp_migration_supported() &&
> -		     pmd_is_valid_softleaf(pmd))) {
> -		copy_huge_non_present_pmd(dst_mm, src_mm, dst_pmd, src_pmd, addr,
> +	if (likely(pmd_present(pmd))) {
> +		ret = copy_present_huge_pmd(dst_mm, src_mm, dst_pmd, src_pmd, addr,
> +					  dst_vma, src_vma, pmd, pgtable, &need_split);
> +	} else if (unlikely(thp_migration_supported() && pmd_is_valid_softleaf(pmd))) {
> +		if (unlikely(!vma_is_anonymous(dst_vma)))
> +			pte_free(dst_mm, pgtable);
> +		else
> +			copy_huge_non_present_pmd(dst_mm, src_mm, dst_pmd, src_pmd, addr,
>  					  dst_vma, src_vma, pmd, pgtable);
> -		ret = 0;
> -		goto out_unlock;
> -	}
> -
> -	if (unlikely(!pmd_trans_huge(pmd))) {
> +	} else {
> +		VM_WARN_ONCE(1, "unexpected non-present PMD %llx\n",
> +				(unsigned long long)pmd_val(pmd));
>  		pte_free(dst_mm, pgtable);
> -		goto out_unlock;
> -	}
> -	/*
> -	 * When page table lock is held, the huge zero pmd should not be
> -	 * under splitting since we don't split the page itself, only pmd to
> -	 * a page table.
> -	 */
> -	if (is_huge_zero_pmd(pmd)) {
> -		/*
> -		 * mm_get_huge_zero_folio() will never allocate a new
> -		 * folio here, since we already have a zero page to
> -		 * copy. It just takes a reference.
> -		 */
> -		mm_get_huge_zero_folio(dst_mm);
> -		goto out_zero_page;
> +		ret = -EAGAIN;
>  	}
>  
> -	src_page = pmd_page(pmd);
> -	VM_BUG_ON_PAGE(!PageHead(src_page), src_page);
> -	src_folio = page_folio(src_page);
> +	spin_unlock(src_ptl);
> +	spin_unlock(dst_ptl);
>  
> -	folio_get(src_folio);
> -	if (unlikely(folio_try_dup_anon_rmap_pmd(src_folio, src_page, dst_vma, src_vma))) {
> -		/* Page maybe pinned: split and retry the fault on PTEs. */
> -		folio_put(src_folio);
> -		pte_free(dst_mm, pgtable);
> -		spin_unlock(src_ptl);
> -		spin_unlock(dst_ptl);
> +	if (unlikely(need_split))
>  		__split_huge_pmd(src_vma, src_pmd, addr, false);
> -		return -EAGAIN;
> -	}
> -	add_mm_counter(dst_mm, MM_ANONPAGES, HPAGE_PMD_NR);
> -out_zero_page:
> -	mm_inc_nr_ptes(dst_mm);
> -	pgtable_trans_huge_deposit(dst_mm, dst_pmd, pgtable);
> -	pmdp_set_wrprotect(src_mm, addr, src_pmd);
> -	if (!userfaultfd_wp(dst_vma))
> -		pmd = pmd_clear_uffd_wp(pmd);
> -	pmd = pmd_wrprotect(pmd);
> -set_pmd:
> -	pmd = pmd_mkold(pmd);
> -	set_pmd_at(dst_mm, addr, dst_pmd, pmd);
>  
> -	ret = 0;
> -out_unlock:
> -	spin_unlock(src_ptl);
> -	spin_unlock(dst_ptl);
> -out:
>  	return ret;
>  }
>  



^ permalink raw reply

* [PATCH] gpio: move ppc4xx gpio driver from arch/powerpc to drivers/gpio
From: Rosen Penev @ 2026-05-28  2:56 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Linus Walleij, Bartosz Golaszewski,
	open list, open list:GPIO SUBSYSTEM

Move the ppc4xx gpio driver out of arch/powerpc/platforms/44x/ into
drivers/gpio/gpio-ppc4xx.c. The driver has no architecture-specific
dependencies and follows the same pattern as other PowerPC GPIO
drivers already in drivers/gpio/ (e.g. gpio-mpc8xxx, gpio-mpc5200).

- Renamed Kconfig symbol from PPC4xx_GPIO to GPIO_PPC4XX
- Updated ppc44x_defconfig and warp_defconfig to use the new symbol
- Marked the new option as tristate (was bool) since the driver
  supports module build via module_platform_driver()
- Added COMPILE_TEST support. Needs PPC as clrbits32 is in use.

Assisted-by: OpenCode:BigPickle
Signed-off-by: mangix <mangix@disroot.org>
---
 arch/powerpc/configs/44x/warp_defconfig                    | 2 +-
 arch/powerpc/configs/ppc44x_defconfig                      | 2 +-
 arch/powerpc/platforms/44x/Kconfig                         | 7 -------
 arch/powerpc/platforms/44x/Makefile                        | 1 -
 drivers/gpio/Kconfig                                       | 7 +++++++
 drivers/gpio/Makefile                                      | 1 +
 .../platforms/44x/gpio.c => drivers/gpio/gpio-ppc4xx.c     | 0
 7 files changed, 10 insertions(+), 10 deletions(-)
 rename arch/powerpc/platforms/44x/gpio.c => drivers/gpio/gpio-ppc4xx.c (100%)

diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig
index 5757625469c4..380fa15af68d 100644
--- a/arch/powerpc/configs/44x/warp_defconfig
+++ b/arch/powerpc/configs/44x/warp_defconfig
@@ -12,7 +12,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_EBONY is not set
 CONFIG_WARP=y
-CONFIG_PPC4xx_GPIO=y
+CONFIG_GPIO_PPC4XX=y
 CONFIG_HZ_1000=y
 CONFIG_CMDLINE="ip=on"
 # CONFIG_PCI is not set
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
index 41c930f74ed4..57a7342232d7 100644
--- a/arch/powerpc/configs/ppc44x_defconfig
+++ b/arch/powerpc/configs/ppc44x_defconfig
@@ -22,7 +22,7 @@ CONFIG_GLACIER=y
 CONFIG_REDWOOD=y
 CONFIG_EIGER=y
 CONFIG_YOSEMITE=y
-CONFIG_PPC4xx_GPIO=y
+CONFIG_GPIO_PPC4XX=y
 CONFIG_MATH_EMULATION=y
 CONFIG_NET=y
 CONFIG_PACKET=y
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index fc79f8466933..150813cea945 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -227,13 +227,6 @@ config PPC44x_SIMPLE
 	help
 	  This option enables the simple PowerPC 44x platform support.
 
-config PPC4xx_GPIO
-	bool "PPC4xx GPIO support"
-	depends on 44x
-	select GPIOLIB
-	help
-	  Enable gpiolib support for ppc440 based boards
-
 # 44x specific CPU modules, selected based on the board above.
 config 440EP
 	bool
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index ca7b1bb442d9..179468a00f5e 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -15,4 +15,3 @@ obj-$(CONFIG_FSP2)	+= fsp2.o
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_PPC4xx_HSTA_MSI)	+= hsta_msi.o
 obj-$(CONFIG_PPC4xx_CPM)	+= cpm.o
-obj-$(CONFIG_PPC4xx_GPIO)	+= gpio.o
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 020e51e30317..b87d2329900b 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -584,6 +584,13 @@ config GPIO_POLARFIRE_SOC
 	help
 	  Say yes here to support the GPIO controllers on Microchip FPGAs.
 
+config GPIO_PPC4XX
+	tristate "PPC4xx GPIO support"
+	depends on 44x || (PPC && COMPILE_TEST)
+	select GPIO_GENERIC
+	help
+	  Enable gpiolib support for ppc440 based boards.
+
 config GPIO_PXA
 	bool "PXA GPIO support"
 	depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index b267598b517d..192242988ecb 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -145,6 +145,7 @@ obj-$(CONFIG_GPIO_PCIE_IDIO_24)		+= gpio-pcie-idio-24.o
 obj-$(CONFIG_GPIO_PCI_IDIO_16)		+= gpio-pci-idio-16.o
 obj-$(CONFIG_GPIO_PISOSR)		+= gpio-pisosr.o
 obj-$(CONFIG_GPIO_PL061)		+= gpio-pl061.o
+obj-$(CONFIG_GPIO_PPC4XX)		+= gpio-ppc4xx.o
 obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)	+= gpio-pmic-eic-sprd.o
 obj-$(CONFIG_GPIO_POLARFIRE_SOC)	+= gpio-mpfs.o
 obj-$(CONFIG_GPIO_PXA)			+= gpio-pxa.o
diff --git a/arch/powerpc/platforms/44x/gpio.c b/drivers/gpio/gpio-ppc4xx.c
similarity index 100%
rename from arch/powerpc/platforms/44x/gpio.c
rename to drivers/gpio/gpio-ppc4xx.c
-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH] gpio: move ppc4xx gpio driver from arch/powerpc to drivers/gpio
From: Rosen Penev @ 2026-05-28  3:05 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Linus Walleij, Bartosz Golaszewski,
	open list, open list:GPIO SUBSYSTEM
In-Reply-To: <20260528025610.713514-1-rosenp@gmail.com>

On Wed, May 27, 2026 at 7:56 PM Rosen Penev <rosenp@gmail.com> wrote:
>
> Move the ppc4xx gpio driver out of arch/powerpc/platforms/44x/ into
> drivers/gpio/gpio-ppc4xx.c. The driver has no architecture-specific
> dependencies and follows the same pattern as other PowerPC GPIO
> drivers already in drivers/gpio/ (e.g. gpio-mpc8xxx, gpio-mpc5200).
>
> - Renamed Kconfig symbol from PPC4xx_GPIO to GPIO_PPC4XX
> - Updated ppc44x_defconfig and warp_defconfig to use the new symbol
> - Marked the new option as tristate (was bool) since the driver
>   supports module build via module_platform_driver()
> - Added COMPILE_TEST support. Needs PPC as clrbits32 is in use.
>
> Assisted-by: OpenCode:BigPickle
> Signed-off-by: mangix <mangix@disroot.org>
Sigh forgot to check this. Was too focused on testing this.
> ---
>  arch/powerpc/configs/44x/warp_defconfig                    | 2 +-
>  arch/powerpc/configs/ppc44x_defconfig                      | 2 +-
>  arch/powerpc/platforms/44x/Kconfig                         | 7 -------
>  arch/powerpc/platforms/44x/Makefile                        | 1 -
>  drivers/gpio/Kconfig                                       | 7 +++++++
>  drivers/gpio/Makefile                                      | 1 +
>  .../platforms/44x/gpio.c => drivers/gpio/gpio-ppc4xx.c     | 0
>  7 files changed, 10 insertions(+), 10 deletions(-)
>  rename arch/powerpc/platforms/44x/gpio.c => drivers/gpio/gpio-ppc4xx.c (100%)
>
> diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig
> index 5757625469c4..380fa15af68d 100644
> --- a/arch/powerpc/configs/44x/warp_defconfig
> +++ b/arch/powerpc/configs/44x/warp_defconfig
> @@ -12,7 +12,7 @@ CONFIG_MODULE_UNLOAD=y
>  # CONFIG_BLK_DEV_BSG is not set
>  # CONFIG_EBONY is not set
>  CONFIG_WARP=y
> -CONFIG_PPC4xx_GPIO=y
> +CONFIG_GPIO_PPC4XX=y
>  CONFIG_HZ_1000=y
>  CONFIG_CMDLINE="ip=on"
>  # CONFIG_PCI is not set
> diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
> index 41c930f74ed4..57a7342232d7 100644
> --- a/arch/powerpc/configs/ppc44x_defconfig
> +++ b/arch/powerpc/configs/ppc44x_defconfig
> @@ -22,7 +22,7 @@ CONFIG_GLACIER=y
>  CONFIG_REDWOOD=y
>  CONFIG_EIGER=y
>  CONFIG_YOSEMITE=y
> -CONFIG_PPC4xx_GPIO=y
> +CONFIG_GPIO_PPC4XX=y
>  CONFIG_MATH_EMULATION=y
>  CONFIG_NET=y
>  CONFIG_PACKET=y
> diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
> index fc79f8466933..150813cea945 100644
> --- a/arch/powerpc/platforms/44x/Kconfig
> +++ b/arch/powerpc/platforms/44x/Kconfig
> @@ -227,13 +227,6 @@ config PPC44x_SIMPLE
>         help
>           This option enables the simple PowerPC 44x platform support.
>
> -config PPC4xx_GPIO
> -       bool "PPC4xx GPIO support"
> -       depends on 44x
> -       select GPIOLIB
> -       help
> -         Enable gpiolib support for ppc440 based boards
> -
>  # 44x specific CPU modules, selected based on the board above.
>  config 440EP
>         bool
> diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
> index ca7b1bb442d9..179468a00f5e 100644
> --- a/arch/powerpc/platforms/44x/Makefile
> +++ b/arch/powerpc/platforms/44x/Makefile
> @@ -15,4 +15,3 @@ obj-$(CONFIG_FSP2)    += fsp2.o
>  obj-$(CONFIG_PCI)              += pci.o
>  obj-$(CONFIG_PPC4xx_HSTA_MSI)  += hsta_msi.o
>  obj-$(CONFIG_PPC4xx_CPM)       += cpm.o
> -obj-$(CONFIG_PPC4xx_GPIO)      += gpio.o
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 020e51e30317..b87d2329900b 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -584,6 +584,13 @@ config GPIO_POLARFIRE_SOC
>         help
>           Say yes here to support the GPIO controllers on Microchip FPGAs.
>
> +config GPIO_PPC4XX
> +       tristate "PPC4xx GPIO support"
> +       depends on 44x || (PPC && COMPILE_TEST)
> +       select GPIO_GENERIC
> +       help
> +         Enable gpiolib support for ppc440 based boards.
> +
>  config GPIO_PXA
>         bool "PXA GPIO support"
>         depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index b267598b517d..192242988ecb 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -145,6 +145,7 @@ obj-$(CONFIG_GPIO_PCIE_IDIO_24)             += gpio-pcie-idio-24.o
>  obj-$(CONFIG_GPIO_PCI_IDIO_16)         += gpio-pci-idio-16.o
>  obj-$(CONFIG_GPIO_PISOSR)              += gpio-pisosr.o
>  obj-$(CONFIG_GPIO_PL061)               += gpio-pl061.o
> +obj-$(CONFIG_GPIO_PPC4XX)              += gpio-ppc4xx.o
>  obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)       += gpio-pmic-eic-sprd.o
>  obj-$(CONFIG_GPIO_POLARFIRE_SOC)       += gpio-mpfs.o
>  obj-$(CONFIG_GPIO_PXA)                 += gpio-pxa.o
> diff --git a/arch/powerpc/platforms/44x/gpio.c b/drivers/gpio/gpio-ppc4xx.c
> similarity index 100%
> rename from arch/powerpc/platforms/44x/gpio.c
> rename to drivers/gpio/gpio-ppc4xx.c
> --
> 2.54.0
>


^ permalink raw reply

* Re: [PATCH v14 7/8] arm64: introduce copy_mc_to_kernel() implementation
From: Shuai Xue @ 2026-05-28  3:10 UTC (permalink / raw)
  To: Ruidong Tian, catalin.marinas, will, rafael, tony.luck, guohanjun,
	mchehab, tongtiangen, james.morse, robin.murphy, andreyknvl,
	dvyukov, vincenzo.frascino, mpe, npiggin, ryabinin.a.a, glider,
	christophe.leroy, aneesh.kumar, naveen.n.rao, tglx, mingo
  Cc: linux-arm-kernel, linux-mm, linuxppc-dev, linux-kernel, kasan-dev
In-Reply-To: <20260518084956.2538442-8-tianruidong@linux.alibaba.com>



On 5/18/26 4:49 PM, Ruidong Tian wrote:
> From: Tong Tiangen <tongtiangen@huawei.com>
> 
> The copy_mc_to_kernel() helper is memory copy implementation that handles
> source exceptions. It can be used in memory copy scenarios that tolerate
> hardware memory errors(e.g: pmem_read/dax_copy_to_iter).
> 
> Currently, only x86 and ppc support this helper, Add this for ARM64 as
> well, if ARCH_HAS_COPY_MC is defined, by implementing copy_mc_to_kernel()
> and memcpy_mc() functions.
> 
> Because there is no caller-saved GPR is available for saving "bytes not
> copied" in memcpy(), the memcpy_mc() is referenced to the implementation
> of copy_from_user(). In addition, the fixup of MOPS insn is not considered
> at present.
> 
> [Ruidong: refactor memcpy_mc on top of the new memcpy implementation.]
> 
> Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
> Signed-off-by: Ruidong Tian <tianruidong@linux.alibaba.com>
> ---
>   arch/arm64/include/asm/string.h  |   5 +
>   arch/arm64/include/asm/uaccess.h |  17 +++
>   arch/arm64/lib/Makefile          |   2 +-
>   arch/arm64/lib/memcpy.S          | 253 +++----------------------------
>   arch/arm64/lib/memcpy_mc.S       |  56 +++++++
>   arch/arm64/lib/memcpy_template.S | 249 ++++++++++++++++++++++++++++++
>   mm/kasan/shadow.c                |  12 ++
>   7 files changed, 359 insertions(+), 235 deletions(-)
>   create mode 100644 arch/arm64/lib/memcpy_mc.S
>   create mode 100644 arch/arm64/lib/memcpy_template.S
> 
> diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
> index 3a3264ff47b9..23eca4fb24fa 100644
> --- a/arch/arm64/include/asm/string.h
> +++ b/arch/arm64/include/asm/string.h
> @@ -35,6 +35,10 @@ extern void *memchr(const void *, int, __kernel_size_t);
>   extern void *memcpy(void *, const void *, __kernel_size_t);
>   extern void *__memcpy(void *, const void *, __kernel_size_t);
>   
> +#define __HAVE_ARCH_MEMCPY_MC
> +extern int memcpy_mc(void *, const void *, __kernel_size_t);
> +extern int __memcpy_mc(void *, const void *, __kernel_size_t);
> +
>   #define __HAVE_ARCH_MEMMOVE
>   extern void *memmove(void *, const void *, __kernel_size_t);
>   extern void *__memmove(void *, const void *, __kernel_size_t);
> @@ -57,6 +61,7 @@ void memcpy_flushcache(void *dst, const void *src, size_t cnt);
>    */
>   
>   #define memcpy(dst, src, len) __memcpy(dst, src, len)
> +#define memcpy_mc(dst, src, len) __memcpy_mc(dst, src, len)
>   #define memmove(dst, src, len) __memmove(dst, src, len)
>   #define memset(s, c, n) __memset(s, c, n)
>   
> diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
> index b0c83a08dda9..93277eca2268 100644
> --- a/arch/arm64/include/asm/uaccess.h
> +++ b/arch/arm64/include/asm/uaccess.h
> @@ -499,5 +499,22 @@ static inline size_t probe_subpage_writeable(const char __user *uaddr,
>   }
>   
>   #endif /* CONFIG_ARCH_HAS_SUBPAGE_FAULTS */
> +#ifdef CONFIG_ARCH_HAS_COPY_MC
> +/**
> + * copy_mc_to_kernel - memory copy that handles source exceptions
> + *
> + * @to:		destination address
> + * @from:	source address
> + * @size:	number of bytes to copy
> + *
> + * Return 0 for success, or bytes not copied.
> + */
> +static inline unsigned long __must_check
> +copy_mc_to_kernel(void *to, const void *from, unsigned long size)
> +{
> +	return memcpy_mc(to, from, size);
> +}
> +#define copy_mc_to_kernel copy_mc_to_kernel
> +#endif
>   
>   #endif /* __ASM_UACCESS_H */
> diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile
> index 1f4c3f743a20..a5820e6c33d4 100644
> --- a/arch/arm64/lib/Makefile
> +++ b/arch/arm64/lib/Makefile
> @@ -7,7 +7,7 @@ lib-y		:= clear_user.o delay.o copy_from_user.o		\
>   
>   lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o
>   
> -lib-$(CONFIG_ARCH_HAS_COPY_MC) += copy_mc_page.o
> +lib-$(CONFIG_ARCH_HAS_COPY_MC) += copy_mc_page.o memcpy_mc.o
>   
>   obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
>   
> diff --git a/arch/arm64/lib/memcpy.S b/arch/arm64/lib/memcpy.S
> index 9b99106fb95f..ef6aea2de9b4 100644
> --- a/arch/arm64/lib/memcpy.S
> +++ b/arch/arm64/lib/memcpy.S
> @@ -15,247 +15,32 @@
>    *
>    */
>   
> -#define L(label) .L ## label
> +	.macro ldrb1 reg, addr:vararg
> +		ldrb  \reg, \addr
> +	.endm
>   
> -#define dstin	x0
> -#define src	x1
> -#define count	x2
> -#define dst	x3
> -#define srcend	x4
> -#define dstend	x5
> -#define A_l	x6
> -#define A_lw	w6
> -#define A_h	x7
> -#define B_l	x8
> -#define B_lw	w8
> -#define B_h	x9
> -#define C_l	x10
> -#define C_lw	w10
> -#define C_h	x11
> -#define D_l	x12
> -#define D_h	x13
> -#define E_l	x14
> -#define E_h	x15
> -#define F_l	x16
> -#define F_h	x17
> -#define G_l	count
> -#define G_h	dst
> -#define H_l	src
> -#define H_h	srcend
> -#define tmp1	x14
> +	.macro ldr1 reg, addr:vararg
> +		ldr   \reg, \addr
> +	.endm
>   
> -/* This implementation handles overlaps and supports both memcpy and memmove
> -   from a single entry point.  It uses unaligned accesses and branchless
> -   sequences to keep the code small, simple and improve performance.
> +	.macro ldp1 reg1, reg2, addr:vararg
> +		ldp   \reg1, \reg2, \addr
> +	.endm
>   
> -   Copies are split into 3 main cases: small copies of up to 32 bytes, medium
> -   copies of up to 128 bytes, and large copies.  The overhead of the overlap
> -   check is negligible since it is only required for large copies.
> +	.macro ret1
> +		ret
> +	.endm
>   
> -   Large copies use a software pipelined loop processing 64 bytes per iteration.
> -   The destination pointer is 16-byte aligned to minimize unaligned accesses.
> -   The loop tail is handled by always copying 64 bytes from the end.
> -*/
> +	.macro cpy1 dst, src, count
> +		.arch_extension mops
> +		cpyp [\dst]!, [\src]!, \count!
> +		cpym [\dst]!, [\src]!, \count!
> +		cpye [\dst]!, [\src]!, \count!
> +	.endm
>   
> -SYM_FUNC_START_LOCAL(__pi_memcpy_generic)
> -	add	srcend, src, count
> -	add	dstend, dstin, count
> -	cmp	count, 128
> -	b.hi	L(copy_long)
> -	cmp	count, 32
> -	b.hi	L(copy32_128)
> -
> -	/* Small copies: 0..32 bytes.  */
> -	cmp	count, 16
> -	b.lo	L(copy16)
> -	ldp	A_l, A_h, [src]
> -	ldp	D_l, D_h, [srcend, -16]
> -	stp	A_l, A_h, [dstin]
> -	stp	D_l, D_h, [dstend, -16]
> -	ret
> -
> -	/* Copy 8-15 bytes.  */
> -L(copy16):
> -	tbz	count, 3, L(copy8)
> -	ldr	A_l, [src]
> -	ldr	A_h, [srcend, -8]
> -	str	A_l, [dstin]
> -	str	A_h, [dstend, -8]
> -	ret
> -
> -	.p2align 3
> -	/* Copy 4-7 bytes.  */
> -L(copy8):
> -	tbz	count, 2, L(copy4)
> -	ldr	A_lw, [src]
> -	ldr	B_lw, [srcend, -4]
> -	str	A_lw, [dstin]
> -	str	B_lw, [dstend, -4]
> -	ret
> -
> -	/* Copy 0..3 bytes using a branchless sequence.  */
> -L(copy4):
> -	cbz	count, L(copy0)
> -	lsr	tmp1, count, 1
> -	ldrb	A_lw, [src]
> -	ldrb	C_lw, [srcend, -1]
> -	ldrb	B_lw, [src, tmp1]
> -	strb	A_lw, [dstin]
> -	strb	B_lw, [dstin, tmp1]
> -	strb	C_lw, [dstend, -1]
> -L(copy0):
> -	ret
> -
> -	.p2align 4
> -	/* Medium copies: 33..128 bytes.  */
> -L(copy32_128):
> -	ldp	A_l, A_h, [src]
> -	ldp	B_l, B_h, [src, 16]
> -	ldp	C_l, C_h, [srcend, -32]
> -	ldp	D_l, D_h, [srcend, -16]
> -	cmp	count, 64
> -	b.hi	L(copy128)
> -	stp	A_l, A_h, [dstin]
> -	stp	B_l, B_h, [dstin, 16]
> -	stp	C_l, C_h, [dstend, -32]
> -	stp	D_l, D_h, [dstend, -16]
> -	ret
> -
> -	.p2align 4
> -	/* Copy 65..128 bytes.  */
> -L(copy128):
> -	ldp	E_l, E_h, [src, 32]
> -	ldp	F_l, F_h, [src, 48]
> -	cmp	count, 96
> -	b.ls	L(copy96)
> -	ldp	G_l, G_h, [srcend, -64]
> -	ldp	H_l, H_h, [srcend, -48]
> -	stp	G_l, G_h, [dstend, -64]
> -	stp	H_l, H_h, [dstend, -48]
> -L(copy96):
> -	stp	A_l, A_h, [dstin]
> -	stp	B_l, B_h, [dstin, 16]
> -	stp	E_l, E_h, [dstin, 32]
> -	stp	F_l, F_h, [dstin, 48]
> -	stp	C_l, C_h, [dstend, -32]
> -	stp	D_l, D_h, [dstend, -16]
> -	ret
> -
> -	.p2align 4
> -	/* Copy more than 128 bytes.  */
> -L(copy_long):
> -	/* Use backwards copy if there is an overlap.  */
> -	sub	tmp1, dstin, src
> -	cbz	tmp1, L(copy0)
> -	cmp	tmp1, count
> -	b.lo	L(copy_long_backwards)
> -
> -	/* Copy 16 bytes and then align dst to 16-byte alignment.  */
> -
> -	ldp	D_l, D_h, [src]
> -	and	tmp1, dstin, 15
> -	bic	dst, dstin, 15
> -	sub	src, src, tmp1
> -	add	count, count, tmp1	/* Count is now 16 too large.  */
> -	ldp	A_l, A_h, [src, 16]
> -	stp	D_l, D_h, [dstin]
> -	ldp	B_l, B_h, [src, 32]
> -	ldp	C_l, C_h, [src, 48]
> -	ldp	D_l, D_h, [src, 64]!
> -	subs	count, count, 128 + 16	/* Test and readjust count.  */
> -	b.ls	L(copy64_from_end)
> -
> -L(loop64):
> -	stp	A_l, A_h, [dst, 16]
> -	ldp	A_l, A_h, [src, 16]
> -	stp	B_l, B_h, [dst, 32]
> -	ldp	B_l, B_h, [src, 32]
> -	stp	C_l, C_h, [dst, 48]
> -	ldp	C_l, C_h, [src, 48]
> -	stp	D_l, D_h, [dst, 64]!
> -	ldp	D_l, D_h, [src, 64]!
> -	subs	count, count, 64
> -	b.hi	L(loop64)
> -
> -	/* Write the last iteration and copy 64 bytes from the end.  */
> -L(copy64_from_end):
> -	ldp	E_l, E_h, [srcend, -64]
> -	stp	A_l, A_h, [dst, 16]
> -	ldp	A_l, A_h, [srcend, -48]
> -	stp	B_l, B_h, [dst, 32]
> -	ldp	B_l, B_h, [srcend, -32]
> -	stp	C_l, C_h, [dst, 48]
> -	ldp	C_l, C_h, [srcend, -16]
> -	stp	D_l, D_h, [dst, 64]
> -	stp	E_l, E_h, [dstend, -64]
> -	stp	A_l, A_h, [dstend, -48]
> -	stp	B_l, B_h, [dstend, -32]
> -	stp	C_l, C_h, [dstend, -16]
> -	ret
> -
> -	.p2align 4
> -
> -	/* Large backwards copy for overlapping copies.
> -	   Copy 16 bytes and then align dst to 16-byte alignment.  */
> -L(copy_long_backwards):
> -	ldp	D_l, D_h, [srcend, -16]
> -	and	tmp1, dstend, 15
> -	sub	srcend, srcend, tmp1
> -	sub	count, count, tmp1
> -	ldp	A_l, A_h, [srcend, -16]
> -	stp	D_l, D_h, [dstend, -16]
> -	ldp	B_l, B_h, [srcend, -32]
> -	ldp	C_l, C_h, [srcend, -48]
> -	ldp	D_l, D_h, [srcend, -64]!
> -	sub	dstend, dstend, tmp1
> -	subs	count, count, 128
> -	b.ls	L(copy64_from_start)
> -
> -L(loop64_backwards):
> -	stp	A_l, A_h, [dstend, -16]
> -	ldp	A_l, A_h, [srcend, -16]
> -	stp	B_l, B_h, [dstend, -32]
> -	ldp	B_l, B_h, [srcend, -32]
> -	stp	C_l, C_h, [dstend, -48]
> -	ldp	C_l, C_h, [srcend, -48]
> -	stp	D_l, D_h, [dstend, -64]!
> -	ldp	D_l, D_h, [srcend, -64]!
> -	subs	count, count, 64
> -	b.hi	L(loop64_backwards)
> -
> -	/* Write the last iteration and copy 64 bytes from the start.  */
> -L(copy64_from_start):
> -	ldp	G_l, G_h, [src, 48]
> -	stp	A_l, A_h, [dstend, -16]
> -	ldp	A_l, A_h, [src, 32]
> -	stp	B_l, B_h, [dstend, -32]
> -	ldp	B_l, B_h, [src, 16]
> -	stp	C_l, C_h, [dstend, -48]
> -	ldp	C_l, C_h, [src]
> -	stp	D_l, D_h, [dstend, -64]
> -	stp	G_l, G_h, [dstin, 48]
> -	stp	A_l, A_h, [dstin, 32]
> -	stp	B_l, B_h, [dstin, 16]
> -	stp	C_l, C_h, [dstin]
> -	ret
> -SYM_FUNC_END(__pi_memcpy_generic)
> -
> -#ifdef CONFIG_AS_HAS_MOPS
> -	.arch_extension mops
>   SYM_FUNC_START(__pi_memcpy)
> -alternative_if_not ARM64_HAS_MOPS
> -	b	__pi_memcpy_generic
> -alternative_else_nop_endif
> -
> -	mov	dst, dstin
> -	cpyp	[dst]!, [src]!, count!
> -	cpym	[dst]!, [src]!, count!
> -	cpye	[dst]!, [src]!, count!
> -	ret
> +#include "memcpy_template.S"
>   SYM_FUNC_END(__pi_memcpy)
> -#else
> -SYM_FUNC_ALIAS(__pi_memcpy, __pi_memcpy_generic)
> -#endif
>   
>   SYM_FUNC_ALIAS(__memcpy, __pi_memcpy)
>   EXPORT_SYMBOL(__memcpy)
> diff --git a/arch/arm64/lib/memcpy_mc.S b/arch/arm64/lib/memcpy_mc.S
> new file mode 100644
> index 000000000000..90624d35af4b
> --- /dev/null
> +++ b/arch/arm64/lib/memcpy_mc.S
> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2012-2021, Arm Limited.
> + *
> + * Adapted from the original at:
> + * https://github.com/ARM-software/optimized-routines/blob/afd6244a1f8d9229/string/aarch64/memcpy.S
> + */
> +
> +#include <linux/linkage.h>
> +#include <asm/assembler.h>
> +#include <asm/asm-uaccess.h>
> +
> +/* Assumptions:
> + *
> + * ARMv8-a, AArch64, unaligned accesses.
> + *
> + */
> +
> +	.macro ldrb1 reg, addr:vararg
> +		KERNEL_MEM_ERR(9998f, ldrb  \reg, \addr)
> +	.endm
> +
> +	.macro ldr1 reg, addr:vararg
> +		KERNEL_MEM_ERR(9998f, ldr   \reg, \addr)
> +	.endm
> +
> +	.macro ldp1 reg1, reg2, addr:vararg
> +		KERNEL_MEM_ERR(9998f, ldp   \reg1, \reg2, \addr)
> +	.endm
> +
> +	.macro ret1
> +		mov	x0, #0
> +		ret
> +	.endm
> +
> +	.macro cpy1 dst, src, count
> +	.arch_extension mops
> +	USER_CPY(9998f, 0, cpyp [\dst]!, [\src]!, \count!)
> +	USER_CPY(9996f, 0, cpym [\dst]!, [\src]!, \count!)
> +	USER_CPY(9996f, 0, cpye [\dst]!, [\src]!, \count!)

memcpy_mc.S annotates kernel-to-kernel MOPS with USER_CPY, registering
EX_TYPE_UACCESS_CPY entries. fixup_exception_me() then routes those
through ex_handler_uaccess_cpy(...., esr=0), whose
cpy_faulted_on_uaccess() applies page-fault read/write match
semantics. It only happens to work today because uaccess_is_write=0
matches a hard-coded fault_on_write=0; any tightening (e.g. real esr
threading) immediately breaks recovery.

Please fix this in conjunction with patch 3:
   (a) introduce KERNEL_CPY / EX_TYPE_KACCESS_CPY_MC, or
   (b) give EX_TYPE_UACCESS_CPY a separate MC handler in
       fixup_exception_me() that just redirects PC.

> +	.endm
> +
> +SYM_FUNC_START(__memcpy_mc)
> +#include "memcpy_template.S"
> +
> +	// Exception fixups
> +9996:	b.cs	9998f
> +	// Registers are in Option A format
> +	add	dst, dst, count
> +9998:	sub	x0, dstend, dstin			// bytes not copied


The MOPS branch in memcpy_template.S executes cpy1 *before* the
no_mops block runs `add dstend, dstin, count`. So if the cpy1 takes
an SEA, control jumps to the 9998 fixup in memcpy_mc.S:

     9998: sub x0, dstend, dstin            // bytes not copied
           ret

with dstend uninitialised. The "bytes not copied" return value is
arbitrary garbage in this case, and copy_mc_to_kernel() will pass
that to its caller (dax/pmem), which will then re-touch dst[0..ret]
based on a bogus boundary. Please initialise srcend/dstend before
the cpy1, or save the original count to a callee-saved register and
return it directly


> +	ret
> +SYM_FUNC_END(__memcpy_mc)
> +
> +EXPORT_SYMBOL(__memcpy_mc)
> +SYM_FUNC_ALIAS_WEAK(memcpy_mc, __memcpy_mc)
> +EXPORT_SYMBOL(memcpy_mc)
> diff --git a/arch/arm64/lib/memcpy_template.S b/arch/arm64/lib/memcpy_template.S
> new file mode 100644
> index 000000000000..205516c6e076
> --- /dev/null
> +++ b/arch/arm64/lib/memcpy_template.S
> @@ -0,0 +1,249 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2012-2021, Arm Limited.
> + *
> + * Adapted from the original at:
> + * https://github.com/ARM-software/optimized-routines/blob/afd6244a1f8d9229/string/aarch64/memcpy.S
> + */
> +
> +#include <linux/linkage.h>
> +#include <asm/assembler.h>
> +
> +/* Assumptions:
> + *
> + * ARMv8-a, AArch64, unaligned accesses.
> + *
> + */
> +
> +#define L(label) .L ## label
> +
> +#define dstin	x0
> +#define src	x1
> +#define count	x2
> +#define dst	x3
> +#define srcend	x4
> +#define dstend	x5
> +#define A_l	x6
> +#define A_lw	w6
> +#define A_h	x7
> +#define B_l	x8
> +#define B_lw	w8
> +#define B_h	x9
> +#define C_l	x10
> +#define C_lw	w10
> +#define C_h	x11
> +#define D_l	x12
> +#define D_h	x13
> +#define E_l	x14
> +#define E_h	x15
> +#define F_l	x16
> +#define F_h	x17
> +#define G_l	count
> +#define G_h	dst
> +#define H_l	src
> +#define H_h	srcend
> +#define tmp1	x14
> +
> +/* This implementation handles overlaps and supports both memcpy and memmove
> +   from a single entry point.  It uses unaligned accesses and branchless
> +   sequences to keep the code small, simple and improve performance.
> +
> +   Copies are split into 3 main cases: small copies of up to 32 bytes, medium
> +   copies of up to 128 bytes, and large copies.  The overhead of the overlap
> +   check is negligible since it is only required for large copies.
> +
> +   Large copies use a software pipelined loop processing 64 bytes per iteration.
> +   The destination pointer is 16-byte aligned to minimize unaligned accesses.
> +   The loop tail is handled by always copying 64 bytes from the end.
> +*/
> +
> +#ifdef CONFIG_AS_HAS_MOPS
> +alternative_if_not ARM64_HAS_MOPS
> +	b	L(no_mops):

Trailing colon. Should be:

     b   L(no_mops)

GNU as either rejects this outright or accepts it as nonsense. Either
way, FEAT_MOPS-capable toolchain builds (binutils >= 2.39, recent LLVM)
will fail or produce broken code. Please verify v2 with both
CONFIG_AS_HAS_MOPS=y and =n.


> +alternative_else_nop_endif
> +
> +	cpy1	dst, src, count

Does this execute the hardware copy instruction using an uninitialized
dst (x3) register?

Before the refactoring, memcpy.S had:

     mov  dst, dstin          ; x3 = x0 (preserve x0 as return value)
     cpyp [dst]!, [src]!, count!
     cpym [dst]!, [src]!, count!
     cpye [dst]!, [src]!, count!
     ret                      ; x0 still holds original dest

After: the template jumps straight to `cpy1 dst, src, count` which
expands to `cpyp [x3]!, [x1]!, x2!` with x3 uninitialised. On any
CPU with FEAT_MOPS (Cortex-X3/X4, A720, etc.) this writes src data to
whatever garbage address x3 held at function entry -- silent memory
corruption or an immediate abort, depending on luck.

This affects both plain memcpy() (through memcpy.S -> memcpy_template.S)
and memcpy_mc() (through memcpy_mc.S -> memcpy_template.S).


> +	ret1
> +#endif
> +
> +L(no_mops):
> +	add	srcend, src, count
> +	add	dstend, dstin, count
> +	cmp	count, 128
> +	b.hi	L(copy_long)
> +	cmp	count, 32
> +	b.hi	L(copy32_128)
> +
> +	/* Small copies: 0..32 bytes.  */
> +	cmp	count, 16
> +	b.lo	L(copy16)
> +	ldp1	A_l, A_h, [src]
> +	ldp1	D_l, D_h, [srcend, -16]
> +	stp	A_l, A_h, [dstin]
> +	stp	D_l, D_h, [dstend, -16]
> +	ret1
> +
> +	/* Copy 8-15 bytes.  */
> +L(copy16):
> +	tbz	count, 3, L(copy8)
> +	ldr1	A_l, [src]
> +	ldr1	A_h, [srcend, -8]
> +	str	A_l, [dstin]
> +	str	A_h, [dstend, -8]
> +	ret1
> +
> +	.p2align 3
> +	/* Copy 4-7 bytes.  */
> +L(copy8):
> +	tbz	count, 2, L(copy4)
> +	ldr1	A_lw, [src]
> +	ldr1	B_lw, [srcend, -4]
> +	str	A_lw, [dstin]
> +	str	B_lw, [dstend, -4]
> +	ret1
> +
> +	/* Copy 0..3 bytes using a branchless sequence.  */
> +L(copy4):
> +	cbz	count, L(copy0)
> +	lsr	tmp1, count, 1
> +	ldrb1	A_lw, [src]
> +	ldrb1	C_lw, [srcend, -1]
> +	ldrb1	B_lw, [src, tmp1]
> +	strb	A_lw, [dstin]
> +	strb	B_lw, [dstin, tmp1]
> +	strb	C_lw, [dstend, -1]
> +L(copy0):
> +	ret1
> +
> +	.p2align 4
> +	/* Medium copies: 33..128 bytes.  */
> +L(copy32_128):
> +	ldp1	A_l, A_h, [src]
> +	ldp1	B_l, B_h, [src, 16]
> +	ldp1	C_l, C_h, [srcend, -32]
> +	ldp1	D_l, D_h, [srcend, -16]
> +	cmp	count, 64
> +	b.hi	L(copy128)
> +	stp	A_l, A_h, [dstin]
> +	stp	B_l, B_h, [dstin, 16]
> +	stp	C_l, C_h, [dstend, -32]
> +	stp	D_l, D_h, [dstend, -16]
> +	ret1
> +
> +	.p2align 4
> +	/* Copy 65..128 bytes.  */
> +L(copy128):
> +	ldp1	E_l, E_h, [src, 32]
> +	ldp1	F_l, F_h, [src, 48]
> +	cmp	count, 96
> +	b.ls	L(copy96)
> +	ldp1	G_l, G_h, [srcend, -64]
> +	ldp1	H_l, H_h, [srcend, -48]
> +	stp	G_l, G_h, [dstend, -64]
> +	stp	H_l, H_h, [dstend, -48]
> +L(copy96):
> +	stp	A_l, A_h, [dstin]
> +	stp	B_l, B_h, [dstin, 16]
> +	stp	E_l, E_h, [dstin, 32]
> +	stp	F_l, F_h, [dstin, 48]
> +	stp	C_l, C_h, [dstend, -32]
> +	stp	D_l, D_h, [dstend, -16]
> +	ret1
> +
> +	.p2align 4
> +	/* Copy more than 128 bytes.  */
> +L(copy_long):
> +	/* Use backwards copy if there is an overlap.  */
> +	sub	tmp1, dstin, src
> +	cbz	tmp1, L(copy0)
> +	cmp	tmp1, count
> +	b.lo	L(copy_long_backwards)
> +
> +	/* Copy 16 bytes and then align dst to 16-byte alignment.  */
> +
> +	ldp1	D_l, D_h, [src]
> +	and	tmp1, dstin, 15
> +	bic	dst, dstin, 15
> +	sub	src, src, tmp1
> +	add	count, count, tmp1	/* Count is now 16 too large.  */
> +	ldp1	A_l, A_h, [src, 16]
> +	stp	D_l, D_h, [dstin]
> +	ldp1	B_l, B_h, [src, 32]
> +	ldp1	C_l, C_h, [src, 48]
> +	ldp1	D_l, D_h, [src, 64]!
> +	subs	count, count, 128 + 16	/* Test and readjust count.  */
> +	b.ls	L(copy64_from_end)
> +
> +L(loop64):
> +	stp	A_l, A_h, [dst, 16]
> +	ldp1	A_l, A_h, [src, 16]
> +	stp	B_l, B_h, [dst, 32]
> +	ldp1	B_l, B_h, [src, 32]
> +	stp	C_l, C_h, [dst, 48]
> +	ldp1	C_l, C_h, [src, 48]
> +	stp	D_l, D_h, [dst, 64]!
> +	ldp1	D_l, D_h, [src, 64]!
> +	subs	count, count, 64
> +	b.hi	L(loop64)
> +
> +	/* Write the last iteration and copy 64 bytes from the end.  */
> +L(copy64_from_end):
> +	ldp1	E_l, E_h, [srcend, -64]
> +	stp	A_l, A_h, [dst, 16]
> +	ldp1	A_l, A_h, [srcend, -48]
> +	stp	B_l, B_h, [dst, 32]
> +	ldp1	B_l, B_h, [srcend, -32]
> +	stp	C_l, C_h, [dst, 48]
> +	ldp1	C_l, C_h, [srcend, -16]
> +	stp	D_l, D_h, [dst, 64]
> +	stp	E_l, E_h, [dstend, -64]
> +	stp	A_l, A_h, [dstend, -48]
> +	stp	B_l, B_h, [dstend, -32]
> +	stp	C_l, C_h, [dstend, -16]
> +	ret1
> +
> +	.p2align 4
> +
> +	/* Large backwards copy for overlapping copies.
> +	   Copy 16 bytes and then align dst to 16-byte alignment.  */
> +L(copy_long_backwards):
> +	ldp1	D_l, D_h, [srcend, -16]
> +	and	tmp1, dstend, 15
> +	sub	srcend, srcend, tmp1
> +	sub	count, count, tmp1
> +	ldp1	A_l, A_h, [srcend, -16]
> +	stp	D_l, D_h, [dstend, -16]
> +	ldp1	B_l, B_h, [srcend, -32]
> +	ldp1	C_l, C_h, [srcend, -48]
> +	ldp1	D_l, D_h, [srcend, -64]!
> +	sub	dstend, dstend, tmp1
> +	subs	count, count, 128
> +	b.ls	L(copy64_from_start)
> +
> +L(loop64_backwards):
> +	stp	A_l, A_h, [dstend, -16]
> +	ldp1	A_l, A_h, [srcend, -16]
> +	stp	B_l, B_h, [dstend, -32]
> +	ldp1	B_l, B_h, [srcend, -32]
> +	stp	C_l, C_h, [dstend, -48]
> +	ldp1	C_l, C_h, [srcend, -48]
> +	stp	D_l, D_h, [dstend, -64]!
> +	ldp1	D_l, D_h, [srcend, -64]!
> +	subs	count, count, 64
> +	b.hi	L(loop64_backwards)
> +
> +	/* Write the last iteration and copy 64 bytes from the start.  */
> +L(copy64_from_start):
> +	ldp1	G_l, G_h, [src, 48]
> +	stp	A_l, A_h, [dstend, -16]
> +	ldp1	A_l, A_h, [src, 32]
> +	stp	B_l, B_h, [dstend, -32]
> +	ldp1	B_l, B_h, [src, 16]
> +	stp	C_l, C_h, [dstend, -48]
> +	ldp1	C_l, C_h, [src]
> +	stp	D_l, D_h, [dstend, -64]
> +	stp	G_l, G_h, [dstin, 48]
> +	stp	A_l, A_h, [dstin, 32]
> +	stp	B_l, B_h, [dstin, 16]
> +	stp	C_l, C_h, [dstin]
> +	ret1
> diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c
> index d286e0a04543..3128f0d9cc46 100644
> --- a/mm/kasan/shadow.c
> +++ b/mm/kasan/shadow.c
> @@ -79,6 +79,18 @@ void *memcpy(void *dest, const void *src, size_t len)
>   }
>   #endif
>   
> +#ifdef __HAVE_ARCH_MEMCPY_MC
> +#undef memcpy_mc
> +int memcpy_mc(void *dest, const void *src, size_t len)
> +{
> +	if (!kasan_check_range(src, len, false, _RET_IP_) ||
> +	    !kasan_check_range(dest, len, true, _RET_IP_))
> +		return (int)len;
> +
> +	return __memcpy_mc(dest, src, len);
> +}

memcpy_mc() is declared `int` while copy_mc_to_kernel() returns
unsigned long, and the asm side returns the full 64-bit (dstend - dstin).
For len >= 2GiB (real on dax_copy_to_iter over large NVDIMM regions)
the int truncation produces garbage "bytes not copied". Please use
unsigned long throughout:

     extern unsigned long memcpy_mc(void *, const void *,
                                    __kernel_size_t);
     extern unsigned long __memcpy_mc(void *, const void *,
                                      __kernel_size_t);

and in mm/kasan/shadow.c drop the `(int)len` cast accordingly:

     unsigned long memcpy_mc(...)
     {
         ...
             return len;          /* not (int)len */
         return __memcpy_mc(...);
     }


Thanks.
Shuai


^ permalink raw reply

* Re: [PATCH v14 8/8] lib/tests: memcpy_kunit: add memcpy_mc() and memcpy_mc_large() test
From: Shuai Xue @ 2026-05-28  3:17 UTC (permalink / raw)
  To: Ruidong Tian, catalin.marinas, will, rafael, tony.luck, guohanjun,
	mchehab, tongtiangen, james.morse, robin.murphy, andreyknvl,
	dvyukov, vincenzo.frascino, mpe, npiggin, ryabinin.a.a, glider,
	christophe.leroy, aneesh.kumar, naveen.n.rao, tglx, mingo
  Cc: linux-arm-kernel, linux-mm, linuxppc-dev, linux-kernel, kasan-dev
In-Reply-To: <20260518084956.2538442-9-tianruidong@linux.alibaba.com>



On 5/18/26 4:49 PM, Ruidong Tian wrote:
> memcpy_mc() is the Machine-Check safe memcpy variant that returns the
> number of bytes NOT copied on a hardware memory error, or 0 on success.
> 
> Add two test cases modeled after the existing memcpy_test() and
> memcpy_large_test() implementations:

Same build issue as with copy_mc_page_test: memcpy_mc() is an arm64-
only symbol.

1. Cross-architecture build break (BLOCKER, same as patch 6)

    These tests are gated on CONFIG_ARCH_HAS_COPY_MC, which is also
    selected by x86_64 and ppc64. Neither architecture provides a
    memcpy_mc() symbol -- they use copy_mc_to_kernel() directly.

    On x86_64:

        lib/tests/memcpy_kunit.c: error: implicit declaration of
        function 'memcpy_mc' [-Werror=implicit-function-declaration]

    Fix: guard with __HAVE_ARCH_MEMCPY_MC instead:

        #ifdef __HAVE_ARCH_MEMCPY_MC
        static void memcpy_mc_test(...) { ... }
        static void memcpy_mc_large_test(...) { ... }
        #endif


> 
> Signed-off-by: Ruidong Tian <tianruidong@linux.alibaba.com>
> ---
>   lib/tests/memcpy_kunit.c | 113 ++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 112 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/tests/memcpy_kunit.c b/lib/tests/memcpy_kunit.c
> index 85df53ccfb0c..b4b2dafb50f1 100644
> --- a/lib/tests/memcpy_kunit.c
> +++ b/lib/tests/memcpy_kunit.c
> @@ -552,6 +552,115 @@ static void copy_mc_page_test(struct kunit *test)
>   		memcmp(page_dst + PAGE_SIZE, page_zero, PAGE_SIZE), 0,
>   		"copy_mc_page overflow into adjacent page");
>   }
> +/*
> + * memcpy_mc() is a Machine-Check safe memcpy variant.
> + * Signature: int memcpy_mc(void *dst, const void *src, size_t len)
> + * Returns:   0 on success, or number of bytes NOT copied on MC error.
> + *
> + * In the normal (no-poison) path it must behave identically to memcpy()
> + * and always return 0.
> + */
> +static void memcpy_mc_test(struct kunit *test)
> +{
> +#define TEST_OP "memcpy_mc"
> +	struct some_bytes control = {
> +		.data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> +			  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> +			  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> +			  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> +		},
> +	};
> +	struct some_bytes zero = { };
> +	struct some_bytes middle = {
> +		.data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> +			  0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
> +			  0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
> +			  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> +		},
> +	};
> +	struct some_bytes three = {
> +		.data = { 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> +			  0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
> +			  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> +			  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> +			},
> +	};
> +	struct some_bytes dest = { };
> +	int ret, count;
> +	u8 *ptr;
> +
> +	/* Verify static initializers. */
> +	check(control, 0x20);
> +	check(zero, 0);
> +	compare("static initializers", dest, zero);
> +
> +	/* Verify assignment. */
> +	dest = control;
> +	compare("direct assignment", dest, control);
> +
> +	/* Verify complete overwrite. */
> +	ret = memcpy_mc(dest.data, control.data, sizeof(dest.data));
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +	compare("complete overwrite", dest, control);
> +
> +	/* Verify middle overwrite: 7 bytes at offset 12. */
> +	dest = control;
> +	ret = memcpy_mc(dest.data + 12, zero.data, 7);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +	compare("middle overwrite", dest, middle);
> +
> +	/* Verify zero-length copy is a no-op. */
> +	dest = control;
> +	ret = memcpy_mc(dest.data, zero.data, 0);
> +	KUNIT_ASSERT_EQ(test, ret, 0);
> +	compare("zero length", dest, control);
> +
> +	/* Verify argument side-effects aren't repeated. */
> +	dest = control;
> +	ptr = dest.data;
> +	count = 1;
> +	memcpy(ptr++, zero.data, count++);
> +	ptr += 8;
> +	memcpy(ptr++, zero.data, count++);


    This is a verbatim paste from memcpy_test(). The intent is to
    verify that the memcpy_mc macro doesn't double-evaluate arguments,
    but the test doesn't actually call memcpy_mc(). Please change the
    two memcpy() calls to memcpy_mc() and assert their return values.

Thanks
Shuai


^ permalink raw reply

* Re: [BUG] sched/cache: "Make LLC id continuous" causes NULL cpumask
From: Shrikanth Hegde @ 2026-05-28  4:58 UTC (permalink / raw)
  To: Chen, Yu C, kprateek.nayak
  Cc: srikar, venkat88, maddy, riteshh, chleroy, tim.c.chen, peterz,
	linux-kernel, linuxppc-dev, linux-sched
In-Reply-To: <42a19577-fe56-44b4-b0ed-37cde6d03ff5@linux.ibm.com>



On 5/27/26 11:37 PM, Shrikanth Hegde wrote:
> Hi Chen, Prateek.
> 
> On 5/27/26 9:35 PM, Chen, Yu C wrote:
>> Hi Shrikanth,
>>
>> On 5/27/2026 3:01 PM, Shrikanth Hegde wrote:
>>> Hi Chen, Prateek.
>>>
>>> I got back to work today, sorry for delay.
>>> I am trying to go through the mails.
>>> Apologies in case i have missed any bits.
>>>
>>
>> Thanks for taking a look at this!
>>
>>> On 5/26/26 7:38 PM, Chen Yu wrote:
>>>> Hi Prateek,
>>>>
>>>> On Tue, 26 May 2026 11:23:59 +0530, K Prateek Nayak 
>>>> <kprateek.nayak@amd.com> wrote:
>>>>> Hello Srikar,
>>>>>
>>>>> On 5/26/2026 10:28 AM, Srikar Dronamraju wrote:
>>>>>> L2 Cache reported here is for SMT8 Core aka CACHE domain.
>>>>>
>>>>> Apart for the scheduler, nothing in tree currently cares about
>>>>> cpu_coregroup_mask() except for drivers/base/arch_topology.c but
>>>>> Power doesn't select GENERIC_ARCH_TOPOLOGY.
>>>>>
>>>>> Why can't Power have an internal mask for MC domain (tl_mc_mask) and
>>>>> the scheduler can use cpu_coregroup_mask() for the actual LLc? (The L2
>>>>> mask in this case.)
>>>
>>> This seems wrong. there is no notion that coregroup_mask
>>> (MC domain) has to point at LLC domain.
>>>
>>> For example, on Shared LPAR, there is no MC domain and LLC is at SMT 
>>> core level.
>>> In that case coregroup_mask has point at SMT mask is wrong.
>>>
>>
>> On Shared LPAR, highest_flag_domain(SD_SHARE_LLC) selected the
>> SMT domain(L2 shared)prior to commit b5ea300a17e3.
>> Prateek suggested changing cpu_coregroup_mask() to use
>> cpu_l2_cache_mask(), which makes the LLC mask cover the same range.
>> sd_llc, size and grouping remain unchanged. Only sd_llc_id becomes
>> contiguous, which aligns with the intent of this commit.
>>
>> But yes, the naming is confusing. cpu_coregroup_mask suggests a
>> "group of cores", but after the change, it only covers threads
>> within a single SMT core.
>>
> 
> Yes. Though it might achieve the same effect, keeping it explicit may
> help in maintaining it better.
> 
> On PowerPC, there are these subtleties of Shared LPAR where MC domain
> per se doesn't exit etc, and on power9 and earlier has different 
> topologies. Maybe one could figure it all out and simplifies them into
> a few masks. But yes, it is slightly different as of today.
> 
>>> If we need a mask to point to the LLC mask which arch has to return, 
>>> then we would
>>> need a new api say cpu_llc_mask ? that can point accordingly.
>>>
>>
>> Do you mean something like this?
>> https://lore.kernel.org/lkml/8d14c844-b4a8-4af6- 
>> acab-2cfdd42225be@intel.com/
> 
> Yes. This is something i prefer, but not to make it point to l2 mask 
> always. See below diff which now make it boot on Shared Processor LPAR
> where i see panic without it.
> 
> Need to add proper comments where appropriate.
> 
> diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/ 
> asm/topology.h
> index 66ed5fe1b718..bd1db3b1dbb0 100644
> --- a/arch/powerpc/include/asm/topology.h
> +++ b/arch/powerpc/include/asm/topology.h
> @@ -131,6 +131,9 @@ static inline int cpu_to_coregroup_id(int cpu)
>   #ifdef CONFIG_SMP
>   #include <asm/cputable.h>
> 
> +const struct cpumask *arch_llc_mask(int cpu);
> +#define arch_llc_mask  arch_llc_mask
> +
>   struct cpumask *cpu_coregroup_mask(int cpu);
>   const struct cpumask *cpu_die_mask(int cpu);
>   int cpu_die_id(int cpu);
> diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
> index 3467f86fd78f..26c15c786c55 100644
> --- a/arch/powerpc/kernel/smp.c
> +++ b/arch/powerpc/kernel/smp.c
> @@ -1101,6 +1101,13 @@ const struct cpumask *cpu_die_mask(int cpu)
>   }
>   EXPORT_SYMBOL_GPL(cpu_die_mask);
> 
> +const struct cpumask *arch_llc_mask(int cpu)
> +{
> +       if (has_coregroup_support())
> +               return cpu_coregroup_mask(cpu);
> +       return cpu_smallcore_mask(cpu);


This function body needs change, since LLC is not at MC.
and I didn't account for power9.

Rest of the structure is what i would prefer the direction to go.
This will help future architectures too to account for their specific
needs.

What do you think?

> +}
> +
>   int cpu_die_id(int cpu)
>   {
>          if (has_coregroup_support())
> diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
> index df2ceb54c970..3b5155121276 100644
> --- a/kernel/sched/topology.c
> +++ b/kernel/sched/topology.c
> @@ -2063,7 +2063,11 @@ const struct cpumask *tl_mc_mask(struct 
> sched_domain_topology_level *tl, int cpu
>          return cpu_coregroup_mask(cpu);
>   }
> 
> +#ifndef arch_llc_mask
>   #define llc_mask(cpu) cpu_coregroup_mask(cpu)
> +#else
> +#define llc_mask(cpu) arch_llc_mask(cpu)
> +#endif
> 
>   #else
>   #define llc_mask(cpu) cpumask_of(cpu)
> 
> (One more subtlety; crash would be seen only with NR_CPUS=8192 as 
> CPUMASK_OFFSTACK=y, but that's a different concern altogether.)
> 
> 
>>
>>> I don't like mixing MC domain and LLC into one bit.
>>>
>>
>> [ ... ]
>>
>>>>   struct cpumask *cpu_coregroup_mask(int cpu)
>>>>   {
>>>> -    return per_cpu(cpu_coregroup_map, cpu);
>>>> +    return cpu_l2_cache_mask(cpu);
>>>> +}
>>>
>>> This looks wrong to me too. In different hardware topologies
>>> there maybe distinction between coregroup and l2 mask.
>>>
>>> Let me go through the code and see if there is better way.
>>>
>>
>> Sure, please go ahead - I'm on board with the direction
>> you settle on.
>>
>> thanks,
>> Chenyu
>>
> 



^ permalink raw reply

* Re: [PATCH v6 13/15] sh: cast away constness from the zero page when flushing it from the cache
From: Mike Rapoport @ 2026-05-28  5:46 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-kernel, will, catalin.marinas,
	mark.rutland, Ard Biesheuvel, Ryan Roberts, Anshuman Khandual,
	Liz Prucka, Seth Jenkins, Kees Cook, David Hildenbrand,
	Andrew Morton, Jann Horn, linux-mm, linux-hardening, linuxppc-dev,
	linux-sh, Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz
In-Reply-To: <20260526175846.2694125-30-ardb+git@google.com>

On Tue, May 26, 2026 at 07:59:00PM +0200, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb@kernel.org>
> 
> SH performs cache maintenance on the zero page during boot, presumably
> to ensure that any clearing of BSS that has occurred at startup is
> visible to other CPUs and DMA devices.

It flushes the cache there because before 6215d9f4470f ("arch, mm:
consolidate empty_zero_page") empty_zero_page used was for boot parameters
at the very early boot.

I removed memset(empty_zero_page, 0, PAGE_SIZE) that was a line above but
missed the cache flush. 

This whole "clear zero-page" can be removed IMO.
 
> The __flush_wback_region() function takes a void* argument, which is
> conceptually sound, but given that empty_zero_page[] must never be
> modified, it is being repainted as const, making it incompatible with a
> void* formal parameter.
> 
> Given the above, and the fact that __flush_wback_region() is in fact a
> function pointer variable with multiple implementations, take the easy
> way out, and cast away the constness in this particular invocation.
> 
> Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
> Cc: Rich Felker <dalias@libc.org>
> Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
>  arch/sh/mm/init.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
> index 4e40d5e96be9..acbb481cdbfe 100644
> --- a/arch/sh/mm/init.c
> +++ b/arch/sh/mm/init.c
> @@ -332,7 +332,7 @@ void __init mem_init(void)
>  	cpu_cache_init();
>  
>  	/* clear the zero-page */
> -	__flush_wback_region(empty_zero_page, PAGE_SIZE);
> +	__flush_wback_region((void *)empty_zero_page, PAGE_SIZE);
>  
>  	vsyscall_init();
>  
> -- 
> 2.54.0.794.g4f17f83d09-goog
> 

-- 
Sincerely yours,
Mike.


^ permalink raw reply

* Re: [PATCH v6 13/15] sh: cast away constness from the zero page when flushing it from the cache
From: Ard Biesheuvel @ 2026-05-28  6:14 UTC (permalink / raw)
  To: Mike Rapoport, Ard Biesheuvel
  Cc: linux-arm-kernel, linux-kernel, Will Deacon, Catalin Marinas,
	Mark Rutland, Ryan Roberts, Anshuman Khandual, Liz Prucka,
	Seth Jenkins, Kees Cook, David Hildenbrand, Andrew Morton,
	Jann Horn, linux-mm, linux-hardening, linuxppc-dev, linux-sh,
	Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz
In-Reply-To: <ahfWnLIwZXJvbvNg@kernel.org>

Hi Mike,

On Thu, 28 May 2026, at 07:46, Mike Rapoport wrote:
> On Tue, May 26, 2026 at 07:59:00PM +0200, Ard Biesheuvel wrote:
>> From: Ard Biesheuvel <ardb@kernel.org>
>> 
>> SH performs cache maintenance on the zero page during boot, presumably
>> to ensure that any clearing of BSS that has occurred at startup is
>> visible to other CPUs and DMA devices.
>
> It flushes the cache there because before 6215d9f4470f ("arch, mm:
> consolidate empty_zero_page") empty_zero_page used was for boot parameters
> at the very early boot.
>
> I removed memset(empty_zero_page, 0, PAGE_SIZE) that was a line above but
> missed the cache flush. 
>
> This whole "clear zero-page" can be removed IMO.
> 

Good point.


^ permalink raw reply

* Re: [BUG] sched/cache: "Make LLC id continuous" causes NULL cpumask dereference in build_sched_domains on POWER9
From: Ritesh Harjani @ 2026-05-28  6:54 UTC (permalink / raw)
  To: Venkat Rao Bagalkote, Peter Zijlstra, K Prateek Nayak, Chen, Yu C,
	tim.c.chen
  Cc: Madhavan Srinivasan, Shrikanth Hegde, Ritesh Harjani,
	Christophe Leroy (CS GROUP), LKML, linuxppc-dev, linux-sched
In-Reply-To: <51154de7-3700-4cb4-82f2-1b3a8fa427f7@linux.ibm.com>

Venkat Rao Bagalkote <venkat88@linux.ibm.com> writes:

> Greetings!!!
>
> I am seeing an early boot kernel panic due to NULL pointer dereference 
> on a POWER9 (pSeries) system when testing linux-next (next-20260522).
>
>
> [    0.039029] NIP [c000000000e58504] _find_first_bit+0x44/0x130
> [    0.039043] LR [c000000000e58500] _find_first_bit+0x40/0x130
> [    0.039054] Call Trace:
> [    0.039060] [c0000000090e7b80] [c00000000416af20] 
> schedutil_gov+0x0/0xa0 (unreliable)
> [    0.039076] [c0000000090e7bc0] [c00000000038b3b8] 
> build_sched_domains+0xad8/0xe50
> [    0.039089] [c0000000090e7ce0] [c000000003045d78] 
> sched_init_smp+0xa8/0x164
> [    0.039102] [c0000000090e7d30] [c00000000300f374] 
> kernel_init_freeable+0x250/0x370
> [    0.039117] [c0000000090e7de0] [c000000000011f90] kernel_init+0x34/0x1e4
> [    0.039129] [c0000000090e7e50] [c00000000000debc] 
> ret_from_kernel_user_thread+0x14/0x1c
> [    0.039142] ---- interrupt: 0 at 0x0
> [    0.039150] Code: 41820090 7c0802a6 393cffff fbe10038 7c7f1b78 
> fba10028 fbc10030 3bc00000 793dd7e2 f8010050 4bae6e9d 60000000 
> <e93f0000> 2c290000 408200bc 283c0040
> [    0.039196] ---[ end trace 0000000000000000 ]---
>
>

Well, I am hitting this on 7.1.0-rc5-next-20260526-00010-gbfac43765a97
with Qemu Pseries TCG power10/11.

[    0.342868][    T1] smp: Bringing up secondary CPUs ...
[    0.342868][    T1] smp: Bringing up secondary CPUs ...
[    0.525419][    T1] smp: Brought up 1 node, 4 CPUs
[    0.525419][    T1] smp: Brought up 1 node, 4 CPUs
[    0.527992][    T1] numa: Node 0 CPUs: 0-3
[    0.527992][    T1] numa: Node 0 CPUs: 0-3
[    0.552787][    T1] BUG: Kernel NULL pointer dereference on read at 0x00000000
[    0.552787][    T1] BUG: Kernel NULL pointer dereference on read at 0x00000000
[    0.557446][    T1] Faulting instruction address: 0xc000000000fe3f1c
[    0.557446][    T1] Faulting instruction address: 0xc000000000fe3f1c
cpu 0x0: Vector: 300 (Data Access) at [c000000006607800]
    pc: c000000000fe3f1c: _find_first_bit+0xc/0xc0
    lr: c00000000027b7d8: build_sched_domains+0xbb4/0x1938
    sp: c000000006607ac0
   msr: 8000000002009033
   dar: 0
 dsisr: 80000
  current = 0xc000000006f9fb00
  paca    = 0xc000000005670000   irqmask: 0x03   irq_happened: 0x09
    pid   = 1, comm = swapper/0
Linux version 7.1.0-rc5-next-20260526-00010-gbfac43765a97-dirty (powerpc64le-linux-gnu-gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40) #19 SMP PREEMPT Thu May 28 12:29:51 IST 2026
enter ? for help
[link register   ] c00000000027b7d8 build_sched_domains+0xbb4/0x1938
[c000000006607ac0] c00000000027b0a8 build_sched_domains+0x484/0x1938 (unreliable)
[c000000006607c20] c000000004053180 sched_init_domains+0x114/0x1cc
[c000000006607c70] c0000000040515e0 sched_init_smp+0x5c/0x17c
[c000000006607cc0] c000000004012888 kernel_init_freeable+0x258/0x790
[c000000006607dc0] c000000000011f3c kernel_init+0x34/0x268
[c000000006607e30] c00000000000debc ret_from_kernel_user_thread+0x14/0x1c
---- Exception: 0  at 0000000000000000



-ritesh


^ permalink raw reply

* Re: [PATCH v14 00/17] arm64/riscv: Add support for crashkernel CMA reservation
From: Jinjie Ruan @ 2026-05-28  7:38 UTC (permalink / raw)
  To: Huacai Chen
  Cc: corbet, skhan, catalin.marinas, will, kernel, maddy, mpe, npiggin,
	chleroy, pjw, palmer, aou, alex, tglx, mingo, bp, dave.hansen,
	hpa, robh, saravanak, akpm, bhe, rppt, pasha.tatashin, pratyush,
	ruirui.yang, rdunlap, pmladek, feng.tang, dapeng1.mi, kees, elver,
	kuba, lirongqing, ebiggers, paulmck, thuth, ardb, masahiroy,
	mark.rutland, maz, james.morse, leitao, sourabhjain, yeoreum.yun,
	coxu, jbohac, ryan.roberts, cfsworks, tangyouling, ritesh.list,
	songshuaishuai, junhui.liu, vishal.moola, kas, debug, namcao,
	liaoyuanhong, fuqiang.wang, seanjc, guoren, chenjiahao16,
	hbathini, bgwin, takahiro.akashi, lizhengyu3, x86, linux-doc,
	linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
	linux-riscv, devicetree, kexec
In-Reply-To: <CAAhV-H4NA7vgyxKnK+N_3C6pWBnwXc2URUyLh_h1m-MO=MnsGQ@mail.gmail.com>



On 5/25/2026 6:14 PM, Huacai Chen wrote:
> Hi, Jinjie,
> 
> On Mon, May 25, 2026 at 4:50 PM Jinjie Ruan <ruanjinjie@huawei.com> wrote:
>>
>> The crash memory allocation, and the exclude of crashk_res, crashk_low_res
>> and crashk_cma memory are almost identical across different architectures,
>> This patch set handle them in crash core in a general way, which eliminate
>> a lot of duplication code.
>>
>> And add support for crashkernel CMA reservation for arm64 and riscv.
>>
>> Also add support for arm64 crash hotplug.
>>
>> This patch set is rebased on v7.1-rc1.
>>
>> Basic second kernel boot test were performed on QEMU platforms for x86,
>> ARM64 and RISC-V architectures with the following parameters:
>>
>>         "cma=256M crashkernel=4G crashkernel=64M,cma"
>>
>> For first kernel, there will be such log:
>>
>>         # dmesg | grep crash
>>         [    0.000000] crashkernel low memory reserved: 0xe8000000 - 0xf0000000 (128 MB)
>>         [    0.000000] crashkernel reserved: 0x000000023e600000 - 0x000000033e600000 (4096 MB)
>>         [    0.000000] crashkernel CMA reserved: 64 MB in 1 ranges
>>
>>         # dmesg | grep cma
>>         [    0.000000] cma: Reserved 256 MiB at 0x00000000f0000000
>>         [    0.000000] cma: Reserved 64 MiB at 0x0000000100000000
>>
>> For second kernel, there will be such log:
>>
>>         [    0.000000] OF: fdt: Looking for usable-memory-range property...
>>         [    0.000000] OF: fdt: cap_mem_regions[0]: base=0x000000023e600000, size=0x0000000100000000
>>         [    0.000000] OF: fdt: cap_mem_regions[1]: base=0x00000000e8000000, size=0x0000000008000000
>>         [    0.000000] OF: fdt: cap_mem_regions[2]: base=0x0000000100000000, size=0x0000000004000000
>>
>> Changes in v14:
>> - Fix image->elf_headers memory leak during retry loop for arm64 as Sashiko
>>   AI code review pointed out.
>> - Solve the hotplug notifier arch_crash_handle_hotplug_event() AA
>>   self-deadlock problem as Sashiko AI code review pointed out.
>> - Fix the TOCTOU issue in prepare_elf_headers() by get_online_mems().
>> - -ENOMEM -> -EAGAIN as Breno suggested.
>> - Add support for arm64 crash hotplug.
>> - Link to v13: https://lore.kernel.org/all/20260511030454.1730881-1-ruanjinjie@huawei.com/
>>
>> Changes in v13:
>> - Rebased on v7.1-rc1.
>> - Update the commit message.
>> - Add Reviewed-by.
>> - Link to v12: https://lore.kernel.org/all/20260402072701.628293-1-ruanjinjie@huawei.com/
>>
>> Changes in v12:
>> - Remove the unused "nr_mem_ranges" for x86.
>> - Add "Fix crashk_low_res not exclude bug" test log.
>> - Provide a separate patch for each architecture for using
>>   crash_prepare_headers(), which will make the review more convenient.
>> - Add Reviewed-by and Tested-by.
>> - Link to v11: https://lore.kernel.org/all/20260328074013.3589544-1-ruanjinjie@huawei.com/
>>
>> Changes in v11:
>> - Avoid silently drop crash memory if the crash kernel is built without
>>   CONFIG_CMA.
>> - Remove unnecessary "cmem->nr_ranges = 0" for arch_crash_populate_cmem()
>>   as we use kvzalloc().
>> - Provide a separate patch for each architecture to fix the existing
>>   buffer overflow issue.
>> - Add Acked-bys for arm64.
>>
>> Changes in v10:
>> - Fix crashk_low_res not excluded bug in the existing
>>   RISC-V code.
>> - Fix an existing memory leak issue in the existing PowerPC code.
>> - Fix the ordering issue of adding CMA ranges to
>>   "linux,usable-memory-range".
>> - Fix an existing concurrency issue. A Concurrent memory hotplug may occur
>>   between reading memblock and attempting to fill cmem during kexec_load()
>>   for almost all existing architectures.
>> - Link to v9: https://lore.kernel.org/all/20260323072745.2481719-1-ruanjinjie@huawei.com/
>>
>> Changes in v9:
>> - Collect Reviewed-by and Acked-by, and prepare for Sashiko AI review.
>> - Link to v8: https://lore.kernel.org/all/20260302035315.3892241-1-ruanjinjie@huawei.com/
>>
>> Changes in v8:
>> - Fix the build issues reported by kernel test robot and Sourabh.
>> - Link to v7: https://lore.kernel.org/all/20260226130437.1867658-1-ruanjinjie@huawei.com/
>>
>> Changes in v7:
>> - Correct the inclusion of CMA-reserved ranges for kdump kernel in of/kexec
>>   for arm64 and riscv.
>> - Add Acked-by.
>> - Link to v6: https://lore.kernel.org/all/20260224085342.387996-1-ruanjinjie@huawei.com/
>>
>> Changes in v6:
>> - Update the crash core exclude code as Mike suggested.
>> - Rebased on v7.0-rc1.
>> - Add acked-by.
>> - Link to v5: https://lore.kernel.org/all/20260212101001.343158-1-ruanjinjie@huawei.com/
>>
>> Jinjie Ruan (16):
>>   riscv: kexec_file: Fix crashk_low_res not exclude bug
>>   powerpc/crash: Fix possible memory leak in update_crash_elfcorehdr()
>>   arm64: kexec: Fix image->elf_headers memory leak during retry loop
>>   x86/kexec: Fix potential buffer overflow in prepare_elf_headers()
>>   arm64: kexec_file: Fix potential buffer overflow in
>>     prepare_elf_headers()
>>   riscv: kexec_file: Fix potential buffer overflow in
>>     prepare_elf_headers()
>>   LoongArch: kexec: Fix potential buffer overflow in
>>     prepare_elf_headers()
>>   crash: Add crash_prepare_headers() to exclude crash kernel memory
>>   arm64: kexec_file: Use crash_prepare_headers() helper to simplify code
>>   x86/kexec: Use crash_prepare_headers() helper to simplify code
>>   riscv: kexec_file: Use crash_prepare_headers() helper to simplify code
>>   LoongArch: kexec: Use crash_prepare_headers() helper to simplify code
>>   crash: Use crash_exclude_core_ranges() on powerpc
>>   arm64: kexec: Add support for crashkernel CMA reservation
>>   riscv: kexec: Add support for crashkernel CMA reservation
>>   arm64/crash: Add crash hotplug support
> I have some bikesheedings about the subjects. Can we unify the prefix formats?
> x86/kexec, arm64: kexec_file, riscv: kexec_file, LoongArch: kexec .....
> 
> Huacai

Sure, will update it in next version.

> 
>>
>> Sourabh Jain (1):
>>   powerpc/crash: sort crash memory ranges before preparing elfcorehdr
>>
>>  .../admin-guide/kernel-parameters.txt         |  16 +--
>>  arch/arm64/Kconfig                            |   3 +
>>  arch/arm64/include/asm/kexec.h                |  14 +-
>>  arch/arm64/kernel/Makefile                    |   1 +
>>  arch/arm64/kernel/crash.c                     | 125 ++++++++++++++++++
>>  arch/arm64/kernel/kexec_image.c               |  22 ++-
>>  arch/arm64/kernel/machine_kexec_file.c        |  78 ++++++-----
>>  arch/arm64/mm/init.c                          |   5 +-
>>  arch/loongarch/kernel/machine_kexec_file.c    |  43 +++---
>>  arch/powerpc/include/asm/kexec_ranges.h       |   1 -
>>  arch/powerpc/kexec/crash.c                    |   7 +-
>>  arch/powerpc/kexec/ranges.c                   | 101 +-------------
>>  arch/riscv/kernel/machine_kexec_file.c        |  42 +++---
>>  arch/riscv/mm/init.c                          |   5 +-
>>  arch/x86/kernel/crash.c                       |  92 ++-----------
>>  drivers/of/fdt.c                              |   9 +-
>>  drivers/of/kexec.c                            |   9 ++
>>  include/linux/crash_core.h                    |  11 ++
>>  include/linux/crash_reserve.h                 |   4 +-
>>  kernel/crash_core.c                           | 102 +++++++++++++-
>>  20 files changed, 392 insertions(+), 298 deletions(-)
>>  create mode 100644 arch/arm64/kernel/crash.c
>>
>> --
>> 2.34.1
>>
> 



^ permalink raw reply

* Re: [PATCH v14 00/17] arm64/riscv: Add support for crashkernel CMA reservation
From: Jinjie Ruan @ 2026-05-28  7:39 UTC (permalink / raw)
  To: Mike Rapoport, Huacai Chen
  Cc: corbet, skhan, catalin.marinas, will, kernel, maddy, mpe, npiggin,
	chleroy, pjw, palmer, aou, alex, tglx, mingo, bp, dave.hansen,
	hpa, robh, saravanak, akpm, bhe, pasha.tatashin, pratyush,
	ruirui.yang, rdunlap, pmladek, feng.tang, dapeng1.mi, kees, elver,
	kuba, lirongqing, ebiggers, paulmck, thuth, ardb, masahiroy,
	mark.rutland, maz, james.morse, leitao, sourabhjain, yeoreum.yun,
	coxu, jbohac, ryan.roberts, cfsworks, tangyouling, ritesh.list,
	songshuaishuai, junhui.liu, vishal.moola, kas, debug, namcao,
	liaoyuanhong, fuqiang.wang, seanjc, guoren, chenjiahao16,
	hbathini, bgwin, takahiro.akashi, lizhengyu3, x86, linux-doc,
	linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
	linux-riscv, devicetree, kexec
In-Reply-To: <ahQ0WRiMsB011tym@kernel.org>



On 5/25/2026 7:36 PM, Mike Rapoport wrote:
> Hi Huacai,
> 
> On Mon, May 25, 2026 at 06:14:52PM +0800, Huacai Chen wrote:
>> On Mon, May 25, 2026 at 4:50 PM Jinjie Ruan <ruanjinjie@huawei.com> wrote:
>>>
>>> Jinjie Ruan (16):
>>>   riscv: kexec_file: Fix crashk_low_res not exclude bug
>>>   powerpc/crash: Fix possible memory leak in update_crash_elfcorehdr()
>>>   arm64: kexec: Fix image->elf_headers memory leak during retry loop
>>>   x86/kexec: Fix potential buffer overflow in prepare_elf_headers()
>>>   arm64: kexec_file: Fix potential buffer overflow in
>>>     prepare_elf_headers()
>>>   riscv: kexec_file: Fix potential buffer overflow in
>>>     prepare_elf_headers()
>>>   LoongArch: kexec: Fix potential buffer overflow in
>>>     prepare_elf_headers()
>>>   crash: Add crash_prepare_headers() to exclude crash kernel memory
>>>   arm64: kexec_file: Use crash_prepare_headers() helper to simplify code
>>>   x86/kexec: Use crash_prepare_headers() helper to simplify code
>>>   riscv: kexec_file: Use crash_prepare_headers() helper to simplify code
>>>   LoongArch: kexec: Use crash_prepare_headers() helper to simplify code
>>>   crash: Use crash_exclude_core_ranges() on powerpc
>>>   arm64: kexec: Add support for crashkernel CMA reservation
>>>   riscv: kexec: Add support for crashkernel CMA reservation
>>>   arm64/crash: Add crash hotplug support
>> I have some bikesheedings about the subjects. Can we unify the prefix formats?
>> x86/kexec, arm64: kexec_file, riscv: kexec_file, LoongArch: kexec .....
> 
> It might look weird in the series, but powerpc and x86 use '/' and arm64 and
> riscv use ':' so in the logs in arch/ this would be actually fine.
> 
> With the only exception of arm64/crash that should have been arm64: crash:

Thanks, will update it in next version.

>  
>> Huacai
> 



^ permalink raw reply

* Re: [PATCH v14 00/17] arm64/riscv: Add support for crashkernel CMA reservation
From: Jinjie Ruan @ 2026-05-28  7:48 UTC (permalink / raw)
  To: Huacai Chen, Mike Rapoport
  Cc: corbet, skhan, catalin.marinas, will, kernel, maddy, mpe, npiggin,
	chleroy, pjw, palmer, aou, alex, tglx, mingo, bp, dave.hansen,
	hpa, robh, saravanak, akpm, bhe, pasha.tatashin, pratyush,
	ruirui.yang, rdunlap, pmladek, feng.tang, dapeng1.mi, kees, elver,
	kuba, lirongqing, ebiggers, paulmck, thuth, ardb, masahiroy,
	mark.rutland, maz, james.morse, leitao, sourabhjain, yeoreum.yun,
	coxu, jbohac, ryan.roberts, cfsworks, tangyouling, ritesh.list,
	songshuaishuai, junhui.liu, vishal.moola, kas, debug, namcao,
	liaoyuanhong, fuqiang.wang, seanjc, guoren, chenjiahao16,
	hbathini, bgwin, takahiro.akashi, lizhengyu3, x86, linux-doc,
	linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
	linux-riscv, devicetree, kexec
In-Reply-To: <CAAhV-H5x3m08=acrUr2VOAQ8-r2PhN1xTdr3NihHocoPM5=3hQ@mail.gmail.com>



On 5/25/2026 9:17 PM, Huacai Chen wrote:
> On Mon, May 25, 2026 at 7:37 PM Mike Rapoport <rppt@kernel.org> wrote:
>>
>> Hi Huacai,
>>
>> On Mon, May 25, 2026 at 06:14:52PM +0800, Huacai Chen wrote:
>>> On Mon, May 25, 2026 at 4:50 PM Jinjie Ruan <ruanjinjie@huawei.com> wrote:
>>>>
>>>> Jinjie Ruan (16):
>>>>   riscv: kexec_file: Fix crashk_low_res not exclude bug
>>>>   powerpc/crash: Fix possible memory leak in update_crash_elfcorehdr()
>>>>   arm64: kexec: Fix image->elf_headers memory leak during retry loop
>>>>   x86/kexec: Fix potential buffer overflow in prepare_elf_headers()
>>>>   arm64: kexec_file: Fix potential buffer overflow in
>>>>     prepare_elf_headers()
>>>>   riscv: kexec_file: Fix potential buffer overflow in
>>>>     prepare_elf_headers()
>>>>   LoongArch: kexec: Fix potential buffer overflow in
>>>>     prepare_elf_headers()
>>>>   crash: Add crash_prepare_headers() to exclude crash kernel memory
>>>>   arm64: kexec_file: Use crash_prepare_headers() helper to simplify code
>>>>   x86/kexec: Use crash_prepare_headers() helper to simplify code
>>>>   riscv: kexec_file: Use crash_prepare_headers() helper to simplify code
>>>>   LoongArch: kexec: Use crash_prepare_headers() helper to simplify code
>>>>   crash: Use crash_exclude_core_ranges() on powerpc
>>>>   arm64: kexec: Add support for crashkernel CMA reservation
>>>>   riscv: kexec: Add support for crashkernel CMA reservation
>>>>   arm64/crash: Add crash hotplug support
>>> I have some bikesheedings about the subjects. Can we unify the prefix formats?
>>> x86/kexec, arm64: kexec_file, riscv: kexec_file, LoongArch: kexec .....
>>
>> It might look weird in the series, but powerpc and x86 use '/' and arm64 and
>> riscv use ':' so in the logs in arch/ this would be actually fine.
> OK, but at least we can unify kexec and kexec_file.

That looks fine.

Jinjie

> 
> Huacai
> 
>>
>> With the only exception of arm64/crash that should have been arm64: crash:
>>
>>> Huacai
>>
>> --
>> Sincerely yours,
>> Mike.
> 



^ permalink raw reply

* [PATCH] powerpc/boot: drop redundant assignment in serial_edit_cmdline
From: Thorsten Blum @ 2026-05-28  8:23 UTC (permalink / raw)
  To: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP)
  Cc: Thorsten Blum, linuxppc-dev, linux-kernel

Drop the redundant buffer assignment in serial_edit_cmdline() since the
cp pointer is immediately overwritten.

Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
 arch/powerpc/boot/serial.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
index c6d32a8c3612..1d221ff420fd 100644
--- a/arch/powerpc/boot/serial.c
+++ b/arch/powerpc/boot/serial.c
@@ -37,7 +37,6 @@ static void serial_edit_cmdline(char *buf, int len, unsigned int timeout)
 	char ch, *cp;
 	struct serial_console_data *scdp = console_ops.data;
 
-	cp = buf;
 	count = strlen(buf);
 	cp = &buf[count];
 	count++;


^ permalink raw reply related

* Re: [PATCH] powerpc: Export set_memory_encrypted and set_memory_decrypted
From: Christoph Hellwig @ 2026-05-28  8:53 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Jason Gunthorpe, Christoph Hellwig, T.J. Mercier, maddy, mpe,
	npiggin, chleroy, linuxppc-dev, mripard, sumit.semwal, lkp,
	linux-kernel, iommu, linux-mm, agordeev, gerald.schaefer,
	linux-s390, Dan Williams, Tom Lendacky, x86
In-Reply-To: <20260527181549.GBahc01Xflm2yo5OqI@fat_crate.local>

On Wed, May 27, 2026 at 11:15:49AM -0700, Borislav Petkov wrote:
> On Wed, May 27, 2026 at 01:07:16PM -0300, Jason Gunthorpe wrote:
> > > Setting memory decrypted is a dangerous operations and should only
> > > be available to core code.  We should have various allocators for
> > > decrypted code, but not export the functionality to random code.
> > 
> > At the very least an EXPORT_SYMBOL_NS.
> > 
> > Looks like there are about 3 modules using it already..
> 
> Looks like more to me...
> 
> In any case, we exported them back then for some framebuffer things:
> 
> 95cf9264d5f3 ("x86, drm, fbdev: Do not specify encrypted memory for video mappings")

Which is exactly one of these things that should not happen - mapping
random I/O memory without the proper helpers..



^ permalink raw reply

* [PATCH v1 0/4] ASoC: Use named initializers for platform_device_id arrays
From: Uwe Kleine-König (The Capable Hub) @ 2026-05-28  9:05 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown
  Cc: Jaroslav Kysela, Takashi Iwai, Matthias Brugger,
	AngeloGioacchino Del Regno, Charles Keepax, Kuninori Morimoto,
	linux-sound, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-renesas-soc, Vijendar Mukunda, Venkata Prasad Potturu,
	James Ogletree, Fred Treven, Ben Bright, David Rhodes,
	Richard Fitzgerald, Cezary Rojewski, Peter Ujfalusi, Bard Liao,
	Kai Vehmanen, Pierre-Louis Bossart, Syed Saba Kareem,
	Mario Limonciello (AMD), Krzysztof Kozlowski, Mark Pearson,
	Hasun Park, Li Qiang, Kees Cook, Ranjani Sridharan, Mac Chiang,
	Maciej Strozek, patches, Lars-Peter Clausen, Nuno Sá,
	Srinivas Kandagatla, Shengjiu Wang, Xiubo Li, Fabio Estevam,
	Nicolin Chen, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Guilherme G. Piccoli, Mario Limonciello, Cristian Ciocaltea,
	Amadeusz Sławiński, linux-arm-msm, linuxppc-dev, imx

Hello,

this series targets to use named initializers for platform_device_id
arrays. In general these are better readable for humans and more robust
to changes in the respective struct definition.

This robustness is needed as I want to do

	diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
	--- a/include/linux/mod_devicetable.h
	+++ b/include/linux/mod_devicetable.h
	@@ -610,4 +610,7 @@ struct dmi_system_id {
	 struct platform_device_id {
		char name[PLATFORM_NAME_SIZE];
	-	kernel_ulong_t driver_data;
	+	union {
	+		kernel_ulong_t driver_data;
	+		const void *driver_data_ptr;
	+	};
	 };

which allows dropping several casts and eases porting CHERI to mainline
linux. When adapting e.g. sound/soc/amd/acp/acp-legacy-mach.c to that
and make use of driver_data_ptr, the added const makes it obvious that
acp_asoc_probe() modifies the structs linked in the id_table resulting
in issues if more than one device is probed using the same platform id.
sound/soc/amd/acp/acp-sof-mach.c has the same issue.

If you consider the last patch mostly churn, just drop it.

Best regards
Uwe

Uwe Kleine-König (The Capable Hub) (4):
  ASoC: codecs: mt6357: Drop unused assignment of platform_device_id
    driver data
  ASoC: renesas: fsi: Simplify driver_data handling
  ASoC: Use named initializers for platform_device_id arrays
  ASOC: Unify code style for platform_device_id arrays

 sound/soc/amd/acp/acp-sdw-legacy-mach.c |  4 ++--
 sound/soc/amd/acp/acp-sdw-sof-mach.c    |  4 ++--
 sound/soc/amd/acp/acp-sof-mach.c        | 14 +++++++-------
 sound/soc/codecs/adau7118-hw.c          |  2 +-
 sound/soc/codecs/bt-sco.c               | 10 +++-------
 sound/soc/codecs/cs40l50-codec.c        |  4 ++--
 sound/soc/codecs/cs42l43.c              |  4 ++--
 sound/soc/codecs/mt6357.c               |  4 ++--
 sound/soc/codecs/wcd934x.c              |  6 ++----
 sound/soc/fsl/imx-pcm-rpmsg.c           |  6 +++---
 sound/soc/intel/avs/boards/da7219.c     |  6 ++----
 sound/soc/intel/avs/boards/dmic.c       |  6 ++----
 sound/soc/intel/avs/boards/es8336.c     |  6 ++----
 sound/soc/intel/avs/boards/hdaudio.c    |  6 ++----
 sound/soc/intel/avs/boards/i2s_test.c   |  6 ++----
 sound/soc/intel/avs/boards/max98357a.c  |  6 ++----
 sound/soc/intel/avs/boards/max98373.c   |  6 ++----
 sound/soc/intel/avs/boards/max98927.c   |  6 ++----
 sound/soc/intel/avs/boards/nau8825.c    |  6 ++----
 sound/soc/intel/avs/boards/pcm3168a.c   |  6 ++----
 sound/soc/intel/boards/sof_sdw.c        |  4 ++--
 sound/soc/renesas/fsi.c                 |  8 +++-----
 22 files changed, 51 insertions(+), 79 deletions(-)


base-commit: e7d700e14934e68f86338c5610cf2ae76798b663
-- 
2.47.3



^ permalink raw reply

* [PATCH v1 4/4] ASOC: Unify code style for platform_device_id arrays
From: Uwe Kleine-König (The Capable Hub) @ 2026-05-28  9:06 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown
  Cc: Vijendar Mukunda, Venkata Prasad Potturu, Jaroslav Kysela,
	Takashi Iwai, Lars-Peter Clausen, Nuno Sá,
	Srinivas Kandagatla, Shengjiu Wang, Xiubo Li, Fabio Estevam,
	Nicolin Chen, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Cezary Rojewski, Peter Ujfalusi, Bard Liao, Kai Vehmanen,
	Pierre-Louis Bossart, Guilherme G. Piccoli, Mario Limonciello,
	Cristian Ciocaltea, Kuninori Morimoto,
	Amadeusz Sławiński, Charles Keepax, linux-sound,
	linux-kernel, linux-arm-msm, linuxppc-dev, imx, linux-arm-kernel
In-Reply-To: <cover.1779958164.git.u.kleine-koenig@baylibre.com>

 - Add a trailing comma for initializers unless the closing brace is on
   the same line and for the list terminator;
 - Use a single space in the list terminator;
 - Use compact one-line style for small entries;
 - s/\t=/ =/ were the tab is only one char wide anyhow;

Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
---
 sound/soc/amd/acp/acp-sof-mach.c       | 14 +++++++-------
 sound/soc/codecs/adau7118-hw.c         |  2 +-
 sound/soc/codecs/bt-sco.c              | 10 +++-------
 sound/soc/codecs/wcd934x.c             |  6 ++----
 sound/soc/fsl/imx-pcm-rpmsg.c          |  6 +++---
 sound/soc/intel/avs/boards/da7219.c    |  6 ++----
 sound/soc/intel/avs/boards/dmic.c      |  6 ++----
 sound/soc/intel/avs/boards/es8336.c    |  6 ++----
 sound/soc/intel/avs/boards/hdaudio.c   |  6 ++----
 sound/soc/intel/avs/boards/i2s_test.c  |  6 ++----
 sound/soc/intel/avs/boards/max98357a.c |  6 ++----
 sound/soc/intel/avs/boards/max98373.c  |  6 ++----
 sound/soc/intel/avs/boards/max98927.c  |  6 ++----
 sound/soc/intel/avs/boards/nau8825.c   |  6 ++----
 sound/soc/intel/avs/boards/pcm3168a.c  |  6 ++----
 15 files changed, 36 insertions(+), 62 deletions(-)

diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
index 36ecef7013b9..8874151e159a 100644
--- a/sound/soc/amd/acp/acp-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sof-mach.c
@@ -128,31 +128,31 @@ static int acp_sof_probe(struct platform_device *pdev)
 static const struct platform_device_id board_ids[] = {
 	{
 		.name = "rt5682-rt1019",
-		.driver_data = (kernel_ulong_t)&sof_rt5682_rt1019_data
+		.driver_data = (kernel_ulong_t)&sof_rt5682_rt1019_data,
 	},
 	{
 		.name = "rt5682-max",
-		.driver_data = (kernel_ulong_t)&sof_rt5682_max_data
+		.driver_data = (kernel_ulong_t)&sof_rt5682_max_data,
 	},
 	{
 		.name = "rt5682s-max",
-		.driver_data = (kernel_ulong_t)&sof_rt5682s_max_data
+		.driver_data = (kernel_ulong_t)&sof_rt5682s_max_data,
 	},
 	{
 		.name = "rt5682s-rt1019",
-		.driver_data = (kernel_ulong_t)&sof_rt5682s_rt1019_data
+		.driver_data = (kernel_ulong_t)&sof_rt5682s_rt1019_data,
 	},
 	{
 		.name = "nau8825-max",
-		.driver_data = (kernel_ulong_t)&sof_nau8825_data
+		.driver_data = (kernel_ulong_t)&sof_nau8825_data,
 	},
 	{
 		.name = "rt5682s-hs-rt1019",
-		.driver_data = (kernel_ulong_t)&sof_rt5682s_hs_rt1019_data
+		.driver_data = (kernel_ulong_t)&sof_rt5682s_hs_rt1019_data,
 	},
 	{
 		.name = "nau8821-max",
-		.driver_data = (kernel_ulong_t)&sof_nau8821_max98388_data
+		.driver_data = (kernel_ulong_t)&sof_nau8821_max98388_data,
 	},
 	{ }
 };
diff --git a/sound/soc/codecs/adau7118-hw.c b/sound/soc/codecs/adau7118-hw.c
index 45a5d2dcc0f2..ffbd2ea3cde3 100644
--- a/sound/soc/codecs/adau7118-hw.c
+++ b/sound/soc/codecs/adau7118-hw.c
@@ -23,7 +23,7 @@ static const struct of_device_id adau7118_of_match[] = {
 MODULE_DEVICE_TABLE(of, adau7118_of_match);
 
 static const struct platform_device_id adau7118_id[] = {
-	{ .name	= "adau7118" },
+	{ .name = "adau7118" },
 	{ }
 };
 MODULE_DEVICE_TABLE(platform, adau7118_id);
diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c
index 3afcef2dfa35..6507bd20a650 100644
--- a/sound/soc/codecs/bt-sco.c
+++ b/sound/soc/codecs/bt-sco.c
@@ -79,13 +79,9 @@ static int bt_sco_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id bt_sco_driver_ids[] = {
-	{
-		.name		= "dfbmcs320",
-	},
-	{
-		.name		= "bt-sco",
-	},
-	{},
+	{ .name = "dfbmcs320" },
+	{ .name = "bt-sco" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids);
 
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index bc41a1466c70..a9e6f2923099 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -5899,10 +5899,8 @@ static int wcd934x_codec_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id wcd934x_driver_id[] = {
-	{
-		.name = "wcd934x-codec",
-	},
-	{},
+	{ .name = "wcd934x-codec" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, wcd934x_driver_id);
 
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
index 031e5272215d..8f1185dff780 100644
--- a/sound/soc/fsl/imx-pcm-rpmsg.c
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -829,9 +829,9 @@ static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = {
 };
 
 static const struct platform_device_id imx_rpmsg_pcm_id_table[] = {
-	{ .name	= "rpmsg-audio-channel" },
-	{ .name	= "rpmsg-micfil-channel" },
-	{ },
+	{ .name = "rpmsg-audio-channel" },
+	{ .name = "rpmsg-micfil-channel" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, imx_rpmsg_pcm_id_table);
 
diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c
index 2b17abcbd2bc..163d9982d797 100644
--- a/sound/soc/intel/avs/boards/da7219.c
+++ b/sound/soc/intel/avs/boards/da7219.c
@@ -259,10 +259,8 @@ static int avs_da7219_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_da7219_driver_ids[] = {
-	{
-		.name = "avs_da7219",
-	},
-	{},
+	{ .name = "avs_da7219" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_da7219_driver_ids);
 
diff --git a/sound/soc/intel/avs/boards/dmic.c b/sound/soc/intel/avs/boards/dmic.c
index bf6f580a5164..8d36bc7ddf16 100644
--- a/sound/soc/intel/avs/boards/dmic.c
+++ b/sound/soc/intel/avs/boards/dmic.c
@@ -104,10 +104,8 @@ static int avs_dmic_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_dmic_driver_ids[] = {
-	{
-		.name = "avs_dmic",
-	},
-	{},
+	{ .name = "avs_dmic" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_dmic_driver_ids);
 
diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c
index 301cfb3cf15b..36c13db3a272 100644
--- a/sound/soc/intel/avs/boards/es8336.c
+++ b/sound/soc/intel/avs/boards/es8336.c
@@ -309,10 +309,8 @@ static int avs_es8336_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_es8336_driver_ids[] = {
-	{
-		.name = "avs_es8336",
-	},
-	{},
+	{ .name = "avs_es8336" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_es8336_driver_ids);
 
diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c
index aec769e2396c..03cfd91202d3 100644
--- a/sound/soc/intel/avs/boards/hdaudio.c
+++ b/sound/soc/intel/avs/boards/hdaudio.c
@@ -231,10 +231,8 @@ static int avs_hdaudio_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_hdaudio_driver_ids[] = {
-	{
-		.name = "avs_hdaudio",
-	},
-	{},
+	{ .name = "avs_hdaudio" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_hdaudio_driver_ids);
 
diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c
index 9a6b89ffdf14..787d781ba1d9 100644
--- a/sound/soc/intel/avs/boards/i2s_test.c
+++ b/sound/soc/intel/avs/boards/i2s_test.c
@@ -107,10 +107,8 @@ static int avs_i2s_test_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_i2s_test_driver_ids[] = {
-	{
-		.name = "avs_i2s_test",
-	},
-	{},
+	{ .name = "avs_i2s_test" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_i2s_test_driver_ids);
 
diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c
index e9a87804f918..389a50923d3b 100644
--- a/sound/soc/intel/avs/boards/max98357a.c
+++ b/sound/soc/intel/avs/boards/max98357a.c
@@ -136,10 +136,8 @@ static int avs_max98357a_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_max98357a_driver_ids[] = {
-	{
-		.name = "avs_max98357a",
-	},
-	{},
+	{ .name = "avs_max98357a" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_max98357a_driver_ids);
 
diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c
index 8b45b643ca29..b8231f71d3d6 100644
--- a/sound/soc/intel/avs/boards/max98373.c
+++ b/sound/soc/intel/avs/boards/max98373.c
@@ -191,10 +191,8 @@ static int avs_max98373_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_max98373_driver_ids[] = {
-	{
-		.name = "avs_max98373",
-	},
-	{},
+	{ .name = "avs_max98373" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_max98373_driver_ids);
 
diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c
index db073125fa4d..d657e7da1cc0 100644
--- a/sound/soc/intel/avs/boards/max98927.c
+++ b/sound/soc/intel/avs/boards/max98927.c
@@ -188,10 +188,8 @@ static int avs_max98927_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_max98927_driver_ids[] = {
-	{
-		.name = "avs_max98927",
-	},
-	{},
+	{ .name = "avs_max98927" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_max98927_driver_ids);
 
diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c
index d44edacbfc9a..d7ea08bb27cd 100644
--- a/sound/soc/intel/avs/boards/nau8825.c
+++ b/sound/soc/intel/avs/boards/nau8825.c
@@ -293,10 +293,8 @@ static int avs_nau8825_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_nau8825_driver_ids[] = {
-	{
-		.name = "avs_nau8825",
-	},
-	{},
+	{ .name = "avs_nau8825" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_nau8825_driver_ids);
 
diff --git a/sound/soc/intel/avs/boards/pcm3168a.c b/sound/soc/intel/avs/boards/pcm3168a.c
index b5bebadbbcb2..9d415fd0499a 100644
--- a/sound/soc/intel/avs/boards/pcm3168a.c
+++ b/sound/soc/intel/avs/boards/pcm3168a.c
@@ -132,10 +132,8 @@ static int avs_pcm3168a_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id avs_pcm3168a_driver_ids[] = {
-	{
-		.name = "avs_pcm3168a",
-	},
-	{},
+	{ .name = "avs_pcm3168a" },
+	{ }
 };
 MODULE_DEVICE_TABLE(platform, avs_pcm3168a_driver_ids);
 
-- 
2.47.3



^ permalink raw reply related

* Re: [BUG] sched/cache: "Make LLC id continuous" causes NULL cpumask
From: Chen, Yu C @ 2026-05-28  9:12 UTC (permalink / raw)
  To: Shrikanth Hegde
  Cc: srikar, venkat88, maddy, riteshh, chleroy, tim.c.chen, peterz,
	linux-kernel, linuxppc-dev, linux-sched, kprateek.nayak
In-Reply-To: <508a604b-2d30-47f4-a63c-36778a1d47c7@linux.ibm.com>

On 5/28/2026 12:58 PM, Shrikanth Hegde wrote:
> 
> 
> On 5/27/26 11:37 PM, Shrikanth Hegde wrote:

[ ... ]

>> diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/ 
>> include/ asm/topology.h
>> index 66ed5fe1b718..bd1db3b1dbb0 100644
>> --- a/arch/powerpc/include/asm/topology.h
>> +++ b/arch/powerpc/include/asm/topology.h
>> @@ -131,6 +131,9 @@ static inline int cpu_to_coregroup_id(int cpu)
>>   #ifdef CONFIG_SMP
>>   #include <asm/cputable.h>
>>
>> +const struct cpumask *arch_llc_mask(int cpu);
>> +#define arch_llc_mask  arch_llc_mask
>> +
>>   struct cpumask *cpu_coregroup_mask(int cpu);
>>   const struct cpumask *cpu_die_mask(int cpu);
>>   int cpu_die_id(int cpu);
>> diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
>> index 3467f86fd78f..26c15c786c55 100644
>> --- a/arch/powerpc/kernel/smp.c
>> +++ b/arch/powerpc/kernel/smp.c
>> @@ -1101,6 +1101,13 @@ const struct cpumask *cpu_die_mask(int cpu)
>>   }
>>   EXPORT_SYMBOL_GPL(cpu_die_mask);
>>
>> +const struct cpumask *arch_llc_mask(int cpu)
>> +{
>> +       if (has_coregroup_support())
>> +               return cpu_coregroup_mask(cpu);
>> +       return cpu_smallcore_mask(cpu);
> 
> 
> This function body needs change, since LLC is not at MC.
> and I didn't account for power9.
> 
> Rest of the structure is what i would prefer the direction to go.
> This will help future architectures too to account for their specific
> needs.
> 
> What do you think?
> 

Yes this direction look good to me. Regarding the arch_llc_mask(),
how about the following per Srikar's description

const struct cpumask *arch_llc_mask(int cpu)
{
	/* Power9, CACHE domain is the LLC*/	if (shared_caches)
		return cpu_l2_cache_mask(cpu);

	/* P7, P8, P10, P11, SMT domain is the LLC*/	return cpu_smt_mask(cpu);
}

thanks,
Chenyu



^ permalink raw reply

* Re: [PATCH v1 4/4] ASOC: Unify code style for platform_device_id arrays
From: Cezary Rojewski @ 2026-05-28  9:27 UTC (permalink / raw)
  To: Uwe Kleine-König (The Capable Hub)
  Cc: Vijendar Mukunda, Venkata Prasad Potturu, Jaroslav Kysela,
	Takashi Iwai, Lars-Peter Clausen, Nuno Sá,
	Srinivas Kandagatla, Shengjiu Wang, Xiubo Li, Fabio Estevam,
	Nicolin Chen, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Peter Ujfalusi, Bard Liao, Kai Vehmanen, Pierre-Louis Bossart,
	Guilherme G. Piccoli, Mario Limonciello, Cristian Ciocaltea,
	Kuninori Morimoto, Amadeusz Sławiński, Charles Keepax,
	linux-sound, linux-kernel, linux-arm-msm, linuxppc-dev, imx,
	linux-arm-kernel, Liam Girdwood, Mark Brown
In-Reply-To: <d131f7afc3c61ca8ac82a848aaa6ecfbb57ec63b.1779958164.git.u.kleine-koenig@baylibre.com>

On 5/28/2026 11:06 AM, Uwe Kleine-König (The Capable Hub) wrote:
>   - Add a trailing comma for initializers unless the closing brace is on
>     the same line and for the list terminator;
>   - Use a single space in the list terminator;
>   - Use compact one-line style for small entries;
>   - s/\t=/ =/ were the tab is only one char wide anyhow;
> 
> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
> ---
>   sound/soc/amd/acp/acp-sof-mach.c       | 14 +++++++-------
>   sound/soc/codecs/adau7118-hw.c         |  2 +-
>   sound/soc/codecs/bt-sco.c              | 10 +++-------
>   sound/soc/codecs/wcd934x.c             |  6 ++----
>   sound/soc/fsl/imx-pcm-rpmsg.c          |  6 +++---

...

>   sound/soc/intel/avs/boards/da7219.c    |  6 ++----
>   sound/soc/intel/avs/boards/dmic.c      |  6 ++----
>   sound/soc/intel/avs/boards/es8336.c    |  6 ++----
>   sound/soc/intel/avs/boards/hdaudio.c   |  6 ++----
>   sound/soc/intel/avs/boards/i2s_test.c  |  6 ++----
>   sound/soc/intel/avs/boards/max98357a.c |  6 ++----
>   sound/soc/intel/avs/boards/max98373.c  |  6 ++----
>   sound/soc/intel/avs/boards/max98927.c  |  6 ++----
>   sound/soc/intel/avs/boards/nau8825.c   |  6 ++----
>   sound/soc/intel/avs/boards/pcm3168a.c  |  6 ++----

Please separate all the avs-driver changes into a separate patch with 
the following prefix for the title: "ASoC: Intel: avs:".

The code itself looks good. Provided the separation is done, feel free 
to add my tag:

Acked-by: Cezary Rojewski <cezary.rojewski@intel.com>


^ permalink raw reply

* Re: [BUG] sched/cache: "Make LLC id continuous" causes NULL cpumask
From: Shrikanth Hegde @ 2026-05-28 10:26 UTC (permalink / raw)
  To: Chen, Yu C
  Cc: srikar, venkat88, maddy, riteshh, chleroy, tim.c.chen, peterz,
	linux-kernel, linuxppc-dev, linux-sched, kprateek.nayak
In-Reply-To: <db443a1e-e6fc-491c-a38a-1cafc8e674cd@intel.com>

Hi Chenyu.

> Yes this direction look good to me. Regarding the arch_llc_mask(),
> how about the following per Srikar's description
> 
> const struct cpumask *arch_llc_mask(int cpu)
> {
>      /* Power9, CACHE domain is the LLC*/    if (shared_caches)
>          return cpu_l2_cache_mask(cpu);
> 
>      /* P7, P8, P10, P11, SMT domain is the LLC*/    return 
> cpu_smt_mask(cpu);
> }
> 
> thanks,
> Chenyu
> 

Yes. this is what i was thinking too. I have the patch, let me send it 
across shortly. It is fixing the boot panic for me in SPLPAR. Hopefully
it should work for others too.

I will send it as reply to main thread so one doesn't miss it out.


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox