From patchwork Tue Jun 21 08:53:46 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 9189871 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B1F766075A for ; Tue, 21 Jun 2016 08:54:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A049827F7F for ; Tue, 21 Jun 2016 08:54:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9435827FA7; Tue, 21 Jun 2016 08:54:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D2D4127F7F for ; Tue, 21 Jun 2016 08:54:28 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8A92A6E64C; Tue, 21 Jun 2016 08:54:27 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-lf0-x241.google.com (mail-lf0-x241.google.com [IPv6:2a00:1450:4010:c07::241]) by gabe.freedesktop.org (Postfix) with ESMTPS id C1E856E653 for ; Tue, 21 Jun 2016 08:54:08 +0000 (UTC) Received: by mail-lf0-x241.google.com with SMTP id a2so1953253lfe.3 for ; Tue, 21 Jun 2016 01:54:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=c+XWAXcSzqjTgdcVltYOJ6NSFMbwkdFzcZ4HHBhuTYs=; b=OkXoI0sMzGYnYpNFrX6UpgghYv/4PMO2ic9MOv6sxFf1KsGL1Hb0CSUJ9HKqcooqCB fC/7UIV66wrB9nDOkBcTjKuYOplD7peSkCJ9/0cKP0VKbikJTYWDilSyFC3MrIsOXFUp GxW7xIAQ5d7B7SmXGSFUwrGEDWOs1YNVwV0wy3RzEDdzoDcZ4wWM8eUJUyXW49kDnwLQ cF0J+jofbbvQs/i/KSi63160r2r82PMApd45+qmpdNF8v7XBNwwL7Xfk2lIpHe9ZG4bA iGVF66P7gohoZXktgEULIgsxIuDIjBl6iSwcUEJV/K1c7ZdRhzJrds5IFkhUxOZoQZB3 IL7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=c+XWAXcSzqjTgdcVltYOJ6NSFMbwkdFzcZ4HHBhuTYs=; b=XYpCtAkEDfS/sQPZ51R+eOnWPNO0gy9gy2DFEpmNRBCpGXr17STHrutOTc3V3SZAYM 2JoFPpLTd9Qvwbjy/9IPC7jczrH0fFFH0D47nfsXFNIo7j8WBaTKOS01zMDX5gcT7GEh KkoP0kJFuT7ZIaw6ARpM3IwTf89eVRyXLoH6JqpEaYIdFFtkE9sBwAtuCAbEZXnilFmR sNoHY9RxnEzrGY5DyI3sBid4tuWcDOXfTRoFcYRlyw8CI1Vobw8qr0AQwZlLRHAlfBmz mxE5FQ3scZdsktm/gyMiKWckzNznTtpmiXEdGzHXWZdujDv3DJpWcRfapzziIEW0vdnb 8brg== X-Gm-Message-State: ALyK8tL9Xc7LlxaeLkgFeoiqJATh1VE69trmqYNPiBKqNE8YXnUwQjg7PG6JSvZWLP/kXA== X-Received: by 10.28.104.214 with SMTP id d205mr2101539wmc.102.1466499246668; Tue, 21 Jun 2016 01:54:06 -0700 (PDT) Received: from haswell.alporthouse.com ([78.156.65.138]) by smtp.gmail.com with ESMTPSA id k3sm29143351wju.29.2016.06.21.01.54.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Jun 2016 01:54:05 -0700 (PDT) From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Tue, 21 Jun 2016 09:53:46 +0100 Message-Id: <1466499228-30290-7-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.8.1 In-Reply-To: <1466499228-30290-1-git-send-email-chris@chris-wilson.co.uk> References: <1466499228-30290-1-git-send-email-chris@chris-wilson.co.uk> MIME-Version: 1.0 Cc: Daniel Vetter Subject: [Intel-gfx] [PATCH 6/8] drm/i915: Demidlayer driver loading X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Take control over allocating, loading and registering the driver from the DRM midlayer by performing it manually from i915_pci_probe. This allows us to carefully control the order of when we setup the hardware vs when it becomes visible to third parties (including userspace). The current ordering makes the driver visible to userspace first (in order to coordinate with removed DRI1 userspace), but that ordering incurs risk. The risk increases as we strive for more asynchronous loading. One side effect of controlling the allocation is that we can allocate both the drm_device + drm_i915_private in one block, the next step towards subclassing. Unload is still left as before, a mix of midlayer and driver. v2: After drm_dev_init(), we should call drm_dev_unref() so that we call drm_dev_release() and free everything from drm_dev_init(). Suggested-by: Daniel Vetter Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Ville Syrjälä --- drivers/gpu/drm/i915/i915_dma.c | 76 ++++++++++++++++++++++++++--------------- drivers/gpu/drm/i915/i915_drv.c | 3 +- drivers/gpu/drm/i915/i915_drv.h | 6 +++- 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 91623874f9a3..0e43ad511833 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1075,9 +1075,10 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) * function hooks not requiring accessing the device. */ static int i915_driver_init_early(struct drm_i915_private *dev_priv, - struct drm_device *dev, - struct intel_device_info *info) + const struct pci_device_id *ent) { + const struct intel_device_info *match_info = + (struct intel_device_info *)ent->driver_data; struct intel_device_info *device_info; int ret = 0; @@ -1086,8 +1087,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, /* Setup the write-once "constant" device info */ device_info = (struct intel_device_info *)&dev_priv->info; - memcpy(device_info, info, sizeof(dev_priv->info)); - device_info->device_id = dev->pdev->device; + memcpy(device_info, match_info, sizeof(*device_info)); + device_info->device_id = dev_priv->drm.pdev->device; BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE); device_info->gen_mask = BIT(device_info->gen - 1); @@ -1113,18 +1114,18 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, goto err_workqueues; /* This must be called before any calls to HAS_PCH_* */ - intel_detect_pch(dev); + intel_detect_pch(&dev_priv->drm); - intel_pm_setup(dev); + intel_pm_setup(&dev_priv->drm); intel_init_dpio(dev_priv); intel_power_domains_init(dev_priv); intel_irq_init(dev_priv); intel_init_display_hooks(dev_priv); intel_init_clock_gating_hooks(dev_priv); intel_init_audio_hooks(dev_priv); - i915_gem_load_init(dev); + i915_gem_load_init(&dev_priv->drm); - intel_display_crc_init(dev); + intel_display_crc_init(&dev_priv->drm); i915_dump_device_info(dev_priv); @@ -1132,7 +1133,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, * very first ones. Almost everything should work, except for maybe * suspend/resume. And we don't implement workarounds that affect only * pre-production machines. */ - if (IS_HSW_EARLY_SDV(dev)) + if (IS_HSW_EARLY_SDV(dev_priv)) DRM_INFO("This is an early pre-production Haswell machine. " "It may not be fully functional.\n"); @@ -1390,6 +1391,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; i915_gem_shrinker_init(dev_priv); + /* * Notify a valid surface after modesetting, * when running inside a VM. @@ -1397,9 +1399,13 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) if (intel_vgpu_active(dev_priv)) I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY); - i915_debugfs_register(dev_priv); - i915_setup_sysfs(dev); - intel_modeset_register(dev_priv); + /* Reveal our presence to userspace */ + if (drm_dev_register(dev, 0) == 0) { + i915_debugfs_register(dev_priv); + i915_setup_sysfs(dev); + intel_modeset_register(dev_priv); + } else + DRM_ERROR("Failed to register driver for userspace access!\n"); if (INTEL_INFO(dev_priv)->num_pipes) { /* Must be done after probing outputs */ @@ -1449,24 +1455,38 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) * - allocate initial config memory * - setup the DRM framebuffer with the allocated memory */ -int i915_driver_load(struct drm_device *dev, unsigned long flags) +int i915_driver_load(struct pci_dev *pdev, + const struct pci_device_id *ent, + struct drm_driver *driver) { struct drm_i915_private *dev_priv; - int ret = 0; + int ret; + ret = 0; dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); - if (dev_priv == NULL) + if (dev_priv) + ret = drm_dev_init(&dev_priv->drm, driver, &pdev->dev); + if (ret) { + dev_printk(KERN_ERR, &pdev->dev, + "[" DRM_NAME ":%s] allocation failed\n", __func__); + kfree(dev_priv); return -ENOMEM; + } - dev->dev_private = dev_priv; /* Must be set before calling __i915_printk */ - dev_priv->dev = dev; + dev_priv->drm.pdev = pdev; + dev_priv->drm.dev_private = dev_priv; + dev_priv->dev = &dev_priv->drm; - ret = i915_driver_init_early(dev_priv, dev, - (struct intel_device_info *)flags); + ret = pci_enable_device(pdev); + if (ret) + goto out_free_priv; + pci_set_drvdata(pdev, &dev_priv->drm); + + ret = i915_driver_init_early(dev_priv, ent); if (ret < 0) - goto out_free_priv; + goto out_pci_disable; intel_runtime_pm_get(dev_priv); @@ -1483,13 +1503,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) * of the i915_driver_init_/i915_driver_register functions according * to the role/effect of the given init step. */ - if (INTEL_INFO(dev)->num_pipes) { - ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes); + if (INTEL_INFO(dev_priv)->num_pipes) { + ret = drm_vblank_init(dev_priv->dev, + INTEL_INFO(dev_priv)->num_pipes); if (ret) goto out_cleanup_hw; } - ret = i915_load_modeset_init(dev); + ret = i915_load_modeset_init(dev_priv->dev); if (ret < 0) goto out_cleanup_vblank; @@ -1502,7 +1523,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return 0; out_cleanup_vblank: - drm_vblank_cleanup(dev); + drm_vblank_cleanup(dev_priv->dev); out_cleanup_hw: i915_driver_cleanup_hw(dev_priv); out_cleanup_mmio: @@ -1510,11 +1531,11 @@ out_cleanup_mmio: out_runtime_pm_put: intel_runtime_pm_put(dev_priv); i915_driver_cleanup_early(dev_priv); +out_pci_disable: + pci_disable_device(pdev); out_free_priv: i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret); - - kfree(dev_priv); - + drm_dev_unref(&dev_priv->drm); return ret; } @@ -1579,7 +1600,6 @@ int i915_driver_unload(struct drm_device *dev) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); i915_driver_cleanup_early(dev_priv); - kfree(dev_priv); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3ea09bd83a5a..1a335e1a8b62 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1034,7 +1034,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (vga_switcheroo_client_probe_defer(pdev)) return -EPROBE_DEFER; - return drm_get_pci_dev(pdev, ent, &driver); + return i915_driver_load(pdev, ent, &driver); } static void @@ -1748,7 +1748,6 @@ static struct drm_driver driver = { .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_MODESET, - .load = i915_driver_load, .unload = i915_driver_unload, .open = i915_driver_open, .lastclose = i915_driver_lastclose, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 44e6715d8b1d..20a82b6a050d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1732,6 +1732,8 @@ struct intel_wm_config { }; struct drm_i915_private { + struct drm_device drm; + struct drm_device *dev; struct kmem_cache *objects; struct kmem_cache *vmas; @@ -2902,7 +2904,9 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, #define i915_report_error(dev_priv, fmt, ...) \ __i915_printk(dev_priv, KERN_ERR, fmt, ##__VA_ARGS__) -extern int i915_driver_load(struct drm_device *, unsigned long flags); +extern int i915_driver_load(struct pci_dev *pdev, + const struct pci_device_id *ent, + struct drm_driver *driver); extern int i915_driver_unload(struct drm_device *); extern int i915_driver_open(struct drm_device *dev, struct drm_file *file); extern void i915_driver_lastclose(struct drm_device * dev);