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: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
f1938cd6e9
commit
ec2a4c3fdc
3 changed files with 44 additions and 55 deletions
|
@ -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,
|
||||||
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)
|
||||||
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:
|
||||||
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)
|
||||||
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 {
|
||||||
|
|
||||||
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 @@
|
||||||
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)
|
||||||
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:
|
||||||
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
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue