[PATCH 08/12] drm/i915 + agp/intel-gtt: prep work for direct setup

Daniel Vetter daniel.vetter at ffwll.ch
Thu Jun 7 06:56:00 PDT 2012


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



More information about the dri-devel mailing list