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: Jani Nikula <jani.nikula@linux.intel.com> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
7e8f6306fe
commit
14be93ddff
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
@ -1539,15 +1558,17 @@ int intel_gmch_probe(struct pci_dev *pdev,
|
|||
if (!intel_private.driver)
|
||||
return 0;
|
||||
|
||||
intel_private.refcount++;
|
||||
|
||||
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)))
|
||||
|
@ -1557,8 +1578,11 @@ int intel_gmch_probe(struct pci_dev *pdev,
|
|||
pci_set_consistent_dma_mask(intel_private.pcidev,
|
||||
DMA_BIT_MASK(mask));
|
||||
|
||||
if (intel_gtt_init() != 0)
|
||||
if (intel_gtt_init() != 0) {
|
||||
intel_gmch_remove();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1577,12 +1601,16 @@ 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)
|
||||
pci_dev_put(intel_private.bridge_dev);
|
||||
intel_private.driver = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(intel_gmch_remove);
|
||||
|
||||
|
|
|
@ -1474,11 +1474,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;
|
||||
|
@ -1489,7 +1496,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,
|
||||
|
@ -1611,6 +1618,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:
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue