Commit b64c115e authored by Dave Airlie's avatar Dave Airlie

drm: fix race between driver loading and userspace open.

Not 100% sure this is due to BKL removal, its most likely a combination
of that + userspace timing changes in udev/plymouth. The drm adds the sysfs
device before the driver has completed internal loading, this causes udev
to make the node and plymouth to open it before we've completed loading.

The proper solution is to delay the sysfs manipulation until later in loading
however this causes knock on issues with sysfs connector nodes, so we can use
the global mutex to serialise loading and userspace opens.

Reported-by: Toni Spets (hifi on #radeon)
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 930a9e28
...@@ -164,6 +164,8 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, ...@@ -164,6 +164,8 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
dev->hose = pdev->sysdata; dev->hose = pdev->sysdata;
#endif #endif
mutex_lock(&drm_global_mutex);
if ((ret = drm_fill_in_dev(dev, ent, driver))) { if ((ret = drm_fill_in_dev(dev, ent, driver))) {
printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
goto err_g2; goto err_g2;
...@@ -199,6 +201,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, ...@@ -199,6 +201,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
driver->name, driver->major, driver->minor, driver->patchlevel, driver->name, driver->major, driver->minor, driver->patchlevel,
driver->date, pci_name(pdev), dev->primary->index); driver->date, pci_name(pdev), dev->primary->index);
mutex_unlock(&drm_global_mutex);
return 0; return 0;
err_g4: err_g4:
...@@ -210,6 +213,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, ...@@ -210,6 +213,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
pci_disable_device(pdev); pci_disable_device(pdev);
err_g1: err_g1:
kfree(dev); kfree(dev);
mutex_unlock(&drm_global_mutex);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_get_pci_dev); EXPORT_SYMBOL(drm_get_pci_dev);
......
...@@ -53,6 +53,8 @@ int drm_get_platform_dev(struct platform_device *platdev, ...@@ -53,6 +53,8 @@ int drm_get_platform_dev(struct platform_device *platdev,
dev->platformdev = platdev; dev->platformdev = platdev;
dev->dev = &platdev->dev; dev->dev = &platdev->dev;
mutex_lock(&drm_global_mutex);
ret = drm_fill_in_dev(dev, NULL, driver); ret = drm_fill_in_dev(dev, NULL, driver);
if (ret) { if (ret) {
...@@ -87,6 +89,8 @@ int drm_get_platform_dev(struct platform_device *platdev, ...@@ -87,6 +89,8 @@ int drm_get_platform_dev(struct platform_device *platdev,
list_add_tail(&dev->driver_item, &driver->device_list); list_add_tail(&dev->driver_item, &driver->device_list);
mutex_unlock(&drm_global_mutex);
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
driver->name, driver->major, driver->minor, driver->patchlevel, driver->name, driver->major, driver->minor, driver->patchlevel,
driver->date, dev->primary->index); driver->date, dev->primary->index);
...@@ -100,6 +104,7 @@ int drm_get_platform_dev(struct platform_device *platdev, ...@@ -100,6 +104,7 @@ int drm_get_platform_dev(struct platform_device *platdev,
drm_put_minor(&dev->control); drm_put_minor(&dev->control);
err_g1: err_g1:
kfree(dev); kfree(dev);
mutex_unlock(&drm_global_mutex);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_get_platform_dev); EXPORT_SYMBOL(drm_get_platform_dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment