[PATCH 2/2] UBUNTU: SAUCE: drm -- stop early access to drm devices

Stefan Bader stefan.bader at canonical.com
Thu Jul 29 15:57:51 UTC 2010


Seems ok.

Acked-by: Stefan Bader <stefan.bader at canonical.com>

On 07/29/2010 05:48 PM, Andy Whitcroft wrote:
> When a drm driver is initialised we first allocate and initialise the
> drm minor numbers including creating the sysfs files, then we trigger
> the driver load method.  The act of creating the sysfs files triggers the
> uevent.  This means udev may start programs which open /dev/dri/card0 and
> other interfaces, this can occur before the load method has even started
> and thus before the driver has fully initialised its data structures.
> In the case of plymouthd this leads to it opening and closing (in disgust)
> the interface, which in turn leads to a kernel panic as the mutexes are
> yet to be initialised.
> 
> This patch delays the linking up of the drm devices minor numbers until
> the driver is fully initialised.  As it is possible for consumers of
> these interfaces to reach them before they are fully initialised we
> arrange for opens of these devices to return EAGAIN until the device is
> fully initialised.
> 
> Signed-off-by: Andy Whitcroft <apw at canonical.com>
> ---
>  drivers/gpu/drm/drm_fops.c |    8 ++++++--
>  drivers/gpu/drm/drm_stub.c |    6 +++++-
>  2 files changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index e7aace2..3bd5552 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -125,7 +125,8 @@ int drm_open(struct inode *inode, struct file *filp)
>  	minor = idr_find(&drm_minors_idr, minor_id);
>  	if (!minor)
>  		return -ENODEV;
> -
> +	if (IS_ERR(minor))
> +		return PTR_ERR(minor);
>  	if (!(dev = minor->dev))
>  		return -ENODEV;
>  
> @@ -180,7 +181,10 @@ int drm_stub_open(struct inode *inode, struct file *filp)
>  	minor = idr_find(&drm_minors_idr, minor_id);
>  	if (!minor)
>  		goto out;
> -
> +	if (IS_ERR(minor)) {
> +		err = PTR_ERR(minor);
> +		goto out;
> +	}
>  	if (!(dev = minor->dev))
>  		goto out;
>  
> diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
> index a0c365f..1110c37 100644
> --- a/drivers/gpu/drm/drm_stub.c
> +++ b/drivers/gpu/drm/drm_stub.c
> @@ -345,7 +345,7 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
>  	new_minor->index = minor_id;
>  	INIT_LIST_HEAD(&new_minor->master_list);
>  
> -	idr_replace(&drm_minors_idr, new_minor, minor_id);
> +	idr_replace(&drm_minors_idr, ERR_PTR(-EAGAIN), minor_id);
>  
>  	if (type == DRM_MINOR_LEGACY) {
>  		ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
> @@ -445,6 +445,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
>  
>  	list_add_tail(&dev->driver_item, &driver->device_list);
>  
> +	if (drm_core_check_feature(dev, DRIVER_MODESET))
> +		idr_replace(&drm_minors_idr, dev->control, dev->control->index);
> +	idr_replace(&drm_minors_idr, dev->primary, dev->primary->index);
> +
>  	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
>  		 driver->name, driver->major, driver->minor, driver->patchlevel,
>  		 driver->date, pci_name(pdev), dev->primary->index);





More information about the kernel-team mailing list