Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14be93dd authored by Daniel Vetter's avatar Daniel Vetter
Browse files

drm/i915 + agp/intel-gtt: prep work for direct setup



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

v2: Fix up the cleanup and refcount, noticed by Jani Nikula.

Reviewed-by: default avatarJani Nikula <jani.nikula@linux.intel.com>
Signed-Off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 7e8f6306
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -12,6 +12,7 @@
#include <asm/smp.h>
#include <asm/smp.h>
#include "agp.h"
#include "agp.h"
#include "intel-agp.h"
#include "intel-agp.h"
#include <drm/intel-gtt.h>


int intel_agp_enabled;
int intel_agp_enabled;
EXPORT_SYMBOL(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;
	bridge->capndx = cap_ptr;


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


	for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
	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);
	agp_remove_bridge(bridge);


	intel_gmch_remove(pdev);
	intel_gmch_remove();


	agp_put_bridge(bridge);
	agp_put_bridge(bridge);
}
}
+0 −3
Original line number Original line Diff line number Diff line
@@ -250,7 +250,4 @@
#define PCI_DEVICE_ID_INTEL_HASWELL_SDV		0x0c16 /* SDV */
#define PCI_DEVICE_ID_INTEL_HASWELL_SDV		0x0c16 /* SDV */
#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB			0x0c04
#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
#endif
+37 −9
Original line number Original line Diff line number Diff line
@@ -75,6 +75,7 @@ static struct _intel_private {
	struct resource ifp_resource;
	struct resource ifp_resource;
	int resource_valid;
	int resource_valid;
	struct page *scratch_page;
	struct page *scratch_page;
	int refcount;
} intel_private;
} intel_private;


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


int intel_gmch_probe(struct pci_dev *pdev,
int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
		     struct agp_bridge_data *bridge)
		     struct agp_bridge_data *bridge)
{
{
	int i, mask;
	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++) {
	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_private.driver =
				intel_gtt_chipsets[i].gtt_driver;
				intel_gtt_chipsets[i].gtt_driver;
			break;
			break;
@@ -1539,15 +1558,17 @@ int intel_gmch_probe(struct pci_dev *pdev,
	if (!intel_private.driver)
	if (!intel_private.driver)
		return 0;
		return 0;


	intel_private.refcount++;

	if (bridge) {
	if (bridge) {
		bridge->driver = &intel_fake_agp_driver;
		bridge->driver = &intel_fake_agp_driver;
		bridge->dev_private_data = &intel_private;
		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;
	mask = intel_private.driver->dma_mask_size;
	if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
	if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
@@ -1557,8 +1578,11 @@ int intel_gmch_probe(struct pci_dev *pdev,
		pci_set_consistent_dma_mask(intel_private.pcidev,
		pci_set_consistent_dma_mask(intel_private.pcidev,
					    DMA_BIT_MASK(mask));
					    DMA_BIT_MASK(mask));


	if (intel_gtt_init() != 0)
	if (intel_gtt_init() != 0) {
		intel_gmch_remove();

		return 0;
		return 0;
	}


	return 1;
	return 1;
}
}
@@ -1577,12 +1601,16 @@ void intel_gtt_chipset_flush(void)
}
}
EXPORT_SYMBOL(intel_gtt_chipset_flush);
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)
	if (intel_private.pcidev)
		pci_dev_put(intel_private.pcidev);
		pci_dev_put(intel_private.pcidev);
	if (intel_private.bridge_dev)
	if (intel_private.bridge_dev)
		pci_dev_put(intel_private.bridge_dev);
		pci_dev_put(intel_private.bridge_dev);
	intel_private.driver = NULL;
}
}
EXPORT_SYMBOL(intel_gmch_remove);
EXPORT_SYMBOL(intel_gmch_remove);


+11 −2
Original line number Original line Diff line number Diff line
@@ -1474,11 +1474,18 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
		goto put_bridge;
		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();
	dev_priv->mm.gtt = intel_gtt_get();
	if (!dev_priv->mm.gtt) {
	if (!dev_priv->mm.gtt) {
		DRM_ERROR("Failed to initialize GTT\n");
		DRM_ERROR("Failed to initialize GTT\n");
		ret = -ENODEV;
		ret = -ENODEV;
		goto out_rmmap;
		goto put_gmch;
	}
	}


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


	i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr,
	i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr,
@@ -1611,6 +1618,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
		dev_priv->mm.gtt_mtrr = -1;
		dev_priv->mm.gtt_mtrr = -1;
	}
	}
	io_mapping_free(dev_priv->mm.gtt_mapping);
	io_mapping_free(dev_priv->mm.gtt_mapping);
put_gmch:
	intel_gmch_remove();
out_rmmap:
out_rmmap:
	pci_iounmap(dev->pdev, dev_priv->regs);
	pci_iounmap(dev->pdev, dev_priv->regs);
put_bridge:
put_bridge:
+4 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,10 @@ const struct intel_gtt {
	phys_addr_t gma_bus_addr;
	phys_addr_t gma_bus_addr;
} *intel_gtt_get(void);
} *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_chipset_flush(void);
void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg);
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);
void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries);