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

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

Merge tag 'drm-intel-next-2013-02-01' of...

Merge tag 'drm-intel-next-2013-02-01' of git://people.freedesktop.org/~danvet/drm-intel into drm-next

Daniel writes:
"Probably the last feature pull for 3.9, there's some fixes outstanding
thought that I'd like to sneak in. And maybe 3.8 takes a bit longer ...
Anyway, highlights of this pull:
- Kill the horrible IS_DISPLAYREG hack to handle the mmio offset movements
  on vlv, big thanks to Ville.
- Dynamic power well support for Haswell, shaves away a bit when only
  using the eDP port on pipe A (Paulo). Plus unclaimed register fixes
  uncovered by this.
- Clarifications of the gpu hang/reset state transitions, hopefully fixing
  a few spurious -EIO deaths in userspace.
- Haswell ELD fixes.
- Some more (pp)gtt cleanups from Ben.
- A few smaller things all over.

Plus all the stuff from the previous rather small pull request:
- Broadcast RBG improvements and reduced color range fixes from Ville.
- Ben is on a "kill legacy gtt code for good" spree, first pile of patches
  included.
- No-relocs and bo lut improvements for faster execbuf from Chris.
- Some refactorings from Imre."

* tag 'drm-intel-next-2013-02-01' of git://people.freedesktop.org/~danvet/drm-intel: (101 commits)
  GPU/i915: Fix acpi_bus_get_device() check in drivers/gpu/drm/i915/intel_opregion.c
  drm/i915: Set the SR01 "screen off" bit in i915_redisable_vga() too
  drm/i915: Kill IS_DISPLAYREG()
  drm/i915: Introduce i915_vgacntrl_reg()
  drm/i915: gen6_gmch_remove can be static
  drm/i915: dynamic Haswell display power well support
  drm/i915: check the power down well on assert_pipe()
  drm/i915: don't send DP "idle" pattern before "normal" on HSW PORT_A
  drm/i915: don't run hsw power well code on !hsw
  drm/i915: kill cargo-culted locking from power well code
  drm/i915: Only run idle processing from i915_gem_retire_requests_worker
  drm/i915: Fix CAGF for HSW
  drm/i915: Reclaim GTT space for failed PPGTT
  drm/i915: remove intel_gtt structure
  drm/i915: Add probe and remove to the gtt ops
  drm/i915: extract hw ppgtt setup/cleanup code
  drm/i915: pte_encode is gen6+
  drm/i915: vfuncs for ppgtt
  drm/i915: vfuncs for gtt_clear_range/insert_entries
  drm/i915: Error state should print /sys/kernel/debug
  ...
parents 67c96400 7d37beaa
Loading
Loading
Loading
Loading
+35 −52
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@ struct intel_gtt_driver {
};

static struct _intel_private {
	struct intel_gtt base;
	const struct intel_gtt_driver *driver;
	struct pci_dev *pcidev;	/* device one */
	struct pci_dev *bridge_dev;
@@ -75,7 +74,18 @@ static struct _intel_private {
	struct resource ifp_resource;
	int resource_valid;
	struct page *scratch_page;
	phys_addr_t scratch_page_dma;
	int refcount;
	/* Whether i915 needs to use the dmar apis or not. */
	unsigned int needs_dmar : 1;
	phys_addr_t gma_bus_addr;
	/*  Size of memory reserved for graphics by the BIOS */
	unsigned int stolen_size;
	/* Total number of gtt entries. */
	unsigned int gtt_total_entries;
	/* Part of the gtt that is mappable by the cpu, for those chips where
	 * this is not the full gtt. */
	unsigned int gtt_mappable_entries;
} intel_private;

#define INTEL_GTT_GEN	intel_private.driver->gen
@@ -291,15 +301,15 @@ static int intel_gtt_setup_scratch_page(void)
	get_page(page);
	set_pages_uc(page, 1);

	if (intel_private.base.needs_dmar) {
	if (intel_private.needs_dmar) {
		dma_addr = pci_map_page(intel_private.pcidev, page, 0,
				    PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
		if (pci_dma_mapping_error(intel_private.pcidev, dma_addr))
			return -EINVAL;

		intel_private.base.scratch_page_dma = dma_addr;
		intel_private.scratch_page_dma = dma_addr;
	} else
		intel_private.base.scratch_page_dma = page_to_phys(page);
		intel_private.scratch_page_dma = page_to_phys(page);

	intel_private.scratch_page = page;

@@ -506,7 +516,7 @@ static unsigned int intel_gtt_total_entries(void)
		/* On previous hardware, the GTT size was just what was
		 * required to map the aperture.
		 */
		return intel_private.base.gtt_mappable_entries;
		return intel_private.gtt_mappable_entries;
	}
}

@@ -546,7 +556,7 @@ static unsigned int intel_gtt_mappable_entries(void)
static void intel_gtt_teardown_scratch_page(void)
{
	set_pages_wb(intel_private.scratch_page, 1);
	pci_unmap_page(intel_private.pcidev, intel_private.base.scratch_page_dma,
	pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma,
		       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
	put_page(intel_private.scratch_page);
	__free_page(intel_private.scratch_page);
@@ -572,8 +582,8 @@ static int intel_gtt_init(void)
	if (ret != 0)
		return ret;

	intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries();
	intel_private.base.gtt_total_entries = intel_gtt_total_entries();
	intel_private.gtt_mappable_entries = intel_gtt_mappable_entries();
	intel_private.gtt_total_entries = intel_gtt_total_entries();

	/* save the PGETBL reg for resume */
	intel_private.PGETBL_save =
@@ -585,10 +595,10 @@ static int intel_gtt_init(void)

	dev_info(&intel_private.bridge_dev->dev,
			"detected gtt size: %dK total, %dK mappable\n",
			intel_private.base.gtt_total_entries * 4,
			intel_private.base.gtt_mappable_entries * 4);
			intel_private.gtt_total_entries * 4,
			intel_private.gtt_mappable_entries * 4);

	gtt_map_size = intel_private.base.gtt_total_entries * 4;
	gtt_map_size = intel_private.gtt_total_entries * 4;

	intel_private.gtt = NULL;
	if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2)
@@ -605,9 +615,9 @@ static int intel_gtt_init(void)

	global_cache_flush();   /* FIXME: ? */

	intel_private.base.stolen_size = intel_gtt_stolen_size();
	intel_private.stolen_size = intel_gtt_stolen_size();

	intel_private.base.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2;
	intel_private.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2;

	ret = intel_gtt_setup_scratch_page();
	if (ret != 0) {
@@ -622,7 +632,7 @@ static int intel_gtt_init(void)
		pci_read_config_dword(intel_private.pcidev, I915_GMADDR,
				      &gma_addr);

	intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);
	intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);

	return 0;
}
@@ -633,8 +643,7 @@ static int intel_fake_agp_fetch_size(void)
	unsigned int aper_size;
	int i;

	aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT)
		    / MB(1);
	aper_size = (intel_private.gtt_mappable_entries << PAGE_SHIFT) / MB(1);

	for (i = 0; i < num_sizes; i++) {
		if (aper_size == intel_fake_agp_sizes[i].size) {
@@ -778,7 +787,7 @@ static int intel_fake_agp_configure(void)
	    return -EIO;

	intel_private.clear_fake_agp = true;
	agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr;
	agp_bridge->gart_bus_addr = intel_private.gma_bus_addr;

	return 0;
}
@@ -840,12 +849,9 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem,
{
	int ret = -EINVAL;

	if (intel_private.base.do_idle_maps)
		return -ENODEV;

	if (intel_private.clear_fake_agp) {
		int start = intel_private.base.stolen_size / PAGE_SIZE;
		int end = intel_private.base.gtt_mappable_entries;
		int start = intel_private.stolen_size / PAGE_SIZE;
		int end = intel_private.gtt_mappable_entries;
		intel_gtt_clear_range(start, end - start);
		intel_private.clear_fake_agp = false;
	}
@@ -856,7 +862,7 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem,
	if (mem->page_count == 0)
		goto out;

	if (pg_start + mem->page_count > intel_private.base.gtt_total_entries)
	if (pg_start + mem->page_count > intel_private.gtt_total_entries)
		goto out_err;

	if (type != mem->type)
@@ -868,7 +874,7 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem,
	if (!mem->is_flushed)
		global_cache_flush();

	if (intel_private.base.needs_dmar) {
	if (intel_private.needs_dmar) {
		struct sg_table st;

		ret = intel_gtt_map_memory(mem->pages, mem->page_count, &st);
@@ -894,7 +900,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
	unsigned int i;

	for (i = first_entry; i < (first_entry + num_entries); i++) {
		intel_private.driver->write_entry(intel_private.base.scratch_page_dma,
		intel_private.driver->write_entry(intel_private.scratch_page_dma,
						  i, 0);
	}
	readl(intel_private.gtt+i-1);
@@ -907,12 +913,9 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem,
	if (mem->page_count == 0)
		return 0;

	if (intel_private.base.do_idle_maps)
		return -ENODEV;

	intel_gtt_clear_range(pg_start, mem->page_count);

	if (intel_private.base.needs_dmar) {
	if (intel_private.needs_dmar) {
		intel_gtt_unmap_memory(mem->sg_list, mem->num_sg);
		mem->sg_list = NULL;
		mem->num_sg = 0;
@@ -1069,24 +1072,6 @@ static void i965_write_entry(dma_addr_t addr,
	writel(addr | pte_flags, intel_private.gtt + entry);
}

/* Certain Gen5 chipsets require require idling the GPU before
 * unmapping anything from the GTT when VT-d is enabled.
 */
static inline int needs_idle_maps(void)
{
#ifdef CONFIG_INTEL_IOMMU
	const unsigned short gpu_devid = intel_private.pcidev->device;

	/* Query intel_iommu to see if we need the workaround. Presumably that
	 * was loaded first.
	 */
	if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
	     gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
	     intel_iommu_gfx_mapped)
		return 1;
#endif
	return 0;
}

static int i9xx_setup(void)
{
@@ -1115,9 +1100,6 @@ static int i9xx_setup(void)
		break;
	}

	if (needs_idle_maps())
		intel_private.base.do_idle_maps = 1;

	intel_i9xx_setup_flush();

	return 0;
@@ -1389,9 +1371,10 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
}
EXPORT_SYMBOL(intel_gmch_probe);

struct intel_gtt *intel_gtt_get(void)
void intel_gtt_get(size_t *gtt_total, size_t *stolen_size)
{
	return &intel_private.base;
	*gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT;
	*stolen_size = intel_private.stolen_size;
}
EXPORT_SYMBOL(intel_gtt_get);

+33 −0
Original line number Diff line number Diff line
@@ -1483,9 +1483,11 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
#define VIDEO_BLOCK     0x02
#define VENDOR_BLOCK    0x03
#define SPEAKER_BLOCK	0x04
#define VIDEO_CAPABILITY_BLOCK	0x07
#define EDID_BASIC_AUDIO	(1 << 6)
#define EDID_CEA_YCRCB444	(1 << 5)
#define EDID_CEA_YCRCB422	(1 << 4)
#define EDID_CEA_VCDB_QS	(1 << 6)

/**
 * Search EDID for CEA extension block.
@@ -1901,6 +1903,37 @@ end:
}
EXPORT_SYMBOL(drm_detect_monitor_audio);

/**
 * drm_rgb_quant_range_selectable - is RGB quantization range selectable?
 *
 * Check whether the monitor reports the RGB quantization range selection
 * as supported. The AVI infoframe can then be used to inform the monitor
 * which quantization range (full or limited) is used.
 */
bool drm_rgb_quant_range_selectable(struct edid *edid)
{
	u8 *edid_ext;
	int i, start, end;

	edid_ext = drm_find_cea_extension(edid);
	if (!edid_ext)
		return false;

	if (cea_db_offsets(edid_ext, &start, &end))
		return false;

	for_each_cea_db(edid_ext, i, start, end) {
		if (cea_db_tag(&edid_ext[i]) == VIDEO_CAPABILITY_BLOCK &&
		    cea_db_payload_len(&edid_ext[i]) == 2) {
			DRM_DEBUG_KMS("CEA VCDB 0x%02x\n", edid_ext[i + 2]);
			return edid_ext[i + 2] & EDID_CEA_VCDB_QS;
		}
	}

	return false;
}
EXPORT_SYMBOL(drm_rgb_quant_range_selectable);

/**
 * drm_add_display_info - pull display info out if present
 * @edid: EDID data
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
	  i915_gem_tiling.o \
	  i915_sysfs.o \
	  i915_trace_points.o \
	  i915_ums.o \
	  intel_display.o \
	  intel_crt.o \
	  intel_lvds.o \
+120 −11
Original line number Diff line number Diff line
@@ -258,8 +258,9 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
	seq_printf(m, "%u fault mappable objects, %zu bytes\n",
		   count, size);

	seq_printf(m, "%zu [%zu] gtt total\n",
		   dev_priv->mm.gtt_total, dev_priv->mm.mappable_gtt_total);
	seq_printf(m, "%zu [%lu] gtt total\n",
		   dev_priv->gtt.total,
		   dev_priv->gtt.mappable_end - dev_priv->gtt.start);

	mutex_unlock(&dev->struct_mutex);

@@ -813,11 +814,11 @@ static int i915_error_state_open(struct inode *inode, struct file *file)

	error_priv->dev = dev;

	spin_lock_irqsave(&dev_priv->error_lock, flags);
	error_priv->error = dev_priv->first_error;
	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
	error_priv->error = dev_priv->gpu_error.first_error;
	if (error_priv->error)
		kref_get(&error_priv->error->ref);
	spin_unlock_irqrestore(&dev_priv->error_lock, flags);
	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);

	return single_open(file, i915_error_state, error_priv);
}
@@ -956,7 +957,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
		u32 rpstat;
		u32 rpstat, cagf;
		u32 rpupei, rpcurup, rpprevup;
		u32 rpdownei, rpcurdown, rpprevdown;
		int max_freq;
@@ -975,6 +976,11 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
		rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI);
		rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
		rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
		if (IS_HASWELL(dev))
			cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
		else
			cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
		cagf *= GT_FREQUENCY_MULTIPLIER;

		gen6_gt_force_wake_put(dev_priv);
		mutex_unlock(&dev->struct_mutex);
@@ -987,8 +993,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
			   gt_perf_status & 0xff);
		seq_printf(m, "Render p-state limit: %d\n",
			   rp_state_limits & 0xff);
		seq_printf(m, "CAGF: %dMHz\n", ((rpstat & GEN6_CAGF_MASK) >>
						GEN6_CAGF_SHIFT) * GT_FREQUENCY_MULTIPLIER);
		seq_printf(m, "CAGF: %dMHz\n", cagf);
		seq_printf(m, "RP CUR UP EI: %dus\n", rpupei &
			   GEN6_CURICONT_MASK);
		seq_printf(m, "RP CUR UP: %dus\n", rpcurup &
@@ -1674,7 +1679,7 @@ i915_wedged_read(struct file *filp,

	len = snprintf(buf, sizeof(buf),
		       "wedged :  %d\n",
		       atomic_read(&dev_priv->mm.wedged));
		       atomic_read(&dev_priv->gpu_error.reset_counter));

	if (len > sizeof(buf))
		len = sizeof(buf);
@@ -1729,7 +1734,7 @@ i915_ring_stop_read(struct file *filp,
	int len;

	len = snprintf(buf, sizeof(buf),
		       "0x%08x\n", dev_priv->stop_rings);
		       "0x%08x\n", dev_priv->gpu_error.stop_rings);

	if (len > sizeof(buf))
		len = sizeof(buf);
@@ -1765,7 +1770,7 @@ i915_ring_stop_write(struct file *filp,
	if (ret)
		return ret;

	dev_priv->stop_rings = val;
	dev_priv->gpu_error.stop_rings = val;
	mutex_unlock(&dev->struct_mutex);

	return cnt;
@@ -1779,6 +1784,102 @@ static const struct file_operations i915_ring_stop_fops = {
	.llseek = default_llseek,
};

#define DROP_UNBOUND 0x1
#define DROP_BOUND 0x2
#define DROP_RETIRE 0x4
#define DROP_ACTIVE 0x8
#define DROP_ALL (DROP_UNBOUND | \
		  DROP_BOUND | \
		  DROP_RETIRE | \
		  DROP_ACTIVE)
static ssize_t
i915_drop_caches_read(struct file *filp,
		      char __user *ubuf,
		      size_t max,
		      loff_t *ppos)
{
	char buf[20];
	int len;

	len = snprintf(buf, sizeof(buf), "0x%08x\n", DROP_ALL);
	if (len > sizeof(buf))
		len = sizeof(buf);

	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
}

static ssize_t
i915_drop_caches_write(struct file *filp,
		       const char __user *ubuf,
		       size_t cnt,
		       loff_t *ppos)
{
	struct drm_device *dev = filp->private_data;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_gem_object *obj, *next;
	char buf[20];
	int val = 0, ret;

	if (cnt > 0) {
		if (cnt > sizeof(buf) - 1)
			return -EINVAL;

		if (copy_from_user(buf, ubuf, cnt))
			return -EFAULT;
		buf[cnt] = 0;

		val = simple_strtoul(buf, NULL, 0);
	}

	DRM_DEBUG_DRIVER("Dropping caches: 0x%08x\n", val);

	/* No need to check and wait for gpu resets, only libdrm auto-restarts
	 * on ioctls on -EAGAIN. */
	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	if (val & DROP_ACTIVE) {
		ret = i915_gpu_idle(dev);
		if (ret)
			goto unlock;
	}

	if (val & (DROP_RETIRE | DROP_ACTIVE))
		i915_gem_retire_requests(dev);

	if (val & DROP_BOUND) {
		list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list, mm_list)
			if (obj->pin_count == 0) {
				ret = i915_gem_object_unbind(obj);
				if (ret)
					goto unlock;
			}
	}

	if (val & DROP_UNBOUND) {
		list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list)
			if (obj->pages_pin_count == 0) {
				ret = i915_gem_object_put_pages(obj);
				if (ret)
					goto unlock;
			}
	}

unlock:
	mutex_unlock(&dev->struct_mutex);

	return ret ?: cnt;
}

static const struct file_operations i915_drop_caches_fops = {
	.owner = THIS_MODULE,
	.open = simple_open,
	.read = i915_drop_caches_read,
	.write = i915_drop_caches_write,
	.llseek = default_llseek,
};

static ssize_t
i915_max_freq_read(struct file *filp,
		   char __user *ubuf,
@@ -2175,6 +2276,12 @@ int i915_debugfs_init(struct drm_minor *minor)
	if (ret)
		return ret;

	ret = i915_debugfs_create(minor->debugfs_root, minor,
				  "i915_gem_drop_caches",
				  &i915_drop_caches_fops);
	if (ret)
		return ret;

	ret = i915_debugfs_create(minor->debugfs_root, minor,
				  "i915_error_state",
				  &i915_error_state_fops);
@@ -2206,6 +2313,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
				 1, minor);
	drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops,
				 1, minor);
	drm_debugfs_remove_files((struct drm_info_list *) &i915_drop_caches_fops,
				 1, minor);
	drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops,
				 1, minor);
	drm_debugfs_remove_files((struct drm_info_list *) &i915_error_state_fops,
+24 −19
Original line number Diff line number Diff line
@@ -992,6 +992,12 @@ static int i915_getparam(struct drm_device *dev, void *data,
	case I915_PARAM_HAS_PINNED_BATCHES:
		value = 1;
		break;
	case I915_PARAM_HAS_EXEC_NO_RELOC:
		value = 1;
		break;
	case I915_PARAM_HAS_EXEC_HANDLE_LUT:
		value = 1;
		break;
	default:
		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
				 param->param);
@@ -1070,7 +1076,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
	ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12);

	dev_priv->dri1.gfx_hws_cpu_addr =
		ioremap_wc(dev_priv->mm.gtt_base_addr + hws->addr, 4096);
		ioremap_wc(dev_priv->gtt.mappable_base + hws->addr, 4096);
	if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) {
		i915_dma_cleanup(dev);
		ring->status_page.gfx_addr = 0;
@@ -1420,9 +1426,9 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
	if (!ap)
		return;

	ap->ranges[0].base = dev_priv->mm.gtt->gma_bus_addr;
	ap->ranges[0].size =
		dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
	ap->ranges[0].base = dev_priv->gtt.mappable_base;
	ap->ranges[0].size = dev_priv->gtt.mappable_end - dev_priv->gtt.start;

	primary =
		pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;

@@ -1536,18 +1542,17 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
		goto put_gmch;
	}

	aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
	dev_priv->mm.gtt_base_addr = dev_priv->mm.gtt->gma_bus_addr;
	aperture_size = dev_priv->gtt.mappable_end;

	dev_priv->mm.gtt_mapping =
		io_mapping_create_wc(dev_priv->mm.gtt_base_addr,
	dev_priv->gtt.mappable =
		io_mapping_create_wc(dev_priv->gtt.mappable_base,
				     aperture_size);
	if (dev_priv->mm.gtt_mapping == NULL) {
	if (dev_priv->gtt.mappable == NULL) {
		ret = -EIO;
		goto out_rmmap;
	}

	i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr,
	i915_mtrr_setup(dev_priv, dev_priv->gtt.mappable_base,
			aperture_size);

	/* The i915 workqueue is primarily used for batched retirement of
@@ -1600,7 +1605,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
		pci_enable_msi(dev->pdev);

	spin_lock_init(&dev_priv->irq_lock);
	spin_lock_init(&dev_priv->error_lock);
	spin_lock_init(&dev_priv->gpu_error.lock);
	spin_lock_init(&dev_priv->rps.lock);
	mutex_init(&dev_priv->dpio_lock);

@@ -1652,15 +1657,15 @@ out_gem_unload:
out_mtrrfree:
	if (dev_priv->mm.gtt_mtrr >= 0) {
		mtrr_del(dev_priv->mm.gtt_mtrr,
			 dev_priv->mm.gtt_base_addr,
			 dev_priv->gtt.mappable_base,
			 aperture_size);
		dev_priv->mm.gtt_mtrr = -1;
	}
	io_mapping_free(dev_priv->mm.gtt_mapping);
	io_mapping_free(dev_priv->gtt.mappable);
out_rmmap:
	pci_iounmap(dev->pdev, dev_priv->regs);
put_gmch:
	i915_gem_gtt_fini(dev);
	dev_priv->gtt.gtt_remove(dev);
put_bridge:
	pci_dev_put(dev_priv->bridge_dev);
free_priv:
@@ -1690,11 +1695,11 @@ int i915_driver_unload(struct drm_device *dev)
	/* Cancel the retire work handler, which should be idle now. */
	cancel_delayed_work_sync(&dev_priv->mm.retire_work);

	io_mapping_free(dev_priv->mm.gtt_mapping);
	io_mapping_free(dev_priv->gtt.mappable);
	if (dev_priv->mm.gtt_mtrr >= 0) {
		mtrr_del(dev_priv->mm.gtt_mtrr,
			 dev_priv->mm.gtt_base_addr,
			 dev_priv->mm.gtt->gtt_mappable_entries * PAGE_SIZE);
			 dev_priv->gtt.mappable_base,
			 dev_priv->gtt.mappable_end);
		dev_priv->mm.gtt_mtrr = -1;
	}

@@ -1720,8 +1725,8 @@ int i915_driver_unload(struct drm_device *dev)
	}

	/* Free error state after interrupts are fully disabled. */
	del_timer_sync(&dev_priv->hangcheck_timer);
	cancel_work_sync(&dev_priv->error_work);
	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
	cancel_work_sync(&dev_priv->gpu_error.work);
	i915_destroy_error_state(dev);

	if (dev->pdev->msi_enabled)
Loading