To be able to directly set up the intel-gtt code from drm/i915 and
avoid setting up the fake-agp driver we need to prepare a few things:
- pass both the bridge and gpu pci_dev to the probe function and add
  code to handle the gpu pdev both being present (for drm/i915) and
  not present (fake agp).
- add refcounting to the remove function so that unloading drm/i915
  doesn't kill the fake agp driver

Signed-Off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/char/agp/intel-agp.c    |    5 +++--
 drivers/char/agp/intel-agp.h    |    3 ---
 drivers/char/agp/intel-gtt.c    |   38 ++++++++++++++++++++++++++++++--------
 drivers/gpu/drm/i915/i915_dma.c |   13 +++++++++++--
 include/drm/intel-gtt.h         |    4 ++++
 5 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 764f70c..c98c568 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -12,6 +12,7 @@
 #include <asm/smp.h>
 #include "agp.h"
 #include "intel-agp.h"
+#include <drm/intel-gtt.h>

 int intel_agp_enabled;
 EXPORT_SYMBOL(intel_agp_enabled);
@@ -747,7 +748,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,

        bridge->capndx = cap_ptr;

-       if (intel_gmch_probe(pdev, bridge))
+       if (intel_gmch_probe(pdev, NULL, bridge))
                goto found_gmch;

        for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
@@ -824,7 +825,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)

        agp_remove_bridge(bridge);

-       intel_gmch_remove(pdev);
+       intel_gmch_remove();

        agp_put_bridge(bridge);
 }
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index c009175..cf2e764 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -250,7 +250,4 @@
 #define PCI_DEVICE_ID_INTEL_HASWELL_SDV                0x0c16 /* SDV */
 #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB                       0x0c04

-int intel_gmch_probe(struct pci_dev *pdev,
-                              struct agp_bridge_data *bridge);
-void intel_gmch_remove(struct pci_dev *pdev);
 #endif
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 5e6c89e..6499290 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -75,6 +75,7 @@ static struct _intel_private {
        struct resource ifp_resource;
        int resource_valid;
        struct page *scratch_page;
+       int refcount;
 } intel_private;

 #define INTEL_GTT_GEN  intel_private.driver->gen
@@ -1522,14 +1523,32 @@ static int find_gmch(u16 device)
        return 1;
 }

-int intel_gmch_probe(struct pci_dev *pdev,
-                                     struct agp_bridge_data *bridge)
+int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
+                    struct agp_bridge_data *bridge)
 {
        int i, mask;
-       intel_private.driver = NULL;
+
+       /*
+        * Can be called from the fake agp driver but also directly from
+        * drm/i915.ko. Hence we need to check whether everything is set up
+        * already.
+        */
+       if (intel_private.driver) {
+               intel_private.refcount++;
+               return 1;
+       }

        for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) {
-               if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
+               if (gpu_pdev) {
+                       if (gpu_pdev->device ==
+                           intel_gtt_chipsets[i].gmch_chip_id) {
+                               intel_private.pcidev = pci_dev_get(gpu_pdev);
+                               intel_private.driver =
+                                       intel_gtt_chipsets[i].gtt_driver;
+
+                               break;
+                       }
+               } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
                        intel_private.driver =
                                intel_gtt_chipsets[i].gtt_driver;
                        break;
@@ -1542,12 +1561,12 @@ int intel_gmch_probe(struct pci_dev *pdev,
        if (bridge) {
                bridge->driver = &intel_fake_agp_driver;
                bridge->dev_private_data = &intel_private;
-               bridge->dev = pdev;
+               bridge->dev = bridge_pdev;
        }

-       intel_private.bridge_dev = pci_dev_get(pdev);
+       intel_private.bridge_dev = pci_dev_get(bridge_pdev);

-       dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name);
+       dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", 
intel_gtt_chipsets[i].name);

        mask = intel_private.driver->dma_mask_size;
        if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
@@ -1577,8 +1596,11 @@ void intel_gtt_chipset_flush(void)
 }
 EXPORT_SYMBOL(intel_gtt_chipset_flush);

-void intel_gmch_remove(struct pci_dev *pdev)
+void intel_gmch_remove(void)
 {
+       if (--intel_private.refcount)
+               return;
+
        if (intel_private.pcidev)
                pci_dev_put(intel_private.pcidev);
        if (intel_private.bridge_dev)
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 0ab5d3d..29aee99 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1486,11 +1486,18 @@ int i915_driver_load(struct drm_device *dev, unsigned 
long flags)
                goto put_bridge;
        }

+       ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL);
+       if (!ret) {
+               DRM_ERROR("failed to set up gmch\n");
+               ret = -EIO;
+               goto out_rmmap;
+       }
+
        dev_priv->mm.gtt = intel_gtt_get();
        if (!dev_priv->mm.gtt) {
                DRM_ERROR("Failed to initialize GTT\n");
                ret = -ENODEV;
-               goto out_rmmap;
+               goto put_gmch;
        }

        aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
@@ -1501,7 +1508,7 @@ int i915_driver_load(struct drm_device *dev, unsigned 
long flags)
                                     aperture_size);
        if (dev_priv->mm.gtt_mapping == NULL) {
                ret = -EIO;
-               goto out_rmmap;
+               goto put_gmch;
        }

        i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr,
@@ -1623,6 +1630,8 @@ out_mtrrfree:
                dev_priv->mm.gtt_mtrr = -1;
        }
        io_mapping_free(dev_priv->mm.gtt_mapping);
+put_gmch:
+       intel_gmch_remove();
 out_rmmap:
        pci_iounmap(dev->pdev, dev_priv->regs);
 put_bridge:
diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h
index 8048c00..84ebd71 100644
--- a/include/drm/intel-gtt.h
+++ b/include/drm/intel-gtt.h
@@ -23,6 +23,10 @@ const struct intel_gtt {
        phys_addr_t gma_bus_addr;
 } *intel_gtt_get(void);

+int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
+                    struct agp_bridge_data *bridge);
+void intel_gmch_remove(void);
+
 void intel_gtt_chipset_flush(void);
 void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg);
 void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries);
-- 
1.7.7.6

Reply via email to