All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC v6 0/7] mfd: ls2kbmc: multiple fixes for this driver
@ 2026-08-04 19:14 ` Miao Wang
  0 siblings, 0 replies; 27+ messages in thread
From: Miao Wang via B4 Relay @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

Previously, the driver has been introduced to support the Loongson 2K
BMC running on the Loongson Servers, which is essential to prevent
the system from hanging when the BMC is being reset and the default
efi-framebuffer is being used. However, there are some drawbacks in the
driver.

Firstly, the driver tries to read and write to the connected PCI-E host
controller registers, assuming that the BMC is connected to LS7A PCI-E
host controller. This assumption should be true for real products, but
to prevent from accidentally reading and writing to the wrong PCI-E host
controller, this driver should be modified to check this before
accessing the registers.

Secondly, the driver uses non-exported functions to tell the vt
subsystem to redraw the screen, preventing the driver from being
compiling as a module. This can be fixed by using the exported
functions instead.

Thirdly, the driver directly accesses the GPIO controller registers
using hard-coded addresses, which might conflict with the loaded GPIO
controller driver for the same GPIO controller. This is fixed in this
series by using the GPIO subsystem APIs instead. However, legacy GPIO
APIs have to be used in this fixed to correctly request a GPIO
descriptor from the GPIO subsystem, which might be further discussed
to find a better solution.

Finally, there is a minor issue in the driver where it changes the
mode string describing the screen resolution during probing, which
prevents the device from being probed again if -EPROBE_DEFER is
returned by the probe function.

I have tested the changes in this series on a single-socket Loongson
3C6000 server with a Loongson 2K BMC, and the driver works as expected
when the corresponding GPIO driver is additionally loaded.

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
Changes in v6:
- Ajdust the Kconfig entry for IPMI_LS2K, moving the dependency on
  MFD_LS2K_BMC_CORE to the IPMI_SI Kconfig entry, as discussed with
  and agreed by Corey.
- Link to v5: https://lore.kernel.org/r/20260804-ls2kbmc-mod-v5-0-e6bc5cdd9a93@gmail.com

Changes in v5:
- Address issues found by the Sashiko AI review bot
  - Maintain the compatibility with possible unexpected mode string when
    parsing, although such mode string is actually not expected, to
    satisfy the AI bot's concern.
  - Add a comment to point out that the adjustment of the Kconfig entry
    for ls2kbmc is in the following patch, to satisfy the AI bot's
    concern.
- Link to v4: https://lore.kernel.org/r/20260731-ls2kbmc-mod-v4-0-d201502ba239@gmail.com

Changes in v4:
- Use a better way to get the GPIO device fwnode.
- Add a comment to describe a problem found by AI bot which is actually
  intended.
- Link to v3: https://lore.kernel.org/r/20260710-ls2kbmc-mod-v3-0-ef718636e78e@gmail.com

Changes in v3:
- Check the return value of devm_add_action_or_reset when registering
  the cleanup hook of the work queue
- Use swnode to create the link between the device to the GPIO chip,
  and prevent borrowing the legacy GPIO APIs
- Link to v2: https://lore.kernel.org/r/20260708-ls2kbmc-mod-v2-0-2afdd1741766@gmail.com

Changes in v2:
- Several fixes suggested by the Sashiko AI review bot
- Add a cleanup function for the wq on removal of the device
- Relax the reverse dependency from CONFIG_IPMI_LS2K to
  CONFIG_MFD_LS2K_BMC_CORE to allow the driver to be built as a module
- Link to v1: https://lore.kernel.org/r/20260708-ls2kbmc-mod-v1-0-c344bf5defa3@gmail.com

---
Miao Wang (7):
      mfd: ls2kbmc: Make a copy when parsing mode string
      mfd: ls2kbmc: Sanity check for the connected pci port
      mfd: ls2kbmc: Redraw using exported functions
      mfd: ls2kbmc: Cancel the work queue on removal
      ipmi: ls2k: adjust dependency to its mfd driver
      mfd: ls2kbmc: Able to be compiled as a module
      mfd: ls2kbmc: Capture the reset event of BMC through GPIO

 drivers/char/ipmi/Kconfig   |   2 +-
 drivers/mfd/Kconfig         |   2 +-
 drivers/mfd/ls2k-bmc-core.c | 246 ++++++++++++++++++++++++++++++++++----------
 3 files changed, 192 insertions(+), 58 deletions(-)
---
base-commit: 11028ab62899e4191e074ee364c712b77823a9c4
change-id: 20260626-ls2kbmc-mod-5209193009b2

Best regards,
-- 
Miao Wang <shankerwangmiao@gmail.com>



^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 0/7] mfd: ls2kbmc: multiple fixes for this driver
@ 2026-08-04 19:14 ` Miao Wang
  0 siblings, 0 replies; 27+ messages in thread
From: Miao Wang @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

Previously, the driver has been introduced to support the Loongson 2K
BMC running on the Loongson Servers, which is essential to prevent
the system from hanging when the BMC is being reset and the default
efi-framebuffer is being used. However, there are some drawbacks in the
driver.

Firstly, the driver tries to read and write to the connected PCI-E host
controller registers, assuming that the BMC is connected to LS7A PCI-E
host controller. This assumption should be true for real products, but
to prevent from accidentally reading and writing to the wrong PCI-E host
controller, this driver should be modified to check this before
accessing the registers.

Secondly, the driver uses non-exported functions to tell the vt
subsystem to redraw the screen, preventing the driver from being
compiling as a module. This can be fixed by using the exported
functions instead.

Thirdly, the driver directly accesses the GPIO controller registers
using hard-coded addresses, which might conflict with the loaded GPIO
controller driver for the same GPIO controller. This is fixed in this
series by using the GPIO subsystem APIs instead. However, legacy GPIO
APIs have to be used in this fixed to correctly request a GPIO
descriptor from the GPIO subsystem, which might be further discussed
to find a better solution.

Finally, there is a minor issue in the driver where it changes the
mode string describing the screen resolution during probing, which
prevents the device from being probed again if -EPROBE_DEFER is
returned by the probe function.

I have tested the changes in this series on a single-socket Loongson
3C6000 server with a Loongson 2K BMC, and the driver works as expected
when the corresponding GPIO driver is additionally loaded.

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
Changes in v6:
- Ajdust the Kconfig entry for IPMI_LS2K, moving the dependency on
  MFD_LS2K_BMC_CORE to the IPMI_SI Kconfig entry, as discussed with
  and agreed by Corey.
- Link to v5: https://lore.kernel.org/r/20260804-ls2kbmc-mod-v5-0-e6bc5cdd9a93@gmail.com

Changes in v5:
- Address issues found by the Sashiko AI review bot
  - Maintain the compatibility with possible unexpected mode string when
    parsing, although such mode string is actually not expected, to
    satisfy the AI bot's concern.
  - Add a comment to point out that the adjustment of the Kconfig entry
    for ls2kbmc is in the following patch, to satisfy the AI bot's
    concern.
- Link to v4: https://lore.kernel.org/r/20260731-ls2kbmc-mod-v4-0-d201502ba239@gmail.com

Changes in v4:
- Use a better way to get the GPIO device fwnode.
- Add a comment to describe a problem found by AI bot which is actually
  intended.
- Link to v3: https://lore.kernel.org/r/20260710-ls2kbmc-mod-v3-0-ef718636e78e@gmail.com

Changes in v3:
- Check the return value of devm_add_action_or_reset when registering
  the cleanup hook of the work queue
- Use swnode to create the link between the device to the GPIO chip,
  and prevent borrowing the legacy GPIO APIs
- Link to v2: https://lore.kernel.org/r/20260708-ls2kbmc-mod-v2-0-2afdd1741766@gmail.com

Changes in v2:
- Several fixes suggested by the Sashiko AI review bot
- Add a cleanup function for the wq on removal of the device
- Relax the reverse dependency from CONFIG_IPMI_LS2K to
  CONFIG_MFD_LS2K_BMC_CORE to allow the driver to be built as a module
- Link to v1: https://lore.kernel.org/r/20260708-ls2kbmc-mod-v1-0-c344bf5defa3@gmail.com

---
Miao Wang (7):
      mfd: ls2kbmc: Make a copy when parsing mode string
      mfd: ls2kbmc: Sanity check for the connected pci port
      mfd: ls2kbmc: Redraw using exported functions
      mfd: ls2kbmc: Cancel the work queue on removal
      ipmi: ls2k: adjust dependency to its mfd driver
      mfd: ls2kbmc: Able to be compiled as a module
      mfd: ls2kbmc: Capture the reset event of BMC through GPIO

 drivers/char/ipmi/Kconfig   |   2 +-
 drivers/mfd/Kconfig         |   2 +-
 drivers/mfd/ls2k-bmc-core.c | 246 ++++++++++++++++++++++++++++++++++----------
 3 files changed, 192 insertions(+), 58 deletions(-)
---
base-commit: 11028ab62899e4191e074ee364c712b77823a9c4
change-id: 20260626-ls2kbmc-mod-5209193009b2

Best regards,
-- 
Miao Wang <shankerwangmiao@gmail.com>


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 1/7] mfd: ls2kbmc: Make a copy when parsing mode string
  2026-08-04 19:14 ` Miao Wang
@ 2026-08-04 19:14   ` Miao Wang
  -1 siblings, 0 replies; 27+ messages in thread
From: Miao Wang via B4 Relay @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

From: Miao Wang <shankerwangmiao@gmail.com>

When parsing the mode string from BMC, the string is manipulated
in-place with strsep(), preventing from parsing it again. Make a copy of
the original string and manipulate the copy instead to fix this.

Fixes: 0d64f6d1ffe9 ("mfd: ls2kbmc: Introduce Loongson-2K BMC core driver")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 36 ++++++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index 408056bfb2fe757a5bde43775a483a48352e706d..fc9695eedd3662ac92ff116811bb07bff1c994ea 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -427,34 +427,54 @@ static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
  */
 static int ls2k_bmc_parse_mode(struct pci_dev *pdev, struct simplefb_platform_data *pd)
 {
-	char *mode;
+	/* Assume 64 bytes is enough for the resolution string */
+	char mode_buf[64], mode_buf_orig[64];
+	char *mode = mode_buf;
+	const void __iomem *mode_base;
 	int depth, ret;
 
 	/* The last 16M of PCI BAR0 is used to store the resolution string. */
-	mode = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0) + SZ_16M, SZ_16M);
-	if (!mode)
+	mode_base = ioremap(pci_resource_start(pdev, 0) + SZ_16M,
+			    sizeof(mode_buf));
+	if (!mode_base)
 		return -ENOMEM;
+	memcpy_fromio(mode_buf, mode_base, sizeof(mode_buf) - 1);
+	mode_buf[sizeof(mode_buf) - 1] = '\0';
+	iounmap((void __iomem *)mode_base);
+	memcpy(mode_buf_orig, mode_buf, sizeof(mode_buf_orig));
 
 	/* The resolution field starts with the flag "video=". */
 	if (!strncmp(mode, "video=", 6))
 		mode = mode + 6;
 
-	ret = kstrtoint(strsep(&mode, "x"), 10, &pd->width);
+	ret = kstrtouint(strsep(&mode, "x"), 10, &pd->width);
 	if (ret)
-		return ret;
+		goto invalid_mode;
 
-	ret = kstrtoint(strsep(&mode, "-"), 10, &pd->height);
+	if (mode == NULL) {
+		ret = -EINVAL;
+		goto invalid_mode;
+	}
+	ret = kstrtouint(strsep(&mode, "-"), 10, &pd->height);
 	if (ret)
-		return ret;
+		goto invalid_mode;
 
+	if (mode == NULL) {
+		ret = -EINVAL;
+		goto invalid_mode;
+	}
 	ret = kstrtoint(strsep(&mode, "@"), 10, &depth);
 	if (ret)
-		return ret;
+		goto invalid_mode;
 
 	pd->stride = pd->width * depth / 8;
 	pd->format = depth == 32 ? "a8r8g8b8" : "r5g6b5";
 
 	return 0;
+
+invalid_mode:
+	dev_err(&pdev->dev, "Invalid resolution string: %s\n", mode_buf_orig);
+	return ret;
 }
 
 static int ls2k_bmc_probe(struct pci_dev *dev, const struct pci_device_id *id)

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 1/7] mfd: ls2kbmc: Make a copy when parsing mode string
@ 2026-08-04 19:14   ` Miao Wang
  0 siblings, 0 replies; 27+ messages in thread
From: Miao Wang @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

When parsing the mode string from BMC, the string is manipulated
in-place with strsep(), preventing from parsing it again. Make a copy of
the original string and manipulate the copy instead to fix this.

Fixes: 0d64f6d1ffe9 ("mfd: ls2kbmc: Introduce Loongson-2K BMC core driver")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 36 ++++++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index 408056bfb2fe757a5bde43775a483a48352e706d..fc9695eedd3662ac92ff116811bb07bff1c994ea 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -427,34 +427,54 @@ static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
  */
 static int ls2k_bmc_parse_mode(struct pci_dev *pdev, struct simplefb_platform_data *pd)
 {
-	char *mode;
+	/* Assume 64 bytes is enough for the resolution string */
+	char mode_buf[64], mode_buf_orig[64];
+	char *mode = mode_buf;
+	const void __iomem *mode_base;
 	int depth, ret;
 
 	/* The last 16M of PCI BAR0 is used to store the resolution string. */
-	mode = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0) + SZ_16M, SZ_16M);
-	if (!mode)
+	mode_base = ioremap(pci_resource_start(pdev, 0) + SZ_16M,
+			    sizeof(mode_buf));
+	if (!mode_base)
 		return -ENOMEM;
+	memcpy_fromio(mode_buf, mode_base, sizeof(mode_buf) - 1);
+	mode_buf[sizeof(mode_buf) - 1] = '\0';
+	iounmap((void __iomem *)mode_base);
+	memcpy(mode_buf_orig, mode_buf, sizeof(mode_buf_orig));
 
 	/* The resolution field starts with the flag "video=". */
 	if (!strncmp(mode, "video=", 6))
 		mode = mode + 6;
 
-	ret = kstrtoint(strsep(&mode, "x"), 10, &pd->width);
+	ret = kstrtouint(strsep(&mode, "x"), 10, &pd->width);
 	if (ret)
-		return ret;
+		goto invalid_mode;
 
-	ret = kstrtoint(strsep(&mode, "-"), 10, &pd->height);
+	if (mode == NULL) {
+		ret = -EINVAL;
+		goto invalid_mode;
+	}
+	ret = kstrtouint(strsep(&mode, "-"), 10, &pd->height);
 	if (ret)
-		return ret;
+		goto invalid_mode;
 
+	if (mode == NULL) {
+		ret = -EINVAL;
+		goto invalid_mode;
+	}
 	ret = kstrtoint(strsep(&mode, "@"), 10, &depth);
 	if (ret)
-		return ret;
+		goto invalid_mode;
 
 	pd->stride = pd->width * depth / 8;
 	pd->format = depth == 32 ? "a8r8g8b8" : "r5g6b5";
 
 	return 0;
+
+invalid_mode:
+	dev_err(&pdev->dev, "Invalid resolution string: %s\n", mode_buf_orig);
+	return ret;
 }
 
 static int ls2k_bmc_probe(struct pci_dev *dev, const struct pci_device_id *id)

-- 
2.49.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 2/7] mfd: ls2kbmc: Sanity check for the connected pci port
  2026-08-04 19:14 ` Miao Wang
@ 2026-08-04 19:14   ` Miao Wang
  -1 siblings, 0 replies; 27+ messages in thread
From: Miao Wang via B4 Relay @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

From: Miao Wang <shankerwangmiao@gmail.com>

When the bmc resets, the recovery procedure require to reconfigure the
parent device. The driver assumes that the parent device should be LS7A.
Add a sanity check on initialization to ensure this and prevent from
accidentally operating on non-LS7A ports.

Fixes: d952bba3fbb5 ("mfd: ls2kbmc: Add Loongson-2K BMC reset function support")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index fc9695eedd3662ac92ff116811bb07bff1c994ea..a9a30611dde9e31cd86ff67b1d6e02bf67b34755 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -35,6 +35,15 @@
 #define LS2K_IPMI3_RES_START		(LS2K_IPMI2_RES_START + LS2K_IPMI_RES_SIZE)
 #define LS2K_IPMI4_RES_START		(LS2K_IPMI3_RES_START + LS2K_IPMI_RES_SIZE)
 
+/* LS7A port Device IDs */
+#define DEV_LS7A1K_PCIE_PORT0	0x7a09
+#define DEV_LS7A1K_PCIE_PORT1	0x7a19
+#define DEV_LS7A1K_PCIE_PORT2	0x7a29
+#define DEV_LS7A2K_PCIE_PORT0	0x7a39
+#define DEV_LS7A2K_PCIE_PORT1	0x7a49
+#define DEV_LS7A2K_PCIE_PORT2	0x7a59
+#define DEV_LS7A2K_PCIE_PORT3	0x7a69
+
 #define LS7A_PCI_CFG_SIZE		0x100
 
 /* LS7A bridge registers */
@@ -477,6 +486,24 @@ static int ls2k_bmc_parse_mode(struct pci_dev *pdev, struct simplefb_platform_da
 	return ret;
 }
 
+static const struct pci_device_id ls7a_ports[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A1K_PCIE_PORT0) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A1K_PCIE_PORT1) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A1K_PCIE_PORT2) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A2K_PCIE_PORT0) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A2K_PCIE_PORT1) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A2K_PCIE_PORT2) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A2K_PCIE_PORT3) },
+	{ }
+};
+
+static bool ls2k_check_parent(struct pci_dev *dev)
+{
+	struct pci_dev *parent = dev->bus->self;
+
+	return parent && pci_match_id(ls7a_ports, parent) != NULL;
+}
+
 static int ls2k_bmc_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct simplefb_platform_data pd;
@@ -488,6 +515,11 @@ static int ls2k_bmc_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	if (ret)
 		return ret;
 
+	if (!ls2k_check_parent(dev)) {
+		dev_err(&dev->dev, "Expected to be connected to LS7A PCI-E port\n");
+		return -ENODEV;
+	}
+
 	ddata = devm_kzalloc(&dev->dev, sizeof(*ddata), GFP_KERNEL);
 	if (!ddata)
 		return -ENOMEM;

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 2/7] mfd: ls2kbmc: Sanity check for the connected pci port
@ 2026-08-04 19:14   ` Miao Wang
  0 siblings, 0 replies; 27+ messages in thread
From: Miao Wang @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

When the bmc resets, the recovery procedure require to reconfigure the
parent device. The driver assumes that the parent device should be LS7A.
Add a sanity check on initialization to ensure this and prevent from
accidentally operating on non-LS7A ports.

Fixes: d952bba3fbb5 ("mfd: ls2kbmc: Add Loongson-2K BMC reset function support")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index fc9695eedd3662ac92ff116811bb07bff1c994ea..a9a30611dde9e31cd86ff67b1d6e02bf67b34755 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -35,6 +35,15 @@
 #define LS2K_IPMI3_RES_START		(LS2K_IPMI2_RES_START + LS2K_IPMI_RES_SIZE)
 #define LS2K_IPMI4_RES_START		(LS2K_IPMI3_RES_START + LS2K_IPMI_RES_SIZE)
 
+/* LS7A port Device IDs */
+#define DEV_LS7A1K_PCIE_PORT0	0x7a09
+#define DEV_LS7A1K_PCIE_PORT1	0x7a19
+#define DEV_LS7A1K_PCIE_PORT2	0x7a29
+#define DEV_LS7A2K_PCIE_PORT0	0x7a39
+#define DEV_LS7A2K_PCIE_PORT1	0x7a49
+#define DEV_LS7A2K_PCIE_PORT2	0x7a59
+#define DEV_LS7A2K_PCIE_PORT3	0x7a69
+
 #define LS7A_PCI_CFG_SIZE		0x100
 
 /* LS7A bridge registers */
@@ -477,6 +486,24 @@ static int ls2k_bmc_parse_mode(struct pci_dev *pdev, struct simplefb_platform_da
 	return ret;
 }
 
+static const struct pci_device_id ls7a_ports[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A1K_PCIE_PORT0) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A1K_PCIE_PORT1) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A1K_PCIE_PORT2) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A2K_PCIE_PORT0) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A2K_PCIE_PORT1) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A2K_PCIE_PORT2) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, DEV_LS7A2K_PCIE_PORT3) },
+	{ }
+};
+
+static bool ls2k_check_parent(struct pci_dev *dev)
+{
+	struct pci_dev *parent = dev->bus->self;
+
+	return parent && pci_match_id(ls7a_ports, parent) != NULL;
+}
+
 static int ls2k_bmc_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct simplefb_platform_data pd;
@@ -488,6 +515,11 @@ static int ls2k_bmc_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	if (ret)
 		return ret;
 
+	if (!ls2k_check_parent(dev)) {
+		dev_err(&dev->dev, "Expected to be connected to LS7A PCI-E port\n");
+		return -ENODEV;
+	}
+
 	ddata = devm_kzalloc(&dev->dev, sizeof(*ddata), GFP_KERNEL);
 	if (!ddata)
 		return -ENOMEM;

-- 
2.49.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 3/7] mfd: ls2kbmc: Redraw using exported functions
  2026-08-04 19:14 ` Miao Wang
@ 2026-08-04 19:14   ` Miao Wang
  -1 siblings, 0 replies; 27+ messages in thread
From: Miao Wang via B4 Relay @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

From: Miao Wang <shankerwangmiao@gmail.com>

Use update_screen, i.e. redraw_screen() to trigger the redraw of the
current vt.

Fixes: d952bba3fbb5 ("mfd: ls2kbmc: Add Loongson-2K BMC reset function support")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index a9a30611dde9e31cd86ff67b1d6e02bf67b34755..e12f2ca2fbef360ceda14ee6fc64f500e4944120 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -25,6 +25,7 @@
 #include <linux/platform_device.h>
 #include <linux/stop_machine.h>
 #include <linux/vt_kern.h>
+#include <linux/console.h>
 
 /* LS2K BMC resources */
 #define LS2K_DISPLAY_RES_START		(SZ_16M + SZ_2M)
@@ -310,7 +311,9 @@ static void ls2k_bmc_events_fn(struct work_struct *work)
 
 	if (IS_ENABLED(CONFIG_VT)) {
 		/* Re-push the display due to previous PCI-E loss. */
-		set_console(vt_move_to_console(MAX_NR_CONSOLES - 1, 1));
+		console_lock();
+		update_screen(vc_cons[fg_console].d);
+		console_unlock();
 	}
 }
 

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 3/7] mfd: ls2kbmc: Redraw using exported functions
@ 2026-08-04 19:14   ` Miao Wang
  0 siblings, 0 replies; 27+ messages in thread
From: Miao Wang @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

Use update_screen, i.e. redraw_screen() to trigger the redraw of the
current vt.

Fixes: d952bba3fbb5 ("mfd: ls2kbmc: Add Loongson-2K BMC reset function support")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index a9a30611dde9e31cd86ff67b1d6e02bf67b34755..e12f2ca2fbef360ceda14ee6fc64f500e4944120 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -25,6 +25,7 @@
 #include <linux/platform_device.h>
 #include <linux/stop_machine.h>
 #include <linux/vt_kern.h>
+#include <linux/console.h>
 
 /* LS2K BMC resources */
 #define LS2K_DISPLAY_RES_START		(SZ_16M + SZ_2M)
@@ -310,7 +311,9 @@ static void ls2k_bmc_events_fn(struct work_struct *work)
 
 	if (IS_ENABLED(CONFIG_VT)) {
 		/* Re-push the display due to previous PCI-E loss. */
-		set_console(vt_move_to_console(MAX_NR_CONSOLES - 1, 1));
+		console_lock();
+		update_screen(vc_cons[fg_console].d);
+		console_unlock();
 	}
 }
 

-- 
2.49.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 4/7] mfd: ls2kbmc: Cancel the work queue on removal
  2026-08-04 19:14 ` Miao Wang
@ 2026-08-04 19:14   ` Miao Wang
  -1 siblings, 0 replies; 27+ messages in thread
From: Miao Wang via B4 Relay @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

From: Miao Wang <shankerwangmiao@gmail.com>

When the device is being removeed, the work queue should be canceled to
avoid any pending work to be executed after the device is removed.

Fixes: d952bba3fbb5 ("mfd: ls2kbmc: Add Loongson-2K BMC reset function support")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index e12f2ca2fbef360ceda14ee6fc64f500e4944120..e7bebfe696ac4554eb6283279811a27ed865ab73 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -375,6 +375,12 @@ static void ls2k_bmc_save_pci_data(struct pci_dev *pdev, struct ls2k_bmc_ddata *
 	pci_read_config_dword(pdev, PCI_INTERRUPT_LINE, &ddata->bmc_pci_data.interrupt_line);
 }
 
+static void ls2k_bmc_cancel_wq(void *data)
+{
+	struct ls2k_bmc_ddata *ddata = data;
+	(void) cancel_work_sync(&ddata->bmc_reset_work);
+}
+
 static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
 {
 	struct pci_dev *pdev = to_pci_dev(ddata->dev);
@@ -385,6 +391,10 @@ static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
 
 	INIT_WORK(&ddata->bmc_reset_work, ls2k_bmc_events_fn);
 
+	ret = devm_add_action_or_reset(ddata->dev, ls2k_bmc_cancel_wq, ddata);
+	if (ret)
+		return ret;
+
 	ret = devm_request_irq(&pdev->dev, pdev->irq, ls2k_bmc_interrupt,
 			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc pcie", ddata);
 	if (ret) {

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 4/7] mfd: ls2kbmc: Cancel the work queue on removal
@ 2026-08-04 19:14   ` Miao Wang
  0 siblings, 0 replies; 27+ messages in thread
From: Miao Wang @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

When the device is being removeed, the work queue should be canceled to
avoid any pending work to be executed after the device is removed.

Fixes: d952bba3fbb5 ("mfd: ls2kbmc: Add Loongson-2K BMC reset function support")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index e12f2ca2fbef360ceda14ee6fc64f500e4944120..e7bebfe696ac4554eb6283279811a27ed865ab73 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -375,6 +375,12 @@ static void ls2k_bmc_save_pci_data(struct pci_dev *pdev, struct ls2k_bmc_ddata *
 	pci_read_config_dword(pdev, PCI_INTERRUPT_LINE, &ddata->bmc_pci_data.interrupt_line);
 }
 
+static void ls2k_bmc_cancel_wq(void *data)
+{
+	struct ls2k_bmc_ddata *ddata = data;
+	(void) cancel_work_sync(&ddata->bmc_reset_work);
+}
+
 static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
 {
 	struct pci_dev *pdev = to_pci_dev(ddata->dev);
@@ -385,6 +391,10 @@ static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
 
 	INIT_WORK(&ddata->bmc_reset_work, ls2k_bmc_events_fn);
 
+	ret = devm_add_action_or_reset(ddata->dev, ls2k_bmc_cancel_wq, ddata);
+	if (ret)
+		return ret;
+
 	ret = devm_request_irq(&pdev->dev, pdev->irq, ls2k_bmc_interrupt,
 			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc pcie", ddata);
 	if (ret) {

-- 
2.49.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 5/7] ipmi: ls2k: adjust dependency to its mfd driver
  2026-08-04 19:14 ` Miao Wang
@ 2026-08-04 19:14   ` Miao Wang
  -1 siblings, 0 replies; 27+ messages in thread
From: Miao Wang via B4 Relay @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

From: Miao Wang <shankerwangmiao@gmail.com>

There is functional dependency between the IPMI driver and its mfd
driver. Previously, the dependency was set to "select" from
IPMI_LS2K to MFD_LS2K_BMC_CORE. However, the ipmi driver is actually
compiled as a part of the ipmi_si module, and IPMI_LS2K is a bool
option. Therefore, the dependency "select" will force the mfd driver
to be compiled built-in when the ipmi driver is built as a module. This
is not desirable. This patch fixes this by declaring a conditional
dependency from IPMI_SI to MFD_LS2K_BMC_CORE if IPMI_LS2K is selected.
This will allow the mfd driver to be compiled as a module if the ipmi
driver is built as a module. The adjustment to Kconfig for the mfd
driver will be introduced in the later patch in this series.

Fixes: d46651d4e3c0 ("ipmi: Add Loongson-2K BMC support")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/char/ipmi/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 669f7600019747bcd2b37563477cf336f19a0407..07f3308c71616215871a730b87f1991d2b502e63 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -62,6 +62,7 @@ config IPMI_DEVICE_INTERFACE
 config IPMI_SI
 	tristate 'IPMI System Interface handler'
 	select IPMI_PLAT_DATA
+	select MFD_LS2K_BMC_CORE if IPMI_LS2K
 	help
 	  Provides a driver for System Interfaces (KCS, SMIC, BT).
 	  Currently, only KCS and SMIC are supported.  If
@@ -87,7 +88,6 @@ config IPMI_IPMB
 config IPMI_LS2K
 	bool 'Loongson-2K IPMI interface'
 	depends on LOONGARCH
-	select MFD_LS2K_BMC_CORE
 	help
 	  Provides a driver for Loongson-2K IPMI interfaces.
 

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 5/7] ipmi: ls2k: adjust dependency to its mfd driver
@ 2026-08-04 19:14   ` Miao Wang
  0 siblings, 0 replies; 27+ messages in thread
From: Miao Wang @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

There is functional dependency between the IPMI driver and its mfd
driver. Previously, the dependency was set to "select" from
IPMI_LS2K to MFD_LS2K_BMC_CORE. However, the ipmi driver is actually
compiled as a part of the ipmi_si module, and IPMI_LS2K is a bool
option. Therefore, the dependency "select" will force the mfd driver
to be compiled built-in when the ipmi driver is built as a module. This
is not desirable. This patch fixes this by declaring a conditional
dependency from IPMI_SI to MFD_LS2K_BMC_CORE if IPMI_LS2K is selected.
This will allow the mfd driver to be compiled as a module if the ipmi
driver is built as a module. The adjustment to Kconfig for the mfd
driver will be introduced in the later patch in this series.

Fixes: d46651d4e3c0 ("ipmi: Add Loongson-2K BMC support")
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/char/ipmi/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 669f7600019747bcd2b37563477cf336f19a0407..07f3308c71616215871a730b87f1991d2b502e63 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -62,6 +62,7 @@ config IPMI_DEVICE_INTERFACE
 config IPMI_SI
 	tristate 'IPMI System Interface handler'
 	select IPMI_PLAT_DATA
+	select MFD_LS2K_BMC_CORE if IPMI_LS2K
 	help
 	  Provides a driver for System Interfaces (KCS, SMIC, BT).
 	  Currently, only KCS and SMIC are supported.  If
@@ -87,7 +88,6 @@ config IPMI_IPMB
 config IPMI_LS2K
 	bool 'Loongson-2K IPMI interface'
 	depends on LOONGARCH
-	select MFD_LS2K_BMC_CORE
 	help
 	  Provides a driver for Loongson-2K IPMI interfaces.
 

-- 
2.49.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 6/7] mfd: ls2kbmc: Able to be compiled as a module
  2026-08-04 19:14 ` Miao Wang
@ 2026-08-04 19:14   ` Miao Wang
  -1 siblings, 0 replies; 27+ messages in thread
From: Miao Wang via B4 Relay @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

From: Miao Wang <shankerwangmiao@gmail.com>

Make ls2kmc able to be compiled as a module

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 763ce6a34782bdd5d2b1a4d840c75b040092d83e..a7a9f97af248c88489dc1203a1ba05f2ce4827df 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2494,7 +2494,7 @@ config MFD_LOONGSON_SE
 	  which will forward them to the corresponding engine.
 
 config MFD_LS2K_BMC_CORE
-	bool "Loongson-2K Board Management Controller Support"
+	tristate "Loongson-2K Board Management Controller Support"
 	depends on PCI && ACPI_GENERIC_GSI
 	select MFD_CORE
 	help

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 6/7] mfd: ls2kbmc: Able to be compiled as a module
@ 2026-08-04 19:14   ` Miao Wang
  0 siblings, 0 replies; 27+ messages in thread
From: Miao Wang @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

Make ls2kmc able to be compiled as a module

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 763ce6a34782bdd5d2b1a4d840c75b040092d83e..a7a9f97af248c88489dc1203a1ba05f2ce4827df 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2494,7 +2494,7 @@ config MFD_LOONGSON_SE
 	  which will forward them to the corresponding engine.
 
 config MFD_LS2K_BMC_CORE
-	bool "Loongson-2K Board Management Controller Support"
+	tristate "Loongson-2K Board Management Controller Support"
 	depends on PCI && ACPI_GENERIC_GSI
 	select MFD_CORE
 	help

-- 
2.49.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO
  2026-08-04 19:14 ` Miao Wang
@ 2026-08-04 19:14   ` Miao Wang
  -1 siblings, 0 replies; 27+ messages in thread
From: Miao Wang via B4 Relay @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

From: Miao Wang <shankerwangmiao@gmail.com>

The reset event of BMC is captured through GPIO. However, this driver
bypasses the GPIO framework and directly accesses the GPIO controller
through the fixed address. When the same GPIO controller is also
exposed through ACPI and probed by the corresponding GPIO driver,
there would be a conflict between the two drivers.

This patch will try to find the GPIO through declared GPIO pin in the
_CRS resources of the ACPI node. If no such delaration is found, the
driver will fall back to search for the correct GPIO controller and pin
according to the fixed address and pin number. A possible DSDT
declaration for the GPIO pin might be as follows:

    Device (BMC0) {
        Name (_ADR, ...) // Match the PCI address of the BMC device
        // \_SB.GPO1 is the ACPI path of the GPIO controller
        Name (_CRS, ResourceTemplate () {
            GpioInt (Edge, ActiveLow, Exclusive, PullNone, 0,
                     "\\_SB.GPO1", 0) {
                14 // 14 is the GPIO pin number
            }
    }

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 163 +++++++++++++++++++++++++++++++-------------
 1 file changed, 116 insertions(+), 47 deletions(-)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index e7bebfe696ac4554eb6283279811a27ed865ab73..97a666a136fe41ed4268cb70770201533aebb1d5 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -26,6 +26,10 @@
 #include <linux/stop_machine.h>
 #include <linux/vt_kern.h>
 #include <linux/console.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/property.h>
+#include <linux/gpio/machine.h>
 
 /* LS2K BMC resources */
 #define LS2K_DISPLAY_RES_START		(SZ_16M + SZ_2M)
@@ -81,18 +85,6 @@
 
 #define PCI_REG_STRIDE			0x4
 
-#define LS2K_BMC_RESET_GPIO		14
-#define LOONGSON_GPIO_REG_BASE		0x1FE00500
-#define LOONGSON_GPIO_REG_SIZE		0x18
-#define LOONGSON_GPIO_OEN		0x0
-#define LOONGSON_GPIO_FUNC		0x4
-#define LOONGSON_GPIO_INTPOL		0x10
-#define LOONGSON_GPIO_INTEN		0x14
-
-#define LOONGSON_IO_INT_BASE		16
-#define LS2K_BMC_RESET_GPIO_INT_VEC	(LS2K_BMC_RESET_GPIO % 8)
-#define LS2K_BMC_RESET_GPIO_GSI		(LOONGSON_IO_INT_BASE + LS2K_BMC_RESET_GPIO_INT_VEC)
-
 enum {
 	LS2K_BMC_DISPLAY,
 	LS2K_BMC_IPMI0,
@@ -186,6 +178,7 @@ struct ls2k_bmc_ddata {
 	struct work_struct bmc_reset_work;
 	struct ls2k_bmc_pci_data bmc_pci_data;
 	struct ls2k_bmc_bridge_pci_data bridge_pci_data;
+	struct gpio_desc *reset_gpio;
 };
 
 static bool ls2k_bmc_bar0_addr_is_set(struct pci_dev *pdev)
@@ -375,6 +368,91 @@ static void ls2k_bmc_save_pci_data(struct pci_dev *pdev, struct ls2k_bmc_ddata *
 	pci_read_config_dword(pdev, PCI_INTERRUPT_LINE, &ddata->bmc_pci_data.interrupt_line);
 }
 
+static struct fwnode_handle *gpio_dev_get_fwnode(struct gpio_device *gdev)
+{
+	struct device *gdev_dev;
+
+	gdev_dev = gpio_device_to_device(gdev);
+	return dev_fwnode(gdev_dev);
+}
+
+static int ls2k_bmc_gpiochip_find(struct gpio_chip *gc, const void *data)
+{
+	struct acpi_device *adev;
+	struct list_head resource_list;
+	struct resource_entry *rentry;
+	struct fwnode_handle *fwnode = gpio_dev_get_fwnode(gc->gpiodev);
+	phys_addr_t start_addr = (phys_addr_t) data;
+	int ret, found = 0;
+
+	if (!is_acpi_node(fwnode))
+		goto out;
+
+	adev = to_acpi_device_node(fwnode);
+	if (!adev)
+		goto out;
+
+	INIT_LIST_HEAD(&resource_list);
+
+	ret = acpi_dev_get_memory_resources(adev, &resource_list);
+	if (ret < 0)
+		goto out;
+	/*
+	 * ACPI memory resources are ordered and only the first one is
+	 * considered by the driver of the expected GPIO controller. So
+	 * here we also only check the first one to see if it matches the
+	 * expected address.
+	 */
+	rentry = list_first_entry_or_null(&resource_list, struct resource_entry, node);
+	if (!rentry)
+		goto free_resource_list;
+	if (rentry->res->start == start_addr)
+		found = 1;
+
+free_resource_list:
+	acpi_dev_free_resource_list(&resource_list);
+out:
+	return found;
+}
+
+static struct gpio_desc *ls2k_bmc_find_gpio(struct ls2k_bmc_ddata *ddata)
+{
+	/*
+	 * In conventional way, the GPIO should be obtained through ACPI or
+	 * device tree. However, when the information is not available,
+	 * we should find the GPIO according to the convention of the server
+	 * boards with LS2K BMC, the gpio signal reflecting the reset event
+	 * of the BMC should be connected to pin 14 of the GPIO input of
+	 * the first CPU node. The address of that GPIO controller is fixed.
+	 */
+	static const phys_addr_t LOONGSON_GPIO_REG_BASE = 0x1FE00500;
+	static const unsigned int LS2K_BMC_RESET_GPIO = 14;
+	int ret;
+	struct gpio_device *gdev __free(gpio_device_put) = NULL;
+	struct property_entry ls2k_bmc_swnode_properties[2] = { 0 };
+
+	dev_dbg(ddata->dev, "Searching for GPIO chip at address %pa\n", &LOONGSON_GPIO_REG_BASE);
+
+	gdev = gpio_device_find((void *)LOONGSON_GPIO_REG_BASE, ls2k_bmc_gpiochip_find);
+
+	if (!gdev) {
+		dev_dbg(ddata->dev, "cannot find GPIO chip at address %pa, deferring\n",
+			&LOONGSON_GPIO_REG_BASE);
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	ls2k_bmc_swnode_properties[0] = PROPERTY_ENTRY_GPIO("gpio",
+		gpio_dev_get_fwnode(gdev), LS2K_BMC_RESET_GPIO, GPIO_ACTIVE_HIGH);
+
+	ret = device_create_managed_software_node(ddata->dev, ls2k_bmc_swnode_properties, NULL);
+	if (ret) {
+		dev_err(ddata->dev, "Failed to create software node for GPIO reset: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	return devm_gpiod_get_index(ddata->dev, NULL, 0, GPIOD_IN);
+}
+
 static void ls2k_bmc_cancel_wq(void *data)
 {
 	struct ls2k_bmc_ddata *ddata = data;
@@ -384,8 +462,7 @@ static void ls2k_bmc_cancel_wq(void *data)
 static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
 {
 	struct pci_dev *pdev = to_pci_dev(ddata->dev);
-	void __iomem *gpio_base;
-	int gpio_irq, ret, val;
+	int gpio_irq, ret;
 
 	ls2k_bmc_save_pci_data(pdev, ddata);
 
@@ -402,44 +479,36 @@ static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
 		return ret;
 	}
 
-	gpio_base = ioremap(LOONGSON_GPIO_REG_BASE, LOONGSON_GPIO_REG_SIZE);
-	if (!gpio_base)
-		return -ENOMEM;
-
-	/* Disable GPIO output */
-	val = readl(gpio_base + LOONGSON_GPIO_OEN);
-	writel(val | BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_OEN);
-
-	/* Enable GPIO functionality */
-	val = readl(gpio_base + LOONGSON_GPIO_FUNC);
-	writel(val & ~BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_FUNC);
-
-	/* Set GPIO interrupts to low-level active */
-	val = readl(gpio_base + LOONGSON_GPIO_INTPOL);
-	writel(val & ~BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_INTPOL);
-
-	/* Enable GPIO interrupts */
-	val = readl(gpio_base + LOONGSON_GPIO_INTEN);
-	writel(val | BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_INTEN);
+	ddata->reset_gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0, GPIOD_IN);
+	if (IS_ERR(ddata->reset_gpio)) {
+		ret = PTR_ERR(ddata->reset_gpio);
+		ddata->reset_gpio = NULL;
+		return dev_err_probe(ddata->dev, ret, "Failed to get GPIO pin for reset signal\n");
+	}
+	if (ddata->reset_gpio == NULL) {
+		ddata->reset_gpio = ls2k_bmc_find_gpio(ddata);
+		if (IS_ERR(ddata->reset_gpio)) {
+			ret = PTR_ERR(ddata->reset_gpio);
+			ddata->reset_gpio = NULL;
+			return dev_err_probe(ddata->dev, ret,
+					     "Failed to find GPIO pin for reset signal\n");
+		}
+	}
 
-	iounmap(gpio_base);
+	gpio_irq = gpiod_to_irq(ddata->reset_gpio);
 
-	/*
-	 * Since gpio_chip->to_irq is not implemented in the Loongson-3 GPIO driver,
-	 * acpi_register_gsi() is used to obtain the GPIO IRQ. The GPIO interrupt is a
-	 * watchdog interrupt that is triggered when the BMC resets.
-	 */
-	gpio_irq = acpi_register_gsi(NULL, LS2K_BMC_RESET_GPIO_GSI, ACPI_EDGE_SENSITIVE,
-				     ACPI_ACTIVE_LOW);
 	if (gpio_irq < 0)
-		return gpio_irq;
+		return dev_err_probe(ddata->dev, gpio_irq,
+				     "Failed to get IRQ for GPIO reset signal input\n");
 
-	ret = devm_request_irq(ddata->dev, gpio_irq, ls2k_bmc_interrupt,
-			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc gpio", ddata);
-	if (ret)
-		dev_err(ddata->dev, "Failed to request LS2KBMC GPIO IRQ %d.\n", gpio_irq);
+	ret = devm_request_irq(&pdev->dev, gpio_irq, ls2k_bmc_interrupt,
+			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc reset", ddata);
+
+	if (ret != 0)
+		return dev_err_probe(ddata->dev, ret,
+				     "Failed to request IRQ %d for GPIO reset signal input.\n",
+				     gpio_irq);
 
-	acpi_unregister_gsi(LS2K_BMC_RESET_GPIO_GSI);
 	return ret;
 }
 

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH RFC v6 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO
@ 2026-08-04 19:14   ` Miao Wang
  0 siblings, 0 replies; 27+ messages in thread
From: Miao Wang @ 2026-08-04 19:14 UTC (permalink / raw)
  To: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski
  Cc: Xi Ruoyao, WANG Xuerui, Yinbo Zhu, Jiaxun Yang, mfd, linux-kernel,
	linux-gpio, openipmi-developer, Miao Wang

The reset event of BMC is captured through GPIO. However, this driver
bypasses the GPIO framework and directly accesses the GPIO controller
through the fixed address. When the same GPIO controller is also
exposed through ACPI and probed by the corresponding GPIO driver,
there would be a conflict between the two drivers.

This patch will try to find the GPIO through declared GPIO pin in the
_CRS resources of the ACPI node. If no such delaration is found, the
driver will fall back to search for the correct GPIO controller and pin
according to the fixed address and pin number. A possible DSDT
declaration for the GPIO pin might be as follows:

    Device (BMC0) {
        Name (_ADR, ...) // Match the PCI address of the BMC device
        // \_SB.GPO1 is the ACPI path of the GPIO controller
        Name (_CRS, ResourceTemplate () {
            GpioInt (Edge, ActiveLow, Exclusive, PullNone, 0,
                     "\\_SB.GPO1", 0) {
                14 // 14 is the GPIO pin number
            }
    }

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
 drivers/mfd/ls2k-bmc-core.c | 163 +++++++++++++++++++++++++++++++-------------
 1 file changed, 116 insertions(+), 47 deletions(-)

diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
index e7bebfe696ac4554eb6283279811a27ed865ab73..97a666a136fe41ed4268cb70770201533aebb1d5 100644
--- a/drivers/mfd/ls2k-bmc-core.c
+++ b/drivers/mfd/ls2k-bmc-core.c
@@ -26,6 +26,10 @@
 #include <linux/stop_machine.h>
 #include <linux/vt_kern.h>
 #include <linux/console.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/property.h>
+#include <linux/gpio/machine.h>
 
 /* LS2K BMC resources */
 #define LS2K_DISPLAY_RES_START		(SZ_16M + SZ_2M)
@@ -81,18 +85,6 @@
 
 #define PCI_REG_STRIDE			0x4
 
-#define LS2K_BMC_RESET_GPIO		14
-#define LOONGSON_GPIO_REG_BASE		0x1FE00500
-#define LOONGSON_GPIO_REG_SIZE		0x18
-#define LOONGSON_GPIO_OEN		0x0
-#define LOONGSON_GPIO_FUNC		0x4
-#define LOONGSON_GPIO_INTPOL		0x10
-#define LOONGSON_GPIO_INTEN		0x14
-
-#define LOONGSON_IO_INT_BASE		16
-#define LS2K_BMC_RESET_GPIO_INT_VEC	(LS2K_BMC_RESET_GPIO % 8)
-#define LS2K_BMC_RESET_GPIO_GSI		(LOONGSON_IO_INT_BASE + LS2K_BMC_RESET_GPIO_INT_VEC)
-
 enum {
 	LS2K_BMC_DISPLAY,
 	LS2K_BMC_IPMI0,
@@ -186,6 +178,7 @@ struct ls2k_bmc_ddata {
 	struct work_struct bmc_reset_work;
 	struct ls2k_bmc_pci_data bmc_pci_data;
 	struct ls2k_bmc_bridge_pci_data bridge_pci_data;
+	struct gpio_desc *reset_gpio;
 };
 
 static bool ls2k_bmc_bar0_addr_is_set(struct pci_dev *pdev)
@@ -375,6 +368,91 @@ static void ls2k_bmc_save_pci_data(struct pci_dev *pdev, struct ls2k_bmc_ddata *
 	pci_read_config_dword(pdev, PCI_INTERRUPT_LINE, &ddata->bmc_pci_data.interrupt_line);
 }
 
+static struct fwnode_handle *gpio_dev_get_fwnode(struct gpio_device *gdev)
+{
+	struct device *gdev_dev;
+
+	gdev_dev = gpio_device_to_device(gdev);
+	return dev_fwnode(gdev_dev);
+}
+
+static int ls2k_bmc_gpiochip_find(struct gpio_chip *gc, const void *data)
+{
+	struct acpi_device *adev;
+	struct list_head resource_list;
+	struct resource_entry *rentry;
+	struct fwnode_handle *fwnode = gpio_dev_get_fwnode(gc->gpiodev);
+	phys_addr_t start_addr = (phys_addr_t) data;
+	int ret, found = 0;
+
+	if (!is_acpi_node(fwnode))
+		goto out;
+
+	adev = to_acpi_device_node(fwnode);
+	if (!adev)
+		goto out;
+
+	INIT_LIST_HEAD(&resource_list);
+
+	ret = acpi_dev_get_memory_resources(adev, &resource_list);
+	if (ret < 0)
+		goto out;
+	/*
+	 * ACPI memory resources are ordered and only the first one is
+	 * considered by the driver of the expected GPIO controller. So
+	 * here we also only check the first one to see if it matches the
+	 * expected address.
+	 */
+	rentry = list_first_entry_or_null(&resource_list, struct resource_entry, node);
+	if (!rentry)
+		goto free_resource_list;
+	if (rentry->res->start == start_addr)
+		found = 1;
+
+free_resource_list:
+	acpi_dev_free_resource_list(&resource_list);
+out:
+	return found;
+}
+
+static struct gpio_desc *ls2k_bmc_find_gpio(struct ls2k_bmc_ddata *ddata)
+{
+	/*
+	 * In conventional way, the GPIO should be obtained through ACPI or
+	 * device tree. However, when the information is not available,
+	 * we should find the GPIO according to the convention of the server
+	 * boards with LS2K BMC, the gpio signal reflecting the reset event
+	 * of the BMC should be connected to pin 14 of the GPIO input of
+	 * the first CPU node. The address of that GPIO controller is fixed.
+	 */
+	static const phys_addr_t LOONGSON_GPIO_REG_BASE = 0x1FE00500;
+	static const unsigned int LS2K_BMC_RESET_GPIO = 14;
+	int ret;
+	struct gpio_device *gdev __free(gpio_device_put) = NULL;
+	struct property_entry ls2k_bmc_swnode_properties[2] = { 0 };
+
+	dev_dbg(ddata->dev, "Searching for GPIO chip at address %pa\n", &LOONGSON_GPIO_REG_BASE);
+
+	gdev = gpio_device_find((void *)LOONGSON_GPIO_REG_BASE, ls2k_bmc_gpiochip_find);
+
+	if (!gdev) {
+		dev_dbg(ddata->dev, "cannot find GPIO chip at address %pa, deferring\n",
+			&LOONGSON_GPIO_REG_BASE);
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	ls2k_bmc_swnode_properties[0] = PROPERTY_ENTRY_GPIO("gpio",
+		gpio_dev_get_fwnode(gdev), LS2K_BMC_RESET_GPIO, GPIO_ACTIVE_HIGH);
+
+	ret = device_create_managed_software_node(ddata->dev, ls2k_bmc_swnode_properties, NULL);
+	if (ret) {
+		dev_err(ddata->dev, "Failed to create software node for GPIO reset: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	return devm_gpiod_get_index(ddata->dev, NULL, 0, GPIOD_IN);
+}
+
 static void ls2k_bmc_cancel_wq(void *data)
 {
 	struct ls2k_bmc_ddata *ddata = data;
@@ -384,8 +462,7 @@ static void ls2k_bmc_cancel_wq(void *data)
 static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
 {
 	struct pci_dev *pdev = to_pci_dev(ddata->dev);
-	void __iomem *gpio_base;
-	int gpio_irq, ret, val;
+	int gpio_irq, ret;
 
 	ls2k_bmc_save_pci_data(pdev, ddata);
 
@@ -402,44 +479,36 @@ static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
 		return ret;
 	}
 
-	gpio_base = ioremap(LOONGSON_GPIO_REG_BASE, LOONGSON_GPIO_REG_SIZE);
-	if (!gpio_base)
-		return -ENOMEM;
-
-	/* Disable GPIO output */
-	val = readl(gpio_base + LOONGSON_GPIO_OEN);
-	writel(val | BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_OEN);
-
-	/* Enable GPIO functionality */
-	val = readl(gpio_base + LOONGSON_GPIO_FUNC);
-	writel(val & ~BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_FUNC);
-
-	/* Set GPIO interrupts to low-level active */
-	val = readl(gpio_base + LOONGSON_GPIO_INTPOL);
-	writel(val & ~BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_INTPOL);
-
-	/* Enable GPIO interrupts */
-	val = readl(gpio_base + LOONGSON_GPIO_INTEN);
-	writel(val | BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_INTEN);
+	ddata->reset_gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0, GPIOD_IN);
+	if (IS_ERR(ddata->reset_gpio)) {
+		ret = PTR_ERR(ddata->reset_gpio);
+		ddata->reset_gpio = NULL;
+		return dev_err_probe(ddata->dev, ret, "Failed to get GPIO pin for reset signal\n");
+	}
+	if (ddata->reset_gpio == NULL) {
+		ddata->reset_gpio = ls2k_bmc_find_gpio(ddata);
+		if (IS_ERR(ddata->reset_gpio)) {
+			ret = PTR_ERR(ddata->reset_gpio);
+			ddata->reset_gpio = NULL;
+			return dev_err_probe(ddata->dev, ret,
+					     "Failed to find GPIO pin for reset signal\n");
+		}
+	}
 
-	iounmap(gpio_base);
+	gpio_irq = gpiod_to_irq(ddata->reset_gpio);
 
-	/*
-	 * Since gpio_chip->to_irq is not implemented in the Loongson-3 GPIO driver,
-	 * acpi_register_gsi() is used to obtain the GPIO IRQ. The GPIO interrupt is a
-	 * watchdog interrupt that is triggered when the BMC resets.
-	 */
-	gpio_irq = acpi_register_gsi(NULL, LS2K_BMC_RESET_GPIO_GSI, ACPI_EDGE_SENSITIVE,
-				     ACPI_ACTIVE_LOW);
 	if (gpio_irq < 0)
-		return gpio_irq;
+		return dev_err_probe(ddata->dev, gpio_irq,
+				     "Failed to get IRQ for GPIO reset signal input\n");
 
-	ret = devm_request_irq(ddata->dev, gpio_irq, ls2k_bmc_interrupt,
-			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc gpio", ddata);
-	if (ret)
-		dev_err(ddata->dev, "Failed to request LS2KBMC GPIO IRQ %d.\n", gpio_irq);
+	ret = devm_request_irq(&pdev->dev, gpio_irq, ls2k_bmc_interrupt,
+			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc reset", ddata);
+
+	if (ret != 0)
+		return dev_err_probe(ddata->dev, ret,
+				     "Failed to request IRQ %d for GPIO reset signal input.\n",
+				     gpio_irq);
 
-	acpi_unregister_gsi(LS2K_BMC_RESET_GPIO_GSI);
 	return ret;
 }
 

-- 
2.49.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 2/7] mfd: ls2kbmc: Sanity check for the connected pci port
  2026-08-04 19:14   ` Miao Wang
  (?)
@ 2026-08-04 19:23   ` sashiko-bot
  -1 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-08-04 19:23 UTC (permalink / raw)
  To: Miao Wang; +Cc: lee, mfd

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [High] The global `mfd_cell` array `ls2k_bmc_cells` is dynamically mutated during probe with a stack-allocated variable pointer, violating MFD rules and causing a data race.
- [High] Missing cancellation of `bmc_reset_work` on device unbind or probe failure leads to Use-After-Free.
- [High] The `stop_machine()` callback performs highly illegal blocking operations, including a 10-second busy wait and dynamic memory mapping, leading to a system freeze.
--

--- Patch [2]: [PATCH RFC v6 2/7] mfd: ls2kbmc: Sanity check for the connected pci port ---
commit 69486e003cb1f9b1540028b60b63bfa488d9ed41
Author: Miao Wang <shankerwangmiao@gmail.com>

mfd: ls2kbmc: Sanity check for the connected pci port

This commit adds a sanity check to ensure the parent device of the BMC
is an LS7A port during initialization. This prevents the driver from
accidentally operating on non-LS7A ports when attempting recovery
procedures.

> diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
> index fc9695eedd366..a9a30611dde9e 100644
> --- a/drivers/mfd/ls2k-bmc-core.c
> +++ b/drivers/mfd/ls2k-bmc-core.c

[ ... ]

> @@ -488,6 +515,11 @@ static int ls2k_bmc_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  	if (ret)
>  		return ret;
>  
> +	if (!ls2k_check_parent(dev)) {
> +		dev_err(&dev->dev, "Expected to be connected to LS7A PCI-E port\n");
> +		return -ENODEV;
> +	}
> +

[Severity: High]
This isn't a bug introduced by this patch, but while reviewing this probe
function I noticed that it dynamically mutates a global mfd_cell array:

ls2k_bmc_probe() {
    ...
    ls2k_bmc_cells[LS2K_BMC_DISPLAY].platform_data = &pd;
    ...
}

Could this cause a dangling pointer and data race? When the probe function
returns, the local stack variable pd goes out of scope, leaving a dangling
pointer in the global state. This also appears to violate the MFD subsystem
guidelines which require mfd_cell arrays to be static const.

[Severity: High]
This is also a pre-existing issue, but since the commit message mentions
the recovery procedure, I wanted to ask about the reset implementation.
The driver executes ls2k_bmc_recover_pci_data() inside stop_machine() via
ls2k_bmc_events_fn():

ls2k_bmc_events_fn() {
    ...
    stop_machine(ls2k_bmc_recover_pci_data, ddata, NULL);
    ...
}

Inside ls2k_bmc_recover_pci_data(), the code calls mdelay() and pci_iomap()
which can sleep:

ls2k_bmc_recover_pci_data() {
    ...
    mdelay(LS2K_BMC_RESET_WAIT_TIME);
    ...
    base = pci_iomap(parent, 0, LS7A_PCI_CFG_SIZE);
    ...
}

Since stop_machine() executes its callback in an atomic context with local
IRQs disabled, wouldn't these blocking and sleeping operations cause a
deadlock or trigger the NMI watchdog?

>  	ddata = devm_kzalloc(&dev->dev, sizeof(*ddata), GFP_KERNEL);
>  	if (!ddata)
>  		return -ENOMEM;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260805-ls2kbmc-mod-v6-0-16ccde412d86@gmail.com?part=2

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 4/7] mfd: ls2kbmc: Cancel the work queue on removal
  2026-08-04 19:14   ` Miao Wang
  (?)
@ 2026-08-04 19:24   ` sashiko-bot
  -1 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-08-04 19:24 UTC (permalink / raw)
  To: Miao Wang; +Cc: mfd, lee

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Pre-existing issues:
- [Critical] The work queue callback executes a prolonged 10-second busy-wait delay (`mdelay(10000)`) inside `stop_machine`, triggering an immediate NMI watchdog panic.
- [High] Calling `acpi_unregister_gsi` immediately after requesting the IRQ destroys the IRQ mapping while it is actively in use.
- [High] Dynamically modifying the global `mfd_cell` array with a stack-allocated platform data pointer violates MFD guidelines and creates a race condition and use-after-free vulnerability.
- [High] The interrupt rate-limiting logic uses a 0-initialized shared static variable, causing global cross-device interference and silently ignoring all interrupts for the first ~6 minutes of system uptime.
--

--- Patch [4]: [PATCH RFC v6 4/7] mfd: ls2kbmc: Cancel the work queue on removal ---
commit fad0e9633fb652b609b571c7eefab49f76d46696
Author: Miao Wang <shankerwangmiao@gmail.com>

    mfd: ls2kbmc: Cancel the work queue on removal
    
    When the device is being removeed, the work queue should be canceled to
    avoid any pending work to be executed after the device is removed.

> diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
> index e12f2ca2fbef3..e7bebfe696ac4 100644
> --- a/drivers/mfd/ls2k-bmc-core.c
> +++ b/drivers/mfd/ls2k-bmc-core.c

[ ... ]

[Severity: High]
This is a pre-existing issue, but does this destroy the IRQ mapping while
it is still actively in use?

drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_init() {
...
	gpio_irq = acpi_register_gsi(NULL, LS2K_BMC_RESET_GPIO_GSI, ACPI_EDGE_SENSITIVE,
				     ACPI_ACTIVE_LOW);
	if (gpio_irq < 0)
		return gpio_irq;

	ret = devm_request_irq(ddata->dev, gpio_irq, ls2k_bmc_interrupt,
			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc gpio", ddata);
	if (ret)
		dev_err(ddata->dev, "Failed to request LS2KBMC GPIO IRQ %d.\n", gpio_irq);

	acpi_unregister_gsi(LS2K_BMC_RESET_GPIO_GSI);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	return ret;
}

Calling acpi_unregister_gsi() immediately after requesting the IRQ destroys
the mapping via irq_dispose_mapping(), which permanently breaks the BMC
reset GPIO interrupt handler on every initialization.

[Severity: High]
This is a pre-existing issue, but does this create a use-after-free by saving
a stack pointer into a global array?

drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_probe() {
	struct simplefb_platform_data pd;
...
	ret = ls2k_bmc_parse_mode(dev, &pd);
	if (ret)
		return ret;

	ls2k_bmc_cells[LS2K_BMC_DISPLAY].platform_data = &pd;
	ls2k_bmc_cells[LS2K_BMC_DISPLAY].pdata_size = sizeof(pd);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Writing the stack-allocated &pd pointer to the global ls2k_bmc_cells array
leaves a dangling pointer once probe() returns. Furthermore, modifying a
global mfd_cell array at runtime violates MFD subsystem rules, which require
cell arrays to be static const.

[Severity: High]
This is a pre-existing issue, but will this silently drop interrupts for
the first several minutes of system uptime?

drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_interrupt() {
	struct ls2k_bmc_ddata *ddata = arg;
	static unsigned long last_jiffies;

	if (system_state != SYSTEM_RUNNING)
		return IRQ_HANDLED;

	/* Skip interrupt in LS2K_BMC_INT_INTERVAL */
	if (time_after(jiffies, last_jiffies + LS2K_BMC_INT_INTERVAL)) {
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Since jiffies is initialized to -300 * HZ at boot and the shared static
last_jiffies is 0, time_after() evaluates to false until jiffies crosses
the positive threshold. Doesn't this result in all hardware interrupts being
ignored for approximately the first 6 minutes of system uptime? Also, using
a shared static state causes interference if there are multiple device
instances.

[Severity: Critical]
This is a pre-existing issue, but does this cause an NMI watchdog panic?

drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_events_fn() {
...
	/*
	 * The PCI-E is lost when the BMC resets, at which point access to the PCI-E
	 * from other CPUs is suspended to prevent a crash.
	 */
	stop_machine(ls2k_bmc_recover_pci_data, ddata, NULL);
        ^^^^^^^^^^^^

Which executes ls2k_bmc_recover_pci_data() on all CPUs with local interrupts
disabled:

drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_recover_pci_data() {
...
	/* Check if PCI-E is connected */
	if (!ls2k_bmc_pcie_is_connected(parent, ddata))
		return false;

	/* Waiting for U-Boot and DDR ready */
	mdelay(LS2K_BMC_RESET_WAIT_TIME);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

LS2K_BMC_RESET_WAIT_TIME is 10000. Invoking mdelay(10000) inside
stop_machine() forces the entire system to stall with interrupts disabled for
10 seconds. Will this trigger the NMI watchdog hard lockup detector and
result in a kernel panic?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260805-ls2kbmc-mod-v6-0-16ccde412d86@gmail.com?part=4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 1/7] mfd: ls2kbmc: Make a copy when parsing mode string
  2026-08-04 19:14   ` Miao Wang
  (?)
@ 2026-08-04 19:24   ` sashiko-bot
  -1 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-08-04 19:24 UTC (permalink / raw)
  To: Miao Wang; +Cc: lee, mfd

Thank you for your contribution! Sashiko AI review found 9 potential issue(s) to consider:

New issues:
- [Medium] The newly added error path logs the raw resolution string from the BMC without sanitizing it.

Pre-existing issues:
- [Critical] The `stop_machine()` callback `ls2k_bmc_recover_pci_data()` executes an extremely long `mdelay()`, freezing all CPUs.
- [High] The global `ls2k_bmc_cells` array is dynamically mutated during probe, violating MFD guidelines and creating a data race.
- [High] The shared interrupt handler `ls2k_bmc_interrupt` unconditionally returns `IRQ_HANDLED` without checking hardware status.
- [High] Unconditional dereference of `pdev->bus->self` to access the parent bridge could crash the kernel if the device is attached to the root bus.
- [High] The workqueue `bmc_reset_work` is never canceled upon device removal, leading to a Use-After-Free.
- [High] Missing validation of PCI BAR0 length before mapping memory at a 16MB offset.
- [High] Calculating the framebuffer stride can overflow a 32-bit integer, leading to out-of-bounds memory accesses.
- [High] The driver assumes its parent PCI bridge is a Loongson LS7A and blindly modifies vendor-specific registers.
--

--- Patch [1]: [PATCH RFC v6 1/7] mfd: ls2kbmc: Make a copy when parsing mode string ---
commit 79e8b832a812c3929b8bad068187bcaad3dc3920
Author: Miao Wang <shankerwangmiao@gmail.com>

mfd: ls2kbmc: Make a copy when parsing mode string

When parsing the mode string from BMC, the string is manipulated in-place
with strsep(), preventing from parsing it again. This commit makes a copy
of the original string and manipulates the copy instead.

> diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
> --- a/drivers/mfd/ls2k-bmc-core.c
> +++ b/drivers/mfd/ls2k-bmc-core.c
> @@ -427,34 +427,54 @@ static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
>   */
>  static int ls2k_bmc_parse_mode(struct pci_dev *pdev, struct simplefb_platform_data *pd)
>  {
> -	char *mode;
> +	/* Assume 64 bytes is enough for the resolution string */
> +	char mode_buf[64], mode_buf_orig[64];
> +	char *mode = mode_buf;
> +	const void __iomem *mode_base;
>  	int depth, ret;
>  
>  	/* The last 16M of PCI BAR0 is used to store the resolution string. */
> -	mode = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0) + SZ_16M, SZ_16M);
> -	if (!mode)
> +	mode_base = ioremap(pci_resource_start(pdev, 0) + SZ_16M,
> +			    sizeof(mode_buf));

[Severity: High]
This is a pre-existing issue, but does this mapping require a validation check
for the PCI BAR0 length?

If a virtual or malformed device advertises a BAR0 smaller than 16MB, could
calling ioremap at this fixed SZ_16M offset lead to a master abort or
unauthorized reads of memory outside the allocated PCI resources?

> +	if (!mode_base)
>  		return -ENOMEM;
[ ... ]
>  	ret = kstrtoint(strsep(&mode, "@"), 10, &depth);
>  	if (ret)
> -		return ret;
> +		goto invalid_mode;
>  
>  	pd->stride = pd->width * depth / 8;

[Severity: High]
This is a pre-existing issue, but can this stride calculation overflow a
32-bit integer?

Since width and depth are parsed from device memory, could large values like
width = 0x20000001 cause the width * depth / 8 calculation to overflow into
a small stride, potentially causing out-of-bounds memory accesses when passed
to the framebuffer subsystem?

>  	pd->format = depth == 32 ? "a8r8g8b8" : "r5g6b5";
>  
>  	return 0;
> +
> +invalid_mode:
> +	dev_err(&pdev->dev, "Invalid resolution string: %s\n", mode_buf_orig);

[Severity: Medium]
Could this log the raw resolution string from the BMC without escaping it?

If a malformed resolution string contains non-printable characters or ANSI
escape codes in the BMC memory, would printing it directly via %s lead to
terminal escape sequence injection and log spoofing?

> +	return ret;
>  }

While reviewing this file, I also noticed a few other pre-existing issues
outside the patch diff that might need attention:

> static struct mfd_cell ls2k_bmc_cells[] = {

[Severity: High]
This is a pre-existing issue, but is it safe to omit the const modifier from
this global mfd_cell array?

In ls2k_bmc_probe(), this array is dynamically mutated:

ls2k_bmc_probe() {
    ...
    ls2k_bmc_cells[LS2K_BMC_DISPLAY].platform_data = &pd;
    ...
}

Does assigning the address of a local stack variable to this global array
leave a dangling pointer after the probe function returns, potentially leading
to use-after-free or data corruption if another device is probed? Does this
also violate the MFD subsystem guidelines for static const cell arrays?


> static irqreturn_t ls2k_bmc_interrupt(int irq, void *arg)
> {
> 	...
> 	return IRQ_HANDLED;
> }

[Severity: High]
This is a pre-existing issue, but does this shared interrupt handler properly
check hardware status before returning IRQ_HANDLED?

If it unconditionally returns IRQ_HANDLED without verifying if its device
generated the interrupt, will it falsely claim interrupts meant for other
devices sharing the same IRQ line and cause them to malfunction?


> static void ls2k_bmc_events_fn(struct work_struct *work)
> {
> 	...
> 	stop_machine(ls2k_bmc_recover_pci_data, ddata, NULL);
> 	...
> }

[Severity: Critical]
This is a pre-existing issue, but does ls2k_bmc_recover_pci_data() execute a
long delay inside a stop_machine callback?

ls2k_bmc_recover_pci_data() {
    ...
    mdelay(LS2K_BMC_RESET_WAIT_TIME);
    ...
}

Since stop_machine() runs with local interrupts disabled on all CPUs, will a
10-second mdelay freeze the entire system and trigger the NMI watchdog hard
lockup detector?


> static void ls2k_bmc_save_pci_data(struct pci_dev *pdev, struct ls2k_bmc_ddata *ddata)
> {
> 	struct pci_dev *parent = pdev->bus->self;
> 	...
> 	pci_read_config_dword(parent, PCI_COMMAND, &ddata->bridge_pci_data.pci_command);

[Severity: High]
This is a pre-existing issue, but does this code unconditionally dereference
the parent pointer?

If the device is attached to the root bus, such as in a VM passthrough setup,
pdev->bus->self would be NULL. Would passing this NULL pointer directly to
pci_read_config_dword() and other PCI accessors cause a kernel panic?


> static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
> {
> 	...
> 	INIT_WORK(&ddata->bmc_reset_work, ls2k_bmc_events_fn);

[Severity: High]
This is a pre-existing issue, but is the bmc_reset_work properly canceled on
device removal?

If the workqueue is initialized but never properly canceled when the driver
is unbound and the ddata structure is freed by devm, could this lead to a
use-after-free if the work is scheduled or running?


> static void ls2k_bmc_save_pci_data(struct pci_dev *pdev, struct ls2k_bmc_ddata *ddata)
> {
> 	struct pci_dev *parent = pdev->bus->self;
> 	...
> 	pci_read_config_dword(parent, LS7A_GEN2_CTL, &ddata->bridge_pci_data.gen2_ctrl);

[Severity: High]
This is a pre-existing issue, but does the driver unconditionally assume its
parent bridge is a Loongson LS7A device?

If the device is attached behind a standard PCIe switch or QEMU root port,
will writing to vendor-specific registers like LS7A_GEN2_CTL corrupt standard
PCI bridge configuration space and potentially break system routing or crash?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260805-ls2kbmc-mod-v6-0-16ccde412d86@gmail.com?part=1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 5/7] ipmi: ls2k: adjust dependency to its mfd driver
  2026-08-04 19:14   ` Miao Wang
  (?)
@ 2026-08-04 19:25   ` sashiko-bot
  -1 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-08-04 19:25 UTC (permalink / raw)
  To: Miao Wang; +Cc: mfd, lee

> From: Miao Wang <shankerwangmiao@gmail.com>
> 
> There is functional dependency between the IPMI driver and its mfd
> driver. Previously, the dependency was set to "select" from
> IPMI_LS2K to MFD_LS2K_BMC_CORE. However, the ipmi driver is actually
> compiled as a part of the ipmi_si module, and IPMI_LS2K is a bool
> option. Therefore, the dependency "select" will force the mfd driver
> to be compiled built-in when the ipmi driver is built as a module. This
> is not desirable. This patch fixes this by declaring a conditional
> dependency from IPMI_SI to MFD_LS2K_BMC_CORE if IPMI_LS2K is selected.
> This will allow the mfd driver to be compiled as a module if the ipmi
> driver is built as a module. The adjustment to Kconfig for the mfd
> driver will be introduced in the later patch in this series.
> 
> Fixes: d46651d4e3c0 ("ipmi: Add Loongson-2K BMC support")
> Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260805-ls2kbmc-mod-v6-0-16ccde412d86@gmail.com?part=5


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 6/7] mfd: ls2kbmc: Able to be compiled as a module
  2026-08-04 19:14   ` Miao Wang
  (?)
@ 2026-08-04 19:27   ` sashiko-bot
  -1 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-08-04 19:27 UTC (permalink / raw)
  To: Miao Wang; +Cc: mfd, lee

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [High] Immediate disposal of IRQ mapping breaks GPIO interrupt and causes panic on module unload.
- [High] Dynamic mutation of global MFD cell array with a local stack pointer violates MFD API rules.
- [High] System-wide 13-second stall with interrupts disabled inside stop_machine() callback.
--

--- Patch [6]: [PATCH RFC v6 6/7] mfd: ls2kbmc: Able to be compiled as a module ---
commit 9c6121767eaa76246cc34b4848b6602e7e2a88b2
Author: Miao Wang <shankerwangmiao@gmail.com>

mfd: ls2kbmc: Able to be compiled as a module

Make ls2kmc able to be compiled as a module

> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 763ce6a34782b..a7a9f97af248c 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -2494,7 +2494,7 @@ config MFD_LOONGSON_SE
>  	  which will forward them to the corresponding engine.
>  
>  config MFD_LS2K_BMC_CORE
> -	bool "Loongson-2K Board Management Controller Support"
> +	tristate "Loongson-2K Board Management Controller Support"

[Severity: High]
This isn't a bug introduced by this patch, but by allowing this driver to
be built as a module, it exposes an unbind and unload crash path.

In drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_init(), the code unregisters the
GSI immediately after requesting the IRQ:

    ret = devm_request_irq(ddata->dev, gpio_irq, ls2k_bmc_interrupt,
                           IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc gpio", ddata);
    if (ret)
        dev_err(ddata->dev, "Failed to request LS2KBMC GPIO IRQ %d.\n", gpio_irq);

    acpi_unregister_gsi(LS2K_BMC_RESET_GPIO_GSI);
    return ret;

Does this unconditional call to acpi_unregister_gsi() free the IRQ
descriptor while the interrupt is still actively requested? If the module
is unloaded, will the devres cleanup call free_irq() on a destroyed IRQ
descriptor and cause a kernel panic?

[Severity: High]
This is also a pre-existing issue, but it violates MFD subsystem rules
regarding static const cell arrays.

In drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_probe(), the driver mutates the
global ls2k_bmc_cells array:

    struct simplefb_platform_data pd;
    ...
    ls2k_bmc_cells[LS2K_BMC_DISPLAY].platform_data = &pd;
    ls2k_bmc_cells[LS2K_BMC_DISPLAY].pdata_size = sizeof(pd);

Since ls2k_bmc_cells is not declared const, does mutating this global
array with a local stack pointer leave a dangling pointer once the probe
function returns? Would concurrent probes of multiple BMC PCI devices
result in a structural data race?

[Severity: High]
This is another pre-existing issue that might cause severe instability.

In drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_events_fn(), the driver calls
stop_machine():

    stop_machine(ls2k_bmc_recover_pci_data, ddata, NULL);

Inside the callback ls2k_bmc_recover_pci_data(), the code performs a long
delay:

    /* Waiting for U-Boot and DDR ready */
    mdelay(LS2K_BMC_RESET_WAIT_TIME);

Since stop_machine() halts all CPUs and disables local interrupts, will
delaying for 10+ seconds inside this callback trigger the NMI hard lockup
watchdog and panic the host kernel?

>  	depends on PCI && ACPI_GENERIC_GSI
>  	select MFD_CORE
>  	help

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260805-ls2kbmc-mod-v6-0-16ccde412d86@gmail.com?part=6

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 3/7] mfd: ls2kbmc: Redraw using exported functions
  2026-08-04 19:14   ` Miao Wang
  (?)
@ 2026-08-04 19:27   ` sashiko-bot
  -1 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-08-04 19:27 UTC (permalink / raw)
  To: Miao Wang; +Cc: mfd, lee

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Excessive busy-waiting with IRQs disabled in `stop_machine` callback causes hard lockups.
- [High] Global `mfd_cell` array is dynamically mutated using a local stack pointer during probe.
- [High] Missing `cancel_work_sync` on driver unbind leads to use-after-free of `ddata` by the workqueue.
- [High] Ignored failure of PCI recovery leads to kernel crash when updating screen.
--

--- Patch [3]: [PATCH RFC v6 3/7] mfd: ls2kbmc: Redraw using exported functions ---
commit 9d8a26242ae07ab2514af3ffede82d5bccaaf8a9
Author: Miao Wang <shankerwangmiao@gmail.com>

mfd: ls2kbmc: Redraw using exported functions

This commit replaces the manual virtual terminal relocation with a call to
update_screen() to trigger a redraw of the current VT after a BMC reset.

> diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
> index a9a30611dde9e..e12f2ca2fbef3 100644
> --- a/drivers/mfd/ls2k-bmc-core.c
> +++ b/drivers/mfd/ls2k-bmc-core.c
> @@ -25,6 +25,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/stop_machine.h>
>  #include <linux/vt_kern.h>
> +#include <linux/console.h>
>  
>  /* LS2K BMC resources */
>  #define LS2K_DISPLAY_RES_START		(SZ_16M + SZ_2M)
> @@ -310,7 +311,9 @@ static void ls2k_bmc_events_fn(struct work_struct *work)
>  
>  	if (IS_ENABLED(CONFIG_VT)) {
>  		/* Re-push the display due to previous PCI-E loss. */

[Severity: Critical]
This is a pre-existing issue, but can the stop_machine() call that precedes 
this block cause a hard lockup?

In ls2k_bmc_events_fn(), stop_machine() is called to execute 
ls2k_bmc_recover_pci_data():

drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_events_fn() {
...
	stop_machine(ls2k_bmc_recover_pci_data, ddata, NULL);
...
}

During stop_machine(), local interrupts are disabled. However, 
ls2k_bmc_recover_pci_data() performs massive busy waits:

drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_recover_pci_data() {
		mdelay(1);
	}
...
	mdelay(LS2K_BMC_RESET_WAIT_TIME);
}

With mdelay() loops of up to 12 seconds total while interrupts are disabled, 
could this trigger an nmi watchdog timeout panic?


[Severity: High]
This isn't a bug introduced by this patch, but does this code handle PCI 
recovery failures correctly?

Looking at ls2k_bmc_recover_pci_data(), it returns 0 both on success and when 
it fails:

drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_recover_pci_data() {
	if (i == 0)
		return false;
...
	return 0;
}

Because stop_machine() masks the error by propagating this 0, 
update_screen() will be called here unconditionally.

If the PCI link fails to recover, could writing to the unmapped framebuffer 
trigger a synchronous external bus error and crash the system?

> -		set_console(vt_move_to_console(MAX_NR_CONSOLES - 1, 1));
> +		console_lock();
> +		update_screen(vc_cons[fg_console].d);
> +		console_unlock();
>  	}
>  }

[Severity: High]
This isn't a bug introduced by this patch, but is there a data race when 
setting up the mfd_cell array during probe?

In ls2k_bmc_probe(), the global ls2k_bmc_cells array is dynamically mutated 
using a pointer to a local stack variable:

drivers/mfd/ls2k-bmc-core.c:ls2k_bmc_probe() {
...
	ls2k_bmc_cells[LS2K_BMC_DISPLAY].platform_data = &pd;
	ls2k_bmc_cells[LS2K_BMC_DISPLAY].pdata_size = sizeof(pd);
...
}

Since ls2k_bmc_cells is a global static array without a const qualifier:

drivers/mfd/ls2k-bmc-core.c {
static struct mfd_cell ls2k_bmc_cells[] = {
...
}

Does this leave a dangling stack pointer in a global array if multiple 
devices are probed or if the array is referenced later?


[Severity: High]
This is a pre-existing issue, but does this driver safely tear down the 
reset workqueue on unbind?

The bmc_reset_work is initialized in ls2k_bmc_init(), but the driver lacks 
a remove hook to cancel it:

drivers/mfd/ls2k-bmc-core.c {
static struct pci_driver ls2k_bmc_driver = {
	.name = "ls2k-bmc",
	.id_table = ls2k_bmc_devices,
	.probe = ls2k_bmc_probe,
};
...

If the driver unbinds or probe fails, devres frees the irq and ddata.

If the work is already scheduled or executing when this happens, could the 
workqueue dereference the freed ddata memory?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260805-ls2kbmc-mod-v6-0-16ccde412d86@gmail.com?part=3

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO
  2026-08-04 19:14   ` Miao Wang
  (?)
@ 2026-08-04 19:30   ` sashiko-bot
  -1 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-08-04 19:30 UTC (permalink / raw)
  To: Miao Wang; +Cc: lee, mfd

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [Low] Casting phys_addr_t directly to void * causes compiler warnings on 32-bit builds where phys_addr_t is 64-bit.
- [Low] Inconsistent GPIO polarity configuration using GPIO_ACTIVE_HIGH for an active-low reset signal.

Pre-existing issues:
- [High] The driver mutates a global static `mfd_cell` array in the probe function, violating MFD subsystem guidelines and causing a data race.
- [High] The shared interrupt handler `ls2k_bmc_interrupt` unconditionally returns `IRQ_HANDLED`, defeating spurious interrupt detection.
--

--- Patch [7]: [PATCH RFC v6 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO ---
commit 9252e63d105a3c07a23e797a66a7260c9eee7e44
Author: Miao Wang <shankerwangmiao@gmail.com>

mfd: ls2kbmc: Capture the reset event of BMC through GPIO

This patch updates the ls2kbmc driver to retrieve the BMC reset GPIO
through the ACPI node's _CRS resources. If no declaration is found, it
falls back to finding the correct GPIO controller and pin using a fixed
address.

> diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
> --- a/drivers/mfd/ls2k-bmc-core.c
> +++ b/drivers/mfd/ls2k-bmc-core.c
[ ... ]
> @@ -375,6 +368,91 @@ static void ls2k_bmc_save_pci_data(struct pci_dev *pdev, struct ls2k_bmc_ddata *
> +static struct gpio_desc *ls2k_bmc_find_gpio(struct ls2k_bmc_ddata *ddata)
> +{
[ ... ]
> +	static const phys_addr_t LOONGSON_GPIO_REG_BASE = 0x1FE00500;
> +	static const unsigned int LS2K_BMC_RESET_GPIO = 14;
> +	int ret;
> +	struct gpio_device *gdev __free(gpio_device_put) = NULL;
> +	struct property_entry ls2k_bmc_swnode_properties[2] = { 0 };
> +
> +	dev_dbg(ddata->dev, "Searching for GPIO chip at address %pa\n", &LOONGSON_GPIO_REG_BASE);
> +
> +	gdev = gpio_device_find((void *)LOONGSON_GPIO_REG_BASE, ls2k_bmc_gpiochip_find);

[Severity: Low]
Does casting phys_addr_t directly to a void * cause a truncation warning on
32-bit builds where phys_addr_t is 64-bit?

> +
> +	if (!gdev) {
> +		dev_dbg(ddata->dev, "cannot find GPIO chip at address %pa, deferring\n",
> +			&LOONGSON_GPIO_REG_BASE);
> +		return ERR_PTR(-EPROBE_DEFER);
> +	}
> +
> +	ls2k_bmc_swnode_properties[0] = PROPERTY_ENTRY_GPIO("gpio",
> +		gpio_dev_get_fwnode(gdev), LS2K_BMC_RESET_GPIO, GPIO_ACTIVE_HIGH);

[Severity: Low]
Could the fallback software node configure the active polarity inconsistently
with the hardware?

The ACPI specification and the previous hardware implementation define the BMC
reset GPIO as active-low, but it is registered here as GPIO_ACTIVE_HIGH.

> +
> +	ret = device_create_managed_software_node(ddata->dev, ls2k_bmc_swnode_properties, NULL);
[ ... ]
> @@ -402,44 +479,36 @@ static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
[ ... ]
> -	ret = devm_request_irq(ddata->dev, gpio_irq, ls2k_bmc_interrupt,
> -			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc gpio", ddata);
> -	if (ret)
> -		dev_err(ddata->dev, "Failed to request LS2KBMC GPIO IRQ %d.\n", gpio_irq);
> +	ret = devm_request_irq(&pdev->dev, gpio_irq, ls2k_bmc_interrupt,
> +			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc reset", ddata);

[Severity: High]
This is a pre-existing issue, but does unconditionally returning IRQ_HANDLED
in the shared interrupt handler defeat spurious interrupt detection?

The driver requests the PCI and GPIO interrupts with IRQF_SHARED. However,
ls2k_bmc_interrupt() does not verify that the interrupt was generated by the
BMC before claiming it:

static irqreturn_t ls2k_bmc_interrupt(int irq, void *data)
{
        ...
        return IRQ_HANDLED;
}

If another device sharing the IRQ line triggers a spurious interrupt, could
this false claim lead to a system-halting interrupt storm?

[ ... ]

[Severity: High]
This isn't a bug introduced by this patch, but does the driver mutate a
global static mfd_cell array in the probe function?

Looking at ls2k_bmc_probe(), it injects a stack pointer into ls2k_bmc_cells:

static struct mfd_cell ls2k_bmc_cells[] = {
        ...
};

static int ls2k_bmc_probe(...)
{
        struct ls2k_bmc_display_pdata pd;
        ...
        ls2k_bmc_cells[LS2K_BMC_DISPLAY].platform_data = &pd;
        ls2k_bmc_cells[LS2K_BMC_DISPLAY].pdata_size = sizeof(pd);
}

This violates the MFD subsystem guidelines which require cell arrays to be
static const. If multiple devices are probed concurrently, could this cause a
data race and potential use-after-free?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260805-ls2kbmc-mod-v6-0-16ccde412d86@gmail.com?part=7

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 5/7] ipmi: ls2k: adjust dependency to its mfd driver
  2026-08-04 19:14   ` Miao Wang
  (?)
  (?)
@ 2026-08-04 19:34   ` Corey Minyard
  -1 siblings, 0 replies; 27+ messages in thread
From: Corey Minyard @ 2026-08-04 19:34 UTC (permalink / raw)
  To: shankerwangmiao
  Cc: Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Linus Walleij,
	Bartosz Golaszewski, Xi Ruoyao, WANG Xuerui, Yinbo Zhu,
	Jiaxun Yang, mfd, linux-kernel, linux-gpio, openipmi-developer

On Wed, Aug 05, 2026 at 03:14:23AM +0800, Miao Wang via B4 Relay wrote:
> From: Miao Wang <shankerwangmiao@gmail.com>
> 
> There is functional dependency between the IPMI driver and its mfd
> driver. Previously, the dependency was set to "select" from
> IPMI_LS2K to MFD_LS2K_BMC_CORE. However, the ipmi driver is actually
> compiled as a part of the ipmi_si module, and IPMI_LS2K is a bool
> option. Therefore, the dependency "select" will force the mfd driver
> to be compiled built-in when the ipmi driver is built as a module. This
> is not desirable. This patch fixes this by declaring a conditional
> dependency from IPMI_SI to MFD_LS2K_BMC_CORE if IPMI_LS2K is selected.
> This will allow the mfd driver to be compiled as a module if the ipmi
> driver is built as a module. The adjustment to Kconfig for the mfd
> driver will be introduced in the later patch in this series.

Looks good to me.

Acked-by: Corey Minyard <cminyard@mvista.com>

> 
> Fixes: d46651d4e3c0 ("ipmi: Add Loongson-2K BMC support")
> Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
> ---
>  drivers/char/ipmi/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
> index 669f7600019747bcd2b37563477cf336f19a0407..07f3308c71616215871a730b87f1991d2b502e63 100644
> --- a/drivers/char/ipmi/Kconfig
> +++ b/drivers/char/ipmi/Kconfig
> @@ -62,6 +62,7 @@ config IPMI_DEVICE_INTERFACE
>  config IPMI_SI
>  	tristate 'IPMI System Interface handler'
>  	select IPMI_PLAT_DATA
> +	select MFD_LS2K_BMC_CORE if IPMI_LS2K
>  	help
>  	  Provides a driver for System Interfaces (KCS, SMIC, BT).
>  	  Currently, only KCS and SMIC are supported.  If
> @@ -87,7 +88,6 @@ config IPMI_IPMB
>  config IPMI_LS2K
>  	bool 'Loongson-2K IPMI interface'
>  	depends on LOONGARCH
> -	select MFD_LS2K_BMC_CORE
>  	help
>  	  Provides a driver for Loongson-2K IPMI interfaces.
>  
> 
> -- 
> 2.49.0
> 
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO
  2026-08-04 19:14   ` Miao Wang
  (?)
  (?)
@ 2026-08-10 10:14   ` Bartosz Golaszewski
  2026-08-10 11:28     ` Miao Wang
  -1 siblings, 1 reply; 27+ messages in thread
From: Bartosz Golaszewski @ 2026-08-10 10:14 UTC (permalink / raw)
  To: shankerwangmiao
  Cc: Miao Wang via B4 Relay, Xi Ruoyao, WANG Xuerui, Yinbo Zhu,
	Jiaxun Yang, mfd, linux-kernel, linux-gpio, openipmi-developer,
	Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski

On Tue, 4 Aug 2026 21:14:25 +0200, Miao Wang via B4 Relay
<devnull+shankerwangmiao.gmail.com@kernel.org> said:
> From: Miao Wang <shankerwangmiao@gmail.com>
>
> The reset event of BMC is captured through GPIO. However, this driver
> bypasses the GPIO framework and directly accesses the GPIO controller
> through the fixed address. When the same GPIO controller is also
> exposed through ACPI and probed by the corresponding GPIO driver,
> there would be a conflict between the two drivers.
>
> This patch will try to find the GPIO through declared GPIO pin in the
> _CRS resources of the ACPI node. If no such delaration is found, the
> driver will fall back to search for the correct GPIO controller and pin
> according to the fixed address and pin number. A possible DSDT
> declaration for the GPIO pin might be as follows:
>
>     Device (BMC0) {
>         Name (_ADR, ...) // Match the PCI address of the BMC device
>         // \_SB.GPO1 is the ACPI path of the GPIO controller
>         Name (_CRS, ResourceTemplate () {
>             GpioInt (Edge, ActiveLow, Exclusive, PullNone, 0,
>                      "\\_SB.GPO1", 0) {
>                 14 // 14 is the GPIO pin number
>             }
>     }
>
> Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
> ---
>  drivers/mfd/ls2k-bmc-core.c | 163 +++++++++++++++++++++++++++++++-------------
>  1 file changed, 116 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
> index e7bebfe696ac4554eb6283279811a27ed865ab73..97a666a136fe41ed4268cb70770201533aebb1d5 100644
> --- a/drivers/mfd/ls2k-bmc-core.c
> +++ b/drivers/mfd/ls2k-bmc-core.c
> @@ -26,6 +26,10 @@
>  #include <linux/stop_machine.h>
>  #include <linux/vt_kern.h>
>  #include <linux/console.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/gpio/property.h>
> +#include <linux/gpio/machine.h>
>
>  /* LS2K BMC resources */
>  #define LS2K_DISPLAY_RES_START		(SZ_16M + SZ_2M)
> @@ -81,18 +85,6 @@
>
>  #define PCI_REG_STRIDE			0x4
>
> -#define LS2K_BMC_RESET_GPIO		14
> -#define LOONGSON_GPIO_REG_BASE		0x1FE00500
> -#define LOONGSON_GPIO_REG_SIZE		0x18
> -#define LOONGSON_GPIO_OEN		0x0
> -#define LOONGSON_GPIO_FUNC		0x4
> -#define LOONGSON_GPIO_INTPOL		0x10
> -#define LOONGSON_GPIO_INTEN		0x14
> -
> -#define LOONGSON_IO_INT_BASE		16
> -#define LS2K_BMC_RESET_GPIO_INT_VEC	(LS2K_BMC_RESET_GPIO % 8)
> -#define LS2K_BMC_RESET_GPIO_GSI		(LOONGSON_IO_INT_BASE + LS2K_BMC_RESET_GPIO_INT_VEC)
> -
>  enum {
>  	LS2K_BMC_DISPLAY,
>  	LS2K_BMC_IPMI0,
> @@ -186,6 +178,7 @@ struct ls2k_bmc_ddata {
>  	struct work_struct bmc_reset_work;
>  	struct ls2k_bmc_pci_data bmc_pci_data;
>  	struct ls2k_bmc_bridge_pci_data bridge_pci_data;
> +	struct gpio_desc *reset_gpio;
>  };
>
>  static bool ls2k_bmc_bar0_addr_is_set(struct pci_dev *pdev)
> @@ -375,6 +368,91 @@ static void ls2k_bmc_save_pci_data(struct pci_dev *pdev, struct ls2k_bmc_ddata *
>  	pci_read_config_dword(pdev, PCI_INTERRUPT_LINE, &ddata->bmc_pci_data.interrupt_line);
>  }
>
> +static struct fwnode_handle *gpio_dev_get_fwnode(struct gpio_device *gdev)
> +{
> +	struct device *gdev_dev;
> +
> +	gdev_dev = gpio_device_to_device(gdev);
> +	return dev_fwnode(gdev_dev);

You can just do a one-liner:

	return dev_fwnode(gpio_device_to_device(gdev));

> +}
> +
> +static int ls2k_bmc_gpiochip_find(struct gpio_chip *gc, const void *data)
> +{
> +	struct acpi_device *adev;
> +	struct list_head resource_list;
> +	struct resource_entry *rentry;
> +	struct fwnode_handle *fwnode = gpio_dev_get_fwnode(gc->gpiodev);
> +	phys_addr_t start_addr = (phys_addr_t) data;
> +	int ret, found = 0;
> +
> +	if (!is_acpi_node(fwnode))
> +		goto out;
> +
> +	adev = to_acpi_device_node(fwnode);
> +	if (!adev)
> +		goto out;
> +
> +	INIT_LIST_HEAD(&resource_list);
> +
> +	ret = acpi_dev_get_memory_resources(adev, &resource_list);
> +	if (ret < 0)
> +		goto out;
> +	/*
> +	 * ACPI memory resources are ordered and only the first one is
> +	 * considered by the driver of the expected GPIO controller. So
> +	 * here we also only check the first one to see if it matches the
> +	 * expected address.
> +	 */
> +	rentry = list_first_entry_or_null(&resource_list, struct resource_entry, node);
> +	if (!rentry)
> +		goto free_resource_list;
> +	if (rentry->res->start == start_addr)
> +		found = 1;
> +
> +free_resource_list:
> +	acpi_dev_free_resource_list(&resource_list);
> +out:
> +	return found;
> +}
> +
> +static struct gpio_desc *ls2k_bmc_find_gpio(struct ls2k_bmc_ddata *ddata)
> +{
> +	/*
> +	 * In conventional way, the GPIO should be obtained through ACPI or
> +	 * device tree. However, when the information is not available,
> +	 * we should find the GPIO according to the convention of the server
> +	 * boards with LS2K BMC, the gpio signal reflecting the reset event
> +	 * of the BMC should be connected to pin 14 of the GPIO input of
> +	 * the first CPU node. The address of that GPIO controller is fixed.
> +	 */
> +	static const phys_addr_t LOONGSON_GPIO_REG_BASE = 0x1FE00500;
> +	static const unsigned int LS2K_BMC_RESET_GPIO = 14;
> +	int ret;
> +	struct gpio_device *gdev __free(gpio_device_put) = NULL;

Please declare the variable where you initialize it when using __free().

> +	struct property_entry ls2k_bmc_swnode_properties[2] = { 0 };

Prefer `= { };`.

> +
> +	dev_dbg(ddata->dev, "Searching for GPIO chip at address %pa\n", &LOONGSON_GPIO_REG_BASE);
> +
> +	gdev = gpio_device_find((void *)LOONGSON_GPIO_REG_BASE, ls2k_bmc_gpiochip_find);
> +

No need for a blank line here.

> +	if (!gdev) {
> +		dev_dbg(ddata->dev, "cannot find GPIO chip at address %pa, deferring\n",
> +			&LOONGSON_GPIO_REG_BASE);
> +		return ERR_PTR(-EPROBE_DEFER);
> +	}
> +
> +	ls2k_bmc_swnode_properties[0] = PROPERTY_ENTRY_GPIO("gpio",
> +		gpio_dev_get_fwnode(gdev), LS2K_BMC_RESET_GPIO, GPIO_ACTIVE_HIGH);

TBH this could become a GPIOLIB function as gpio_device_get_fwnode().

> +
> +	ret = device_create_managed_software_node(ddata->dev, ls2k_bmc_swnode_properties, NULL);
> +	if (ret) {
> +		dev_err(ddata->dev, "Failed to create software node for GPIO reset: %d\n", ret);
> +		return ERR_PTR(ret);

return dev_err_probe()? This can only be called from probe().

> +	}
> +
> +	return devm_gpiod_get_index(ddata->dev, NULL, 0, GPIOD_IN);
> +}
> +
>  static void ls2k_bmc_cancel_wq(void *data)
>  {
>  	struct ls2k_bmc_ddata *ddata = data;
> @@ -384,8 +462,7 @@ static void ls2k_bmc_cancel_wq(void *data)
>  static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
>  {
>  	struct pci_dev *pdev = to_pci_dev(ddata->dev);
> -	void __iomem *gpio_base;
> -	int gpio_irq, ret, val;
> +	int gpio_irq, ret;
>
>  	ls2k_bmc_save_pci_data(pdev, ddata);
>
> @@ -402,44 +479,36 @@ static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
>  		return ret;
>  	}
>
> -	gpio_base = ioremap(LOONGSON_GPIO_REG_BASE, LOONGSON_GPIO_REG_SIZE);
> -	if (!gpio_base)
> -		return -ENOMEM;
> -
> -	/* Disable GPIO output */
> -	val = readl(gpio_base + LOONGSON_GPIO_OEN);
> -	writel(val | BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_OEN);
> -
> -	/* Enable GPIO functionality */
> -	val = readl(gpio_base + LOONGSON_GPIO_FUNC);
> -	writel(val & ~BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_FUNC);
> -
> -	/* Set GPIO interrupts to low-level active */
> -	val = readl(gpio_base + LOONGSON_GPIO_INTPOL);
> -	writel(val & ~BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_INTPOL);
> -
> -	/* Enable GPIO interrupts */
> -	val = readl(gpio_base + LOONGSON_GPIO_INTEN);
> -	writel(val | BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_INTEN);
> +	ddata->reset_gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0, GPIOD_IN);
> +	if (IS_ERR(ddata->reset_gpio)) {
> +		ret = PTR_ERR(ddata->reset_gpio);
> +		ddata->reset_gpio = NULL;
> +		return dev_err_probe(ddata->dev, ret, "Failed to get GPIO pin for reset signal\n");
> +	}
> +	if (ddata->reset_gpio == NULL) {
> +		ddata->reset_gpio = ls2k_bmc_find_gpio(ddata);
> +		if (IS_ERR(ddata->reset_gpio)) {
> +			ret = PTR_ERR(ddata->reset_gpio);
> +			ddata->reset_gpio = NULL;
> +			return dev_err_probe(ddata->dev, ret,
> +					     "Failed to find GPIO pin for reset signal\n");

Why not just:

	return dev_err_probe(ddata->dev, PTR_ERR(ddata->reset_gpio), ...)?

> +		}
> +	}
>
> -	iounmap(gpio_base);
> +	gpio_irq = gpiod_to_irq(ddata->reset_gpio);
>
> -	/*
> -	 * Since gpio_chip->to_irq is not implemented in the Loongson-3 GPIO driver,
> -	 * acpi_register_gsi() is used to obtain the GPIO IRQ. The GPIO interrupt is a
> -	 * watchdog interrupt that is triggered when the BMC resets.
> -	 */
> -	gpio_irq = acpi_register_gsi(NULL, LS2K_BMC_RESET_GPIO_GSI, ACPI_EDGE_SENSITIVE,
> -				     ACPI_ACTIVE_LOW);
>  	if (gpio_irq < 0)
> -		return gpio_irq;
> +		return dev_err_probe(ddata->dev, gpio_irq,
> +				     "Failed to get IRQ for GPIO reset signal input\n");
>
> -	ret = devm_request_irq(ddata->dev, gpio_irq, ls2k_bmc_interrupt,
> -			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc gpio", ddata);
> -	if (ret)
> -		dev_err(ddata->dev, "Failed to request LS2KBMC GPIO IRQ %d.\n", gpio_irq);
> +	ret = devm_request_irq(&pdev->dev, gpio_irq, ls2k_bmc_interrupt,
> +			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc reset", ddata);
> +
> +	if (ret != 0)
> +		return dev_err_probe(ddata->dev, ret,
> +				     "Failed to request IRQ %d for GPIO reset signal input.\n",
> +				     gpio_irq);
>
> -	acpi_unregister_gsi(LS2K_BMC_RESET_GPIO_GSI);
>  	return ret;
>  }
>
>
> --
> 2.49.0
>
>
>


Obviously this is ugly but I understand the need for this workaround so with
the issues above addressed, this will work for me.

Bart

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO
  2026-08-10 10:14   ` Bartosz Golaszewski
@ 2026-08-10 11:28     ` Miao Wang
  2026-08-10 11:30       ` Bartosz Golaszewski
  0 siblings, 1 reply; 27+ messages in thread
From: Miao Wang @ 2026-08-10 11:28 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Miao Wang via B4 Relay, Xi Ruoyao, WANG Xuerui, Yinbo Zhu,
	Jiaxun Yang, mfd, linux-kernel, linux-gpio, openipmi-developer,
	Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij

Hi,

> 2026年8月10日 18:14,Bartosz Golaszewski <brgl@kernel.org> 写道:
> 
> On Tue, 4 Aug 2026 21:14:25 +0200, Miao Wang via B4 Relay
> <devnull+shankerwangmiao.gmail.com@kernel.org> said:
> 
>> + gpio_dev_get_fwnode(gdev), LS2K_BMC_RESET_GPIO, GPIO_ACTIVE_HIGH);
> 
> TBH this could become a GPIOLIB function as gpio_device_get_fwnode().

I wonder if this function should be a static inline function defined
in gpio/driver.h or a normal function defined in gpiolib.c? I tend
to the former.

Cheers,

Miao Wang



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH RFC v6 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO
  2026-08-10 11:28     ` Miao Wang
@ 2026-08-10 11:30       ` Bartosz Golaszewski
  0 siblings, 0 replies; 27+ messages in thread
From: Bartosz Golaszewski @ 2026-08-10 11:30 UTC (permalink / raw)
  To: Miao Wang
  Cc: Miao Wang via B4 Relay, Xi Ruoyao, WANG Xuerui, Yinbo Zhu,
	Jiaxun Yang, mfd, linux-kernel, linux-gpio, openipmi-developer,
	Binbin Zhou, Chong Qiao, Lee Jones, Huacai Chen, Corey Minyard,
	Linus Walleij, Bartosz Golaszewski

On Mon, 10 Aug 2026 13:28:56 +0200, Miao Wang <shankerwangmiao@gmail.com> said:
> Hi,
>
>> 2026年8月10日 18:14,Bartosz Golaszewski <brgl@kernel.org> 写道:
>>
>> On Tue, 4 Aug 2026 21:14:25 +0200, Miao Wang via B4 Relay
>> <devnull+shankerwangmiao.gmail.com@kernel.org> said:
>>
>>> + gpio_dev_get_fwnode(gdev), LS2K_BMC_RESET_GPIO, GPIO_ACTIVE_HIGH);
>>
>> TBH this could become a GPIOLIB function as gpio_device_get_fwnode().
>
> I wonder if this function should be a static inline function defined
> in gpio/driver.h or a normal function defined in gpiolib.c? I tend
> to the former.
>

Yes, a regular GPL exported function in gpiolib.c please.

Bartosz

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2026-08-10 11:30 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-04 19:14 [PATCH RFC v6 0/7] mfd: ls2kbmc: multiple fixes for this driver Miao Wang via B4 Relay
2026-08-04 19:14 ` Miao Wang
2026-08-04 19:14 ` [PATCH RFC v6 1/7] mfd: ls2kbmc: Make a copy when parsing mode string Miao Wang via B4 Relay
2026-08-04 19:14   ` Miao Wang
2026-08-04 19:24   ` sashiko-bot
2026-08-04 19:14 ` [PATCH RFC v6 2/7] mfd: ls2kbmc: Sanity check for the connected pci port Miao Wang via B4 Relay
2026-08-04 19:14   ` Miao Wang
2026-08-04 19:23   ` sashiko-bot
2026-08-04 19:14 ` [PATCH RFC v6 3/7] mfd: ls2kbmc: Redraw using exported functions Miao Wang via B4 Relay
2026-08-04 19:14   ` Miao Wang
2026-08-04 19:27   ` sashiko-bot
2026-08-04 19:14 ` [PATCH RFC v6 4/7] mfd: ls2kbmc: Cancel the work queue on removal Miao Wang via B4 Relay
2026-08-04 19:14   ` Miao Wang
2026-08-04 19:24   ` sashiko-bot
2026-08-04 19:14 ` [PATCH RFC v6 5/7] ipmi: ls2k: adjust dependency to its mfd driver Miao Wang via B4 Relay
2026-08-04 19:14   ` Miao Wang
2026-08-04 19:25   ` sashiko-bot
2026-08-04 19:34   ` Corey Minyard
2026-08-04 19:14 ` [PATCH RFC v6 6/7] mfd: ls2kbmc: Able to be compiled as a module Miao Wang via B4 Relay
2026-08-04 19:14   ` Miao Wang
2026-08-04 19:27   ` sashiko-bot
2026-08-04 19:14 ` [PATCH RFC v6 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO Miao Wang via B4 Relay
2026-08-04 19:14   ` Miao Wang
2026-08-04 19:30   ` sashiko-bot
2026-08-10 10:14   ` Bartosz Golaszewski
2026-08-10 11:28     ` Miao Wang
2026-08-10 11:30       ` Bartosz Golaszewski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.