Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec2a4c3f authored by Dave Airlie's avatar Dave Airlie
Browse files

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
Loading
Loading
Loading
Loading
+23 −10
Original line number Original line Diff line number Diff line
@@ -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 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
	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;
+1 −0
Original line number Original line Diff line number Diff line
@@ -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;
+20 −45
Original line number Original line Diff line number Diff line
@@ -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 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
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);
		}
		}
	}
	}