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

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
...@@ -12,6 +12,7 @@ ...@@ -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, ...@@ -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) ...@@ -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);
} }
......
...@@ -250,7 +250,4 @@ ...@@ -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
...@@ -75,6 +75,7 @@ static struct _intel_private { ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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);
......
...@@ -1474,11 +1474,18 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -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) ...@@ -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) ...@@ -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:
......
...@@ -23,6 +23,10 @@ const struct intel_gtt { ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment