drm/i915: get the bridge device once.
authorDave Airlie <airlied@redhat.com>
Tue, 4 Aug 2009 01:43:41 +0000 (11:43 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 8 Sep 2009 01:45:15 +0000 (11:45 +1000)
The driver gets the bridge device in a number of places, upcoming
vga arb code paths need the bridge device, however they need it in
under a lock, and the pci lookup can allocate memory. So clean
this code up before then and get the bridge once for the driver lifetime.

Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_tiling.c

index 91ef4c1..9909505 100644 (file)
@@ -898,6 +898,18 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
        return 0;
 }
 
+static int i915_get_bridge_dev(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+       if (!dev_priv->bridge_dev) {
+               DRM_ERROR("bridge device not found\n");
+               return -1;
+       }
+       return 0;
+}
+
 /**
  * i915_probe_agp - get AGP bootup configuration
  * @pdev: PCI device
@@ -911,20 +923,13 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
 static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
                          uint32_t *preallocated_size)
 {
-       struct pci_dev *bridge_dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        u16 tmp = 0;
        unsigned long overhead;
        unsigned long stolen;
 
-       bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
-       if (!bridge_dev) {
-               DRM_ERROR("bridge device not found\n");
-               return -1;
-       }
-
        /* Get the fb aperture size and "stolen" memory amount. */
-       pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
-       pci_dev_put(bridge_dev);
+       pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &tmp);
 
        *aperture_size = 1024 * 1024;
        *preallocated_size = 1024 * 1024;
@@ -1176,11 +1181,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        base = drm_get_resource_start(dev, mmio_bar);
        size = drm_get_resource_len(dev, mmio_bar);
 
+       if (i915_get_bridge_dev(dev)) {
+               ret = -EIO;
+               goto free_priv;
+       }
+
        dev_priv->regs = ioremap(base, size);
        if (!dev_priv->regs) {
                DRM_ERROR("failed to map registers\n");
                ret = -EIO;
-               goto free_priv;
+               goto put_bridge;
        }
 
         dev_priv->mm.gtt_mapping =
@@ -1292,6 +1302,8 @@ out_iomapfree:
        io_mapping_free(dev_priv->mm.gtt_mapping);
 out_rmmap:
        iounmap(dev_priv->regs);
+put_bridge:
+       pci_dev_put(dev_priv->bridge_dev);
 free_priv:
        kfree(dev_priv);
        return ret;
@@ -1335,6 +1347,7 @@ int i915_driver_unload(struct drm_device *dev)
                i915_gem_lastclose(dev);
        }
 
+       pci_dev_put(dev_priv->bridge_dev);
        kfree(dev->dev_private);
 
        return 0;
index 2d5bce6..77ed060 100644 (file)
@@ -155,6 +155,7 @@ typedef struct drm_i915_private {
 
        void __iomem *regs;
 
+       struct pci_dev *bridge_dev;
        drm_i915_ring_buffer_t ring;
 
        drm_dma_handle_t *status_page_dmah;
index e774a4a..200e398 100644 (file)
 static int
 intel_alloc_mchbar_resource(struct drm_device *dev)
 {
-       struct pci_dev *bridge_dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
        u32 temp_lo, temp_hi = 0;
        u64 mchbar_addr;
        int ret = 0;
 
-       bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
-       if (!bridge_dev) {
-               DRM_DEBUG("no bridge dev?!\n");
-               ret = -ENODEV;
-               goto out;
-       }
-
        if (IS_I965G(dev))
-               pci_read_config_dword(bridge_dev, reg + 4, &temp_hi);
-       pci_read_config_dword(bridge_dev, reg, &temp_lo);
+               pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
+       pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
        mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
 
        /* If ACPI doesn't have it, assume we need to allocate it ourselves */
@@ -118,30 +110,28 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
        if (mchbar_addr &&
            pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
                ret = 0;
-               goto out_put;
+               goto out;
        }
 #endif
 
        /* Get some space for it */
-       ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
+       ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
                                     MCHBAR_SIZE, MCHBAR_SIZE,
                                     PCIBIOS_MIN_MEM,
                                     0,   pcibios_align_resource,
-                                    bridge_dev);
+                                    dev_priv->bridge_dev);
        if (ret) {
                DRM_DEBUG("failed bus alloc: %d\n", ret);
                dev_priv->mch_res.start = 0;
-               goto out_put;
+               goto out;
        }
 
        if (IS_I965G(dev))
-               pci_write_config_dword(bridge_dev, reg + 4,
+               pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
                                       upper_32_bits(dev_priv->mch_res.start));
 
-       pci_write_config_dword(bridge_dev, reg,
+       pci_write_config_dword(dev_priv->bridge_dev, reg,
                               lower_32_bits(dev_priv->mch_res.start));
-out_put:
-       pci_dev_put(bridge_dev);
 out:
        return ret;
 }
@@ -150,44 +140,36 @@ out:
 static bool
 intel_setup_mchbar(struct drm_device *dev)
 {
-       struct pci_dev *bridge_dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
        int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
        u32 temp;
        bool need_disable = false, enabled;
 
-       bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
-       if (!bridge_dev) {
-               DRM_DEBUG("no bridge dev?!\n");
-               goto out;
-       }
-
        if (IS_I915G(dev) || IS_I915GM(dev)) {
-               pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
+               pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
                enabled = !!(temp & DEVEN_MCHBAR_EN);
        } else {
-               pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
+               pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
                enabled = temp & 1;
        }
 
        /* If it's already enabled, don't have to do anything */
        if (enabled)
-               goto out_put;
+               goto out;
 
        if (intel_alloc_mchbar_resource(dev))
-               goto out_put;
+               goto out;
 
        need_disable = true;
 
        /* Space is allocated or reserved, so enable it. */
        if (IS_I915G(dev) || IS_I915GM(dev)) {
-               pci_write_config_dword(bridge_dev, DEVEN_REG,
+               pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
                                       temp | DEVEN_MCHBAR_EN);
        } else {
-               pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
-               pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
+               pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
+               pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
        }
-out_put:
-       pci_dev_put(bridge_dev);
 out:
        return need_disable;
 }
@@ -196,25 +178,18 @@ static void
 intel_teardown_mchbar(struct drm_device *dev, bool disable)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct pci_dev *bridge_dev;
        int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
        u32 temp;
 
-       bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
-       if (!bridge_dev) {
-               DRM_DEBUG("no bridge dev?!\n");
-               return;
-       }
-
        if (disable) {
                if (IS_I915G(dev) || IS_I915GM(dev)) {
-                       pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
+                       pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
                        temp &= ~DEVEN_MCHBAR_EN;
-                       pci_write_config_dword(bridge_dev, DEVEN_REG, temp);
+                       pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
                } else {
-                       pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
+                       pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
                        temp &= ~1;
-                       pci_write_config_dword(bridge_dev, mchbar_reg, temp);
+                       pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
                }
        }