aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2010-07-29 16:48:21 +0100
committerJohn Rigby <john.rigby@linaro.org>2011-03-16 15:49:00 -0600
commit8369a88a32b95e53e9540b72dc011438afa3344c (patch)
tree8bdcffd05c933757ea15e5c7e817754daf559dc8 /drivers
parent9924bc680cbda55c159bac4af45c49c4811c4b5c (diff)
UBUNTU: SAUCE: drm -- stop early access to drm devices
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@canonical.com> Acked-by: Stefan Bader <stefan.bader@canonical.com> Signed-off-by: Leann Ogasawara <leann.ogasawara@canonical.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_fops.c8
-rw-r--r--drivers/gpu/drm/drm_pci.c4
-rw-r--r--drivers/gpu/drm/drm_platform.c4
-rw-r--r--drivers/gpu/drm/drm_stub.c2
4 files changed, 15 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 2ec7d48fc4a8..fbd640dbf7ed 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -128,7 +128,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;
@@ -176,7 +177,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_pci.c b/drivers/gpu/drm/drm_pci.c
index f5bd9e590c80..985ef5540818 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -197,6 +197,10 @@ int drm_get_pci_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);
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c
index 92d1d0fb7b75..8cb3e40cd054 100644
--- a/drivers/gpu/drm/drm_platform.c
+++ b/drivers/gpu/drm/drm_platform.c
@@ -89,6 +89,10 @@ int drm_get_platform_dev(struct platform_device *platdev,
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);
+
mutex_unlock(&drm_global_mutex);
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index d59edc18301f..cb0f55b437d4 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -346,7 +346,7 @@ int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
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);