On 2026-07-08 09:30, Alex Deucher wrote:
> On Sun, Jun 28, 2026 at 12:39 PM Geoffrey McRae <[email protected]> 
> wrote:
>>
>> DM I2C adapters can remain visible to userspace while DM teardown is
>> already in progress. A concurrent i2c-dev transfer may then enter
>> amdgpu_dm_i2c_xfer() after the backing DM state has been torn down,
>> leading to a NULL pointer dereference.
>>
>> Create a devres group around the DM I2C adapter lifetime and release it
>> at the start of dm_hw_fini(), before HPD, IRQ, and DM state are torn
>> down. This removes the I2C adapters first and waits for in-flight users
>> to drain before the structures used by amdgpu_dm_i2c_xfer() disappear.
>>
>> This fixes a teardown ordering race seen during device removal:
>>
>> BUG: kernel NULL pointer dereference
>> RIP: amdgpu_dm_i2c_xfer+0x122/0x1c0 [amdgpu]
>> Call Trace:
>> __i2c_transfer
>> i2c_transfer
>> i2cdev_ioctl_rdwr
>>
>> Fixes: 5b3eca05cfb0 ("drm/amd/display: Use devm_i2c_add_adapter to simplify 
>> i2c cleanup logic")
>> Signed-off-by: Geoffrey McRae <[email protected]>
>> Cc: Alex Deucher <[email protected]>
>> Cc: Christian König <[email protected]>
> 
> Acked-by: Alex Deucher <[email protected]>

Reviewed-by: Leo Li <[email protected]>

> 
>> ---
>>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++++++++-
>>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  7 +++++++
>>  2 files changed, 20 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> index b97ceabe6173..5613dc9903fe 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -1496,17 +1496,26 @@ static int dm_hw_init(struct amdgpu_ip_block 
>> *ip_block)
>>         struct amdgpu_device *adev = ip_block->adev;
>>         int r;
>>
>> +       adev->dm.i2c_devres_group = devres_open_group(adev->dev, NULL, 
>> GFP_KERNEL);
>> +       if (!adev->dm.i2c_devres_group)
>> +               return -ENOMEM;
>> +
>>         /* Create DAL display manager */
>>         r = amdgpu_dm_init(adev);
>>         if (r)
>> -               return r;
>> +               goto err_release_i2c;
>>         amdgpu_dm_hpd_init(adev);
>>
>>         r = dm_oem_i2c_hw_init(adev);
>>         if (r)
>>                 drm_info(adev_to_drm(adev), "Failed to add OEM i2c bus\n");
>>
>> +       devres_close_group(adev->dev, adev->dm.i2c_devres_group);
>>         return 0;
>> +
>> +err_release_i2c:
>> +       devres_release_group(adev->dev, adev->dm.i2c_devres_group);
>> +       return r;
>>  }
>>
>>  /**
>> @@ -1521,6 +1530,9 @@ static int dm_hw_fini(struct amdgpu_ip_block *ip_block)
>>  {
>>         struct amdgpu_device *adev = ip_block->adev;
>>
>> +       if (adev->dm.i2c_devres_group)
>> +               devres_release_group(adev->dev, adev->dm.i2c_devres_group);
>> +
>>         amdgpu_dm_hpd_fini(adev);
>>
>>         amdgpu_dm_irq_fini(adev);
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>> index 909ee71d6d59..13a18e1ed576 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>> @@ -688,6 +688,13 @@ struct amdgpu_display_manager {
>>          */
>>         void *bb_from_dmub;
>>
>> +       /**
>> +        * @i2c_devres_group:
>> +        *
>> +        * Devres group for DM i2c adapter lifetime management.
>> +        */
>> +       void *i2c_devres_group;
>> +
>>         /**
>>          * @oem_i2c:
>>          *
>> --
>> 2.43.0
>>

Reply via email to