提交 14be93dd 编写于 作者: D 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: NJani Nikula <jani.nikula@linux.intel.com>
Signed-Off-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
上级 7e8f6306
......@@ -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 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册