From patchwork Thu Jul 29 15:33:37 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Whitcroft X-Patchwork-Id: 86135 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 1A672B6F81 for ; Thu, 10 Mar 2011 04:28:14 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1PxNB3-0002qs-H4; Wed, 09 Mar 2011 17:28:01 +0000 Received: from adelie.canonical.com ([91.189.90.139]) by chlorine.canonical.com with esmtp (Exim 4.69) (envelope-from ) id 1OeV75-0004q6-5E for kernel-team@lists.ubuntu.com; Thu, 29 Jul 2010 16:33:39 +0100 Received: from hutte.canonical.com ([91.189.90.181]) by adelie.canonical.com with esmtp (Exim 4.69 #1 (Debian)) id 1OeV75-000538-3H for ; Thu, 29 Jul 2010 16:33:39 +0100 Received: from [85.210.148.55] (helo=localhost.localdomain) by hutte.canonical.com with esmtpsa (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1OeV74-0007xr-Tk for kernel-team@lists.ubuntu.com; Thu, 29 Jul 2010 16:33:39 +0100 From: Andy Whitcroft To: kernel-team@lists.ubuntu.com Subject: [PATCH 2/2] UBUNTU: SAUCE: drm -- stop early access to drm devices Date: Thu, 29 Jul 2010 16:33:37 +0100 Message-Id: <1280417617-8906-3-git-send-email-apw@canonical.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1280417617-8906-1-git-send-email-apw@canonical.com> References: <1280417617-8906-1-git-send-email-apw@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com 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 --- 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);