[PATCH v2] mfd: loongson-se: Add multi-node support

Qunqin Zhao posted 1 patch 1 month, 2 weeks ago
There is a newer version of this series
drivers/mfd/loongson-se.c       | 38 +++++++++++++++++++++++++++------
include/linux/mfd/loongson-se.h |  3 +++
2 files changed, 35 insertions(+), 6 deletions(-)
[PATCH v2] mfd: loongson-se: Add multi-node support
Posted by Qunqin Zhao 1 month, 2 weeks ago
On the Loongson platform, each node is equipped with a security engine
device. However, due to a hardware flaw, only the device on node 0 can
trigger interrupts. Therefore, interrupts from other nodes are forwarded
by node 0. We need to check in the interrupt handler of node 0 whether
this interrupt is intended for other nodes.

Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
---
Changes in v2:
	-Resending due to no feedback for one month.
	-Rebased on top of latest mainline (7.1-rc1) to ensure the patch
	 applies cleanly.
	-No functional changes since the previous submission.

Link to v1:
https://lore.kernel.org/all/20260226102225.19516-1-zhaoqunqin@loongson.cn/#t

 drivers/mfd/loongson-se.c       | 38 +++++++++++++++++++++++++++------
 include/linux/mfd/loongson-se.h |  3 +++
 2 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/drivers/mfd/loongson-se.c b/drivers/mfd/loongson-se.c
index 3902ba377d6..40e18c21268 100644
--- a/drivers/mfd/loongson-se.c
+++ b/drivers/mfd/loongson-se.c
@@ -37,6 +37,9 @@ struct loongson_se_controller_cmd {
 	u32 info[7];
 };
 
+static DECLARE_COMPLETION(node0);
+static struct loongson_se *se_node[SE_MAX_NODES];
+
 static int loongson_se_poll(struct loongson_se *se, u32 int_bit)
 {
 	u32 status;
@@ -133,8 +136,8 @@ EXPORT_SYMBOL_GPL(loongson_se_init_engine);
 static irqreturn_t se_irq_handler(int irq, void *dev_id)
 {
 	struct loongson_se *se = dev_id;
-	u32 int_status;
-	int id;
+	u32 int_status, node_irq = 0;
+	int id, node;
 
 	spin_lock(&se->dev_lock);
 
@@ -147,6 +150,11 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
 		writel(SE_INT_CONTROLLER, se->base + SE_S2LINT_CL);
 	}
 
+	if (int_status & SE_INT_OTHER_NODE) {
+		int_status &= ~SE_INT_OTHER_NODE;
+		node_irq = 1;
+	}
+
 	/* For engines */
 	while (int_status) {
 		id = __ffs(int_status);
@@ -157,6 +165,14 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
 
 	spin_unlock(&se->dev_lock);
 
+	if (node_irq) {
+		writel(SE_INT_OTHER_NODE, se->base + SE_S2LINT_CL);
+		for (node = 1; node < SE_MAX_NODES; node++) {
+			if (se_node[node])
+				se_irq_handler(irq, se_node[node]);
+		}
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -189,6 +205,7 @@ static int loongson_se_probe(struct platform_device *pdev)
 	struct loongson_se *se;
 	int nr_irq, irq, err, i;
 	dma_addr_t paddr;
+	int node = dev_to_node(dev);
 
 	se = devm_kmalloc(dev, sizeof(*se), GFP_KERNEL);
 	if (!se)
@@ -213,9 +230,16 @@ static int loongson_se_probe(struct platform_device *pdev)
 
 	writel(SE_INT_ALL, se->base + SE_S2LINT_EN);
 
-	nr_irq = platform_irq_count(pdev);
-	if (nr_irq <= 0)
-		return -ENODEV;
+	if (node == 0 || node == NUMA_NO_NODE) {
+		nr_irq = platform_irq_count(pdev);
+		if (nr_irq <= 0)
+			return -ENODEV;
+	} else {
+		/* Only the device on node 0 can trigger interrupts */
+		nr_irq = 0;
+		wait_for_completion_interruptible(&node0);
+		se_node[node] = se;
+	}
 
 	for (i = 0; i < nr_irq; i++) {
 		irq = platform_get_irq(pdev, i);
@@ -228,7 +252,9 @@ static int loongson_se_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, engines,
+	complete_all(&node0);
+
+	return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, engines,
 				    ARRAY_SIZE(engines), NULL, 0, NULL);
 }
 
diff --git a/include/linux/mfd/loongson-se.h b/include/linux/mfd/loongson-se.h
index 07afa0c2524..a80e06eb017 100644
--- a/include/linux/mfd/loongson-se.h
+++ b/include/linux/mfd/loongson-se.h
@@ -20,6 +20,9 @@
 
 #define SE_INT_ALL			0xffffffff
 #define SE_INT_CONTROLLER		BIT(0)
+#define SE_INT_OTHER_NODE		BIT(31)
+
+#define SE_MAX_NODES			8
 
 #define SE_ENGINE_MAX			16
 #define SE_ENGINE_RNG			1

base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
-- 
2.47.2
Re: [PATCH v2] mfd: loongson-se: Add multi-node support
Posted by Huacai Chen 1 month, 2 weeks ago
Hi, Qunqin,

On Mon, Apr 27, 2026 at 4:55 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
>
> On the Loongson platform, each node is equipped with a security engine
> device. However, due to a hardware flaw, only the device on node 0 can
> trigger interrupts. Therefore, interrupts from other nodes are forwarded
> by node 0. We need to check in the interrupt handler of node 0 whether
> this interrupt is intended for other nodes.
Multi-node or multi-package? In my opinion SE has no relationship with
NUMA node, so maybe package?

Huacai

>
> Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
> ---
> Changes in v2:
>         -Resending due to no feedback for one month.
>         -Rebased on top of latest mainline (7.1-rc1) to ensure the patch
>          applies cleanly.
>         -No functional changes since the previous submission.
>
> Link to v1:
> https://lore.kernel.org/all/20260226102225.19516-1-zhaoqunqin@loongson.cn/#t
>
>  drivers/mfd/loongson-se.c       | 38 +++++++++++++++++++++++++++------
>  include/linux/mfd/loongson-se.h |  3 +++
>  2 files changed, 35 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/mfd/loongson-se.c b/drivers/mfd/loongson-se.c
> index 3902ba377d6..40e18c21268 100644
> --- a/drivers/mfd/loongson-se.c
> +++ b/drivers/mfd/loongson-se.c
> @@ -37,6 +37,9 @@ struct loongson_se_controller_cmd {
>         u32 info[7];
>  };
>
> +static DECLARE_COMPLETION(node0);
> +static struct loongson_se *se_node[SE_MAX_NODES];
> +
>  static int loongson_se_poll(struct loongson_se *se, u32 int_bit)
>  {
>         u32 status;
> @@ -133,8 +136,8 @@ EXPORT_SYMBOL_GPL(loongson_se_init_engine);
>  static irqreturn_t se_irq_handler(int irq, void *dev_id)
>  {
>         struct loongson_se *se = dev_id;
> -       u32 int_status;
> -       int id;
> +       u32 int_status, node_irq = 0;
> +       int id, node;
>
>         spin_lock(&se->dev_lock);
>
> @@ -147,6 +150,11 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
>                 writel(SE_INT_CONTROLLER, se->base + SE_S2LINT_CL);
>         }
>
> +       if (int_status & SE_INT_OTHER_NODE) {
> +               int_status &= ~SE_INT_OTHER_NODE;
> +               node_irq = 1;
> +       }
> +
>         /* For engines */
>         while (int_status) {
>                 id = __ffs(int_status);
> @@ -157,6 +165,14 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
>
>         spin_unlock(&se->dev_lock);
>
> +       if (node_irq) {
> +               writel(SE_INT_OTHER_NODE, se->base + SE_S2LINT_CL);
> +               for (node = 1; node < SE_MAX_NODES; node++) {
> +                       if (se_node[node])
> +                               se_irq_handler(irq, se_node[node]);
> +               }
> +       }
> +
>         return IRQ_HANDLED;
>  }
>
> @@ -189,6 +205,7 @@ static int loongson_se_probe(struct platform_device *pdev)
>         struct loongson_se *se;
>         int nr_irq, irq, err, i;
>         dma_addr_t paddr;
> +       int node = dev_to_node(dev);
>
>         se = devm_kmalloc(dev, sizeof(*se), GFP_KERNEL);
>         if (!se)
> @@ -213,9 +230,16 @@ static int loongson_se_probe(struct platform_device *pdev)
>
>         writel(SE_INT_ALL, se->base + SE_S2LINT_EN);
>
> -       nr_irq = platform_irq_count(pdev);
> -       if (nr_irq <= 0)
> -               return -ENODEV;
> +       if (node == 0 || node == NUMA_NO_NODE) {
> +               nr_irq = platform_irq_count(pdev);
> +               if (nr_irq <= 0)
> +                       return -ENODEV;
> +       } else {
> +               /* Only the device on node 0 can trigger interrupts */
> +               nr_irq = 0;
> +               wait_for_completion_interruptible(&node0);
> +               se_node[node] = se;
> +       }
>
>         for (i = 0; i < nr_irq; i++) {
>                 irq = platform_get_irq(pdev, i);
> @@ -228,7 +252,9 @@ static int loongson_se_probe(struct platform_device *pdev)
>         if (err)
>                 return err;
>
> -       return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, engines,
> +       complete_all(&node0);
> +
> +       return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, engines,
>                                     ARRAY_SIZE(engines), NULL, 0, NULL);
>  }
>
> diff --git a/include/linux/mfd/loongson-se.h b/include/linux/mfd/loongson-se.h
> index 07afa0c2524..a80e06eb017 100644
> --- a/include/linux/mfd/loongson-se.h
> +++ b/include/linux/mfd/loongson-se.h
> @@ -20,6 +20,9 @@
>
>  #define SE_INT_ALL                     0xffffffff
>  #define SE_INT_CONTROLLER              BIT(0)
> +#define SE_INT_OTHER_NODE              BIT(31)
> +
> +#define SE_MAX_NODES                   8
>
>  #define SE_ENGINE_MAX                  16
>  #define SE_ENGINE_RNG                  1
>
> base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
> --
> 2.47.2
>
>
Re: [PATCH v2] mfd: loongson-se: Add multi-node support
Posted by Qunqin Zhao 1 month, 2 weeks ago
在 2026/4/27 下午5:02, Huacai Chen 写道:
> Hi, Qunqin,
>
> On Mon, Apr 27, 2026 at 4:55 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
>> On the Loongson platform, each node is equipped with a security engine
>> device. However, due to a hardware flaw, only the device on node 0 can
>> trigger interrupts. Therefore, interrupts from other nodes are forwarded
>> by node 0. We need to check in the interrupt handler of node 0 whether
>> this interrupt is intended for other nodes.
> Multi-node or multi-package? In my opinion SE has no relationship with
> NUMA node, so maybe package?

Here is the output of lscpu from my machine:

[loongson@localhost ~]$ lscpu
Architecture:          loongarch64
   CPU op-mode(s):      32-bit, 64-bit
   Address sizes:       48 bits physical, 48 bits virtual
   Byte Order:          Little Endian
CPU(s):                128
   On-line CPU(s) list: 0-127
Model name:            Loongson-3C6000/D
   CPU family:          Loongson-64bit
   Model:               0x11
   Thread(s) per core:  2
   Core(s) per socket:  32
   Socket(s):           2
   BogoMIPS:            4200.00
   Flags:               cpucfg lam ual fpu lsx lasx crc32 complex crypto 
lvz lbt_x86 lbt_arm lbt_mips
Caches (sum of all):
   L1d:                 4 MiB (64 instances)
   L1i:                 4 MiB (64 instances)
   L2:                  16 MiB (64 instances)
   L3:                  128 MiB (4 instances)
NUMA:
   NUMA node(s):        4
   NUMA node0 CPU(s):   0-31
   NUMA node1 CPU(s):   32-63
   NUMA node2 CPU(s):   64-95
   NUMA node3 CPU(s):   96-127

There are four SE devices in my system, one for each NUMA node.

Qunqin,

Thanks

>
> Huacai
>
>> Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
>> ---
>> Changes in v2:
>>          -Resending due to no feedback for one month.
>>          -Rebased on top of latest mainline (7.1-rc1) to ensure the patch
>>           applies cleanly.
>>          -No functional changes since the previous submission.
>>
>> Link to v1:
>> https://lore.kernel.org/all/20260226102225.19516-1-zhaoqunqin@loongson.cn/#t
>>
>>   drivers/mfd/loongson-se.c       | 38 +++++++++++++++++++++++++++------
>>   include/linux/mfd/loongson-se.h |  3 +++
>>   2 files changed, 35 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/mfd/loongson-se.c b/drivers/mfd/loongson-se.c
>> index 3902ba377d6..40e18c21268 100644
>> --- a/drivers/mfd/loongson-se.c
>> +++ b/drivers/mfd/loongson-se.c
>> @@ -37,6 +37,9 @@ struct loongson_se_controller_cmd {
>>          u32 info[7];
>>   };
>>
>> +static DECLARE_COMPLETION(node0);
>> +static struct loongson_se *se_node[SE_MAX_NODES];
>> +
>>   static int loongson_se_poll(struct loongson_se *se, u32 int_bit)
>>   {
>>          u32 status;
>> @@ -133,8 +136,8 @@ EXPORT_SYMBOL_GPL(loongson_se_init_engine);
>>   static irqreturn_t se_irq_handler(int irq, void *dev_id)
>>   {
>>          struct loongson_se *se = dev_id;
>> -       u32 int_status;
>> -       int id;
>> +       u32 int_status, node_irq = 0;
>> +       int id, node;
>>
>>          spin_lock(&se->dev_lock);
>>
>> @@ -147,6 +150,11 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
>>                  writel(SE_INT_CONTROLLER, se->base + SE_S2LINT_CL);
>>          }
>>
>> +       if (int_status & SE_INT_OTHER_NODE) {
>> +               int_status &= ~SE_INT_OTHER_NODE;
>> +               node_irq = 1;
>> +       }
>> +
>>          /* For engines */
>>          while (int_status) {
>>                  id = __ffs(int_status);
>> @@ -157,6 +165,14 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
>>
>>          spin_unlock(&se->dev_lock);
>>
>> +       if (node_irq) {
>> +               writel(SE_INT_OTHER_NODE, se->base + SE_S2LINT_CL);
>> +               for (node = 1; node < SE_MAX_NODES; node++) {
>> +                       if (se_node[node])
>> +                               se_irq_handler(irq, se_node[node]);
>> +               }
>> +       }
>> +
>>          return IRQ_HANDLED;
>>   }
>>
>> @@ -189,6 +205,7 @@ static int loongson_se_probe(struct platform_device *pdev)
>>          struct loongson_se *se;
>>          int nr_irq, irq, err, i;
>>          dma_addr_t paddr;
>> +       int node = dev_to_node(dev);
>>
>>          se = devm_kmalloc(dev, sizeof(*se), GFP_KERNEL);
>>          if (!se)
>> @@ -213,9 +230,16 @@ static int loongson_se_probe(struct platform_device *pdev)
>>
>>          writel(SE_INT_ALL, se->base + SE_S2LINT_EN);
>>
>> -       nr_irq = platform_irq_count(pdev);
>> -       if (nr_irq <= 0)
>> -               return -ENODEV;
>> +       if (node == 0 || node == NUMA_NO_NODE) {
>> +               nr_irq = platform_irq_count(pdev);
>> +               if (nr_irq <= 0)
>> +                       return -ENODEV;
>> +       } else {
>> +               /* Only the device on node 0 can trigger interrupts */
>> +               nr_irq = 0;
>> +               wait_for_completion_interruptible(&node0);
>> +               se_node[node] = se;
>> +       }
>>
>>          for (i = 0; i < nr_irq; i++) {
>>                  irq = platform_get_irq(pdev, i);
>> @@ -228,7 +252,9 @@ static int loongson_se_probe(struct platform_device *pdev)
>>          if (err)
>>                  return err;
>>
>> -       return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, engines,
>> +       complete_all(&node0);
>> +
>> +       return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, engines,
>>                                      ARRAY_SIZE(engines), NULL, 0, NULL);
>>   }
>>
>> diff --git a/include/linux/mfd/loongson-se.h b/include/linux/mfd/loongson-se.h
>> index 07afa0c2524..a80e06eb017 100644
>> --- a/include/linux/mfd/loongson-se.h
>> +++ b/include/linux/mfd/loongson-se.h
>> @@ -20,6 +20,9 @@
>>
>>   #define SE_INT_ALL                     0xffffffff
>>   #define SE_INT_CONTROLLER              BIT(0)
>> +#define SE_INT_OTHER_NODE              BIT(31)
>> +
>> +#define SE_MAX_NODES                   8
>>
>>   #define SE_ENGINE_MAX                  16
>>   #define SE_ENGINE_RNG                  1
>>
>> base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
>> --
>> 2.47.2
>>
>>

Re: [PATCH v2] mfd: loongson-se: Add multi-node support
Posted by Huacai Chen 1 month, 2 weeks ago
On Mon, Apr 27, 2026 at 5:24 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
>
>
> 在 2026/4/27 下午5:02, Huacai Chen 写道:
> > Hi, Qunqin,
> >
> > On Mon, Apr 27, 2026 at 4:55 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
> >> On the Loongson platform, each node is equipped with a security engine
> >> device. However, due to a hardware flaw, only the device on node 0 can
> >> trigger interrupts. Therefore, interrupts from other nodes are forwarded
> >> by node 0. We need to check in the interrupt handler of node 0 whether
> >> this interrupt is intended for other nodes.
> > Multi-node or multi-package? In my opinion SE has no relationship with
> > NUMA node, so maybe package?
>
> Here is the output of lscpu from my machine:
>
> [loongson@localhost ~]$ lscpu
> Architecture:          loongarch64
>    CPU op-mode(s):      32-bit, 64-bit
>    Address sizes:       48 bits physical, 48 bits virtual
>    Byte Order:          Little Endian
> CPU(s):                128
>    On-line CPU(s) list: 0-127
> Model name:            Loongson-3C6000/D
>    CPU family:          Loongson-64bit
>    Model:               0x11
>    Thread(s) per core:  2
>    Core(s) per socket:  32
>    Socket(s):           2
>    BogoMIPS:            4200.00
>    Flags:               cpucfg lam ual fpu lsx lasx crc32 complex crypto
> lvz lbt_x86 lbt_arm lbt_mips
> Caches (sum of all):
>    L1d:                 4 MiB (64 instances)
>    L1i:                 4 MiB (64 instances)
>    L2:                  16 MiB (64 instances)
>    L3:                  128 MiB (4 instances)
> NUMA:
>    NUMA node(s):        4
>    NUMA node0 CPU(s):   0-31
>    NUMA node1 CPU(s):   32-63
>    NUMA node2 CPU(s):   64-95
>    NUMA node3 CPU(s):   96-127
>
> There are four SE devices in my system, one for each NUMA node.
For Loongson-3C6000 node is the same as package. You should consider
Loongson-3C5000L, one package contains four nodes.

Huacai

>
> Qunqin,
>
> Thanks
>
> >
> > Huacai
> >
> >> Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
> >> ---
> >> Changes in v2:
> >>          -Resending due to no feedback for one month.
> >>          -Rebased on top of latest mainline (7.1-rc1) to ensure the patch
> >>           applies cleanly.
> >>          -No functional changes since the previous submission.
> >>
> >> Link to v1:
> >> https://lore.kernel.org/all/20260226102225.19516-1-zhaoqunqin@loongson.cn/#t
> >>
> >>   drivers/mfd/loongson-se.c       | 38 +++++++++++++++++++++++++++------
> >>   include/linux/mfd/loongson-se.h |  3 +++
> >>   2 files changed, 35 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/mfd/loongson-se.c b/drivers/mfd/loongson-se.c
> >> index 3902ba377d6..40e18c21268 100644
> >> --- a/drivers/mfd/loongson-se.c
> >> +++ b/drivers/mfd/loongson-se.c
> >> @@ -37,6 +37,9 @@ struct loongson_se_controller_cmd {
> >>          u32 info[7];
> >>   };
> >>
> >> +static DECLARE_COMPLETION(node0);
> >> +static struct loongson_se *se_node[SE_MAX_NODES];
> >> +
> >>   static int loongson_se_poll(struct loongson_se *se, u32 int_bit)
> >>   {
> >>          u32 status;
> >> @@ -133,8 +136,8 @@ EXPORT_SYMBOL_GPL(loongson_se_init_engine);
> >>   static irqreturn_t se_irq_handler(int irq, void *dev_id)
> >>   {
> >>          struct loongson_se *se = dev_id;
> >> -       u32 int_status;
> >> -       int id;
> >> +       u32 int_status, node_irq = 0;
> >> +       int id, node;
> >>
> >>          spin_lock(&se->dev_lock);
> >>
> >> @@ -147,6 +150,11 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
> >>                  writel(SE_INT_CONTROLLER, se->base + SE_S2LINT_CL);
> >>          }
> >>
> >> +       if (int_status & SE_INT_OTHER_NODE) {
> >> +               int_status &= ~SE_INT_OTHER_NODE;
> >> +               node_irq = 1;
> >> +       }
> >> +
> >>          /* For engines */
> >>          while (int_status) {
> >>                  id = __ffs(int_status);
> >> @@ -157,6 +165,14 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
> >>
> >>          spin_unlock(&se->dev_lock);
> >>
> >> +       if (node_irq) {
> >> +               writel(SE_INT_OTHER_NODE, se->base + SE_S2LINT_CL);
> >> +               for (node = 1; node < SE_MAX_NODES; node++) {
> >> +                       if (se_node[node])
> >> +                               se_irq_handler(irq, se_node[node]);
> >> +               }
> >> +       }
> >> +
> >>          return IRQ_HANDLED;
> >>   }
> >>
> >> @@ -189,6 +205,7 @@ static int loongson_se_probe(struct platform_device *pdev)
> >>          struct loongson_se *se;
> >>          int nr_irq, irq, err, i;
> >>          dma_addr_t paddr;
> >> +       int node = dev_to_node(dev);
> >>
> >>          se = devm_kmalloc(dev, sizeof(*se), GFP_KERNEL);
> >>          if (!se)
> >> @@ -213,9 +230,16 @@ static int loongson_se_probe(struct platform_device *pdev)
> >>
> >>          writel(SE_INT_ALL, se->base + SE_S2LINT_EN);
> >>
> >> -       nr_irq = platform_irq_count(pdev);
> >> -       if (nr_irq <= 0)
> >> -               return -ENODEV;
> >> +       if (node == 0 || node == NUMA_NO_NODE) {
> >> +               nr_irq = platform_irq_count(pdev);
> >> +               if (nr_irq <= 0)
> >> +                       return -ENODEV;
> >> +       } else {
> >> +               /* Only the device on node 0 can trigger interrupts */
> >> +               nr_irq = 0;
> >> +               wait_for_completion_interruptible(&node0);
> >> +               se_node[node] = se;
> >> +       }
> >>
> >>          for (i = 0; i < nr_irq; i++) {
> >>                  irq = platform_get_irq(pdev, i);
> >> @@ -228,7 +252,9 @@ static int loongson_se_probe(struct platform_device *pdev)
> >>          if (err)
> >>                  return err;
> >>
> >> -       return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, engines,
> >> +       complete_all(&node0);
> >> +
> >> +       return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, engines,
> >>                                      ARRAY_SIZE(engines), NULL, 0, NULL);
> >>   }
> >>
> >> diff --git a/include/linux/mfd/loongson-se.h b/include/linux/mfd/loongson-se.h
> >> index 07afa0c2524..a80e06eb017 100644
> >> --- a/include/linux/mfd/loongson-se.h
> >> +++ b/include/linux/mfd/loongson-se.h
> >> @@ -20,6 +20,9 @@
> >>
> >>   #define SE_INT_ALL                     0xffffffff
> >>   #define SE_INT_CONTROLLER              BIT(0)
> >> +#define SE_INT_OTHER_NODE              BIT(31)
> >> +
> >> +#define SE_MAX_NODES                   8
> >>
> >>   #define SE_ENGINE_MAX                  16
> >>   #define SE_ENGINE_RNG                  1
> >>
> >> base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
> >> --
> >> 2.47.2
> >>
> >>
>
>
Re: [PATCH v2] mfd: loongson-se: Add multi-node support
Posted by Qunqin Zhao 1 month, 2 weeks ago
在 2026/4/27 下午5:37, Huacai Chen 写道:
> On Mon, Apr 27, 2026 at 5:24 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
>>
>> 在 2026/4/27 下午5:02, Huacai Chen 写道:
>>> Hi, Qunqin,
>>>
>>> On Mon, Apr 27, 2026 at 4:55 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
>>>> On the Loongson platform, each node is equipped with a security engine
>>>> device. However, due to a hardware flaw, only the device on node 0 can
>>>> trigger interrupts. Therefore, interrupts from other nodes are forwarded
>>>> by node 0. We need to check in the interrupt handler of node 0 whether
>>>> this interrupt is intended for other nodes.
>>> Multi-node or multi-package? In my opinion SE has no relationship with
>>> NUMA node, so maybe package?
>> Here is the output of lscpu from my machine:
>>
>> [loongson@localhost ~]$ lscpu
>> Architecture:          loongarch64
>>     CPU op-mode(s):      32-bit, 64-bit
>>     Address sizes:       48 bits physical, 48 bits virtual
>>     Byte Order:          Little Endian
>> CPU(s):                128
>>     On-line CPU(s) list: 0-127
>> Model name:            Loongson-3C6000/D
>>     CPU family:          Loongson-64bit
>>     Model:               0x11
>>     Thread(s) per core:  2
>>     Core(s) per socket:  32
>>     Socket(s):           2
>>     BogoMIPS:            4200.00
>>     Flags:               cpucfg lam ual fpu lsx lasx crc32 complex crypto
>> lvz lbt_x86 lbt_arm lbt_mips
>> Caches (sum of all):
>>     L1d:                 4 MiB (64 instances)
>>     L1i:                 4 MiB (64 instances)
>>     L2:                  16 MiB (64 instances)
>>     L3:                  128 MiB (4 instances)
>> NUMA:
>>     NUMA node(s):        4
>>     NUMA node0 CPU(s):   0-31
>>     NUMA node1 CPU(s):   32-63
>>     NUMA node2 CPU(s):   64-95
>>     NUMA node3 CPU(s):   96-127
>>
>> There are four SE devices in my system, one for each NUMA node.
> For Loongson-3C6000 node is the same as package. You should consider
> Loongson-3C5000L, one package contains four nodes.

I am not familiar with the SE-related components on the 3C5000L, and 
this driver is not compatible with the 5000 series.

Qunqin,

Thanks.

>
> Huacai
>
>> Qunqin,
>>
>> Thanks
>>
>>> Huacai
>>>
>>>> Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
>>>> ---
>>>> Changes in v2:
>>>>           -Resending due to no feedback for one month.
>>>>           -Rebased on top of latest mainline (7.1-rc1) to ensure the patch
>>>>            applies cleanly.
>>>>           -No functional changes since the previous submission.
>>>>
>>>> Link to v1:
>>>> https://lore.kernel.org/all/20260226102225.19516-1-zhaoqunqin@loongson.cn/#t
>>>>
>>>>    drivers/mfd/loongson-se.c       | 38 +++++++++++++++++++++++++++------
>>>>    include/linux/mfd/loongson-se.h |  3 +++
>>>>    2 files changed, 35 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/mfd/loongson-se.c b/drivers/mfd/loongson-se.c
>>>> index 3902ba377d6..40e18c21268 100644
>>>> --- a/drivers/mfd/loongson-se.c
>>>> +++ b/drivers/mfd/loongson-se.c
>>>> @@ -37,6 +37,9 @@ struct loongson_se_controller_cmd {
>>>>           u32 info[7];
>>>>    };
>>>>
>>>> +static DECLARE_COMPLETION(node0);
>>>> +static struct loongson_se *se_node[SE_MAX_NODES];
>>>> +
>>>>    static int loongson_se_poll(struct loongson_se *se, u32 int_bit)
>>>>    {
>>>>           u32 status;
>>>> @@ -133,8 +136,8 @@ EXPORT_SYMBOL_GPL(loongson_se_init_engine);
>>>>    static irqreturn_t se_irq_handler(int irq, void *dev_id)
>>>>    {
>>>>           struct loongson_se *se = dev_id;
>>>> -       u32 int_status;
>>>> -       int id;
>>>> +       u32 int_status, node_irq = 0;
>>>> +       int id, node;
>>>>
>>>>           spin_lock(&se->dev_lock);
>>>>
>>>> @@ -147,6 +150,11 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
>>>>                   writel(SE_INT_CONTROLLER, se->base + SE_S2LINT_CL);
>>>>           }
>>>>
>>>> +       if (int_status & SE_INT_OTHER_NODE) {
>>>> +               int_status &= ~SE_INT_OTHER_NODE;
>>>> +               node_irq = 1;
>>>> +       }
>>>> +
>>>>           /* For engines */
>>>>           while (int_status) {
>>>>                   id = __ffs(int_status);
>>>> @@ -157,6 +165,14 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
>>>>
>>>>           spin_unlock(&se->dev_lock);
>>>>
>>>> +       if (node_irq) {
>>>> +               writel(SE_INT_OTHER_NODE, se->base + SE_S2LINT_CL);
>>>> +               for (node = 1; node < SE_MAX_NODES; node++) {
>>>> +                       if (se_node[node])
>>>> +                               se_irq_handler(irq, se_node[node]);
>>>> +               }
>>>> +       }
>>>> +
>>>>           return IRQ_HANDLED;
>>>>    }
>>>>
>>>> @@ -189,6 +205,7 @@ static int loongson_se_probe(struct platform_device *pdev)
>>>>           struct loongson_se *se;
>>>>           int nr_irq, irq, err, i;
>>>>           dma_addr_t paddr;
>>>> +       int node = dev_to_node(dev);
>>>>
>>>>           se = devm_kmalloc(dev, sizeof(*se), GFP_KERNEL);
>>>>           if (!se)
>>>> @@ -213,9 +230,16 @@ static int loongson_se_probe(struct platform_device *pdev)
>>>>
>>>>           writel(SE_INT_ALL, se->base + SE_S2LINT_EN);
>>>>
>>>> -       nr_irq = platform_irq_count(pdev);
>>>> -       if (nr_irq <= 0)
>>>> -               return -ENODEV;
>>>> +       if (node == 0 || node == NUMA_NO_NODE) {
>>>> +               nr_irq = platform_irq_count(pdev);
>>>> +               if (nr_irq <= 0)
>>>> +                       return -ENODEV;
>>>> +       } else {
>>>> +               /* Only the device on node 0 can trigger interrupts */
>>>> +               nr_irq = 0;
>>>> +               wait_for_completion_interruptible(&node0);
>>>> +               se_node[node] = se;
>>>> +       }
>>>>
>>>>           for (i = 0; i < nr_irq; i++) {
>>>>                   irq = platform_get_irq(pdev, i);
>>>> @@ -228,7 +252,9 @@ static int loongson_se_probe(struct platform_device *pdev)
>>>>           if (err)
>>>>                   return err;
>>>>
>>>> -       return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, engines,
>>>> +       complete_all(&node0);
>>>> +
>>>> +       return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, engines,
>>>>                                       ARRAY_SIZE(engines), NULL, 0, NULL);
>>>>    }
>>>>
>>>> diff --git a/include/linux/mfd/loongson-se.h b/include/linux/mfd/loongson-se.h
>>>> index 07afa0c2524..a80e06eb017 100644
>>>> --- a/include/linux/mfd/loongson-se.h
>>>> +++ b/include/linux/mfd/loongson-se.h
>>>> @@ -20,6 +20,9 @@
>>>>
>>>>    #define SE_INT_ALL                     0xffffffff
>>>>    #define SE_INT_CONTROLLER              BIT(0)
>>>> +#define SE_INT_OTHER_NODE              BIT(31)
>>>> +
>>>> +#define SE_MAX_NODES                   8
>>>>
>>>>    #define SE_ENGINE_MAX                  16
>>>>    #define SE_ENGINE_RNG                  1
>>>>
>>>> base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
>>>> --
>>>> 2.47.2
>>>>
>>>>
>>

Re: [PATCH v2] mfd: loongson-se: Add multi-node support
Posted by Huacai Chen 1 month, 2 weeks ago
On Mon, Apr 27, 2026 at 5:52 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
>
>
> 在 2026/4/27 下午5:37, Huacai Chen 写道:
> > On Mon, Apr 27, 2026 at 5:24 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
> >>
> >> 在 2026/4/27 下午5:02, Huacai Chen 写道:
> >>> Hi, Qunqin,
> >>>
> >>> On Mon, Apr 27, 2026 at 4:55 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
> >>>> On the Loongson platform, each node is equipped with a security engine
> >>>> device. However, due to a hardware flaw, only the device on node 0 can
> >>>> trigger interrupts. Therefore, interrupts from other nodes are forwarded
> >>>> by node 0. We need to check in the interrupt handler of node 0 whether
> >>>> this interrupt is intended for other nodes.
> >>> Multi-node or multi-package? In my opinion SE has no relationship with
> >>> NUMA node, so maybe package?
> >> Here is the output of lscpu from my machine:
> >>
> >> [loongson@localhost ~]$ lscpu
> >> Architecture:          loongarch64
> >>     CPU op-mode(s):      32-bit, 64-bit
> >>     Address sizes:       48 bits physical, 48 bits virtual
> >>     Byte Order:          Little Endian
> >> CPU(s):                128
> >>     On-line CPU(s) list: 0-127
> >> Model name:            Loongson-3C6000/D
> >>     CPU family:          Loongson-64bit
> >>     Model:               0x11
> >>     Thread(s) per core:  2
> >>     Core(s) per socket:  32
> >>     Socket(s):           2
> >>     BogoMIPS:            4200.00
> >>     Flags:               cpucfg lam ual fpu lsx lasx crc32 complex crypto
> >> lvz lbt_x86 lbt_arm lbt_mips
> >> Caches (sum of all):
> >>     L1d:                 4 MiB (64 instances)
> >>     L1i:                 4 MiB (64 instances)
> >>     L2:                  16 MiB (64 instances)
> >>     L3:                  128 MiB (4 instances)
> >> NUMA:
> >>     NUMA node(s):        4
> >>     NUMA node0 CPU(s):   0-31
> >>     NUMA node1 CPU(s):   32-63
> >>     NUMA node2 CPU(s):   64-95
> >>     NUMA node3 CPU(s):   96-127
> >>
> >> There are four SE devices in my system, one for each NUMA node.
> > For Loongson-3C6000 node is the same as package. You should consider
> > Loongson-3C5000L, one package contains four nodes.
>
> I am not familiar with the SE-related components on the 3C5000L, and
> this driver is not compatible with the 5000 series.
Whether it is compatible to Loongson-3C5000L is not important. The
importance is package is not always equal to node, and we should
consider whether SE is per-node or per-package.

Huacai

>
> Qunqin,
>
> Thanks.
>
> >
> > Huacai
> >
> >> Qunqin,
> >>
> >> Thanks
> >>
> >>> Huacai
> >>>
> >>>> Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
> >>>> ---
> >>>> Changes in v2:
> >>>>           -Resending due to no feedback for one month.
> >>>>           -Rebased on top of latest mainline (7.1-rc1) to ensure the patch
> >>>>            applies cleanly.
> >>>>           -No functional changes since the previous submission.
> >>>>
> >>>> Link to v1:
> >>>> https://lore.kernel.org/all/20260226102225.19516-1-zhaoqunqin@loongson.cn/#t
> >>>>
> >>>>    drivers/mfd/loongson-se.c       | 38 +++++++++++++++++++++++++++------
> >>>>    include/linux/mfd/loongson-se.h |  3 +++
> >>>>    2 files changed, 35 insertions(+), 6 deletions(-)
> >>>>
> >>>> diff --git a/drivers/mfd/loongson-se.c b/drivers/mfd/loongson-se.c
> >>>> index 3902ba377d6..40e18c21268 100644
> >>>> --- a/drivers/mfd/loongson-se.c
> >>>> +++ b/drivers/mfd/loongson-se.c
> >>>> @@ -37,6 +37,9 @@ struct loongson_se_controller_cmd {
> >>>>           u32 info[7];
> >>>>    };
> >>>>
> >>>> +static DECLARE_COMPLETION(node0);
> >>>> +static struct loongson_se *se_node[SE_MAX_NODES];
> >>>> +
> >>>>    static int loongson_se_poll(struct loongson_se *se, u32 int_bit)
> >>>>    {
> >>>>           u32 status;
> >>>> @@ -133,8 +136,8 @@ EXPORT_SYMBOL_GPL(loongson_se_init_engine);
> >>>>    static irqreturn_t se_irq_handler(int irq, void *dev_id)
> >>>>    {
> >>>>           struct loongson_se *se = dev_id;
> >>>> -       u32 int_status;
> >>>> -       int id;
> >>>> +       u32 int_status, node_irq = 0;
> >>>> +       int id, node;
> >>>>
> >>>>           spin_lock(&se->dev_lock);
> >>>>
> >>>> @@ -147,6 +150,11 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
> >>>>                   writel(SE_INT_CONTROLLER, se->base + SE_S2LINT_CL);
> >>>>           }
> >>>>
> >>>> +       if (int_status & SE_INT_OTHER_NODE) {
> >>>> +               int_status &= ~SE_INT_OTHER_NODE;
> >>>> +               node_irq = 1;
> >>>> +       }
> >>>> +
> >>>>           /* For engines */
> >>>>           while (int_status) {
> >>>>                   id = __ffs(int_status);
> >>>> @@ -157,6 +165,14 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
> >>>>
> >>>>           spin_unlock(&se->dev_lock);
> >>>>
> >>>> +       if (node_irq) {
> >>>> +               writel(SE_INT_OTHER_NODE, se->base + SE_S2LINT_CL);
> >>>> +               for (node = 1; node < SE_MAX_NODES; node++) {
> >>>> +                       if (se_node[node])
> >>>> +                               se_irq_handler(irq, se_node[node]);
> >>>> +               }
> >>>> +       }
> >>>> +
> >>>>           return IRQ_HANDLED;
> >>>>    }
> >>>>
> >>>> @@ -189,6 +205,7 @@ static int loongson_se_probe(struct platform_device *pdev)
> >>>>           struct loongson_se *se;
> >>>>           int nr_irq, irq, err, i;
> >>>>           dma_addr_t paddr;
> >>>> +       int node = dev_to_node(dev);
> >>>>
> >>>>           se = devm_kmalloc(dev, sizeof(*se), GFP_KERNEL);
> >>>>           if (!se)
> >>>> @@ -213,9 +230,16 @@ static int loongson_se_probe(struct platform_device *pdev)
> >>>>
> >>>>           writel(SE_INT_ALL, se->base + SE_S2LINT_EN);
> >>>>
> >>>> -       nr_irq = platform_irq_count(pdev);
> >>>> -       if (nr_irq <= 0)
> >>>> -               return -ENODEV;
> >>>> +       if (node == 0 || node == NUMA_NO_NODE) {
> >>>> +               nr_irq = platform_irq_count(pdev);
> >>>> +               if (nr_irq <= 0)
> >>>> +                       return -ENODEV;
> >>>> +       } else {
> >>>> +               /* Only the device on node 0 can trigger interrupts */
> >>>> +               nr_irq = 0;
> >>>> +               wait_for_completion_interruptible(&node0);
> >>>> +               se_node[node] = se;
> >>>> +       }
> >>>>
> >>>>           for (i = 0; i < nr_irq; i++) {
> >>>>                   irq = platform_get_irq(pdev, i);
> >>>> @@ -228,7 +252,9 @@ static int loongson_se_probe(struct platform_device *pdev)
> >>>>           if (err)
> >>>>                   return err;
> >>>>
> >>>> -       return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, engines,
> >>>> +       complete_all(&node0);
> >>>> +
> >>>> +       return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, engines,
> >>>>                                       ARRAY_SIZE(engines), NULL, 0, NULL);
> >>>>    }
> >>>>
> >>>> diff --git a/include/linux/mfd/loongson-se.h b/include/linux/mfd/loongson-se.h
> >>>> index 07afa0c2524..a80e06eb017 100644
> >>>> --- a/include/linux/mfd/loongson-se.h
> >>>> +++ b/include/linux/mfd/loongson-se.h
> >>>> @@ -20,6 +20,9 @@
> >>>>
> >>>>    #define SE_INT_ALL                     0xffffffff
> >>>>    #define SE_INT_CONTROLLER              BIT(0)
> >>>> +#define SE_INT_OTHER_NODE              BIT(31)
> >>>> +
> >>>> +#define SE_MAX_NODES                   8
> >>>>
> >>>>    #define SE_ENGINE_MAX                  16
> >>>>    #define SE_ENGINE_RNG                  1
> >>>>
> >>>> base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
> >>>> --
> >>>> 2.47.2
> >>>>
> >>>>
> >>
>
Re: [PATCH v2] mfd: loongson-se: Add multi-node support
Posted by Qunqin Zhao 1 month ago
在 2026/4/27 下午6:02, Huacai Chen 写道:
> On Mon, Apr 27, 2026 at 5:52 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
>>
>> 在 2026/4/27 下午5:37, Huacai Chen 写道:
>>> On Mon, Apr 27, 2026 at 5:24 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
>>>> 在 2026/4/27 下午5:02, Huacai Chen 写道:
>>>>> Hi, Qunqin,
>>>>>
>>>>> On Mon, Apr 27, 2026 at 4:55 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
>>>>>> On the Loongson platform, each node is equipped with a security engine
>>>>>> device. However, due to a hardware flaw, only the device on node 0 can
>>>>>> trigger interrupts. Therefore, interrupts from other nodes are forwarded
>>>>>> by node 0. We need to check in the interrupt handler of node 0 whether
>>>>>> this interrupt is intended for other nodes.
>>>>> Multi-node or multi-package? In my opinion SE has no relationship with
>>>>> NUMA node, so maybe package?
>>>> Here is the output of lscpu from my machine:
>>>>
>>>> [loongson@localhost ~]$ lscpu
>>>> Architecture:          loongarch64
>>>>      CPU op-mode(s):      32-bit, 64-bit
>>>>      Address sizes:       48 bits physical, 48 bits virtual
>>>>      Byte Order:          Little Endian
>>>> CPU(s):                128
>>>>      On-line CPU(s) list: 0-127
>>>> Model name:            Loongson-3C6000/D
>>>>      CPU family:          Loongson-64bit
>>>>      Model:               0x11
>>>>      Thread(s) per core:  2
>>>>      Core(s) per socket:  32
>>>>      Socket(s):           2
>>>>      BogoMIPS:            4200.00
>>>>      Flags:               cpucfg lam ual fpu lsx lasx crc32 complex crypto
>>>> lvz lbt_x86 lbt_arm lbt_mips
>>>> Caches (sum of all):
>>>>      L1d:                 4 MiB (64 instances)
>>>>      L1i:                 4 MiB (64 instances)
>>>>      L2:                  16 MiB (64 instances)
>>>>      L3:                  128 MiB (4 instances)
>>>> NUMA:
>>>>      NUMA node(s):        4
>>>>      NUMA node0 CPU(s):   0-31
>>>>      NUMA node1 CPU(s):   32-63
>>>>      NUMA node2 CPU(s):   64-95
>>>>      NUMA node3 CPU(s):   96-127
>>>>
>>>> There are four SE devices in my system, one for each NUMA node.
>>> For Loongson-3C6000 node is the same as package. You should consider
>>> Loongson-3C5000L, one package contains four nodes.
>> I am not familiar with the SE-related components on the 3C5000L, and
>> this driver is not compatible with the 5000 series.
> Whether it is compatible to Loongson-3C5000L is not important. The
> importance is package is not always equal to node, and we should
> consider whether SE is per-node or per-package.

Hi, huacai

After consulting with  hardware team, I learned that while the 3C5000L
has four SE devices, only one is utilized due to interrupt constraints.

Thanks,

Qunqin

>
> Huacai
>

Re: [PATCH v2] mfd: loongson-se: Add multi-node support
Posted by Xi Ruoyao 1 month, 2 weeks ago
On Mon, 2026-04-27 at 18:02 +0800, Huacai Chen wrote:
> On Mon, Apr 27, 2026 at 5:52 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
> > 
> > 
> > 在 2026/4/27 下午5:37, Huacai Chen 写道:
> > > On Mon, Apr 27, 2026 at 5:24 PM Qunqin Zhao <zhaoqunqin@loongson.cn> wrote:
> > > > 
> > > > 在 2026/4/27 下午5:02, Huacai Chen 写道:
> > > > > Hi, Qunqin,
> > > > > 
> > > > > On Mon, Apr 27, 2026 at 4:55 PM Qunqin Zhao
> > > > > <zhaoqunqin@loongson.cn> wrote:
> > > > > > On the Loongson platform, each node is equipped with a
> > > > > > security engine
> > > > > > device. However, due to a hardware flaw, only the device on
> > > > > > node 0 can
> > > > > > trigger interrupts. Therefore, interrupts from other nodes
> > > > > > are forwarded
> > > > > > by node 0. We need to check in the interrupt handler of node
> > > > > > 0 whether
> > > > > > this interrupt is intended for other nodes.
> > > > > Multi-node or multi-package? In my opinion SE has no
> > > > > relationship with
> > > > > NUMA node, so maybe package?
> > > > Here is the output of lscpu from my machine:
> > > > 
> > > > [loongson@localhost ~]$ lscpu
> > > > Architecture:          loongarch64
> > > >     CPU op-mode(s):      32-bit, 64-bit
> > > >     Address sizes:       48 bits physical, 48 bits virtual
> > > >     Byte Order:          Little Endian
> > > > CPU(s):                128
> > > >     On-line CPU(s) list: 0-127
> > > > Model name:            Loongson-3C6000/D
> > > >     CPU family:          Loongson-64bit
> > > >     Model:               0x11
> > > >     Thread(s) per core:  2
> > > >     Core(s) per socket:  32
> > > >     Socket(s):           2
> > > >     BogoMIPS:            4200.00
> > > >     Flags:               cpucfg lam ual fpu lsx lasx crc32
> > > > complex crypto
> > > > lvz lbt_x86 lbt_arm lbt_mips
> > > > Caches (sum of all):
> > > >     L1d:                 4 MiB (64 instances)
> > > >     L1i:                 4 MiB (64 instances)
> > > >     L2:                  16 MiB (64 instances)
> > > >     L3:                  128 MiB (4 instances)
> > > > NUMA:
> > > >     NUMA node(s):        4
> > > >     NUMA node0 CPU(s):   0-31
> > > >     NUMA node1 CPU(s):   32-63
> > > >     NUMA node2 CPU(s):   64-95
> > > >     NUMA node3 CPU(s):   96-127
> > > > 
> > > > There are four SE devices in my system, one for each NUMA node.
> > > For Loongson-3C6000 node is the same as package. You should
> > > consider
> > > Loongson-3C5000L, one package contains four nodes.
> > 
> > I am not familiar with the SE-related components on the 3C5000L, and
> > this driver is not compatible with the 5000 series.
> Whether it is compatible to Loongson-3C5000L is not important. The
> importance is package is not always equal to node, and we should
> consider whether SE is per-node or per-package.

For a "compatible" example, 3C6000/D has two nodes in a package.

-- 
Xi Ruoyao <xry111@xry111.site>