Re: [PATCH RFC v3 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO

Lee Jones <[email protected]> Thu, 23 Jul 2026 12:29:03 +0100
Newsgroups dev.linux.lists.mfd
Message-ID <[email protected]>
On Thu, 09 Jul 2026, [email protected] wrote:

> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> 
> New issues:
> - [High] Unprotected access to `gpio_chip` without a NULL check leads to a potential NULL pointer dereference or use-after-free.
> - [Medium] The ACPI memory resource search for the GPIO controller only checks the first memory descriptor, ignoring any subsequent ones.

Looks like there are a few of these to consider.

I'm unmarking this for review for now.

> Pre-existing issues:
> - [High] The shared interrupt handler unconditionally returns IRQ_HANDLED without checking the hardware status, violating shared IRQ semantics.
> --
> 
> --- Patch [7]: [PATCH RFC v3 7/7] mfd: ls2kbmc: Capture the reset event of BMC through GPIO ---
> commit a2c13d408a04d53aa90ec63a2b31ea6450fb493e
> Author: Miao Wang <[email protected]>
> 
> mfd: ls2kbmc: Capture the reset event of BMC through GPIO
>     
> This patch modifies the driver to find its reset GPIO via ACPI or a fallback 
> software node, rather than directly accessing the GPIO registers.
> 
> > diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c
> > index 1466b314fc4e5..5a2644ff07fee 100644
> > --- a/drivers/mfd/ls2k-bmc-core.c
> > +++ b/drivers/mfd/ls2k-bmc-core.c
> 
> [ ... ]
> 
> > +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_chip_get_fwnode(gc);
> > +	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;
> > +	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;
> 
> [Severity: Medium]
> Will this correctly identify the GPIO controller if the register base is
> defined as the second or later memory resource in the ACPI DSDT?
> 
> The list of memory resources is queried, but only the first element is
> evaluated with list_first_entry_or_null() instead of iterating through the
> entire list with list_for_each_entry().
> 
> > +
> > +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)
> > +{
> 
> [ ... ]
> 
> > +	gc = gpio_device_get_chip(gdev);
> > +
> > +	ls2k_bmc_swnode_properties[0] = PROPERTY_ENTRY_GPIO("gpio",
> > +		gpio_chip_get_fwnode(gc), LS2K_BMC_RESET_GPIO, GPIO_ACTIVE_HIGH);
> 
> [Severity: High]
> Does this code risk a NULL pointer dereference?
> 
> gpio_device_get_chip() can return NULL if the underlying GPIO controller is
> concurrently unregistered.
> 
> Passing this potentially NULL gc pointer to gpio_chip_get_fwnode() results in
> an immediate unconditional dereference of chip->fwnode inside that function.
> 
> > +
> > +	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);
> > +}
> 
> [ ... ]
> 
> > @@ -402,44 +478,32 @@ 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 ls2k_bmc_interrupt() properly handle
> being shared?
> 
> The interrupt is requested with IRQF_SHARED, but ls2k_bmc_interrupt()
> unconditionally returns IRQ_HANDLED and schedules its work without reading
> a hardware register to verify it was the actual source of the interrupt.
> 
> When another device sharing this IRQ line fires an interrupt, wouldn't this
> erroneously reset the BMC and suppress spurious interrupt detection for the
> other devices?
> 
> > +
> > +	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;
> >  }
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7

-- 
Lee Jones