Re: [PATCH 4/5] i3c: dw: Do not use OF match data as a quirk bitmask
Frank Li <[email protected]>
| Newsgroups | org.kernel.vger.stable,org.infradead.lists.linux-i3c,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <anOUqKmzMVwy1mpz@lizhi-Precision-Tower-5810> |
On Tue, Aug 04, 2026 at 10:13:00AM +0000, Akhil R wrote:
> dw_i3c_common_probe() takes the match data as a plain bitmask of quirks
> whenever the device has an ACPI companion, and as a pointer to struct
> dw_i3c_drvdata otherwise. The two are not interchangeable.
> A device that is enumerated from ACPI through the PRP0001 device ID
> matches the OF table, so device_get_match_data() returns the drvdata
> pointer of the matched entry. Casting that pointer to unsigned long
> enables whatever quirks happen to line up with its address bits, for
> instance disabling runtime PM or skipping the clock and reset setup.
>
> Look for a match in the ACPI table of the driver instead of merely
> testing for an ACPI companion, so that the match data is only read as a
> bitmask when it really came from that table. acpi_match_device() returns
> NULL when the driver has no ACPI table and when CONFIG_ACPI is disabled,
> which keeps the ast2600 driver that shares this probe on the device tree
> path.
Suggest commit message
i3c: dw: use acpi_match_device() for ACPI-specific match data
The driver uses has_acpi_companion() to decide whether to obtain quirks
from ACPI match data. However, the presence of an ACPI companion does not
guarantee that the device was matched through the ACPI ID table.
Â
When an ACPI device binds through the PRP0001 OF-compatibility mechanism,
device_get_match_data() returns a pointer to struct dw_i3c_drvdata. Since
has_acpi_companion() still returns true, the driver incorrectly casts that
pointer to an unsigned long quirk bitmask, corrupting the driver state.
Â
Use acpi_match_device() instead of has_acpi_companion() to obtain ACPI
match data. Ensure quirk bits are only retrieved when the device actually
matches an ACPI entry. acpi_match_device() also returns NULL when the
driver has no ACPI match table or when CONFIG_ACPI is disabled, preserving
the existing device tree probe path used by the AST2600 driver.
Frank
>
> Fixes: fba0e56ee752 ("i3c: dw: Disable runtime PM on Agilex5 to avoid bus hang on IBI")
> Reported-by: Sashiko AI review <[email protected]>
> Closes: https://lore.kernel.org/all/[email protected]/
> Cc: [email protected]
> Assisted-by: Cursor:claude-opus-5
> Signed-off-by: Akhil R <[email protected]>
> ---
> drivers/i3c/master/dw-i3c-master.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
> index 3816a50a52cc..17e1dd4fb5f3 100644
> --- a/drivers/i3c/master/dw-i3c-master.c
> +++ b/drivers/i3c/master/dw-i3c-master.c
> @@ -5,6 +5,7 @@
> * Author: Vitor Soares <[email protected]>
> */
>
> +#include <linux/acpi.h>
> #include <linux/bitfield.h>
> #include <linux/bitops.h>
> #include <linux/cleanup.h>
> @@ -1610,6 +1611,7 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
> {
> int ret, irq;
> u32 thld_ctrl;
> + const struct acpi_device_id *acpi_id;
> const struct dw_i3c_drvdata *drvdata;
> unsigned long quirks = 0;
>
> @@ -1618,9 +1620,10 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
>
> master->dev = &pdev->dev;
>
> - if (has_acpi_companion(&pdev->dev)) {
> - quirks = (unsigned long)device_get_match_data(&pdev->dev);
> - } else if (pdev->dev.of_node) {
> + acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
> + if (acpi_id) {
> + quirks = acpi_id->driver_data;
> + } else {
> drvdata = device_get_match_data(&pdev->dev);
> if (drvdata)
> quirks = drvdata->flags;
> --
> 2.43.0
>