On Tue May 12, 2026 at 1:59 PM CEST, Bartosz Golaszewski wrote:
> diff --git a/drivers/gpu/drm/xe/xe_i2c.c b/drivers/gpu/drm/xe/xe_i2c.c
> index 
> 706783863d07d66b4685005d6649b3cd143ecc3b..7f4295e7dc74f112abff8427485b5c8a5ad71383
>  100644
> --- a/drivers/gpu/drm/xe/xe_i2c.c
> +++ b/drivers/gpu/drm/xe/xe_i2c.c
> @@ -53,6 +53,10 @@ static const struct property_entry 
> xe_i2c_adapter_properties[] = {
>       { }
>  };
>  
> +static const struct software_node xe_i2c_adapter_swnode = {
> +     .properties = xe_i2c_adapter_properties,
> +};
> +
>  static inline void xe_i2c_read_endpoint(struct xe_mmio *mmio, void *ep)
>  {
>       u32 *val = ep;
> @@ -96,10 +100,6 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c)
>       struct fwnode_handle *fwnode;
>       int ret;
>  
> -     fwnode = fwnode_create_software_node(xe_i2c_adapter_properties, NULL);
> -     if (IS_ERR(fwnode))
> -             return PTR_ERR(fwnode);
> -
>       /*
>        * Not using platform_device_register_full() here because we don't have
>        * a handle to the platform_device before it returns. xe_i2c_notifier()
> @@ -107,10 +107,12 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c)
>        * platform_device_register_full() is done.
>        */
>       pdev = platform_device_alloc(adapter_name, pci_dev_id(pci));
> -     if (!pdev) {
> -             ret = -ENOMEM;
> -             goto err_fwnode_remove;
> -     }
> +     if (!pdev)
> +             return -ENOMEM;
> +
> +     ret = platform_device_add_software_node(pdev, &xe_i2c_adapter_swnode);

By calling platform_device_add_software_node() the platform device technically
takes ownership of the struct software_node managing its lifetime, by removing
it in release().

However, this is not properly reflected by the
platform_device_add_software_node() API, as it just stores the pointer given by
the driver, which in this case is a pointer to module memory.

The platform device is reference counted and can outlive the module.

So, I think analogous to platform_device_add_data() we need to make a copy of
the struct software_node in platform_device_add_software_node().

> +     if (ret)
> +             goto err_pdev_put;
>  
>       if (i2c->adapter_irq) {
>               struct resource res;
> @@ -123,7 +125,6 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c)
>       }
>  
>       pdev->dev.parent = i2c->drm_dev;
> -     pdev->dev.fwnode = fwnode;
>       i2c->adapter_node = fwnode;
>       i2c->pdev = pdev;
>  
> @@ -135,8 +136,6 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c)
>  
>  err_pdev_put:
>       platform_device_put(pdev);
> -err_fwnode_remove:
> -     fwnode_remove_software_node(fwnode);

There is another call to this in  xe_i2c_unregister_adapter(), which I think was
missed.

Reply via email to