Commit ec2a4c3f authored by Dave Airlie's avatar Dave Airlie

drm/i915: get the bridge device once.

The driver gets the bridge device in a number of places, upcoming
vga arb code paths need the bridge device, however they need it in
under a lock, and the pci lookup can allocate memory. So clean
this code up before then and get the bridge once for the driver lifetime.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent f1938cd6
...@@ -898,6 +898,18 @@ static int i915_set_status_page(struct drm_device *dev, void *data, ...@@ -898,6 +898,18 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
return 0; return 0;
} }
static int i915_get_bridge_dev(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
if (!dev_priv->bridge_dev) {
DRM_ERROR("bridge device not found\n");
return -1;
}
return 0;
}
/** /**
* i915_probe_agp - get AGP bootup configuration * i915_probe_agp - get AGP bootup configuration
* @pdev: PCI device * @pdev: PCI device
...@@ -911,20 +923,13 @@ static int i915_set_status_page(struct drm_device *dev, void *data, ...@@ -911,20 +923,13 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
uint32_t *preallocated_size) uint32_t *preallocated_size)
{ {
struct pci_dev *bridge_dev; struct drm_i915_private *dev_priv = dev->dev_private;
u16 tmp = 0; u16 tmp = 0;
unsigned long overhead; unsigned long overhead;
unsigned long stolen; unsigned long stolen;
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
if (!bridge_dev) {
DRM_ERROR("bridge device not found\n");
return -1;
}
/* Get the fb aperture size and "stolen" memory amount. */ /* Get the fb aperture size and "stolen" memory amount. */
pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &tmp);
pci_dev_put(bridge_dev);
*aperture_size = 1024 * 1024; *aperture_size = 1024 * 1024;
*preallocated_size = 1024 * 1024; *preallocated_size = 1024 * 1024;
...@@ -1176,11 +1181,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1176,11 +1181,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
base = drm_get_resource_start(dev, mmio_bar); base = drm_get_resource_start(dev, mmio_bar);
size = drm_get_resource_len(dev, mmio_bar); size = drm_get_resource_len(dev, mmio_bar);
if (i915_get_bridge_dev(dev)) {
ret = -EIO;
goto free_priv;
}
dev_priv->regs = ioremap(base, size); dev_priv->regs = ioremap(base, size);
if (!dev_priv->regs) { if (!dev_priv->regs) {
DRM_ERROR("failed to map registers\n"); DRM_ERROR("failed to map registers\n");
ret = -EIO; ret = -EIO;
goto free_priv; goto put_bridge;
} }
dev_priv->mm.gtt_mapping = dev_priv->mm.gtt_mapping =
...@@ -1292,6 +1302,8 @@ out_iomapfree: ...@@ -1292,6 +1302,8 @@ out_iomapfree:
io_mapping_free(dev_priv->mm.gtt_mapping); io_mapping_free(dev_priv->mm.gtt_mapping);
out_rmmap: out_rmmap:
iounmap(dev_priv->regs); iounmap(dev_priv->regs);
put_bridge:
pci_dev_put(dev_priv->bridge_dev);
free_priv: free_priv:
kfree(dev_priv); kfree(dev_priv);
return ret; return ret;
...@@ -1335,6 +1347,7 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1335,6 +1347,7 @@ int i915_driver_unload(struct drm_device *dev)
i915_gem_lastclose(dev); i915_gem_lastclose(dev);
} }
pci_dev_put(dev_priv->bridge_dev);
kfree(dev->dev_private); kfree(dev->dev_private);
return 0; return 0;
......
...@@ -155,6 +155,7 @@ typedef struct drm_i915_private { ...@@ -155,6 +155,7 @@ typedef struct drm_i915_private {
void __iomem *regs; void __iomem *regs;
struct pci_dev *bridge_dev;
drm_i915_ring_buffer_t ring; drm_i915_ring_buffer_t ring;
drm_dma_handle_t *status_page_dmah; drm_dma_handle_t *status_page_dmah;
......
...@@ -94,23 +94,15 @@ ...@@ -94,23 +94,15 @@
static int static int
intel_alloc_mchbar_resource(struct drm_device *dev) intel_alloc_mchbar_resource(struct drm_device *dev)
{ {
struct pci_dev *bridge_dev;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
u32 temp_lo, temp_hi = 0; u32 temp_lo, temp_hi = 0;
u64 mchbar_addr; u64 mchbar_addr;
int ret = 0; int ret = 0;
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
if (!bridge_dev) {
DRM_DEBUG("no bridge dev?!\n");
ret = -ENODEV;
goto out;
}
if (IS_I965G(dev)) if (IS_I965G(dev))
pci_read_config_dword(bridge_dev, reg + 4, &temp_hi); pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
pci_read_config_dword(bridge_dev, reg, &temp_lo); pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
mchbar_addr = ((u64)temp_hi << 32) | temp_lo; mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
/* If ACPI doesn't have it, assume we need to allocate it ourselves */ /* If ACPI doesn't have it, assume we need to allocate it ourselves */
...@@ -118,30 +110,28 @@ intel_alloc_mchbar_resource(struct drm_device *dev) ...@@ -118,30 +110,28 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
if (mchbar_addr && if (mchbar_addr &&
pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
ret = 0; ret = 0;
goto out_put; goto out;
} }
#endif #endif
/* Get some space for it */ /* Get some space for it */
ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res, ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
MCHBAR_SIZE, MCHBAR_SIZE, MCHBAR_SIZE, MCHBAR_SIZE,
PCIBIOS_MIN_MEM, PCIBIOS_MIN_MEM,
0, pcibios_align_resource, 0, pcibios_align_resource,
bridge_dev); dev_priv->bridge_dev);
if (ret) { if (ret) {
DRM_DEBUG("failed bus alloc: %d\n", ret); DRM_DEBUG("failed bus alloc: %d\n", ret);
dev_priv->mch_res.start = 0; dev_priv->mch_res.start = 0;
goto out_put; goto out;
} }
if (IS_I965G(dev)) if (IS_I965G(dev))
pci_write_config_dword(bridge_dev, reg + 4, pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
upper_32_bits(dev_priv->mch_res.start)); upper_32_bits(dev_priv->mch_res.start));
pci_write_config_dword(bridge_dev, reg, pci_write_config_dword(dev_priv->bridge_dev, reg,
lower_32_bits(dev_priv->mch_res.start)); lower_32_bits(dev_priv->mch_res.start));
out_put:
pci_dev_put(bridge_dev);
out: out:
return ret; return ret;
} }
...@@ -150,44 +140,36 @@ out: ...@@ -150,44 +140,36 @@ out:
static bool static bool
intel_setup_mchbar(struct drm_device *dev) intel_setup_mchbar(struct drm_device *dev)
{ {
struct pci_dev *bridge_dev; drm_i915_private_t *dev_priv = dev->dev_private;
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
u32 temp; u32 temp;
bool need_disable = false, enabled; bool need_disable = false, enabled;
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
if (!bridge_dev) {
DRM_DEBUG("no bridge dev?!\n");
goto out;
}
if (IS_I915G(dev) || IS_I915GM(dev)) { if (IS_I915G(dev) || IS_I915GM(dev)) {
pci_read_config_dword(bridge_dev, DEVEN_REG, &temp); pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
enabled = !!(temp & DEVEN_MCHBAR_EN); enabled = !!(temp & DEVEN_MCHBAR_EN);
} else { } else {
pci_read_config_dword(bridge_dev, mchbar_reg, &temp); pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
enabled = temp & 1; enabled = temp & 1;
} }
/* If it's already enabled, don't have to do anything */ /* If it's already enabled, don't have to do anything */
if (enabled) if (enabled)
goto out_put; goto out;
if (intel_alloc_mchbar_resource(dev)) if (intel_alloc_mchbar_resource(dev))
goto out_put; goto out;
need_disable = true; need_disable = true;
/* Space is allocated or reserved, so enable it. */ /* Space is allocated or reserved, so enable it. */
if (IS_I915G(dev) || IS_I915GM(dev)) { if (IS_I915G(dev) || IS_I915GM(dev)) {
pci_write_config_dword(bridge_dev, DEVEN_REG, pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
temp | DEVEN_MCHBAR_EN); temp | DEVEN_MCHBAR_EN);
} else { } else {
pci_read_config_dword(bridge_dev, mchbar_reg, &temp); pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1); pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
} }
out_put:
pci_dev_put(bridge_dev);
out: out:
return need_disable; return need_disable;
} }
...@@ -196,25 +178,18 @@ static void ...@@ -196,25 +178,18 @@ static void
intel_teardown_mchbar(struct drm_device *dev, bool disable) intel_teardown_mchbar(struct drm_device *dev, bool disable)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
struct pci_dev *bridge_dev;
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
u32 temp; u32 temp;
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
if (!bridge_dev) {
DRM_DEBUG("no bridge dev?!\n");
return;
}
if (disable) { if (disable) {
if (IS_I915G(dev) || IS_I915GM(dev)) { if (IS_I915G(dev) || IS_I915GM(dev)) {
pci_read_config_dword(bridge_dev, DEVEN_REG, &temp); pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
temp &= ~DEVEN_MCHBAR_EN; temp &= ~DEVEN_MCHBAR_EN;
pci_write_config_dword(bridge_dev, DEVEN_REG, temp); pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
} else { } else {
pci_read_config_dword(bridge_dev, mchbar_reg, &temp); pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
temp &= ~1; temp &= ~1;
pci_write_config_dword(bridge_dev, mchbar_reg, temp); pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
} }
} }
......
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