]> code.ossystems Code Review - openembedded-core.git/commitdiff
Drop linux-moblin obsolete kernels
authorRichard Purdie <rpurdie@linux.intel.com>
Mon, 12 Jan 2009 17:41:01 +0000 (17:41 +0000)
committerRichard Purdie <rpurdie@linux.intel.com>
Mon, 12 Jan 2009 17:41:01 +0000 (17:41 +0000)
58 files changed:
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0001_Export_shmem_file_setup_for_DRM-GEM.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0002_i915.Use_more_consistent_names_for_regs.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0003_i915.Add_support_for_MSI_and_interrupt_mitigation.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0004_i915.Track_progress_inside_of_batchbuffers_for_determining_wedgedness.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0005_i915.remove_settable_use_mi_batchbuffer_start.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0006_i915.Ignore_X_server_provided_mmio_address.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0007_i915.Initialize_hardware_status_page_at_device_load_when_possible.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0008_drm.Add_GEM_graphics_execution_manager_to_i915_driver.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0010_unionfs-2.4_for_2.6.27-rc1.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0011_workaround_unidef_step.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0012_intelfb_945gme.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/defconfig-netbook [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0001-drm-remove-define-for-non-linux-systems.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0002-i915-remove-settable-use_mi_batchbuffer_start.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0003-i915-Ignore-X-server-provided-mmio-address.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0004-i915-Use-more-consistent-names-for-regs-and-store.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0005-i915-Add-support-for-MSI-and-interrupt-mitigation.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0006-i915-Track-progress-inside-of-batchbuffers-for-dete.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0007-i915-Initialize-hardware-status-page-at-device-load.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0008-Add-Intel-ACPI-IGD-OpRegion-support.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0009-drm-fix-sysfs-error-path.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0010-i915-separate-suspend-resume-functions.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0011-drm-vblank-rework.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0012-Export-shmem_file_setup-for-DRM-GEM.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0013-Export-kmap_atomic_pfn-for-DRM-GEM.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0014-drm-Add-GEM-graphics-execution-manager-to-i915.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0015-i915-Add-chip-set-ID-param.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0017-i915-Make-use-of-sarea_priv-conditional.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0018-i915-gem-install-and-uninstall-irq-handler-in-enter.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0019-DRM-Return-EBADF-on-bad-object-in-flink-and-retur.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0020-drm-Avoid-oops-in-GEM-execbuffers-with-bad-argument.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0021-drm-G33-class-hardware-has-a-newer-965-style-MCH-n.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0022-drm-use-ioremap_wc-in-i915-instead-of-ioremap.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0023-drm-clean-up-many-sparse-warnings-in-i915.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0024-fastboot-create-a-asynchronous-initlevel.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0025-fastboot-turn-the-USB-hostcontroller-initcalls-into.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0026-fastboot-convert-a-few-non-critical-ACPI-drivers-to.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0027-fastboot-hold-the-BKL-over-the-async-init-call-sequ.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0028-fastboot-sync-the-async-execution-before-late_initc.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0029-fastboot-make-fastboot-a-config-option.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0030-fastboot-retry-mounting-the-root-fs-if-we-can-t-fin.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0031-fastboot-make-the-raid-autodetect-code-wait-for-all.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0032-fastboot-remove-wait-for-all-devices-before-mounti.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0033-fastboot-make-the-RAID-autostart-code-print-a-messa.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0034-fastboot-fix-typo-in-init-Kconfig-text.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0035-fastboot-remove-duplicate-unpack_to_rootfs.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0036-warning-fix-init-do_mounts_md-c.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0037-init-initramfs.c-unused-function-when-compiling-wit.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0038-fastboot-fix-blackfin-breakage-due-to-vmlinux.lds-c.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0039-Add-a-script-to-visualize-the-kernel-boot-process.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0040-fastboot-fix-issues-and-improve-output-of-bootgraph.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0041-r8169-8101e.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0042-intelfb-945gme.patch [deleted file]
meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/defconfig-netbook [deleted file]
meta-moblin/packages/linux/linux-moblin_2.6.27-rc1.bb [deleted file]
meta-moblin/packages/linux/linux-moblin_2.6.27-rc6.bb [deleted file]

diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0001_Export_shmem_file_setup_for_DRM-GEM.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0001_Export_shmem_file_setup_for_DRM-GEM.patch
deleted file mode 100644 (file)
index 9589838..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From: Keith Packard <keithp@keithp.com>
-Date: Fri, 20 Jun 2008 07:08:06 +0000 (-0700)
-Subject: Export shmem_file_setup for DRM-GEM
-X-Git-Tag: v2.6.12-rc2
-X-Git-Url: http://gitweb.freedesktop.org/?p=users/anholt/anholt/linux-2.6.git;a=commitdiff;h=350ea3ece12744ae154bbc2ea13da6ba84ca5515
-
-Export shmem_file_setup for DRM-GEM
-
-GEM needs to create shmem files to back buffer objects.  Though currently
-creation of files for objects could have been driven from userland, the
-modesetting work will require allocation of buffer objects before userland
-is running, for boot-time message display.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
-
---- a/mm/shmem.c
-+++ b/mm/shmem.c
-@@ -2582,6 +2582,7 @@ put_memory:
-       shmem_unacct_size(flags, size);
-       return ERR_PTR(error);
- }
-+EXPORT_SYMBOL(shmem_file_setup);
- /**
-  * shmem_zero_setup - setup a shared anonymous mapping
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0002_i915.Use_more_consistent_names_for_regs.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0002_i915.Use_more_consistent_names_for_regs.patch
deleted file mode 100644 (file)
index 9a035b5..0000000
+++ /dev/null
@@ -1,2739 +0,0 @@
-From: Jesse Barnes <jbarnes@virtuousgeek.org>
-Date: Tue, 29 Jul 2008 18:54:06 +0000 (-0700)
-Subject: i915: Use more consistent names for regs, and store them in a separate file.
-X-Git-Tag: v2.6.12-rc2
-X-Git-Url: http://gitweb.freedesktop.org/?p=users/anholt/anholt/linux-2.6.git;a=commitdiff;h=db1cbbd8c4d42e58e9acb3e7af59ad1bb238260d
-
-i915: Use more consistent names for regs, and store them in a separate file.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
-
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -40,11 +40,11 @@ int i915_wait_ring(struct drm_device * d
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
--      u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-+      u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-       int i;
-       for (i = 0; i < 10000; i++) {
--              ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-+              ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->Size;
-@@ -67,8 +67,8 @@ void i915_kernel_lost_context(struct drm
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
--      ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
--      ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
-+      ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-+      ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
-       ring->space = ring->head - (ring->tail + 8);
-       if (ring->space < 0)
-               ring->space += ring->Size;
-@@ -98,13 +98,13 @@ static int i915_dma_cleanup(struct drm_d
-               drm_pci_free(dev, dev_priv->status_page_dmah);
-               dev_priv->status_page_dmah = NULL;
-               /* Need to rewrite hardware status page */
--              I915_WRITE(0x02080, 0x1ffff000);
-+              I915_WRITE(HWS_PGA, 0x1ffff000);
-       }
-       if (dev_priv->status_gfx_addr) {
-               dev_priv->status_gfx_addr = 0;
-               drm_core_ioremapfree(&dev_priv->hws_map, dev);
--              I915_WRITE(0x2080, 0x1ffff000);
-+              I915_WRITE(HWS_PGA, 0x1ffff000);
-       }
-       return 0;
-@@ -170,7 +170,7 @@ static int i915_initialize(struct drm_de
-               dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-               memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
--              I915_WRITE(0x02080, dev_priv->dma_status_page);
-+              I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-       }
-       DRM_DEBUG("Enabled hardware status page\n");
-       return 0;
-@@ -201,9 +201,9 @@ static int i915_dma_resume(struct drm_de
-       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-       if (dev_priv->status_gfx_addr != 0)
--              I915_WRITE(0x02080, dev_priv->status_gfx_addr);
-+              I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-       else
--              I915_WRITE(0x02080, dev_priv->dma_status_page);
-+              I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-       DRM_DEBUG("Enabled hardware status page\n");
-       return 0;
-@@ -402,8 +402,8 @@ static void i915_emit_breadcrumb(struct 
-               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
-       BEGIN_LP_RING(4);
--      OUT_RING(CMD_STORE_DWORD_IDX);
--      OUT_RING(20);
-+      OUT_RING(MI_STORE_DWORD_INDEX);
-+      OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-@@ -505,7 +505,7 @@ static int i915_dispatch_flip(struct drm
-       i915_kernel_lost_context(dev);
-       BEGIN_LP_RING(2);
--      OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-+      OUT_RING(MI_FLUSH | MI_READ_FLUSH);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-@@ -530,8 +530,8 @@ static int i915_dispatch_flip(struct drm
-       dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
-       BEGIN_LP_RING(4);
--      OUT_RING(CMD_STORE_DWORD_IDX);
--      OUT_RING(20);
-+      OUT_RING(MI_STORE_DWORD_INDEX);
-+      OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-@@ -728,8 +728,8 @@ static int i915_set_status_page(struct d
-       dev_priv->hw_status_page = dev_priv->hws_map.handle;
-       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
--      I915_WRITE(0x02080, dev_priv->status_gfx_addr);
--      DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
-+      I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-+      DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n",
-                       dev_priv->status_gfx_addr);
-       DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
-       return 0;
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -279,13 +279,13 @@ static int i915_suspend(struct drm_devic
-       dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
-       dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
-       dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
--      dev_priv->saveDSPABASE = I915_READ(DSPABASE);
-+      dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
-       if (IS_I965G(dev)) {
-               dev_priv->saveDSPASURF = I915_READ(DSPASURF);
-               dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
-       }
-       i915_save_palette(dev, PIPE_A);
--      dev_priv->savePIPEASTAT = I915_READ(I915REG_PIPEASTAT);
-+      dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
-       /* Pipe & plane B info */
-       dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
-@@ -307,13 +307,13 @@ static int i915_suspend(struct drm_devic
-       dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
-       dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
-       dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
--      dev_priv->saveDSPBBASE = I915_READ(DSPBBASE);
-+      dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
-       if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
-               dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
-               dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
-       }
-       i915_save_palette(dev, PIPE_B);
--      dev_priv->savePIPEBSTAT = I915_READ(I915REG_PIPEBSTAT);
-+      dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
-       /* CRT state */
-       dev_priv->saveADPA = I915_READ(ADPA);
-@@ -328,9 +328,9 @@ static int i915_suspend(struct drm_devic
-               dev_priv->saveLVDS = I915_READ(LVDS);
-       if (!IS_I830(dev) && !IS_845G(dev))
-               dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
--      dev_priv->saveLVDSPP_ON = I915_READ(LVDSPP_ON);
--      dev_priv->saveLVDSPP_OFF = I915_READ(LVDSPP_OFF);
--      dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE);
-+      dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
-+      dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
-+      dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
-       /* FIXME: save TV & SDVO state */
-@@ -341,19 +341,19 @@ static int i915_suspend(struct drm_devic
-       dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
-       /* Interrupt state */
--      dev_priv->saveIIR = I915_READ(I915REG_INT_IDENTITY_R);
--      dev_priv->saveIER = I915_READ(I915REG_INT_ENABLE_R);
--      dev_priv->saveIMR = I915_READ(I915REG_INT_MASK_R);
-+      dev_priv->saveIIR = I915_READ(IIR);
-+      dev_priv->saveIER = I915_READ(IER);
-+      dev_priv->saveIMR = I915_READ(IMR);
-       /* VGA state */
--      dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0);
--      dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1);
--      dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV);
-+      dev_priv->saveVGA0 = I915_READ(VGA0);
-+      dev_priv->saveVGA1 = I915_READ(VGA1);
-+      dev_priv->saveVGA_PD = I915_READ(VGA_PD);
-       dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
-       /* Clock gating state */
-       dev_priv->saveD_STATE = I915_READ(D_STATE);
--      dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
-+      dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
-       /* Cache mode state */
-       dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
-@@ -363,7 +363,7 @@ static int i915_suspend(struct drm_devic
-       /* Scratch space */
-       for (i = 0; i < 16; i++) {
--              dev_priv->saveSWF0[i] = I915_READ(SWF0 + (i << 2));
-+              dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
-               dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
-       }
-       for (i = 0; i < 3; i++)
-@@ -424,7 +424,7 @@ static int i915_resume(struct drm_device
-       I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
-       I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
-       I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
--      I915_WRITE(DSPABASE, dev_priv->saveDSPABASE);
-+      I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
-       I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
-       if (IS_I965G(dev)) {
-               I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
-@@ -436,7 +436,7 @@ static int i915_resume(struct drm_device
-       i915_restore_palette(dev, PIPE_A);
-       /* Enable the plane */
-       I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
--      I915_WRITE(DSPABASE, I915_READ(DSPABASE));
-+      I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
-       /* Pipe & plane B info */
-       if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
-@@ -466,7 +466,7 @@ static int i915_resume(struct drm_device
-       I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
-       I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
-       I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
--      I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE);
-+      I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
-       I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
-       if (IS_I965G(dev)) {
-               I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
-@@ -478,7 +478,7 @@ static int i915_resume(struct drm_device
-       i915_restore_palette(dev, PIPE_B);
-       /* Enable the plane */
-       I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
--      I915_WRITE(DSPBBASE, I915_READ(DSPBBASE));
-+      I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
-       /* CRT state */
-       I915_WRITE(ADPA, dev_priv->saveADPA);
-@@ -493,9 +493,9 @@ static int i915_resume(struct drm_device
-       I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
-       I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
--      I915_WRITE(LVDSPP_ON, dev_priv->saveLVDSPP_ON);
--      I915_WRITE(LVDSPP_OFF, dev_priv->saveLVDSPP_OFF);
--      I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE);
-+      I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
-+      I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
-+      I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
-       I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
-       /* FIXME: restore TV & SDVO state */
-@@ -508,14 +508,14 @@ static int i915_resume(struct drm_device
-       /* VGA state */
-       I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
--      I915_WRITE(VCLK_DIVISOR_VGA0, dev_priv->saveVCLK_DIVISOR_VGA0);
--      I915_WRITE(VCLK_DIVISOR_VGA1, dev_priv->saveVCLK_DIVISOR_VGA1);
--      I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV);
-+      I915_WRITE(VGA0, dev_priv->saveVGA0);
-+      I915_WRITE(VGA1, dev_priv->saveVGA1);
-+      I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
-       udelay(150);
-       /* Clock gating state */
-       I915_WRITE (D_STATE, dev_priv->saveD_STATE);
--      I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
-+      I915_WRITE(CG_2D_DIS, dev_priv->saveCG_2D_DIS);
-       /* Cache mode state */
-       I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
-@@ -524,7 +524,7 @@ static int i915_resume(struct drm_device
-       I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
-       for (i = 0; i < 16; i++) {
--              I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]);
-+              I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
-               I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
-       }
-       for (i = 0; i < 3; i++)
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -30,6 +30,8 @@
- #ifndef _I915_DRV_H_
- #define _I915_DRV_H_
-+#include "i915_reg.h"
-+
- /* General customization:
-  */
-@@ -138,7 +140,7 @@ typedef struct drm_i915_private {
-       u32 saveDSPASTRIDE;
-       u32 saveDSPASIZE;
-       u32 saveDSPAPOS;
--      u32 saveDSPABASE;
-+      u32 saveDSPAADDR;
-       u32 saveDSPASURF;
-       u32 saveDSPATILEOFF;
-       u32 savePFIT_PGM_RATIOS;
-@@ -159,24 +161,24 @@ typedef struct drm_i915_private {
-       u32 saveDSPBSTRIDE;
-       u32 saveDSPBSIZE;
-       u32 saveDSPBPOS;
--      u32 saveDSPBBASE;
-+      u32 saveDSPBADDR;
-       u32 saveDSPBSURF;
-       u32 saveDSPBTILEOFF;
--      u32 saveVCLK_DIVISOR_VGA0;
--      u32 saveVCLK_DIVISOR_VGA1;
--      u32 saveVCLK_POST_DIV;
-+      u32 saveVGA0;
-+      u32 saveVGA1;
-+      u32 saveVGA_PD;
-       u32 saveVGACNTRL;
-       u32 saveADPA;
-       u32 saveLVDS;
--      u32 saveLVDSPP_ON;
--      u32 saveLVDSPP_OFF;
-+      u32 savePP_ON_DELAYS;
-+      u32 savePP_OFF_DELAYS;
-       u32 saveDVOA;
-       u32 saveDVOB;
-       u32 saveDVOC;
-       u32 savePP_ON;
-       u32 savePP_OFF;
-       u32 savePP_CONTROL;
--      u32 savePP_CYCLE;
-+      u32 savePP_DIVISOR;
-       u32 savePFIT_CONTROL;
-       u32 save_palette_a[256];
-       u32 save_palette_b[256];
-@@ -189,7 +191,7 @@ typedef struct drm_i915_private {
-       u32 saveIMR;
-       u32 saveCACHE_MODE_0;
-       u32 saveD_STATE;
--      u32 saveDSPCLK_GATE_D;
-+      u32 saveCG_2D_DIS;
-       u32 saveMI_ARB_STATE;
-       u32 saveSWF0[16];
-       u32 saveSWF1[16];
-@@ -283,816 +285,26 @@ extern void i915_mem_release(struct drm_
-       if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring);   \
-       dev_priv->ring.tail = outring;                                  \
-       dev_priv->ring.space -= outcount * 4;                           \
--      I915_WRITE(LP_RING + RING_TAIL, outring);                       \
-+      I915_WRITE(PRB0_TAIL, outring);                 \
- } while(0)
--extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
--
--/* Extended config space */
--#define LBB 0xf4
--
--/* VGA stuff */
--
--#define VGA_ST01_MDA 0x3ba
--#define VGA_ST01_CGA 0x3da
--
--#define VGA_MSR_WRITE 0x3c2
--#define VGA_MSR_READ 0x3cc
--#define   VGA_MSR_MEM_EN (1<<1)
--#define   VGA_MSR_CGA_MODE (1<<0)
--
--#define VGA_SR_INDEX 0x3c4
--#define VGA_SR_DATA 0x3c5
--
--#define VGA_AR_INDEX 0x3c0
--#define   VGA_AR_VID_EN (1<<5)
--#define VGA_AR_DATA_WRITE 0x3c0
--#define VGA_AR_DATA_READ 0x3c1
--
--#define VGA_GR_INDEX 0x3ce
--#define VGA_GR_DATA 0x3cf
--/* GR05 */
--#define   VGA_GR_MEM_READ_MODE_SHIFT 3
--#define     VGA_GR_MEM_READ_MODE_PLANE 1
--/* GR06 */
--#define   VGA_GR_MEM_MODE_MASK 0xc
--#define   VGA_GR_MEM_MODE_SHIFT 2
--#define   VGA_GR_MEM_A0000_AFFFF 0
--#define   VGA_GR_MEM_A0000_BFFFF 1
--#define   VGA_GR_MEM_B0000_B7FFF 2
--#define   VGA_GR_MEM_B0000_BFFFF 3
--
--#define VGA_DACMASK 0x3c6
--#define VGA_DACRX 0x3c7
--#define VGA_DACWX 0x3c8
--#define VGA_DACDATA 0x3c9
--
--#define VGA_CR_INDEX_MDA 0x3b4
--#define VGA_CR_DATA_MDA 0x3b5
--#define VGA_CR_INDEX_CGA 0x3d4
--#define VGA_CR_DATA_CGA 0x3d5
--
--#define GFX_OP_USER_INTERRUPT         ((0<<29)|(2<<23))
--#define GFX_OP_BREAKPOINT_INTERRUPT   ((0<<29)|(1<<23))
--#define CMD_REPORT_HEAD                       (7<<23)
--#define CMD_STORE_DWORD_IDX           ((0x21<<23) | 0x1)
--#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
--
--#define INST_PARSER_CLIENT   0x00000000
--#define INST_OP_FLUSH        0x02000000
--#define INST_FLUSH_MAP_CACHE 0x00000001
--
--#define BB1_START_ADDR_MASK   (~0x7)
--#define BB1_PROTECTED         (1<<0)
--#define BB1_UNPROTECTED       (0<<0)
--#define BB2_END_ADDR_MASK     (~0x7)
--
--/* Framebuffer compression */
--#define FBC_CFB_BASE          0x03200 /* 4k page aligned */
--#define FBC_LL_BASE           0x03204 /* 4k page aligned */
--#define FBC_CONTROL           0x03208
--#define   FBC_CTL_EN          (1<<31)
--#define   FBC_CTL_PERIODIC    (1<<30)
--#define   FBC_CTL_INTERVAL_SHIFT (16)
--#define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
--#define   FBC_CTL_STRIDE_SHIFT        (5)
--#define   FBC_CTL_FENCENO     (1<<0)
--#define FBC_COMMAND           0x0320c
--#define   FBC_CMD_COMPRESS    (1<<0)
--#define FBC_STATUS            0x03210
--#define   FBC_STAT_COMPRESSING        (1<<31)
--#define   FBC_STAT_COMPRESSED (1<<30)
--#define   FBC_STAT_MODIFIED   (1<<29)
--#define   FBC_STAT_CURRENT_LINE       (1<<0)
--#define FBC_CONTROL2          0x03214
--#define   FBC_CTL_FENCE_DBL   (0<<4)
--#define   FBC_CTL_IDLE_IMM    (0<<2)
--#define   FBC_CTL_IDLE_FULL   (1<<2)
--#define   FBC_CTL_IDLE_LINE   (2<<2)
--#define   FBC_CTL_IDLE_DEBUG  (3<<2)
--#define   FBC_CTL_CPU_FENCE   (1<<1)
--#define   FBC_CTL_PLANEA      (0<<0)
--#define   FBC_CTL_PLANEB      (1<<0)
--#define FBC_FENCE_OFF         0x0321b
--
--#define FBC_LL_SIZE           (1536)
--#define FBC_LL_PAD            (32)
--
--/* Interrupt bits:
-- */
--#define USER_INT_FLAG    (1<<1)
--#define VSYNC_PIPEB_FLAG (1<<5)
--#define VSYNC_PIPEA_FLAG (1<<7)
--#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
--
--#define I915REG_HWSTAM                0x02098
--#define I915REG_INT_IDENTITY_R        0x020a4
--#define I915REG_INT_MASK_R    0x020a8
--#define I915REG_INT_ENABLE_R  0x020a0
--
--#define I915REG_PIPEASTAT     0x70024
--#define I915REG_PIPEBSTAT     0x71024
--
--#define I915_VBLANK_INTERRUPT_ENABLE  (1UL<<17)
--#define I915_VBLANK_CLEAR             (1UL<<1)
--
--#define SRX_INDEX             0x3c4
--#define SRX_DATA              0x3c5
--#define SR01                  1
--#define SR01_SCREEN_OFF               (1<<5)
--
--#define PPCR                  0x61204
--#define PPCR_ON                       (1<<0)
--
--#define DVOB                  0x61140
--#define DVOB_ON                       (1<<31)
--#define DVOC                  0x61160
--#define DVOC_ON                       (1<<31)
--#define LVDS                  0x61180
--#define LVDS_ON                       (1<<31)
--
--#define ADPA                  0x61100
--#define ADPA_DPMS_MASK                (~(3<<10))
--#define ADPA_DPMS_ON          (0<<10)
--#define ADPA_DPMS_SUSPEND     (1<<10)
--#define ADPA_DPMS_STANDBY     (2<<10)
--#define ADPA_DPMS_OFF         (3<<10)
--
--#define NOPID                   0x2094
--#define LP_RING                       0x2030
--#define HP_RING                       0x2040
--/* The binner has its own ring buffer:
-- */
--#define HWB_RING              0x2400
--
--#define RING_TAIL             0x00
--#define TAIL_ADDR             0x001FFFF8
--#define RING_HEAD             0x04
--#define HEAD_WRAP_COUNT               0xFFE00000
--#define HEAD_WRAP_ONE         0x00200000
--#define HEAD_ADDR             0x001FFFFC
--#define RING_START            0x08
--#define START_ADDR            0x0xFFFFF000
--#define RING_LEN              0x0C
--#define RING_NR_PAGES         0x001FF000
--#define RING_REPORT_MASK      0x00000006
--#define RING_REPORT_64K               0x00000002
--#define RING_REPORT_128K      0x00000004
--#define RING_NO_REPORT                0x00000000
--#define RING_VALID_MASK               0x00000001
--#define RING_VALID            0x00000001
--#define RING_INVALID          0x00000000
--
--/* Instruction parser error reg:
-- */
--#define IPEIR                 0x2088
--
--/* Scratch pad debug 0 reg:
-- */
--#define SCPD0                 0x209c
--
--/* Error status reg:
-- */
--#define ESR                   0x20b8
--
--/* Secondary DMA fetch address debug reg:
-- */
--#define DMA_FADD_S            0x20d4
--
--/* Memory Interface Arbitration State
-- */
--#define MI_ARB_STATE          0x20e4
--
--/* Cache mode 0 reg.
-- *  - Manipulating render cache behaviour is central
-- *    to the concept of zone rendering, tuning this reg can help avoid
-- *    unnecessary render cache reads and even writes (for z/stencil)
-- *    at beginning and end of scene.
-- *
-- * - To change a bit, write to this reg with a mask bit set and the
-- * bit of interest either set or cleared.  EG: (BIT<<16) | BIT to set.
-- */
--#define Cache_Mode_0          0x2120
--#define CACHE_MODE_0          0x2120
--#define CM0_MASK_SHIFT          16
--#define CM0_IZ_OPT_DISABLE      (1<<6)
--#define CM0_ZR_OPT_DISABLE      (1<<5)
--#define CM0_DEPTH_EVICT_DISABLE (1<<4)
--#define CM0_COLOR_EVICT_DISABLE (1<<3)
--#define CM0_DEPTH_WRITE_DISABLE (1<<1)
--#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
--
--
--/* Graphics flush control.  A CPU write flushes the GWB of all writes.
-- * The data is discarded.
-- */
--#define GFX_FLSH_CNTL         0x2170
--
--/* Binner control.  Defines the location of the bin pointer list:
-- */
--#define BINCTL                        0x2420
--#define BC_MASK                       (1 << 9)
--
--/* Binned scene info.
-- */
--#define BINSCENE              0x2428
--#define BS_OP_LOAD            (1 << 8)
--#define BS_MASK                       (1 << 22)
--
--/* Bin command parser debug reg:
-- */
--#define BCPD                  0x2480
--
--/* Bin memory control debug reg:
-- */
--#define BMCD                  0x2484
--
--/* Bin data cache debug reg:
-- */
--#define BDCD                  0x2488
--
--/* Binner pointer cache debug reg:
-- */
--#define BPCD                  0x248c
--
--/* Binner scratch pad debug reg:
-- */
--#define BINSKPD                       0x24f0
--
--/* HWB scratch pad debug reg:
-- */
--#define HWBSKPD                       0x24f4
--
--/* Binner memory pool reg:
-- */
--#define BMP_BUFFER            0x2430
--#define BMP_PAGE_SIZE_4K      (0 << 10)
--#define BMP_BUFFER_SIZE_SHIFT 1
--#define BMP_ENABLE            (1 << 0)
--
--/* Get/put memory from the binner memory pool:
-- */
--#define BMP_GET                       0x2438
--#define BMP_PUT                       0x2440
--#define BMP_OFFSET_SHIFT      5
--
--/* 3D state packets:
-- */
--#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
--
--#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
--#define SC_UPDATE_SCISSOR       (0x1<<1)
--#define SC_ENABLE_MASK          (0x1<<0)
--#define SC_ENABLE               (0x1<<0)
--
--#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
--
--#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
--#define SCI_YMIN_MASK      (0xffff<<16)
--#define SCI_XMIN_MASK      (0xffff<<0)
--#define SCI_YMAX_MASK      (0xffff<<16)
--#define SCI_XMAX_MASK      (0xffff<<0)
--
--#define GFX_OP_SCISSOR_ENABLE  ((0x3<<29)|(0x1c<<24)|(0x10<<19))
--#define GFX_OP_SCISSOR_RECT    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
--#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
--#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
--#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
--#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
--#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
--
--#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
--
--#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
--#define XY_SRC_COPY_BLT_CMD           ((2<<29)|(0x53<<22)|6)
--#define XY_SRC_COPY_BLT_WRITE_ALPHA   (1<<21)
--#define XY_SRC_COPY_BLT_WRITE_RGB     (1<<20)
--#define XY_SRC_COPY_BLT_SRC_TILED     (1<<15)
--#define XY_SRC_COPY_BLT_DST_TILED     (1<<11)
--
--#define MI_BATCH_BUFFER               ((0x30<<23)|1)
--#define MI_BATCH_BUFFER_START (0x31<<23)
--#define MI_BATCH_BUFFER_END   (0xA<<23)
--#define MI_BATCH_NON_SECURE   (1)
--#define MI_BATCH_NON_SECURE_I965 (1<<8)
--
--#define MI_WAIT_FOR_EVENT       ((0x3<<23))
--#define MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
--#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
--#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
--
--#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
--
--#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
--#define ASYNC_FLIP                (1<<22)
--#define DISPLAY_PLANE_A           (0<<20)
--#define DISPLAY_PLANE_B           (1<<20)
--
--/* Display regs */
--#define DSPACNTR                0x70180
--#define DSPBCNTR                0x71180
--#define DISPPLANE_SEL_PIPE_MASK                 (1<<24)
--
--/* Define the region of interest for the binner:
-- */
--#define CMD_OP_BIN_CONTROL     ((0x3<<29)|(0x1d<<24)|(0x84<<16)|4)
--
--#define CMD_OP_DESTBUFFER_INFO         ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
--
--#define CMD_MI_FLUSH         (0x04 << 23)
--#define MI_NO_WRITE_FLUSH    (1 << 2)
--#define MI_READ_FLUSH        (1 << 0)
--#define MI_EXE_FLUSH         (1 << 1)
--#define MI_END_SCENE         (1 << 4) /* flush binner and incr scene count */
--#define MI_SCENE_COUNT       (1 << 3) /* just increment scene count */
--
--#define BREADCRUMB_BITS 31
--#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
--
--#define READ_BREADCRUMB(dev_priv)  (((volatile u32*)(dev_priv->hw_status_page))[5])
--#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
--
--#define BLC_PWM_CTL           0x61254
--#define BACKLIGHT_MODULATION_FREQ_SHIFT               (17)
--
--#define BLC_PWM_CTL2          0x61250
- /**
-- * This is the most significant 15 bits of the number of backlight cycles in a
-- * complete cycle of the modulated backlight control.
-+ * Reads a dword out of the status page, which is written to from the command
-+ * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
-+ * MI_STORE_DATA_IMM.
-+ *
-+ * The following dwords have a reserved meaning:
-+ * 0: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
-+ * 4: ring 0 head pointer
-+ * 5: ring 1 head pointer (915-class)
-+ * 6: ring 2 head pointer (915-class)
-  *
-- * The actual value is this field multiplied by two.
-+ * The area from dword 0x10 to 0x3ff is available for driver usage.
-  */
--#define BACKLIGHT_MODULATION_FREQ_MASK                (0x7fff << 17)
--#define BLM_LEGACY_MODE                               (1 << 16)
--/**
-- * This is the number of cycles out of the backlight modulation cycle for which
-- * the backlight is on.
-- *
-- * This field must be no greater than the number of cycles in the complete
-- * backlight modulation cycle.
-- */
--#define BACKLIGHT_DUTY_CYCLE_SHIFT            (0)
--#define BACKLIGHT_DUTY_CYCLE_MASK             (0xffff)
--
--#define I915_GCFGC                    0xf0
--#define I915_LOW_FREQUENCY_ENABLE             (1 << 7)
--#define I915_DISPLAY_CLOCK_190_200_MHZ                (0 << 4)
--#define I915_DISPLAY_CLOCK_333_MHZ            (4 << 4)
--#define I915_DISPLAY_CLOCK_MASK                       (7 << 4)
--
--#define I855_HPLLCC                   0xc0
--#define I855_CLOCK_CONTROL_MASK                       (3 << 0)
--#define I855_CLOCK_133_200                    (0 << 0)
--#define I855_CLOCK_100_200                    (1 << 0)
--#define I855_CLOCK_100_133                    (2 << 0)
--#define I855_CLOCK_166_250                    (3 << 0)
--
--/* p317, 319
-- */
--#define VCLK2_VCO_M        0x6008 /* treat as 16 bit? (includes msbs) */
--#define VCLK2_VCO_N        0x600a
--#define VCLK2_VCO_DIV_SEL  0x6012
--
--#define VCLK_DIVISOR_VGA0   0x6000
--#define VCLK_DIVISOR_VGA1   0x6004
--#define VCLK_POST_DIV     0x6010
--/** Selects a post divisor of 4 instead of 2. */
--# define VGA1_PD_P2_DIV_4     (1 << 15)
--/** Overrides the p2 post divisor field */
--# define VGA1_PD_P1_DIV_2     (1 << 13)
--# define VGA1_PD_P1_SHIFT     8
--/** P1 value is 2 greater than this field */
--# define VGA1_PD_P1_MASK      (0x1f << 8)
--/** Selects a post divisor of 4 instead of 2. */
--# define VGA0_PD_P2_DIV_4     (1 << 7)
--/** Overrides the p2 post divisor field */
--# define VGA0_PD_P1_DIV_2     (1 << 5)
--# define VGA0_PD_P1_SHIFT     0
--/** P1 value is 2 greater than this field */
--# define VGA0_PD_P1_MASK      (0x1f << 0)
--
--/* PCI D state control register */
--#define D_STATE               0x6104
--#define DSPCLK_GATE_D 0x6200
--
--/* I830 CRTC registers */
--#define HTOTAL_A      0x60000
--#define HBLANK_A      0x60004
--#define HSYNC_A               0x60008
--#define VTOTAL_A      0x6000c
--#define VBLANK_A      0x60010
--#define VSYNC_A               0x60014
--#define PIPEASRC      0x6001c
--#define BCLRPAT_A     0x60020
--#define VSYNCSHIFT_A  0x60028
--
--#define HTOTAL_B      0x61000
--#define HBLANK_B      0x61004
--#define HSYNC_B               0x61008
--#define VTOTAL_B      0x6100c
--#define VBLANK_B      0x61010
--#define VSYNC_B               0x61014
--#define PIPEBSRC      0x6101c
--#define BCLRPAT_B     0x61020
--#define VSYNCSHIFT_B  0x61028
--
--#define PP_STATUS     0x61200
--# define PP_ON                                        (1 << 31)
--/**
-- * Indicates that all dependencies of the panel are on:
-- *
-- * - PLL enabled
-- * - pipe enabled
-- * - LVDS/DVOB/DVOC on
-- */
--# define PP_READY                             (1 << 30)
--# define PP_SEQUENCE_NONE                     (0 << 28)
--# define PP_SEQUENCE_ON                               (1 << 28)
--# define PP_SEQUENCE_OFF                      (2 << 28)
--# define PP_SEQUENCE_MASK                     0x30000000
--#define PP_CONTROL    0x61204
--# define POWER_TARGET_ON                      (1 << 0)
--
--#define LVDSPP_ON       0x61208
--#define LVDSPP_OFF      0x6120c
--#define PP_CYCLE        0x61210
--
--#define PFIT_CONTROL  0x61230
--# define PFIT_ENABLE                          (1 << 31)
--# define PFIT_PIPE_MASK                               (3 << 29)
--# define PFIT_PIPE_SHIFT                      29
--# define VERT_INTERP_DISABLE                  (0 << 10)
--# define VERT_INTERP_BILINEAR                 (1 << 10)
--# define VERT_INTERP_MASK                     (3 << 10)
--# define VERT_AUTO_SCALE                      (1 << 9)
--# define HORIZ_INTERP_DISABLE                 (0 << 6)
--# define HORIZ_INTERP_BILINEAR                        (1 << 6)
--# define HORIZ_INTERP_MASK                    (3 << 6)
--# define HORIZ_AUTO_SCALE                     (1 << 5)
--# define PANEL_8TO6_DITHER_ENABLE             (1 << 3)
--
--#define PFIT_PGM_RATIOS       0x61234
--# define PFIT_VERT_SCALE_MASK                 0xfff00000
--# define PFIT_HORIZ_SCALE_MASK                        0x0000fff0
--
--#define PFIT_AUTO_RATIOS      0x61238
--
--
--#define DPLL_A                0x06014
--#define DPLL_B                0x06018
--# define DPLL_VCO_ENABLE                      (1 << 31)
--# define DPLL_DVO_HIGH_SPEED                  (1 << 30)
--# define DPLL_SYNCLOCK_ENABLE                 (1 << 29)
--# define DPLL_VGA_MODE_DIS                    (1 << 28)
--# define DPLLB_MODE_DAC_SERIAL                        (1 << 26) /* i915 */
--# define DPLLB_MODE_LVDS                      (2 << 26) /* i915 */
--# define DPLL_MODE_MASK                               (3 << 26)
--# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10      (0 << 24) /* i915 */
--# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5               (1 << 24) /* i915 */
--# define DPLLB_LVDS_P2_CLOCK_DIV_14           (0 << 24) /* i915 */
--# define DPLLB_LVDS_P2_CLOCK_DIV_7            (1 << 24) /* i915 */
--# define DPLL_P2_CLOCK_DIV_MASK                       0x03000000 /* i915 */
--# define DPLL_FPA01_P1_POST_DIV_MASK          0x00ff0000 /* i915 */
--/**
-- *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
-- * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
-- */
--# define DPLL_FPA01_P1_POST_DIV_MASK_I830     0x001f0000
--/**
-- * The i830 generation, in LVDS mode, defines P1 as the bit number set within
-- * this field (only one bit may be set).
-- */
--# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS        0x003f0000
--# define DPLL_FPA01_P1_POST_DIV_SHIFT         16
--# define PLL_P2_DIVIDE_BY_4                   (1 << 23) /* i830, required in DVO non-gang */
--# define PLL_P1_DIVIDE_BY_TWO                 (1 << 21) /* i830 */
--# define PLL_REF_INPUT_DREFCLK                        (0 << 13)
--# define PLL_REF_INPUT_TVCLKINA                       (1 << 13) /* i830 */
--# define PLL_REF_INPUT_TVCLKINBC              (2 << 13) /* SDVO TVCLKIN */
--# define PLLB_REF_INPUT_SPREADSPECTRUMIN      (3 << 13)
--# define PLL_REF_INPUT_MASK                   (3 << 13)
--# define PLL_LOAD_PULSE_PHASE_SHIFT           9
--/*
-- * Parallel to Serial Load Pulse phase selection.
-- * Selects the phase for the 10X DPLL clock for the PCIe
-- * digital display port. The range is 4 to 13; 10 or more
-- * is just a flip delay. The default is 6
-- */
--# define PLL_LOAD_PULSE_PHASE_MASK            (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
--# define DISPLAY_RATE_SELECT_FPA1             (1 << 8)
--
--/**
-- * SDVO multiplier for 945G/GM. Not used on 965.
-- *
-- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
-- */
--# define SDVO_MULTIPLIER_MASK                 0x000000ff
--# define SDVO_MULTIPLIER_SHIFT_HIRES          4
--# define SDVO_MULTIPLIER_SHIFT_VGA            0
--
--/** @defgroup DPLL_MD
-- * @{
-- */
--/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
--#define DPLL_A_MD             0x0601c
--/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
--#define DPLL_B_MD             0x06020
--/**
-- * UDI pixel divider, controlling how many pixels are stuffed into a packet.
-- *
-- * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
-- */
--# define DPLL_MD_UDI_DIVIDER_MASK             0x3f000000
--# define DPLL_MD_UDI_DIVIDER_SHIFT            24
--/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
--# define DPLL_MD_VGA_UDI_DIVIDER_MASK         0x003f0000
--# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT                16
--/**
-- * SDVO/UDI pixel multiplier.
-- *
-- * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
-- * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
-- * modes, the bus rate would be below the limits, so SDVO allows for stuffing
-- * dummy bytes in the datastream at an increased clock rate, with both sides of
-- * the link knowing how many bytes are fill.
-- *
-- * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
-- * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
-- * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
-- * through an SDVO command.
-- *
-- * This register field has values of multiplication factor minus 1, with
-- * a maximum multiplier of 5 for SDVO.
-- */
--# define DPLL_MD_UDI_MULTIPLIER_MASK          0x00003f00
--# define DPLL_MD_UDI_MULTIPLIER_SHIFT         8
--/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
-- * This best be set to the default value (3) or the CRT won't work. No,
-- * I don't entirely understand what this does...
-- */
--# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK      0x0000003f
--# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT     0
--/** @} */
--
--#define DPLL_TEST             0x606c
--# define DPLLB_TEST_SDVO_DIV_1                        (0 << 22)
--# define DPLLB_TEST_SDVO_DIV_2                        (1 << 22)
--# define DPLLB_TEST_SDVO_DIV_4                        (2 << 22)
--# define DPLLB_TEST_SDVO_DIV_MASK             (3 << 22)
--# define DPLLB_TEST_N_BYPASS                  (1 << 19)
--# define DPLLB_TEST_M_BYPASS                  (1 << 18)
--# define DPLLB_INPUT_BUFFER_ENABLE            (1 << 16)
--# define DPLLA_TEST_N_BYPASS                  (1 << 3)
--# define DPLLA_TEST_M_BYPASS                  (1 << 2)
--# define DPLLA_INPUT_BUFFER_ENABLE            (1 << 0)
--
--#define ADPA                  0x61100
--#define ADPA_DAC_ENABLE               (1<<31)
--#define ADPA_DAC_DISABLE      0
--#define ADPA_PIPE_SELECT_MASK (1<<30)
--#define ADPA_PIPE_A_SELECT    0
--#define ADPA_PIPE_B_SELECT    (1<<30)
--#define ADPA_USE_VGA_HVPOLARITY (1<<15)
--#define ADPA_SETS_HVPOLARITY  0
--#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
--#define ADPA_VSYNC_CNTL_ENABLE        0
--#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
--#define ADPA_HSYNC_CNTL_ENABLE        0
--#define ADPA_VSYNC_ACTIVE_HIGH        (1<<4)
--#define ADPA_VSYNC_ACTIVE_LOW 0
--#define ADPA_HSYNC_ACTIVE_HIGH        (1<<3)
--#define ADPA_HSYNC_ACTIVE_LOW 0
--
--#define FPA0          0x06040
--#define FPA1          0x06044
--#define FPB0          0x06048
--#define FPB1          0x0604c
--# define FP_N_DIV_MASK                                0x003f0000
--# define FP_N_DIV_SHIFT                               16
--# define FP_M1_DIV_MASK                               0x00003f00
--# define FP_M1_DIV_SHIFT                      8
--# define FP_M2_DIV_MASK                               0x0000003f
--# define FP_M2_DIV_SHIFT                      0
--
--
--#define PORT_HOTPLUG_EN               0x61110
--# define SDVOB_HOTPLUG_INT_EN                 (1 << 26)
--# define SDVOC_HOTPLUG_INT_EN                 (1 << 25)
--# define TV_HOTPLUG_INT_EN                    (1 << 18)
--# define CRT_HOTPLUG_INT_EN                   (1 << 9)
--# define CRT_HOTPLUG_FORCE_DETECT             (1 << 3)
--
--#define PORT_HOTPLUG_STAT     0x61114
--# define CRT_HOTPLUG_INT_STATUS                       (1 << 11)
--# define TV_HOTPLUG_INT_STATUS                        (1 << 10)
--# define CRT_HOTPLUG_MONITOR_MASK             (3 << 8)
--# define CRT_HOTPLUG_MONITOR_COLOR            (3 << 8)
--# define CRT_HOTPLUG_MONITOR_MONO             (2 << 8)
--# define CRT_HOTPLUG_MONITOR_NONE             (0 << 8)
--# define SDVOC_HOTPLUG_INT_STATUS             (1 << 7)
--# define SDVOB_HOTPLUG_INT_STATUS             (1 << 6)
--
--#define SDVOB                 0x61140
--#define SDVOC                 0x61160
--#define SDVO_ENABLE                           (1 << 31)
--#define SDVO_PIPE_B_SELECT                    (1 << 30)
--#define SDVO_STALL_SELECT                     (1 << 29)
--#define SDVO_INTERRUPT_ENABLE                 (1 << 26)
--/**
-- * 915G/GM SDVO pixel multiplier.
-- *
-- * Programmed value is multiplier - 1, up to 5x.
-- *
-- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
-- */
--#define SDVO_PORT_MULTIPLY_MASK                       (7 << 23)
--#define SDVO_PORT_MULTIPLY_SHIFT              23
--#define SDVO_PHASE_SELECT_MASK                        (15 << 19)
--#define SDVO_PHASE_SELECT_DEFAULT             (6 << 19)
--#define SDVO_CLOCK_OUTPUT_INVERT              (1 << 18)
--#define SDVOC_GANG_MODE                               (1 << 16)
--#define SDVO_BORDER_ENABLE                    (1 << 7)
--#define SDVOB_PCIE_CONCURRENCY                        (1 << 3)
--#define SDVO_DETECTED                         (1 << 2)
--/* Bits to be preserved when writing */
--#define SDVOB_PRESERVE_MASK                   ((1 << 17) | (1 << 16) | (1 << 14))
--#define SDVOC_PRESERVE_MASK                   (1 << 17)
--
--/** @defgroup LVDS
-- * @{
-- */
--/**
-- * This register controls the LVDS output enable, pipe selection, and data
-- * format selection.
-- *
-- * All of the clock/data pairs are force powered down by power sequencing.
-- */
--#define LVDS                  0x61180
--/**
-- * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
-- * the DPLL semantics change when the LVDS is assigned to that pipe.
-- */
--# define LVDS_PORT_EN                 (1 << 31)
--/** Selects pipe B for LVDS data.  Must be set on pre-965. */
--# define LVDS_PIPEB_SELECT            (1 << 30)
--
--/**
-- * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
-- * pixel.
-- */
--# define LVDS_A0A2_CLKA_POWER_MASK    (3 << 8)
--# define LVDS_A0A2_CLKA_POWER_DOWN    (0 << 8)
--# define LVDS_A0A2_CLKA_POWER_UP      (3 << 8)
--/**
-- * Controls the A3 data pair, which contains the additional LSBs for 24 bit
-- * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
-- * on.
-- */
--# define LVDS_A3_POWER_MASK           (3 << 6)
--# define LVDS_A3_POWER_DOWN           (0 << 6)
--# define LVDS_A3_POWER_UP             (3 << 6)
--/**
-- * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
-- * is set.
-- */
--# define LVDS_CLKB_POWER_MASK         (3 << 4)
--# define LVDS_CLKB_POWER_DOWN         (0 << 4)
--# define LVDS_CLKB_POWER_UP           (3 << 4)
--
--/**
-- * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
-- * setting for whether we are in dual-channel mode.  The B3 pair will
-- * additionally only be powered up when LVDS_A3_POWER_UP is set.
-- */
--# define LVDS_B0B3_POWER_MASK         (3 << 2)
--# define LVDS_B0B3_POWER_DOWN         (0 << 2)
--# define LVDS_B0B3_POWER_UP           (3 << 2)
--
--#define PIPEACONF 0x70008
--#define PIPEACONF_ENABLE      (1<<31)
--#define PIPEACONF_DISABLE     0
--#define PIPEACONF_DOUBLE_WIDE (1<<30)
--#define I965_PIPECONF_ACTIVE  (1<<30)
--#define PIPEACONF_SINGLE_WIDE 0
--#define PIPEACONF_PIPE_UNLOCKED 0
--#define PIPEACONF_PIPE_LOCKED (1<<25)
--#define PIPEACONF_PALETTE     0
--#define PIPEACONF_GAMMA               (1<<24)
--#define PIPECONF_FORCE_BORDER (1<<25)
--#define PIPECONF_PROGRESSIVE  (0 << 21)
--#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
--#define PIPECONF_INTERLACE_FIELD_0_ONLY               (7 << 21)
--
--#define DSPARB          0x70030
--#define DSPARB_CSTART_MASK    (0x7f << 7)
--#define DSPARB_CSTART_SHIFT   7
--#define DSPARB_BSTART_MASK    (0x7f)           
--#define DSPARB_BSTART_SHIFT   0
--
--#define PIPEBCONF 0x71008
--#define PIPEBCONF_ENABLE      (1<<31)
--#define PIPEBCONF_DISABLE     0
--#define PIPEBCONF_DOUBLE_WIDE (1<<30)
--#define PIPEBCONF_DISABLE     0
--#define PIPEBCONF_GAMMA               (1<<24)
--#define PIPEBCONF_PALETTE     0
--
--#define PIPEBGCMAXRED         0x71010
--#define PIPEBGCMAXGREEN               0x71014
--#define PIPEBGCMAXBLUE                0x71018
--#define PIPEBSTAT             0x71024
--#define PIPEBFRAMEHIGH                0x71040
--#define PIPEBFRAMEPIXEL               0x71044
--
--#define DSPACNTR              0x70180
--#define DSPBCNTR              0x71180
--#define DISPLAY_PLANE_ENABLE                  (1<<31)
--#define DISPLAY_PLANE_DISABLE                 0
--#define DISPPLANE_GAMMA_ENABLE                        (1<<30)
--#define DISPPLANE_GAMMA_DISABLE                       0
--#define DISPPLANE_PIXFORMAT_MASK              (0xf<<26)
--#define DISPPLANE_8BPP                                (0x2<<26)
--#define DISPPLANE_15_16BPP                    (0x4<<26)
--#define DISPPLANE_16BPP                               (0x5<<26)
--#define DISPPLANE_32BPP_NO_ALPHA              (0x6<<26)
--#define DISPPLANE_32BPP                               (0x7<<26)
--#define DISPPLANE_STEREO_ENABLE                       (1<<25)
--#define DISPPLANE_STEREO_DISABLE              0
--#define DISPPLANE_SEL_PIPE_MASK                       (1<<24)
--#define DISPPLANE_SEL_PIPE_A                  0
--#define DISPPLANE_SEL_PIPE_B                  (1<<24)
--#define DISPPLANE_SRC_KEY_ENABLE              (1<<22)
--#define DISPPLANE_SRC_KEY_DISABLE             0
--#define DISPPLANE_LINE_DOUBLE                 (1<<20)
--#define DISPPLANE_NO_LINE_DOUBLE              0
--#define DISPPLANE_STEREO_POLARITY_FIRST               0
--#define DISPPLANE_STEREO_POLARITY_SECOND      (1<<18)
--/* plane B only */
--#define DISPPLANE_ALPHA_TRANS_ENABLE          (1<<15)
--#define DISPPLANE_ALPHA_TRANS_DISABLE         0
--#define DISPPLANE_SPRITE_ABOVE_DISPLAYA               0
--#define DISPPLANE_SPRITE_ABOVE_OVERLAY                (1)
--
--#define DSPABASE              0x70184
--#define DSPASTRIDE            0x70188
--
--#define DSPBBASE              0x71184
--#define DSPBADDR              DSPBBASE
--#define DSPBSTRIDE            0x71188
--
--#define DSPAKEYVAL            0x70194
--#define DSPAKEYMASK           0x70198
--
--#define DSPAPOS                       0x7018C /* reserved */
--#define DSPASIZE              0x70190
--#define DSPBPOS                       0x7118C
--#define DSPBSIZE              0x71190
--
--#define DSPASURF              0x7019C
--#define DSPATILEOFF           0x701A4
--
--#define DSPBSURF              0x7119C
--#define DSPBTILEOFF           0x711A4
--
--#define VGACNTRL              0x71400
--# define VGA_DISP_DISABLE                     (1 << 31)
--# define VGA_2X_MODE                          (1 << 30)
--# define VGA_PIPE_B_SELECT                    (1 << 29)
--
--/*
-- * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
-- * of video memory available to the BIOS in SWF1.
-- */
--
--#define SWF0                  0x71410
--
--/*
-- * 855 scratch registers.
-- */
--#define SWF10                 0x70410
--
--#define SWF30                 0x72414
--
--/*
-- * Overlay registers.  These are overlay registers accessed via MMIO.
-- * Those loaded via the overlay register page are defined in i830_video.c.
-- */
--#define OVADD                 0x30000
--
--#define DOVSTA                        0x30008
--#define OC_BUF                        (0x3<<20)
-+#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
-+#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, 5)
--#define OGAMC5                        0x30010
--#define OGAMC4                        0x30014
--#define OGAMC3                        0x30018
--#define OGAMC2                        0x3001c
--#define OGAMC1                        0x30020
--#define OGAMC0                        0x30024
--/*
-- * Palette registers
-- */
--#define PALETTE_A             0x0a000
--#define PALETTE_B             0x0a800
-+extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
- #define IS_I830(dev) ((dev)->pci_device == 0x3577)
- #define IS_845G(dev) ((dev)->pci_device == 0x2562)
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -31,10 +31,6 @@
- #include "i915_drm.h"
- #include "i915_drv.h"
--#define USER_INT_FLAG (1<<1)
--#define VSYNC_PIPEB_FLAG (1<<5)
--#define VSYNC_PIPEA_FLAG (1<<7)
--
- #define MAX_NOPID ((u32)~0)
- /**
-@@ -236,40 +232,43 @@ irqreturn_t i915_driver_irq_handler(DRM_
-       u16 temp;
-       u32 pipea_stats, pipeb_stats;
--      pipea_stats = I915_READ(I915REG_PIPEASTAT);
--      pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
-+      pipea_stats = I915_READ(PIPEASTAT);
-+      pipeb_stats = I915_READ(PIPEBSTAT);
--      temp = I915_READ16(I915REG_INT_IDENTITY_R);
-+      temp = I915_READ16(IIR);
--      temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
-+      temp &= (I915_USER_INTERRUPT |
-+               I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
-+               I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT);
-       DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
-       if (temp == 0)
-               return IRQ_NONE;
--      I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
--      (void) I915_READ16(I915REG_INT_IDENTITY_R);
-+      I915_WRITE16(IIR, temp);
-+      (void) I915_READ16(IIR);
-       DRM_READMEMORYBARRIER();
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
--      if (temp & USER_INT_FLAG)
-+      if (temp & I915_USER_INTERRUPT)
-               DRM_WAKEUP(&dev_priv->irq_queue);
--      if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
-+      if (temp & (I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
-+                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)) {
-               int vblank_pipe = dev_priv->vblank_pipe;
-               if ((vblank_pipe &
-                    (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
-                   == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
--                      if (temp & VSYNC_PIPEA_FLAG)
-+                      if (temp & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-                               atomic_inc(&dev->vbl_received);
--                      if (temp & VSYNC_PIPEB_FLAG)
-+                      if (temp & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-                               atomic_inc(&dev->vbl_received2);
--              } else if (((temp & VSYNC_PIPEA_FLAG) &&
-+              } else if (((temp & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
--                         ((temp & VSYNC_PIPEB_FLAG) &&
-+                         ((temp & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
-                       atomic_inc(&dev->vbl_received);
-@@ -278,12 +277,12 @@ irqreturn_t i915_driver_irq_handler(DRM_
-               if (dev_priv->swaps_pending > 0)
-                       drm_locked_tasklet(dev, i915_vblank_tasklet);
--              I915_WRITE(I915REG_PIPEASTAT,
-+              I915_WRITE(PIPEASTAT,
-                       pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
--                      I915_VBLANK_CLEAR);
--              I915_WRITE(I915REG_PIPEBSTAT,
-+                      PIPE_VBLANK_INTERRUPT_STATUS);
-+              I915_WRITE(PIPEBSTAT,
-                       pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
--                      I915_VBLANK_CLEAR);
-+                      PIPE_VBLANK_INTERRUPT_STATUS);
-       }
-       return IRQ_HANDLED;
-@@ -304,12 +303,12 @@ static int i915_emit_irq(struct drm_devi
-               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
-       BEGIN_LP_RING(6);
--      OUT_RING(CMD_STORE_DWORD_IDX);
--      OUT_RING(20);
-+      OUT_RING(MI_STORE_DWORD_INDEX);
-+      OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
-       OUT_RING(0);
--      OUT_RING(GFX_OP_USER_INTERRUPT);
-+      OUT_RING(MI_USER_INTERRUPT);
-       ADVANCE_LP_RING();
-       return dev_priv->counter;
-@@ -421,11 +420,11 @@ static void i915_enable_interrupt (struc
-       flag = 0;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
--              flag |= VSYNC_PIPEA_FLAG;
-+              flag |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
--              flag |= VSYNC_PIPEB_FLAG;
-+              flag |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
--      I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
-+      I915_WRITE16(IER, I915_USER_INTERRUPT | flag);
- }
- /* Set the vblank monitor pipe
-@@ -465,11 +464,11 @@ int i915_vblank_pipe_get(struct drm_devi
-               return -EINVAL;
-       }
--      flag = I915_READ(I915REG_INT_ENABLE_R);
-+      flag = I915_READ(IER);
-       pipe->pipe = 0;
--      if (flag & VSYNC_PIPEA_FLAG)
-+      if (flag & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-               pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
--      if (flag & VSYNC_PIPEB_FLAG)
-+      if (flag & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-               pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
-       return 0;
-@@ -587,9 +586,9 @@ void i915_driver_irq_preinstall(struct d
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      I915_WRITE16(I915REG_HWSTAM, 0xfffe);
--      I915_WRITE16(I915REG_INT_MASK_R, 0x0);
--      I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
-+      I915_WRITE16(HWSTAM, 0xfffe);
-+      I915_WRITE16(IMR, 0x0);
-+      I915_WRITE16(IER, 0x0);
- }
- void i915_driver_irq_postinstall(struct drm_device * dev)
-@@ -614,10 +613,10 @@ void i915_driver_irq_uninstall(struct dr
-       if (!dev_priv)
-               return;
--      I915_WRITE16(I915REG_HWSTAM, 0xffff);
--      I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
--      I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
-+      I915_WRITE16(HWSTAM, 0xffff);
-+      I915_WRITE16(IMR, 0xffff);
-+      I915_WRITE16(IER, 0x0);
--      temp = I915_READ16(I915REG_INT_IDENTITY_R);
--      I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
-+      temp = I915_READ16(IIR);
-+      I915_WRITE16(IIR, temp);
- }
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_reg.h
-@@ -0,0 +1,1405 @@
-+/* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
-+ * All Rights Reserved.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the
-+ * "Software"), to deal in the Software without restriction, including
-+ * without limitation the rights to use, copy, modify, merge, publish,
-+ * distribute, sub license, and/or sell copies of the Software, and to
-+ * permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the
-+ * next paragraph) shall be included in all copies or substantial portions
-+ * of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
-+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-+ */
-+
-+#ifndef _I915_REG_H_
-+#define _I915_REG_H_
-+
-+/* MCH MMIO space */
-+/** 915-945 and GM965 MCH register controlling DRAM channel access */
-+#define DCC           0x200
-+#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL            (0 << 0)
-+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC   (1 << 0)
-+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED  (2 << 0)
-+#define DCC_ADDRESSING_MODE_MASK                      (3 << 0)
-+#define DCC_CHANNEL_XOR_DISABLE                               (1 << 10)
-+
-+/** 965 MCH register controlling DRAM channel configuration */
-+#define CHDECMISC             0x111
-+#define CHDECMISC_FLEXMEMORY          (1 << 1)
-+
-+/*
-+ * The Bridge device's PCI config space has information about the
-+ * fb aperture size and the amount of pre-reserved memory.
-+ */
-+#define INTEL_GMCH_CTRL               0x52
-+#define INTEL_GMCH_ENABLED    0x4
-+#define INTEL_GMCH_MEM_MASK   0x1
-+#define INTEL_GMCH_MEM_64M    0x1
-+#define INTEL_GMCH_MEM_128M   0
-+
-+#define INTEL_855_GMCH_GMS_MASK               (0x7 << 4)
-+#define INTEL_855_GMCH_GMS_DISABLED   (0x0 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_1M  (0x1 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_4M  (0x2 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_8M  (0x3 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4)
-+
-+#define INTEL_915G_GMCH_GMS_STOLEN_48M        (0x6 << 4)
-+#define INTEL_915G_GMCH_GMS_STOLEN_64M        (0x7 << 4)
-+
-+/* PCI config space */
-+
-+#define HPLLCC        0xc0 /* 855 only */
-+#define   GC_CLOCK_CONTROL_MASK               (3 << 0)
-+#define   GC_CLOCK_133_200            (0 << 0)
-+#define   GC_CLOCK_100_200            (1 << 0)
-+#define   GC_CLOCK_100_133            (2 << 0)
-+#define   GC_CLOCK_166_250            (3 << 0)
-+#define GCFGC 0xf0 /* 915+ only */
-+#define   GC_LOW_FREQUENCY_ENABLE     (1 << 7)
-+#define   GC_DISPLAY_CLOCK_190_200_MHZ        (0 << 4)
-+#define   GC_DISPLAY_CLOCK_333_MHZ    (4 << 4)
-+#define   GC_DISPLAY_CLOCK_MASK               (7 << 4)
-+#define LBB   0xf4
-+
-+/* VGA stuff */
-+
-+#define VGA_ST01_MDA 0x3ba
-+#define VGA_ST01_CGA 0x3da
-+
-+#define VGA_MSR_WRITE 0x3c2
-+#define VGA_MSR_READ 0x3cc
-+#define   VGA_MSR_MEM_EN (1<<1)
-+#define   VGA_MSR_CGA_MODE (1<<0)
-+
-+#define VGA_SR_INDEX 0x3c4
-+#define VGA_SR_DATA 0x3c5
-+
-+#define VGA_AR_INDEX 0x3c0
-+#define   VGA_AR_VID_EN (1<<5)
-+#define VGA_AR_DATA_WRITE 0x3c0
-+#define VGA_AR_DATA_READ 0x3c1
-+
-+#define VGA_GR_INDEX 0x3ce
-+#define VGA_GR_DATA 0x3cf
-+/* GR05 */
-+#define   VGA_GR_MEM_READ_MODE_SHIFT 3
-+#define     VGA_GR_MEM_READ_MODE_PLANE 1
-+/* GR06 */
-+#define   VGA_GR_MEM_MODE_MASK 0xc
-+#define   VGA_GR_MEM_MODE_SHIFT 2
-+#define   VGA_GR_MEM_A0000_AFFFF 0
-+#define   VGA_GR_MEM_A0000_BFFFF 1
-+#define   VGA_GR_MEM_B0000_B7FFF 2
-+#define   VGA_GR_MEM_B0000_BFFFF 3
-+
-+#define VGA_DACMASK 0x3c6
-+#define VGA_DACRX 0x3c7
-+#define VGA_DACWX 0x3c8
-+#define VGA_DACDATA 0x3c9
-+
-+#define VGA_CR_INDEX_MDA 0x3b4
-+#define VGA_CR_DATA_MDA 0x3b5
-+#define VGA_CR_INDEX_CGA 0x3d4
-+#define VGA_CR_DATA_CGA 0x3d5
-+
-+/*
-+ * Memory interface instructions used by the kernel
-+ */
-+#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
-+
-+#define MI_NOOP                       MI_INSTR(0, 0)
-+#define MI_USER_INTERRUPT     MI_INSTR(0x02, 0)
-+#define MI_WAIT_FOR_EVENT       MI_INSTR(0x03, 0)
-+#define   MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
-+#define   MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
-+#define   MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-+#define MI_FLUSH              MI_INSTR(0x04, 0)
-+#define   MI_READ_FLUSH               (1 << 0)
-+#define   MI_EXE_FLUSH                (1 << 1)
-+#define   MI_NO_WRITE_FLUSH   (1 << 2)
-+#define   MI_SCENE_COUNT      (1 << 3) /* just increment scene count */
-+#define   MI_END_SCENE                (1 << 4) /* flush binner and incr scene count */
-+#define MI_BATCH_BUFFER_END   MI_INSTR(0x0a, 0)
-+#define MI_REPORT_HEAD                MI_INSTR(0x07, 0)
-+#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
-+#define MI_STORE_DWORD_IMM    MI_INSTR(0x20, 1)
-+#define   MI_MEM_VIRTUAL      (1 << 22) /* 965+ only */
-+#define MI_STORE_DWORD_INDEX  MI_INSTR(0x21, 1)
-+#define   MI_STORE_DWORD_INDEX_SHIFT 2
-+#define MI_LOAD_REGISTER_IMM  MI_INSTR(0x22, 1)
-+#define MI_BATCH_BUFFER               MI_INSTR(0x30, 1)
-+#define   MI_BATCH_NON_SECURE (1)
-+#define   MI_BATCH_NON_SECURE_I965 (1<<8)
-+#define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0)
-+
-+/*
-+ * 3D instructions used by the kernel
-+ */
-+#define GFX_INSTR(opcode, flags) ((0x3 << 29) | ((opcode) << 24) | (flags))
-+
-+#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
-+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-+#define   SC_UPDATE_SCISSOR       (0x1<<1)
-+#define   SC_ENABLE_MASK          (0x1<<0)
-+#define   SC_ENABLE               (0x1<<0)
-+#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
-+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-+#define   SCI_YMIN_MASK      (0xffff<<16)
-+#define   SCI_XMIN_MASK      (0xffff<<0)
-+#define   SCI_YMAX_MASK      (0xffff<<16)
-+#define   SCI_XMAX_MASK      (0xffff<<0)
-+#define GFX_OP_SCISSOR_ENABLE  ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-+#define GFX_OP_SCISSOR_RECT    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
-+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
-+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-+#define GFX_OP_DESTBUFFER_INFO         ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
-+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-+#define GFX_OP_DRAWRECT_INFO_I965  ((0x7900<<16)|0x2)
-+#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
-+#define XY_SRC_COPY_BLT_CMD           ((2<<29)|(0x53<<22)|6)
-+#define XY_MONO_SRC_COPY_IMM_BLT      ((2<<29)|(0x71<<22)|5)
-+#define XY_SRC_COPY_BLT_WRITE_ALPHA   (1<<21)
-+#define XY_SRC_COPY_BLT_WRITE_RGB     (1<<20)
-+#define   BLT_DEPTH_8                 (0<<24)
-+#define   BLT_DEPTH_16_565            (1<<24)
-+#define   BLT_DEPTH_16_1555           (2<<24)
-+#define   BLT_DEPTH_32                        (3<<24)
-+#define   BLT_ROP_GXCOPY              (0xcc<<16)
-+#define XY_SRC_COPY_BLT_SRC_TILED     (1<<15) /* 965+ only */
-+#define XY_SRC_COPY_BLT_DST_TILED     (1<<11) /* 965+ only */
-+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
-+#define   ASYNC_FLIP                (1<<22)
-+#define   DISPLAY_PLANE_A           (0<<20)
-+#define   DISPLAY_PLANE_B           (1<<20)
-+
-+/*
-+ * Instruction and interrupt control regs
-+ */
-+
-+#define PRB0_TAIL     0x02030
-+#define PRB0_HEAD     0x02034
-+#define PRB0_START    0x02038
-+#define PRB0_CTL      0x0203c
-+#define   TAIL_ADDR           0x001FFFF8
-+#define   HEAD_WRAP_COUNT     0xFFE00000
-+#define   HEAD_WRAP_ONE               0x00200000
-+#define   HEAD_ADDR           0x001FFFFC
-+#define   RING_NR_PAGES               0x001FF000
-+#define   RING_REPORT_MASK    0x00000006
-+#define   RING_REPORT_64K     0x00000002
-+#define   RING_REPORT_128K    0x00000004
-+#define   RING_NO_REPORT      0x00000000
-+#define   RING_VALID_MASK     0x00000001
-+#define   RING_VALID          0x00000001
-+#define   RING_INVALID                0x00000000
-+#define PRB1_TAIL     0x02040 /* 915+ only */
-+#define PRB1_HEAD     0x02044 /* 915+ only */
-+#define PRB1_START    0x02048 /* 915+ only */
-+#define PRB1_CTL      0x0204c /* 915+ only */
-+#define ACTHD_I965    0x02074
-+#define HWS_PGA               0x02080
-+#define HWS_ADDRESS_MASK      0xfffff000
-+#define HWS_START_ADDRESS_SHIFT       4
-+#define IPEIR         0x02088
-+#define NOPID         0x02094
-+#define HWSTAM                0x02098
-+#define SCPD0         0x0209c /* 915+ only */
-+#define IER           0x020a0
-+#define IIR           0x020a4
-+#define IMR           0x020a8
-+#define ISR           0x020ac
-+#define   I915_PIPE_CONTROL_NOTIFY_INTERRUPT          (1<<18)
-+#define   I915_DISPLAY_PORT_INTERRUPT                 (1<<17)
-+#define   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT  (1<<15)
-+#define   I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT    (1<<14)
-+#define   I915_HWB_OOM_INTERRUPT                      (1<<13)
-+#define   I915_SYNC_STATUS_INTERRUPT                  (1<<12)
-+#define   I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11)
-+#define   I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10)
-+#define   I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT   (1<<9)
-+#define   I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8)
-+#define   I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT                (1<<7)
-+#define   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT         (1<<6)
-+#define   I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT                (1<<5)
-+#define   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT         (1<<4)
-+#define   I915_DEBUG_INTERRUPT                                (1<<2)
-+#define   I915_USER_INTERRUPT                         (1<<1)
-+#define   I915_ASLE_INTERRUPT                         (1<<0)
-+#define EIR           0x020b0
-+#define EMR           0x020b4
-+#define ESR           0x020b8
-+#define INSTPM                0x020c0
-+#define ACTHD         0x020c8
-+#define FW_BLC                0x020d8
-+#define FW_BLC_SELF   0x020e0 /* 915+ only */
-+#define MI_ARB_STATE  0x020e4 /* 915+ only */
-+#define CACHE_MODE_0  0x02120 /* 915+ only */
-+#define   CM0_MASK_SHIFT          16
-+#define   CM0_IZ_OPT_DISABLE      (1<<6)
-+#define   CM0_ZR_OPT_DISABLE      (1<<5)
-+#define   CM0_DEPTH_EVICT_DISABLE (1<<4)
-+#define   CM0_COLOR_EVICT_DISABLE (1<<3)
-+#define   CM0_DEPTH_WRITE_DISABLE (1<<1)
-+#define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
-+#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
-+
-+/*
-+ * Framebuffer compression (915+ only)
-+ */
-+
-+#define FBC_CFB_BASE          0x03200 /* 4k page aligned */
-+#define FBC_LL_BASE           0x03204 /* 4k page aligned */
-+#define FBC_CONTROL           0x03208
-+#define   FBC_CTL_EN          (1<<31)
-+#define   FBC_CTL_PERIODIC    (1<<30)
-+#define   FBC_CTL_INTERVAL_SHIFT (16)
-+#define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
-+#define   FBC_CTL_STRIDE_SHIFT        (5)
-+#define   FBC_CTL_FENCENO     (1<<0)
-+#define FBC_COMMAND           0x0320c
-+#define   FBC_CMD_COMPRESS    (1<<0)
-+#define FBC_STATUS            0x03210
-+#define   FBC_STAT_COMPRESSING        (1<<31)
-+#define   FBC_STAT_COMPRESSED (1<<30)
-+#define   FBC_STAT_MODIFIED   (1<<29)
-+#define   FBC_STAT_CURRENT_LINE       (1<<0)
-+#define FBC_CONTROL2          0x03214
-+#define   FBC_CTL_FENCE_DBL   (0<<4)
-+#define   FBC_CTL_IDLE_IMM    (0<<2)
-+#define   FBC_CTL_IDLE_FULL   (1<<2)
-+#define   FBC_CTL_IDLE_LINE   (2<<2)
-+#define   FBC_CTL_IDLE_DEBUG  (3<<2)
-+#define   FBC_CTL_CPU_FENCE   (1<<1)
-+#define   FBC_CTL_PLANEA      (0<<0)
-+#define   FBC_CTL_PLANEB      (1<<0)
-+#define FBC_FENCE_OFF         0x0321b
-+
-+#define FBC_LL_SIZE           (1536)
-+
-+/*
-+ * GPIO regs
-+ */
-+#define GPIOA                 0x5010
-+#define GPIOB                 0x5014
-+#define GPIOC                 0x5018
-+#define GPIOD                 0x501c
-+#define GPIOE                 0x5020
-+#define GPIOF                 0x5024
-+#define GPIOG                 0x5028
-+#define GPIOH                 0x502c
-+# define GPIO_CLOCK_DIR_MASK          (1 << 0)
-+# define GPIO_CLOCK_DIR_IN            (0 << 1)
-+# define GPIO_CLOCK_DIR_OUT           (1 << 1)
-+# define GPIO_CLOCK_VAL_MASK          (1 << 2)
-+# define GPIO_CLOCK_VAL_OUT           (1 << 3)
-+# define GPIO_CLOCK_VAL_IN            (1 << 4)
-+# define GPIO_CLOCK_PULLUP_DISABLE    (1 << 5)
-+# define GPIO_DATA_DIR_MASK           (1 << 8)
-+# define GPIO_DATA_DIR_IN             (0 << 9)
-+# define GPIO_DATA_DIR_OUT            (1 << 9)
-+# define GPIO_DATA_VAL_MASK           (1 << 10)
-+# define GPIO_DATA_VAL_OUT            (1 << 11)
-+# define GPIO_DATA_VAL_IN             (1 << 12)
-+# define GPIO_DATA_PULLUP_DISABLE     (1 << 13)
-+
-+/*
-+ * Clock control & power management
-+ */
-+
-+#define VGA0  0x6000
-+#define VGA1  0x6004
-+#define VGA_PD        0x6010
-+#define   VGA0_PD_P2_DIV_4    (1 << 7)
-+#define   VGA0_PD_P1_DIV_2    (1 << 5)
-+#define   VGA0_PD_P1_SHIFT    0
-+#define   VGA0_PD_P1_MASK     (0x1f << 0)
-+#define   VGA1_PD_P2_DIV_4    (1 << 15)
-+#define   VGA1_PD_P1_DIV_2    (1 << 13)
-+#define   VGA1_PD_P1_SHIFT    8
-+#define   VGA1_PD_P1_MASK     (0x1f << 8)
-+#define DPLL_A        0x06014
-+#define DPLL_B        0x06018
-+#define   DPLL_VCO_ENABLE             (1 << 31)
-+#define   DPLL_DVO_HIGH_SPEED         (1 << 30)
-+#define   DPLL_SYNCLOCK_ENABLE                (1 << 29)
-+#define   DPLL_VGA_MODE_DIS           (1 << 28)
-+#define   DPLLB_MODE_DAC_SERIAL               (1 << 26) /* i915 */
-+#define   DPLLB_MODE_LVDS             (2 << 26) /* i915 */
-+#define   DPLL_MODE_MASK              (3 << 26)
-+#define   DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
-+#define   DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
-+#define   DPLLB_LVDS_P2_CLOCK_DIV_14  (0 << 24) /* i915 */
-+#define   DPLLB_LVDS_P2_CLOCK_DIV_7   (1 << 24) /* i915 */
-+#define   DPLL_P2_CLOCK_DIV_MASK      0x03000000 /* i915 */
-+#define   DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
-+
-+#define I915_FIFO_UNDERRUN_STATUS             (1UL<<31)
-+#define I915_CRC_ERROR_ENABLE                 (1UL<<29)
-+#define I915_CRC_DONE_ENABLE                  (1UL<<28)
-+#define I915_GMBUS_EVENT_ENABLE                       (1UL<<27)
-+#define I915_VSYNC_INTERRUPT_ENABLE           (1UL<<25)
-+#define I915_DISPLAY_LINE_COMPARE_ENABLE      (1UL<<24)
-+#define I915_DPST_EVENT_ENABLE                        (1UL<<23)
-+#define I915_LEGACY_BLC_EVENT_ENABLE          (1UL<<22)
-+#define I915_ODD_FIELD_INTERRUPT_ENABLE               (1UL<<21)
-+#define I915_EVEN_FIELD_INTERRUPT_ENABLE      (1UL<<20)
-+#define I915_START_VBLANK_INTERRUPT_ENABLE    (1UL<<18)       /* 965 or later */
-+#define I915_VBLANK_INTERRUPT_ENABLE          (1UL<<17)
-+#define I915_OVERLAY_UPDATED_ENABLE           (1UL<<16)
-+#define I915_CRC_ERROR_INTERRUPT_STATUS               (1UL<<13)
-+#define I915_CRC_DONE_INTERRUPT_STATUS                (1UL<<12)
-+#define I915_GMBUS_INTERRUPT_STATUS           (1UL<<11)
-+#define I915_VSYNC_INTERRUPT_STATUS           (1UL<<9)
-+#define I915_DISPLAY_LINE_COMPARE_STATUS      (1UL<<8)
-+#define I915_DPST_EVENT_STATUS                        (1UL<<7)
-+#define I915_LEGACY_BLC_EVENT_STATUS          (1UL<<6)
-+#define I915_ODD_FIELD_INTERRUPT_STATUS               (1UL<<5)
-+#define I915_EVEN_FIELD_INTERRUPT_STATUS      (1UL<<4)
-+#define I915_START_VBLANK_INTERRUPT_STATUS    (1UL<<2)        /* 965 or later */
-+#define I915_VBLANK_INTERRUPT_STATUS          (1UL<<1)
-+#define I915_OVERLAY_UPDATED_STATUS           (1UL<<0)
-+
-+#define SRX_INDEX             0x3c4
-+#define SRX_DATA              0x3c5
-+#define SR01                  1
-+#define SR01_SCREEN_OFF               (1<<5)
-+
-+#define PPCR                  0x61204
-+#define PPCR_ON                       (1<<0)
-+
-+#define DVOB                  0x61140
-+#define DVOB_ON                       (1<<31)
-+#define DVOC                  0x61160
-+#define DVOC_ON                       (1<<31)
-+#define LVDS                  0x61180
-+#define LVDS_ON                       (1<<31)
-+
-+#define ADPA                  0x61100
-+#define ADPA_DPMS_MASK                (~(3<<10))
-+#define ADPA_DPMS_ON          (0<<10)
-+#define ADPA_DPMS_SUSPEND     (1<<10)
-+#define ADPA_DPMS_STANDBY     (2<<10)
-+#define ADPA_DPMS_OFF         (3<<10)
-+
-+#define RING_TAIL             0x00
-+#define TAIL_ADDR             0x001FFFF8
-+#define RING_HEAD             0x04
-+#define HEAD_WRAP_COUNT               0xFFE00000
-+#define HEAD_WRAP_ONE         0x00200000
-+#define HEAD_ADDR             0x001FFFFC
-+#define RING_START            0x08
-+#define START_ADDR            0xFFFFF000
-+#define RING_LEN              0x0C
-+#define RING_NR_PAGES         0x001FF000
-+#define RING_REPORT_MASK      0x00000006
-+#define RING_REPORT_64K               0x00000002
-+#define RING_REPORT_128K      0x00000004
-+#define RING_NO_REPORT                0x00000000
-+#define RING_VALID_MASK               0x00000001
-+#define RING_VALID            0x00000001
-+#define RING_INVALID          0x00000000
-+
-+/* Scratch pad debug 0 reg:
-+ */
-+#define   DPLL_FPA01_P1_POST_DIV_MASK_I830    0x001f0000
-+/*
-+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
-+ * this field (only one bit may be set).
-+ */
-+#define   DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS       0x003f0000
-+#define   DPLL_FPA01_P1_POST_DIV_SHIFT        16
-+/* i830, required in DVO non-gang */
-+#define   PLL_P2_DIVIDE_BY_4          (1 << 23)
-+#define   PLL_P1_DIVIDE_BY_TWO                (1 << 21) /* i830 */
-+#define   PLL_REF_INPUT_DREFCLK               (0 << 13)
-+#define   PLL_REF_INPUT_TVCLKINA      (1 << 13) /* i830 */
-+#define   PLL_REF_INPUT_TVCLKINBC     (2 << 13) /* SDVO TVCLKIN */
-+#define   PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
-+#define   PLL_REF_INPUT_MASK          (3 << 13)
-+#define   PLL_LOAD_PULSE_PHASE_SHIFT          9
-+/*
-+ * Parallel to Serial Load Pulse phase selection.
-+ * Selects the phase for the 10X DPLL clock for the PCIe
-+ * digital display port. The range is 4 to 13; 10 or more
-+ * is just a flip delay. The default is 6
-+ */
-+#define   PLL_LOAD_PULSE_PHASE_MASK           (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-+#define   DISPLAY_RATE_SELECT_FPA1            (1 << 8)
-+/*
-+ * SDVO multiplier for 945G/GM. Not used on 965.
-+ */
-+#define   SDVO_MULTIPLIER_MASK                        0x000000ff
-+#define   SDVO_MULTIPLIER_SHIFT_HIRES         4
-+#define   SDVO_MULTIPLIER_SHIFT_VGA           0
-+#define DPLL_A_MD 0x0601c /* 965+ only */
-+/*
-+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
-+ *
-+ * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
-+ */
-+#define   DPLL_MD_UDI_DIVIDER_MASK            0x3f000000
-+#define   DPLL_MD_UDI_DIVIDER_SHIFT           24
-+/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-+#define   DPLL_MD_VGA_UDI_DIVIDER_MASK                0x003f0000
-+#define   DPLL_MD_VGA_UDI_DIVIDER_SHIFT               16
-+/*
-+ * SDVO/UDI pixel multiplier.
-+ *
-+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
-+ * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
-+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
-+ * dummy bytes in the datastream at an increased clock rate, with both sides of
-+ * the link knowing how many bytes are fill.
-+ *
-+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
-+ * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
-+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
-+ * through an SDVO command.
-+ *
-+ * This register field has values of multiplication factor minus 1, with
-+ * a maximum multiplier of 5 for SDVO.
-+ */
-+#define   DPLL_MD_UDI_MULTIPLIER_MASK         0x00003f00
-+#define   DPLL_MD_UDI_MULTIPLIER_SHIFT                8
-+/*
-+ * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
-+ * This best be set to the default value (3) or the CRT won't work. No,
-+ * I don't entirely understand what this does...
-+ */
-+#define   DPLL_MD_VGA_UDI_MULTIPLIER_MASK     0x0000003f
-+#define   DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT    0
-+#define DPLL_B_MD 0x06020 /* 965+ only */
-+#define FPA0  0x06040
-+#define FPA1  0x06044
-+#define FPB0  0x06048
-+#define FPB1  0x0604c
-+#define   FP_N_DIV_MASK               0x003f0000
-+#define   FP_N_DIV_SHIFT              16
-+#define   FP_M1_DIV_MASK      0x00003f00
-+#define   FP_M1_DIV_SHIFT              8
-+#define   FP_M2_DIV_MASK      0x0000003f
-+#define   FP_M2_DIV_SHIFT              0
-+#define DPLL_TEST     0x606c
-+#define   DPLLB_TEST_SDVO_DIV_1               (0 << 22)
-+#define   DPLLB_TEST_SDVO_DIV_2               (1 << 22)
-+#define   DPLLB_TEST_SDVO_DIV_4               (2 << 22)
-+#define   DPLLB_TEST_SDVO_DIV_MASK    (3 << 22)
-+#define   DPLLB_TEST_N_BYPASS         (1 << 19)
-+#define   DPLLB_TEST_M_BYPASS         (1 << 18)
-+#define   DPLLB_INPUT_BUFFER_ENABLE   (1 << 16)
-+#define   DPLLA_TEST_N_BYPASS         (1 << 3)
-+#define   DPLLA_TEST_M_BYPASS         (1 << 2)
-+#define   DPLLA_INPUT_BUFFER_ENABLE   (1 << 0)
-+#define D_STATE               0x6104
-+#define CG_2D_DIS     0x6200
-+#define CG_3D_DIS     0x6204
-+
-+/*
-+ * Palette regs
-+ */
-+
-+#define PALETTE_A             0x0a000
-+#define PALETTE_B             0x0a800
-+
-+/*
-+ * Overlay regs
-+ */
-+
-+#define OVADD                 0x30000
-+#define DOVSTA                        0x30008
-+#define OC_BUF                        (0x3<<20)
-+#define OGAMC5                        0x30010
-+#define OGAMC4                        0x30014
-+#define OGAMC3                        0x30018
-+#define OGAMC2                        0x3001c
-+#define OGAMC1                        0x30020
-+#define OGAMC0                        0x30024
-+
-+/*
-+ * Display engine regs
-+ */
-+
-+/* Pipe A timing regs */
-+#define HTOTAL_A      0x60000
-+#define HBLANK_A      0x60004
-+#define HSYNC_A               0x60008
-+#define VTOTAL_A      0x6000c
-+#define VBLANK_A      0x60010
-+#define VSYNC_A               0x60014
-+#define PIPEASRC      0x6001c
-+#define BCLRPAT_A     0x60020
-+
-+/* Pipe B timing regs */
-+#define HTOTAL_B      0x61000
-+#define HBLANK_B      0x61004
-+#define HSYNC_B               0x61008
-+#define VTOTAL_B      0x6100c
-+#define VBLANK_B      0x61010
-+#define VSYNC_B               0x61014
-+#define PIPEBSRC      0x6101c
-+#define BCLRPAT_B     0x61020
-+
-+/* VGA port control */
-+#define ADPA                  0x61100
-+#define   ADPA_DAC_ENABLE     (1<<31)
-+#define   ADPA_DAC_DISABLE    0
-+#define   ADPA_PIPE_SELECT_MASK       (1<<30)
-+#define   ADPA_PIPE_A_SELECT  0
-+#define   ADPA_PIPE_B_SELECT  (1<<30)
-+#define   ADPA_USE_VGA_HVPOLARITY (1<<15)
-+#define   ADPA_SETS_HVPOLARITY        0
-+#define   ADPA_VSYNC_CNTL_DISABLE (1<<11)
-+#define   ADPA_VSYNC_CNTL_ENABLE 0
-+#define   ADPA_HSYNC_CNTL_DISABLE (1<<10)
-+#define   ADPA_HSYNC_CNTL_ENABLE 0
-+#define   ADPA_VSYNC_ACTIVE_HIGH (1<<4)
-+#define   ADPA_VSYNC_ACTIVE_LOW       0
-+#define   ADPA_HSYNC_ACTIVE_HIGH (1<<3)
-+#define   ADPA_HSYNC_ACTIVE_LOW       0
-+#define   ADPA_DPMS_MASK      (~(3<<10))
-+#define   ADPA_DPMS_ON                (0<<10)
-+#define   ADPA_DPMS_SUSPEND   (1<<10)
-+#define   ADPA_DPMS_STANDBY   (2<<10)
-+#define   ADPA_DPMS_OFF               (3<<10)
-+
-+/* Hotplug control (945+ only) */
-+#define PORT_HOTPLUG_EN               0x61110
-+#define   SDVOB_HOTPLUG_INT_EN                        (1 << 26)
-+#define   SDVOC_HOTPLUG_INT_EN                        (1 << 25)
-+#define   TV_HOTPLUG_INT_EN                   (1 << 18)
-+#define   CRT_HOTPLUG_INT_EN                  (1 << 9)
-+#define   CRT_HOTPLUG_FORCE_DETECT            (1 << 3)
-+
-+#define PORT_HOTPLUG_STAT     0x61114
-+#define   CRT_HOTPLUG_INT_STATUS              (1 << 11)
-+#define   TV_HOTPLUG_INT_STATUS                       (1 << 10)
-+#define   CRT_HOTPLUG_MONITOR_MASK            (3 << 8)
-+#define   CRT_HOTPLUG_MONITOR_COLOR           (3 << 8)
-+#define   CRT_HOTPLUG_MONITOR_MONO            (2 << 8)
-+#define   CRT_HOTPLUG_MONITOR_NONE            (0 << 8)
-+#define   SDVOC_HOTPLUG_INT_STATUS            (1 << 7)
-+#define   SDVOB_HOTPLUG_INT_STATUS            (1 << 6)
-+
-+/* SDVO port control */
-+#define SDVOB                 0x61140
-+#define SDVOC                 0x61160
-+#define   SDVO_ENABLE         (1 << 31)
-+#define   SDVO_PIPE_B_SELECT  (1 << 30)
-+#define   SDVO_STALL_SELECT   (1 << 29)
-+#define   SDVO_INTERRUPT_ENABLE       (1 << 26)
-+/**
-+ * 915G/GM SDVO pixel multiplier.
-+ *
-+ * Programmed value is multiplier - 1, up to 5x.
-+ *
-+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
-+ */
-+#define   SDVO_PORT_MULTIPLY_MASK     (7 << 23)
-+#define   SDVO_PORT_MULTIPLY_SHIFT            23
-+#define   SDVO_PHASE_SELECT_MASK      (15 << 19)
-+#define   SDVO_PHASE_SELECT_DEFAULT   (6 << 19)
-+#define   SDVO_CLOCK_OUTPUT_INVERT    (1 << 18)
-+#define   SDVOC_GANG_MODE             (1 << 16)
-+#define   SDVO_BORDER_ENABLE          (1 << 7)
-+#define   SDVOB_PCIE_CONCURRENCY      (1 << 3)
-+#define   SDVO_DETECTED                       (1 << 2)
-+/* Bits to be preserved when writing */
-+#define   SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26))
-+#define   SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26))
-+
-+/* DVO port control */
-+#define DVOA                  0x61120
-+#define DVOB                  0x61140
-+#define DVOC                  0x61160
-+#define   DVO_ENABLE                  (1 << 31)
-+#define   DVO_PIPE_B_SELECT           (1 << 30)
-+#define   DVO_PIPE_STALL_UNUSED               (0 << 28)
-+#define   DVO_PIPE_STALL              (1 << 28)
-+#define   DVO_PIPE_STALL_TV           (2 << 28)
-+#define   DVO_PIPE_STALL_MASK         (3 << 28)
-+#define   DVO_USE_VGA_SYNC            (1 << 15)
-+#define   DVO_DATA_ORDER_I740         (0 << 14)
-+#define   DVO_DATA_ORDER_FP           (1 << 14)
-+#define   DVO_VSYNC_DISABLE           (1 << 11)
-+#define   DVO_HSYNC_DISABLE           (1 << 10)
-+#define   DVO_VSYNC_TRISTATE          (1 << 9)
-+#define   DVO_HSYNC_TRISTATE          (1 << 8)
-+#define   DVO_BORDER_ENABLE           (1 << 7)
-+#define   DVO_DATA_ORDER_GBRG         (1 << 6)
-+#define   DVO_DATA_ORDER_RGGB         (0 << 6)
-+#define   DVO_DATA_ORDER_GBRG_ERRATA  (0 << 6)
-+#define   DVO_DATA_ORDER_RGGB_ERRATA  (1 << 6)
-+#define   DVO_VSYNC_ACTIVE_HIGH               (1 << 4)
-+#define   DVO_HSYNC_ACTIVE_HIGH               (1 << 3)
-+#define   DVO_BLANK_ACTIVE_HIGH               (1 << 2)
-+#define   DVO_OUTPUT_CSTATE_PIXELS    (1 << 1)        /* SDG only */
-+#define   DVO_OUTPUT_SOURCE_SIZE_PIXELS       (1 << 0)        /* SDG only */
-+#define   DVO_PRESERVE_MASK           (0x7<<24)
-+#define DVOA_SRCDIM           0x61124
-+#define DVOB_SRCDIM           0x61144
-+#define DVOC_SRCDIM           0x61164
-+#define   DVO_SRCDIM_HORIZONTAL_SHIFT 12
-+#define   DVO_SRCDIM_VERTICAL_SHIFT   0
-+
-+/* LVDS port control */
-+#define LVDS                  0x61180
-+/*
-+ * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
-+ * the DPLL semantics change when the LVDS is assigned to that pipe.
-+ */
-+#define   LVDS_PORT_EN                        (1 << 31)
-+/* Selects pipe B for LVDS data.  Must be set on pre-965. */
-+#define   LVDS_PIPEB_SELECT           (1 << 30)
-+/*
-+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
-+ * pixel.
-+ */
-+#define   LVDS_A0A2_CLKA_POWER_MASK   (3 << 8)
-+#define   LVDS_A0A2_CLKA_POWER_DOWN   (0 << 8)
-+#define   LVDS_A0A2_CLKA_POWER_UP     (3 << 8)
-+/*
-+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
-+ * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
-+ * on.
-+ */
-+#define   LVDS_A3_POWER_MASK          (3 << 6)
-+#define   LVDS_A3_POWER_DOWN          (0 << 6)
-+#define   LVDS_A3_POWER_UP            (3 << 6)
-+/*
-+ * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
-+ * is set.
-+ */
-+#define   LVDS_CLKB_POWER_MASK                (3 << 4)
-+#define   LVDS_CLKB_POWER_DOWN                (0 << 4)
-+#define   LVDS_CLKB_POWER_UP          (3 << 4)
-+/*
-+ * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
-+ * setting for whether we are in dual-channel mode.  The B3 pair will
-+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
-+ */
-+#define   LVDS_B0B3_POWER_MASK                (3 << 2)
-+#define   LVDS_B0B3_POWER_DOWN                (0 << 2)
-+#define   LVDS_B0B3_POWER_UP          (3 << 2)
-+
-+/* Panel power sequencing */
-+#define PP_STATUS     0x61200
-+#define   PP_ON               (1 << 31)
-+/*
-+ * Indicates that all dependencies of the panel are on:
-+ *
-+ * - PLL enabled
-+ * - pipe enabled
-+ * - LVDS/DVOB/DVOC on
-+ */
-+#define   PP_READY            (1 << 30)
-+#define   PP_SEQUENCE_NONE    (0 << 28)
-+#define   PP_SEQUENCE_ON      (1 << 28)
-+#define   PP_SEQUENCE_OFF     (2 << 28)
-+#define   PP_SEQUENCE_MASK    0x30000000
-+#define PP_CONTROL    0x61204
-+#define   POWER_TARGET_ON     (1 << 0)
-+#define PP_ON_DELAYS  0x61208
-+#define PP_OFF_DELAYS 0x6120c
-+#define PP_DIVISOR    0x61210
-+
-+/* Panel fitting */
-+#define PFIT_CONTROL  0x61230
-+#define   PFIT_ENABLE         (1 << 31)
-+#define   PFIT_PIPE_MASK      (3 << 29)
-+#define   PFIT_PIPE_SHIFT     29
-+#define   VERT_INTERP_DISABLE (0 << 10)
-+#define   VERT_INTERP_BILINEAR        (1 << 10)
-+#define   VERT_INTERP_MASK    (3 << 10)
-+#define   VERT_AUTO_SCALE     (1 << 9)
-+#define   HORIZ_INTERP_DISABLE        (0 << 6)
-+#define   HORIZ_INTERP_BILINEAR       (1 << 6)
-+#define   HORIZ_INTERP_MASK   (3 << 6)
-+#define   HORIZ_AUTO_SCALE    (1 << 5)
-+#define   PANEL_8TO6_DITHER_ENABLE (1 << 3)
-+#define PFIT_PGM_RATIOS       0x61234
-+#define   PFIT_VERT_SCALE_MASK                        0xfff00000
-+#define   PFIT_HORIZ_SCALE_MASK                       0x0000fff0
-+#define PFIT_AUTO_RATIOS 0x61238
-+
-+/* Backlight control */
-+#define BLC_PWM_CTL           0x61254
-+#define   BACKLIGHT_MODULATION_FREQ_SHIFT             (17)
-+#define BLC_PWM_CTL2          0x61250 /* 965+ only */
-+/*
-+ * This is the most significant 15 bits of the number of backlight cycles in a
-+ * complete cycle of the modulated backlight control.
-+ *
-+ * The actual value is this field multiplied by two.
-+ */
-+#define   BACKLIGHT_MODULATION_FREQ_MASK              (0x7fff << 17)
-+#define   BLM_LEGACY_MODE                             (1 << 16)
-+/*
-+ * This is the number of cycles out of the backlight modulation cycle for which
-+ * the backlight is on.
-+ *
-+ * This field must be no greater than the number of cycles in the complete
-+ * backlight modulation cycle.
-+ */
-+#define   BACKLIGHT_DUTY_CYCLE_SHIFT          (0)
-+#define   BACKLIGHT_DUTY_CYCLE_MASK           (0xffff)
-+
-+/* TV port control */
-+#define TV_CTL                        0x68000
-+/** Enables the TV encoder */
-+# define TV_ENC_ENABLE                        (1 << 31)
-+/** Sources the TV encoder input from pipe B instead of A. */
-+# define TV_ENC_PIPEB_SELECT          (1 << 30)
-+/** Outputs composite video (DAC A only) */
-+# define TV_ENC_OUTPUT_COMPOSITE      (0 << 28)
-+/** Outputs SVideo video (DAC B/C) */
-+# define TV_ENC_OUTPUT_SVIDEO         (1 << 28)
-+/** Outputs Component video (DAC A/B/C) */
-+# define TV_ENC_OUTPUT_COMPONENT      (2 << 28)
-+/** Outputs Composite and SVideo (DAC A/B/C) */
-+# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE       (3 << 28)
-+# define TV_TRILEVEL_SYNC             (1 << 21)
-+/** Enables slow sync generation (945GM only) */
-+# define TV_SLOW_SYNC                 (1 << 20)
-+/** Selects 4x oversampling for 480i and 576p */
-+# define TV_OVERSAMPLE_4X             (0 << 18)
-+/** Selects 2x oversampling for 720p and 1080i */
-+# define TV_OVERSAMPLE_2X             (1 << 18)
-+/** Selects no oversampling for 1080p */
-+# define TV_OVERSAMPLE_NONE           (2 << 18)
-+/** Selects 8x oversampling */
-+# define TV_OVERSAMPLE_8X             (3 << 18)
-+/** Selects progressive mode rather than interlaced */
-+# define TV_PROGRESSIVE                       (1 << 17)
-+/** Sets the colorburst to PAL mode.  Required for non-M PAL modes. */
-+# define TV_PAL_BURST                 (1 << 16)
-+/** Field for setting delay of Y compared to C */
-+# define TV_YC_SKEW_MASK              (7 << 12)
-+/** Enables a fix for 480p/576p standard definition modes on the 915GM only */
-+# define TV_ENC_SDP_FIX                       (1 << 11)
-+/**
-+ * Enables a fix for the 915GM only.
-+ *
-+ * Not sure what it does.
-+ */
-+# define TV_ENC_C0_FIX                        (1 << 10)
-+/** Bits that must be preserved by software */
-+# define TV_CTL_SAVE                  ((3 << 8) | (3 << 6))
-+# define TV_FUSE_STATE_MASK           (3 << 4)
-+/** Read-only state that reports all features enabled */
-+# define TV_FUSE_STATE_ENABLED                (0 << 4)
-+/** Read-only state that reports that Macrovision is disabled in hardware*/
-+# define TV_FUSE_STATE_NO_MACROVISION (1 << 4)
-+/** Read-only state that reports that TV-out is disabled in hardware. */
-+# define TV_FUSE_STATE_DISABLED               (2 << 4)
-+/** Normal operation */
-+# define TV_TEST_MODE_NORMAL          (0 << 0)
-+/** Encoder test pattern 1 - combo pattern */
-+# define TV_TEST_MODE_PATTERN_1               (1 << 0)
-+/** Encoder test pattern 2 - full screen vertical 75% color bars */
-+# define TV_TEST_MODE_PATTERN_2               (2 << 0)
-+/** Encoder test pattern 3 - full screen horizontal 75% color bars */
-+# define TV_TEST_MODE_PATTERN_3               (3 << 0)
-+/** Encoder test pattern 4 - random noise */
-+# define TV_TEST_MODE_PATTERN_4               (4 << 0)
-+/** Encoder test pattern 5 - linear color ramps */
-+# define TV_TEST_MODE_PATTERN_5               (5 << 0)
-+/**
-+ * This test mode forces the DACs to 50% of full output.
-+ *
-+ * This is used for load detection in combination with TVDAC_SENSE_MASK
-+ */
-+# define TV_TEST_MODE_MONITOR_DETECT  (7 << 0)
-+# define TV_TEST_MODE_MASK            (7 << 0)
-+
-+#define TV_DAC                        0x68004
-+/**
-+ * Reports that DAC state change logic has reported change (RO).
-+ *
-+ * This gets cleared when TV_DAC_STATE_EN is cleared
-+*/
-+# define TVDAC_STATE_CHG              (1 << 31)
-+# define TVDAC_SENSE_MASK             (7 << 28)
-+/** Reports that DAC A voltage is above the detect threshold */
-+# define TVDAC_A_SENSE                        (1 << 30)
-+/** Reports that DAC B voltage is above the detect threshold */
-+# define TVDAC_B_SENSE                        (1 << 29)
-+/** Reports that DAC C voltage is above the detect threshold */
-+# define TVDAC_C_SENSE                        (1 << 28)
-+/**
-+ * Enables DAC state detection logic, for load-based TV detection.
-+ *
-+ * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set
-+ * to off, for load detection to work.
-+ */
-+# define TVDAC_STATE_CHG_EN           (1 << 27)
-+/** Sets the DAC A sense value to high */
-+# define TVDAC_A_SENSE_CTL            (1 << 26)
-+/** Sets the DAC B sense value to high */
-+# define TVDAC_B_SENSE_CTL            (1 << 25)
-+/** Sets the DAC C sense value to high */
-+# define TVDAC_C_SENSE_CTL            (1 << 24)
-+/** Overrides the ENC_ENABLE and DAC voltage levels */
-+# define DAC_CTL_OVERRIDE             (1 << 7)
-+/** Sets the slew rate.  Must be preserved in software */
-+# define ENC_TVDAC_SLEW_FAST          (1 << 6)
-+# define DAC_A_1_3_V                  (0 << 4)
-+# define DAC_A_1_1_V                  (1 << 4)
-+# define DAC_A_0_7_V                  (2 << 4)
-+# define DAC_A_OFF                    (3 << 4)
-+# define DAC_B_1_3_V                  (0 << 2)
-+# define DAC_B_1_1_V                  (1 << 2)
-+# define DAC_B_0_7_V                  (2 << 2)
-+# define DAC_B_OFF                    (3 << 2)
-+# define DAC_C_1_3_V                  (0 << 0)
-+# define DAC_C_1_1_V                  (1 << 0)
-+# define DAC_C_0_7_V                  (2 << 0)
-+# define DAC_C_OFF                    (3 << 0)
-+
-+/**
-+ * CSC coefficients are stored in a floating point format with 9 bits of
-+ * mantissa and 2 or 3 bits of exponent.  The exponent is represented as 2**-n,
-+ * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
-+ * -1 (0x3) being the only legal negative value.
-+ */
-+#define TV_CSC_Y              0x68010
-+# define TV_RY_MASK                   0x07ff0000
-+# define TV_RY_SHIFT                  16
-+# define TV_GY_MASK                   0x00000fff
-+# define TV_GY_SHIFT                  0
-+
-+#define TV_CSC_Y2             0x68014
-+# define TV_BY_MASK                   0x07ff0000
-+# define TV_BY_SHIFT                  16
-+/**
-+ * Y attenuation for component video.
-+ *
-+ * Stored in 1.9 fixed point.
-+ */
-+# define TV_AY_MASK                   0x000003ff
-+# define TV_AY_SHIFT                  0
-+
-+#define TV_CSC_U              0x68018
-+# define TV_RU_MASK                   0x07ff0000
-+# define TV_RU_SHIFT                  16
-+# define TV_GU_MASK                   0x000007ff
-+# define TV_GU_SHIFT                  0
-+
-+#define TV_CSC_U2             0x6801c
-+# define TV_BU_MASK                   0x07ff0000
-+# define TV_BU_SHIFT                  16
-+/**
-+ * U attenuation for component video.
-+ *
-+ * Stored in 1.9 fixed point.
-+ */
-+# define TV_AU_MASK                   0x000003ff
-+# define TV_AU_SHIFT                  0
-+
-+#define TV_CSC_V              0x68020
-+# define TV_RV_MASK                   0x0fff0000
-+# define TV_RV_SHIFT                  16
-+# define TV_GV_MASK                   0x000007ff
-+# define TV_GV_SHIFT                  0
-+
-+#define TV_CSC_V2             0x68024
-+# define TV_BV_MASK                   0x07ff0000
-+# define TV_BV_SHIFT                  16
-+/**
-+ * V attenuation for component video.
-+ *
-+ * Stored in 1.9 fixed point.
-+ */
-+# define TV_AV_MASK                   0x000007ff
-+# define TV_AV_SHIFT                  0
-+
-+#define TV_CLR_KNOBS          0x68028
-+/** 2s-complement brightness adjustment */
-+# define TV_BRIGHTNESS_MASK           0xff000000
-+# define TV_BRIGHTNESS_SHIFT          24
-+/** Contrast adjustment, as a 2.6 unsigned floating point number */
-+# define TV_CONTRAST_MASK             0x00ff0000
-+# define TV_CONTRAST_SHIFT            16
-+/** Saturation adjustment, as a 2.6 unsigned floating point number */
-+# define TV_SATURATION_MASK           0x0000ff00
-+# define TV_SATURATION_SHIFT          8
-+/** Hue adjustment, as an integer phase angle in degrees */
-+# define TV_HUE_MASK                  0x000000ff
-+# define TV_HUE_SHIFT                 0
-+
-+#define TV_CLR_LEVEL          0x6802c
-+/** Controls the DAC level for black */
-+# define TV_BLACK_LEVEL_MASK          0x01ff0000
-+# define TV_BLACK_LEVEL_SHIFT         16
-+/** Controls the DAC level for blanking */
-+# define TV_BLANK_LEVEL_MASK          0x000001ff
-+# define TV_BLANK_LEVEL_SHIFT         0
-+
-+#define TV_H_CTL_1            0x68030
-+/** Number of pixels in the hsync. */
-+# define TV_HSYNC_END_MASK            0x1fff0000
-+# define TV_HSYNC_END_SHIFT           16
-+/** Total number of pixels minus one in the line (display and blanking). */
-+# define TV_HTOTAL_MASK                       0x00001fff
-+# define TV_HTOTAL_SHIFT              0
-+
-+#define TV_H_CTL_2            0x68034
-+/** Enables the colorburst (needed for non-component color) */
-+# define TV_BURST_ENA                 (1 << 31)
-+/** Offset of the colorburst from the start of hsync, in pixels minus one. */
-+# define TV_HBURST_START_SHIFT                16
-+# define TV_HBURST_START_MASK         0x1fff0000
-+/** Length of the colorburst */
-+# define TV_HBURST_LEN_SHIFT          0
-+# define TV_HBURST_LEN_MASK           0x0001fff
-+
-+#define TV_H_CTL_3            0x68038
-+/** End of hblank, measured in pixels minus one from start of hsync */
-+# define TV_HBLANK_END_SHIFT          16
-+# define TV_HBLANK_END_MASK           0x1fff0000
-+/** Start of hblank, measured in pixels minus one from start of hsync */
-+# define TV_HBLANK_START_SHIFT                0
-+# define TV_HBLANK_START_MASK         0x0001fff
-+
-+#define TV_V_CTL_1            0x6803c
-+/** XXX */
-+# define TV_NBR_END_SHIFT             16
-+# define TV_NBR_END_MASK              0x07ff0000
-+/** XXX */
-+# define TV_VI_END_F1_SHIFT           8
-+# define TV_VI_END_F1_MASK            0x00003f00
-+/** XXX */
-+# define TV_VI_END_F2_SHIFT           0
-+# define TV_VI_END_F2_MASK            0x0000003f
-+
-+#define TV_V_CTL_2            0x68040
-+/** Length of vsync, in half lines */
-+# define TV_VSYNC_LEN_MASK            0x07ff0000
-+# define TV_VSYNC_LEN_SHIFT           16
-+/** Offset of the start of vsync in field 1, measured in one less than the
-+ * number of half lines.
-+ */
-+# define TV_VSYNC_START_F1_MASK               0x00007f00
-+# define TV_VSYNC_START_F1_SHIFT      8
-+/**
-+ * Offset of the start of vsync in field 2, measured in one less than the
-+ * number of half lines.
-+ */
-+# define TV_VSYNC_START_F2_MASK               0x0000007f
-+# define TV_VSYNC_START_F2_SHIFT      0
-+
-+#define TV_V_CTL_3            0x68044
-+/** Enables generation of the equalization signal */
-+# define TV_EQUAL_ENA                 (1 << 31)
-+/** Length of vsync, in half lines */
-+# define TV_VEQ_LEN_MASK              0x007f0000
-+# define TV_VEQ_LEN_SHIFT             16
-+/** Offset of the start of equalization in field 1, measured in one less than
-+ * the number of half lines.
-+ */
-+# define TV_VEQ_START_F1_MASK         0x0007f00
-+# define TV_VEQ_START_F1_SHIFT                8
-+/**
-+ * Offset of the start of equalization in field 2, measured in one less than
-+ * the number of half lines.
-+ */
-+# define TV_VEQ_START_F2_MASK         0x000007f
-+# define TV_VEQ_START_F2_SHIFT                0
-+
-+#define TV_V_CTL_4            0x68048
-+/**
-+ * Offset to start of vertical colorburst, measured in one less than the
-+ * number of lines from vertical start.
-+ */
-+# define TV_VBURST_START_F1_MASK      0x003f0000
-+# define TV_VBURST_START_F1_SHIFT     16
-+/**
-+ * Offset to the end of vertical colorburst, measured in one less than the
-+ * number of lines from the start of NBR.
-+ */
-+# define TV_VBURST_END_F1_MASK                0x000000ff
-+# define TV_VBURST_END_F1_SHIFT               0
-+
-+#define TV_V_CTL_5            0x6804c
-+/**
-+ * Offset to start of vertical colorburst, measured in one less than the
-+ * number of lines from vertical start.
-+ */
-+# define TV_VBURST_START_F2_MASK      0x003f0000
-+# define TV_VBURST_START_F2_SHIFT     16
-+/**
-+ * Offset to the end of vertical colorburst, measured in one less than the
-+ * number of lines from the start of NBR.
-+ */
-+# define TV_VBURST_END_F2_MASK                0x000000ff
-+# define TV_VBURST_END_F2_SHIFT               0
-+
-+#define TV_V_CTL_6            0x68050
-+/**
-+ * Offset to start of vertical colorburst, measured in one less than the
-+ * number of lines from vertical start.
-+ */
-+# define TV_VBURST_START_F3_MASK      0x003f0000
-+# define TV_VBURST_START_F3_SHIFT     16
-+/**
-+ * Offset to the end of vertical colorburst, measured in one less than the
-+ * number of lines from the start of NBR.
-+ */
-+# define TV_VBURST_END_F3_MASK                0x000000ff
-+# define TV_VBURST_END_F3_SHIFT               0
-+
-+#define TV_V_CTL_7            0x68054
-+/**
-+ * Offset to start of vertical colorburst, measured in one less than the
-+ * number of lines from vertical start.
-+ */
-+# define TV_VBURST_START_F4_MASK      0x003f0000
-+# define TV_VBURST_START_F4_SHIFT     16
-+/**
-+ * Offset to the end of vertical colorburst, measured in one less than the
-+ * number of lines from the start of NBR.
-+ */
-+# define TV_VBURST_END_F4_MASK                0x000000ff
-+# define TV_VBURST_END_F4_SHIFT               0
-+
-+#define TV_SC_CTL_1           0x68060
-+/** Turns on the first subcarrier phase generation DDA */
-+# define TV_SC_DDA1_EN                        (1 << 31)
-+/** Turns on the first subcarrier phase generation DDA */
-+# define TV_SC_DDA2_EN                        (1 << 30)
-+/** Turns on the first subcarrier phase generation DDA */
-+# define TV_SC_DDA3_EN                        (1 << 29)
-+/** Sets the subcarrier DDA to reset frequency every other field */
-+# define TV_SC_RESET_EVERY_2          (0 << 24)
-+/** Sets the subcarrier DDA to reset frequency every fourth field */
-+# define TV_SC_RESET_EVERY_4          (1 << 24)
-+/** Sets the subcarrier DDA to reset frequency every eighth field */
-+# define TV_SC_RESET_EVERY_8          (2 << 24)
-+/** Sets the subcarrier DDA to never reset the frequency */
-+# define TV_SC_RESET_NEVER            (3 << 24)
-+/** Sets the peak amplitude of the colorburst.*/
-+# define TV_BURST_LEVEL_MASK          0x00ff0000
-+# define TV_BURST_LEVEL_SHIFT         16
-+/** Sets the increment of the first subcarrier phase generation DDA */
-+# define TV_SCDDA1_INC_MASK           0x00000fff
-+# define TV_SCDDA1_INC_SHIFT          0
-+
-+#define TV_SC_CTL_2           0x68064
-+/** Sets the rollover for the second subcarrier phase generation DDA */
-+# define TV_SCDDA2_SIZE_MASK          0x7fff0000
-+# define TV_SCDDA2_SIZE_SHIFT         16
-+/** Sets the increent of the second subcarrier phase generation DDA */
-+# define TV_SCDDA2_INC_MASK           0x00007fff
-+# define TV_SCDDA2_INC_SHIFT          0
-+
-+#define TV_SC_CTL_3           0x68068
-+/** Sets the rollover for the third subcarrier phase generation DDA */
-+# define TV_SCDDA3_SIZE_MASK          0x7fff0000
-+# define TV_SCDDA3_SIZE_SHIFT         16
-+/** Sets the increent of the third subcarrier phase generation DDA */
-+# define TV_SCDDA3_INC_MASK           0x00007fff
-+# define TV_SCDDA3_INC_SHIFT          0
-+
-+#define TV_WIN_POS            0x68070
-+/** X coordinate of the display from the start of horizontal active */
-+# define TV_XPOS_MASK                 0x1fff0000
-+# define TV_XPOS_SHIFT                        16
-+/** Y coordinate of the display from the start of vertical active (NBR) */
-+# define TV_YPOS_MASK                 0x00000fff
-+# define TV_YPOS_SHIFT                        0
-+
-+#define TV_WIN_SIZE           0x68074
-+/** Horizontal size of the display window, measured in pixels*/
-+# define TV_XSIZE_MASK                        0x1fff0000
-+# define TV_XSIZE_SHIFT                       16
-+/**
-+ * Vertical size of the display window, measured in pixels.
-+ *
-+ * Must be even for interlaced modes.
-+ */
-+# define TV_YSIZE_MASK                        0x00000fff
-+# define TV_YSIZE_SHIFT                       0
-+
-+#define TV_FILTER_CTL_1               0x68080
-+/**
-+ * Enables automatic scaling calculation.
-+ *
-+ * If set, the rest of the registers are ignored, and the calculated values can
-+ * be read back from the register.
-+ */
-+# define TV_AUTO_SCALE                        (1 << 31)
-+/**
-+ * Disables the vertical filter.
-+ *
-+ * This is required on modes more than 1024 pixels wide */
-+# define TV_V_FILTER_BYPASS           (1 << 29)
-+/** Enables adaptive vertical filtering */
-+# define TV_VADAPT                    (1 << 28)
-+# define TV_VADAPT_MODE_MASK          (3 << 26)
-+/** Selects the least adaptive vertical filtering mode */
-+# define TV_VADAPT_MODE_LEAST         (0 << 26)
-+/** Selects the moderately adaptive vertical filtering mode */
-+# define TV_VADAPT_MODE_MODERATE      (1 << 26)
-+/** Selects the most adaptive vertical filtering mode */
-+# define TV_VADAPT_MODE_MOST          (3 << 26)
-+/**
-+ * Sets the horizontal scaling factor.
-+ *
-+ * This should be the fractional part of the horizontal scaling factor divided
-+ * by the oversampling rate.  TV_HSCALE should be less than 1, and set to:
-+ *
-+ * (src width - 1) / ((oversample * dest width) - 1)
-+ */
-+# define TV_HSCALE_FRAC_MASK          0x00003fff
-+# define TV_HSCALE_FRAC_SHIFT         0
-+
-+#define TV_FILTER_CTL_2               0x68084
-+/**
-+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
-+ *
-+ * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1)
-+ */
-+# define TV_VSCALE_INT_MASK           0x00038000
-+# define TV_VSCALE_INT_SHIFT          15
-+/**
-+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
-+ *
-+ * \sa TV_VSCALE_INT_MASK
-+ */
-+# define TV_VSCALE_FRAC_MASK          0x00007fff
-+# define TV_VSCALE_FRAC_SHIFT         0
-+
-+#define TV_FILTER_CTL_3               0x68088
-+/**
-+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
-+ *
-+ * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1))
-+ *
-+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
-+ */
-+# define TV_VSCALE_IP_INT_MASK                0x00038000
-+# define TV_VSCALE_IP_INT_SHIFT               15
-+/**
-+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
-+ *
-+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
-+ *
-+ * \sa TV_VSCALE_IP_INT_MASK
-+ */
-+# define TV_VSCALE_IP_FRAC_MASK               0x00007fff
-+# define TV_VSCALE_IP_FRAC_SHIFT              0
-+
-+#define TV_CC_CONTROL         0x68090
-+# define TV_CC_ENABLE                 (1 << 31)
-+/**
-+ * Specifies which field to send the CC data in.
-+ *
-+ * CC data is usually sent in field 0.
-+ */
-+# define TV_CC_FID_MASK                       (1 << 27)
-+# define TV_CC_FID_SHIFT              27
-+/** Sets the horizontal position of the CC data.  Usually 135. */
-+# define TV_CC_HOFF_MASK              0x03ff0000
-+# define TV_CC_HOFF_SHIFT             16
-+/** Sets the vertical position of the CC data.  Usually 21 */
-+# define TV_CC_LINE_MASK              0x0000003f
-+# define TV_CC_LINE_SHIFT             0
-+
-+#define TV_CC_DATA            0x68094
-+# define TV_CC_RDY                    (1 << 31)
-+/** Second word of CC data to be transmitted. */
-+# define TV_CC_DATA_2_MASK            0x007f0000
-+# define TV_CC_DATA_2_SHIFT           16
-+/** First word of CC data to be transmitted. */
-+# define TV_CC_DATA_1_MASK            0x0000007f
-+# define TV_CC_DATA_1_SHIFT           0
-+
-+#define TV_H_LUMA_0           0x68100
-+#define TV_H_LUMA_59          0x681ec
-+#define TV_H_CHROMA_0         0x68200
-+#define TV_H_CHROMA_59                0x682ec
-+#define TV_V_LUMA_0           0x68300
-+#define TV_V_LUMA_42          0x683a8
-+#define TV_V_CHROMA_0         0x68400
-+#define TV_V_CHROMA_42                0x684a8
-+
-+/* Display & cursor control */
-+
-+/* Pipe A */
-+#define PIPEADSL              0x70000
-+#define PIPEACONF             0x70008
-+#define   PIPEACONF_ENABLE    (1<<31)
-+#define   PIPEACONF_DISABLE   0
-+#define   PIPEACONF_DOUBLE_WIDE       (1<<30)
-+#define   I965_PIPECONF_ACTIVE        (1<<30)
-+#define   PIPEACONF_SINGLE_WIDE       0
-+#define   PIPEACONF_PIPE_UNLOCKED 0
-+#define   PIPEACONF_PIPE_LOCKED       (1<<25)
-+#define   PIPEACONF_PALETTE   0
-+#define   PIPEACONF_GAMMA             (1<<24)
-+#define   PIPECONF_FORCE_BORDER       (1<<25)
-+#define   PIPECONF_PROGRESSIVE        (0 << 21)
-+#define   PIPECONF_INTERLACE_W_FIELD_INDICATION       (6 << 21)
-+#define   PIPECONF_INTERLACE_FIELD_0_ONLY             (7 << 21)
-+#define PIPEASTAT             0x70024
-+#define   PIPE_FIFO_UNDERRUN_STATUS           (1UL<<31)
-+#define   PIPE_CRC_ERROR_ENABLE                       (1UL<<29)
-+#define   PIPE_CRC_DONE_ENABLE                        (1UL<<28)
-+#define   PIPE_GMBUS_EVENT_ENABLE             (1UL<<27)
-+#define   PIPE_HOTPLUG_INTERRUPT_ENABLE               (1UL<<26)
-+#define   PIPE_VSYNC_INTERRUPT_ENABLE         (1UL<<25)
-+#define   PIPE_DISPLAY_LINE_COMPARE_ENABLE    (1UL<<24)
-+#define   PIPE_DPST_EVENT_ENABLE              (1UL<<23)
-+#define   PIPE_LEGACY_BLC_EVENT_ENABLE                (1UL<<22)
-+#define   PIPE_ODD_FIELD_INTERRUPT_ENABLE     (1UL<<21)
-+#define   PIPE_EVEN_FIELD_INTERRUPT_ENABLE    (1UL<<20)
-+#define   PIPE_HOTPLUG_TV_INTERRUPT_ENABLE    (1UL<<18) /* pre-965 */
-+#define   PIPE_START_VBLANK_INTERRUPT_ENABLE  (1UL<<18) /* 965 or later */
-+#define   PIPE_VBLANK_INTERRUPT_ENABLE                (1UL<<17)
-+#define   PIPE_OVERLAY_UPDATED_ENABLE         (1UL<<16)
-+#define   PIPE_CRC_ERROR_INTERRUPT_STATUS     (1UL<<13)
-+#define   PIPE_CRC_DONE_INTERRUPT_STATUS      (1UL<<12)
-+#define   PIPE_GMBUS_INTERRUPT_STATUS         (1UL<<11)
-+#define   PIPE_HOTPLUG_INTERRUPT_STATUS               (1UL<<10)
-+#define   PIPE_VSYNC_INTERRUPT_STATUS         (1UL<<9)
-+#define   PIPE_DISPLAY_LINE_COMPARE_STATUS    (1UL<<8)
-+#define   PIPE_DPST_EVENT_STATUS              (1UL<<7)
-+#define   PIPE_LEGACY_BLC_EVENT_STATUS                (1UL<<6)
-+#define   PIPE_ODD_FIELD_INTERRUPT_STATUS     (1UL<<5)
-+#define   PIPE_EVEN_FIELD_INTERRUPT_STATUS    (1UL<<4)
-+#define   PIPE_HOTPLUG_TV_INTERRUPT_STATUS    (1UL<<2) /* pre-965 */
-+#define   PIPE_START_VBLANK_INTERRUPT_STATUS  (1UL<<2) /* 965 or later */
-+#define   PIPE_VBLANK_INTERRUPT_STATUS                (1UL<<1)
-+#define   PIPE_OVERLAY_UPDATED_STATUS         (1UL<<0)
-+
-+#define DSPARB                        0x70030
-+#define   DSPARB_CSTART_MASK  (0x7f << 7)
-+#define   DSPARB_CSTART_SHIFT 7
-+#define   DSPARB_BSTART_MASK  (0x7f)
-+#define   DSPARB_BSTART_SHIFT 0
-+/*
-+ * The two pipe frame counter registers are not synchronized, so
-+ * reading a stable value is somewhat tricky. The following code
-+ * should work:
-+ *
-+ *  do {
-+ *    high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
-+ *             PIPE_FRAME_HIGH_SHIFT;
-+ *    low1 =  ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
-+ *             PIPE_FRAME_LOW_SHIFT);
-+ *    high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
-+ *             PIPE_FRAME_HIGH_SHIFT);
-+ *  } while (high1 != high2);
-+ *  frame = (high1 << 8) | low1;
-+ */
-+#define PIPEAFRAMEHIGH          0x70040
-+#define   PIPE_FRAME_HIGH_MASK    0x0000ffff
-+#define   PIPE_FRAME_HIGH_SHIFT   0
-+#define PIPEAFRAMEPIXEL         0x70044
-+#define   PIPE_FRAME_LOW_MASK     0xff000000
-+#define   PIPE_FRAME_LOW_SHIFT    24
-+#define   PIPE_PIXEL_MASK         0x00ffffff
-+#define   PIPE_PIXEL_SHIFT        0
-+
-+/* Cursor A & B regs */
-+#define CURACNTR              0x70080
-+#define   CURSOR_MODE_DISABLE   0x00
-+#define   CURSOR_MODE_64_32B_AX 0x07
-+#define   CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
-+#define   MCURSOR_GAMMA_ENABLE  (1 << 26)
-+#define CURABASE              0x70084
-+#define CURAPOS                       0x70088
-+#define   CURSOR_POS_MASK       0x007FF
-+#define   CURSOR_POS_SIGN       0x8000
-+#define   CURSOR_X_SHIFT        0
-+#define   CURSOR_Y_SHIFT        16
-+#define CURBCNTR              0x700c0
-+#define CURBBASE              0x700c4
-+#define CURBPOS                       0x700c8
-+
-+/* Display A control */
-+#define DSPACNTR                0x70180
-+#define   DISPLAY_PLANE_ENABLE                        (1<<31)
-+#define   DISPLAY_PLANE_DISABLE                       0
-+#define   DISPPLANE_GAMMA_ENABLE              (1<<30)
-+#define   DISPPLANE_GAMMA_DISABLE             0
-+#define   DISPPLANE_PIXFORMAT_MASK            (0xf<<26)
-+#define   DISPPLANE_8BPP                      (0x2<<26)
-+#define   DISPPLANE_15_16BPP                  (0x4<<26)
-+#define   DISPPLANE_16BPP                     (0x5<<26)
-+#define   DISPPLANE_32BPP_NO_ALPHA            (0x6<<26)
-+#define   DISPPLANE_32BPP                     (0x7<<26)
-+#define   DISPPLANE_STEREO_ENABLE             (1<<25)
-+#define   DISPPLANE_STEREO_DISABLE            0
-+#define   DISPPLANE_SEL_PIPE_MASK             (1<<24)
-+#define   DISPPLANE_SEL_PIPE_A                        0
-+#define   DISPPLANE_SEL_PIPE_B                        (1<<24)
-+#define   DISPPLANE_SRC_KEY_ENABLE            (1<<22)
-+#define   DISPPLANE_SRC_KEY_DISABLE           0
-+#define   DISPPLANE_LINE_DOUBLE                       (1<<20)
-+#define   DISPPLANE_NO_LINE_DOUBLE            0
-+#define   DISPPLANE_STEREO_POLARITY_FIRST     0
-+#define   DISPPLANE_STEREO_POLARITY_SECOND    (1<<18)
-+#define DSPAADDR              0x70184
-+#define DSPASTRIDE            0x70188
-+#define DSPAPOS                       0x7018C /* reserved */
-+#define DSPASIZE              0x70190
-+#define DSPASURF              0x7019C /* 965+ only */
-+#define DSPATILEOFF           0x701A4 /* 965+ only */
-+
-+/* VBIOS flags */
-+#define SWF00                 0x71410
-+#define SWF01                 0x71414
-+#define SWF02                 0x71418
-+#define SWF03                 0x7141c
-+#define SWF04                 0x71420
-+#define SWF05                 0x71424
-+#define SWF06                 0x71428
-+#define SWF10                 0x70410
-+#define SWF11                 0x70414
-+#define SWF14                 0x71420
-+#define SWF30                 0x72414
-+#define SWF31                 0x72418
-+#define SWF32                 0x7241c
-+
-+/* Pipe B */
-+#define PIPEBDSL              0x71000
-+#define PIPEBCONF             0x71008
-+#define PIPEBSTAT             0x71024
-+#define PIPEBFRAMEHIGH                0x71040
-+#define PIPEBFRAMEPIXEL               0x71044
-+
-+/* Display B control */
-+#define DSPBCNTR              0x71180
-+#define   DISPPLANE_ALPHA_TRANS_ENABLE                (1<<15)
-+#define   DISPPLANE_ALPHA_TRANS_DISABLE               0
-+#define   DISPPLANE_SPRITE_ABOVE_DISPLAY      0
-+#define   DISPPLANE_SPRITE_ABOVE_OVERLAY      (1)
-+#define DSPBADDR              0x71184
-+#define DSPBSTRIDE            0x71188
-+#define DSPBPOS                       0x7118C
-+#define DSPBSIZE              0x71190
-+#define DSPBSURF              0x7119C
-+#define DSPBTILEOFF           0x711A4
-+
-+/* VBIOS regs */
-+#define VGACNTRL              0x71400
-+# define VGA_DISP_DISABLE                     (1 << 31)
-+# define VGA_2X_MODE                          (1 << 30)
-+# define VGA_PIPE_B_SELECT                    (1 << 29)
-+
-+#endif /* _I915_REG_H_ */
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0003_i915.Add_support_for_MSI_and_interrupt_mitigation.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0003_i915.Add_support_for_MSI_and_interrupt_mitigation.patch
deleted file mode 100644 (file)
index 70f9119..0000000
+++ /dev/null
@@ -1,421 +0,0 @@
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 29 Jul 2008 19:10:39 +0000 (-0700)
-Subject: i915: Add support for MSI and interrupt mitigation.
-X-Git-Tag: v2.6.12-rc2
-X-Git-Url: http://gitweb.freedesktop.org/?p=users/anholt/anholt/linux-2.6.git;a=commitdiff;h=aae4223e2fd3b29ae8e070b7a16d8cfc70c6a0c0
-
-i915: Add support for MSI and interrupt mitigation.
-
-Previous attempts at interrupt mitigation had been foiled by i915_wait_irq's
-failure to update the sarea seqno value when the status page indicated that
-the seqno had already been passed.  MSI support has been seen to cut CPU
-costs by up to 40% in some workloads by avoiding other expensive interrupt
-handlers for frequent graphics interrupts.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
-
---- a/drivers/gpu/drm/drm_irq.c
-+++ b/drivers/gpu/drm/drm_irq.c
-@@ -63,7 +63,7 @@ int drm_irq_by_busid(struct drm_device *
-           p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
-               return -EINVAL;
--      p->irq = dev->irq;
-+      p->irq = dev->pdev->irq;
-       DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
-                 p->irq);
-@@ -89,7 +89,7 @@ static int drm_irq_install(struct drm_de
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-               return -EINVAL;
--      if (dev->irq == 0)
-+      if (dev->pdev->irq == 0)
-               return -EINVAL;
-       mutex_lock(&dev->struct_mutex);
-@@ -107,7 +107,7 @@ static int drm_irq_install(struct drm_de
-       dev->irq_enabled = 1;
-       mutex_unlock(&dev->struct_mutex);
--      DRM_DEBUG("irq=%d\n", dev->irq);
-+      DRM_DEBUG("irq=%d\n", dev->pdev->irq);
-       if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
-               init_waitqueue_head(&dev->vbl_queue);
-@@ -127,8 +127,12 @@ static int drm_irq_install(struct drm_de
-       if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
-               sh_flags = IRQF_SHARED;
--      ret = request_irq(dev->irq, dev->driver->irq_handler,
-+      ret = request_irq(dev->pdev->irq, dev->driver->irq_handler,
-                         sh_flags, dev->devname, dev);
-+      /* Expose the device irq number to drivers that want to export it for
-+       * whatever reason.
-+       */
-+      dev->irq = dev->pdev->irq;
-       if (ret < 0) {
-               mutex_lock(&dev->struct_mutex);
-               dev->irq_enabled = 0;
-@@ -164,11 +168,11 @@ int drm_irq_uninstall(struct drm_device 
-       if (!irq_enabled)
-               return -EINVAL;
--      DRM_DEBUG("irq=%d\n", dev->irq);
-+      DRM_DEBUG("irq=%d\n", dev->pdev->irq);
-       dev->driver->irq_uninstall(dev);
--      free_irq(dev->irq, dev);
-+      free_irq(dev->pdev->irq, dev);
-       dev->locked_tasklet_func = NULL;
-@@ -201,7 +205,7 @@ int drm_control(struct drm_device *dev, 
-               if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-                       return 0;
-               if (dev->if_version < DRM_IF_VERSION(1, 2) &&
--                  ctl->irq != dev->irq)
-+                  ctl->irq != dev->pdev->irq)
-                       return -EINVAL;
-               return drm_irq_install(dev);
-       case DRM_UNINST_HANDLER:
-@@ -239,7 +243,7 @@ int drm_wait_vblank(struct drm_device *d
-       int ret = 0;
-       unsigned int flags, seq;
--      if ((!dev->irq) || (!dev->irq_enabled))
-+      if ((!dev->pdev->irq) || (!dev->irq_enabled))
-               return -EINVAL;
-       if (vblwait->request.type &
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -84,7 +84,7 @@ static int i915_dma_cleanup(struct drm_d
-        * may not have been called from userspace and after dev_private
-        * is freed, it's too late.
-        */
--      if (dev->irq)
-+      if (dev->irq_enabled)
-               drm_irq_uninstall(dev);
-       if (dev_priv->ring.virtual_start) {
-@@ -644,7 +644,7 @@ static int i915_getparam(struct drm_devi
-       switch (param->param) {
-       case I915_PARAM_IRQ_ACTIVE:
--              value = dev->irq ? 1 : 0;
-+              value = dev->irq_enabled;
-               break;
-       case I915_PARAM_ALLOW_BATCHBUFFER:
-               value = dev_priv->allow_batchbuffer ? 1 : 0;
-@@ -763,6 +763,20 @@ int i915_driver_load(struct drm_device *
-       ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
-                        _DRM_KERNEL | _DRM_DRIVER,
-                        &dev_priv->mmio_map);
-+
-+
-+      /* On the 945G/GM, the chipset reports the MSI capability on the
-+       * integrated graphics even though the support isn't actually there
-+       * according to the published specs.  It doesn't appear to function
-+       * correctly in testing on 945G.
-+       * This may be a side effect of MSI having been made available for PEG
-+       * and the registers being closely associated.
-+       */
-+      if (!IS_I945G(dev) && !IS_I945GM(dev))
-+              pci_enable_msi(dev->pdev);
-+
-+      spin_lock_init(&dev_priv->user_irq_lock);
-+
-       return ret;
- }
-@@ -770,6 +784,9 @@ int i915_driver_unload(struct drm_device
- {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-+      if (dev->pdev->msi_enabled)
-+              pci_disable_msi(dev->pdev);
-+
-       if (dev_priv->mmio_map)
-               drm_rmmap(dev, dev_priv->mmio_map);
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -105,6 +105,12 @@ typedef struct drm_i915_private {
-       wait_queue_head_t irq_queue;
-       atomic_t irq_received;
-       atomic_t irq_emitted;
-+      /** Protects user_irq_refcount and irq_mask_reg */
-+      spinlock_t user_irq_lock;
-+      /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
-+      int user_irq_refcount;
-+      /** Cached value of IMR to avoid reads in updating the bitfield */
-+      u32 irq_mask_reg;
-       int tex_lru_log_granularity;
-       int allow_batchbuffer;
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -33,6 +33,31 @@
- #define MAX_NOPID ((u32)~0)
-+/** These are the interrupts used by the driver */
-+#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT |             \
-+                                  I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \
-+                                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-+
-+static inline void
-+i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
-+{
-+      if ((dev_priv->irq_mask_reg & mask) != 0) {
-+              dev_priv->irq_mask_reg &= ~mask;
-+              I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+              (void) I915_READ(IMR);
-+      }
-+}
-+
-+static inline void
-+i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
-+{
-+      if ((dev_priv->irq_mask_reg & mask) != mask) {
-+              dev_priv->irq_mask_reg |= mask;
-+              I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+              (void) I915_READ(IMR);
-+      }
-+}
-+
- /**
-  * Emit blits for scheduled buffer swaps.
-  *
-@@ -229,46 +254,50 @@ irqreturn_t i915_driver_irq_handler(DRM_
- {
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      u16 temp;
-       u32 pipea_stats, pipeb_stats;
-+      u32 iir;
-       pipea_stats = I915_READ(PIPEASTAT);
-       pipeb_stats = I915_READ(PIPEBSTAT);
--      temp = I915_READ16(IIR);
--
--      temp &= (I915_USER_INTERRUPT |
--               I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
--               I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT);
--
--      DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
--
--      if (temp == 0)
-+      if (dev->pdev->msi_enabled)
-+              I915_WRITE(IMR, ~0);
-+      iir = I915_READ(IIR);
-+
-+      DRM_DEBUG("iir=%08x\n", iir);
-+
-+      if (iir == 0) {
-+              if (dev->pdev->msi_enabled) {
-+                      I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+                      (void) I915_READ(IMR);
-+              }
-               return IRQ_NONE;
-+      }
--      I915_WRITE16(IIR, temp);
--      (void) I915_READ16(IIR);
--      DRM_READMEMORYBARRIER();
-+      I915_WRITE(IIR, iir);
-+      if (dev->pdev->msi_enabled)
-+              I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+      (void) I915_READ(IIR); /* Flush posted writes */
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
--      if (temp & I915_USER_INTERRUPT)
-+      if (iir & I915_USER_INTERRUPT)
-               DRM_WAKEUP(&dev_priv->irq_queue);
--      if (temp & (I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
--                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)) {
-+      if (iir & (I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
-+                 I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)) {
-               int vblank_pipe = dev_priv->vblank_pipe;
-               if ((vblank_pipe &
-                    (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
-                   == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
--                      if (temp & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-+                      if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-                               atomic_inc(&dev->vbl_received);
--                      if (temp & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-+                      if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-                               atomic_inc(&dev->vbl_received2);
--              } else if (((temp & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) &&
-+              } else if (((iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
--                         ((temp & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) &&
-+                         ((iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
-                       atomic_inc(&dev->vbl_received);
-@@ -314,6 +343,27 @@ static int i915_emit_irq(struct drm_devi
-       return dev_priv->counter;
- }
-+static void i915_user_irq_get(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+
-+      spin_lock(&dev_priv->user_irq_lock);
-+      if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
-+              i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
-+      spin_unlock(&dev_priv->user_irq_lock);
-+}
-+
-+static void i915_user_irq_put(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+
-+      spin_lock(&dev_priv->user_irq_lock);
-+      BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
-+      if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
-+              i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
-+      spin_unlock(&dev_priv->user_irq_lock);
-+}
-+
- static int i915_wait_irq(struct drm_device * dev, int irq_nr)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-@@ -322,13 +372,17 @@ static int i915_wait_irq(struct drm_devi
-       DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
-                 READ_BREADCRUMB(dev_priv));
--      if (READ_BREADCRUMB(dev_priv) >= irq_nr)
-+      if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
-+              dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-               return 0;
-+      }
-       dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-+      i915_user_irq_get(dev);
-       DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
-                   READ_BREADCRUMB(dev_priv) >= irq_nr);
-+      i915_user_irq_put(dev);
-       if (ret == -EBUSY) {
-               DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
-@@ -413,20 +467,6 @@ int i915_irq_wait(struct drm_device *dev
-       return i915_wait_irq(dev, irqwait->irq_seq);
- }
--static void i915_enable_interrupt (struct drm_device *dev)
--{
--      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      u16 flag;
--
--      flag = 0;
--      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
--              flag |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
--      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
--              flag |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
--
--      I915_WRITE16(IER, I915_USER_INTERRUPT | flag);
--}
--
- /* Set the vblank monitor pipe
-  */
- int i915_vblank_pipe_set(struct drm_device *dev, void *data,
-@@ -434,6 +474,7 @@ int i915_vblank_pipe_set(struct drm_devi
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_pipe_t *pipe = data;
-+      u32 enable_mask = 0, disable_mask = 0;
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-@@ -445,9 +486,20 @@ int i915_vblank_pipe_set(struct drm_devi
-               return -EINVAL;
-       }
--      dev_priv->vblank_pipe = pipe->pipe;
-+      if (pipe->pipe & DRM_I915_VBLANK_PIPE_A)
-+              enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-+      else
-+              disable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-+
-+      if (pipe->pipe & DRM_I915_VBLANK_PIPE_B)
-+              enable_mask |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-+      else
-+              disable_mask |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
--      i915_enable_interrupt (dev);
-+      i915_enable_irq(dev_priv, enable_mask);
-+      i915_disable_irq(dev_priv, disable_mask);
-+
-+      dev_priv->vblank_pipe = pipe->pipe;
-       return 0;
- }
-@@ -464,7 +516,7 @@ int i915_vblank_pipe_get(struct drm_devi
-               return -EINVAL;
-       }
--      flag = I915_READ(IER);
-+      flag = I915_READ(IMR);
-       pipe->pipe = 0;
-       if (flag & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-               pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
-@@ -586,9 +638,9 @@ void i915_driver_irq_preinstall(struct d
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      I915_WRITE16(HWSTAM, 0xfffe);
--      I915_WRITE16(IMR, 0x0);
--      I915_WRITE16(IER, 0x0);
-+      I915_WRITE(HWSTAM, 0xfffe);
-+      I915_WRITE(IMR, 0x0);
-+      I915_WRITE(IER, 0x0);
- }
- void i915_driver_irq_postinstall(struct drm_device * dev)
-@@ -601,7 +653,18 @@ void i915_driver_irq_postinstall(struct 
-       if (!dev_priv->vblank_pipe)
-               dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
--      i915_enable_interrupt(dev);
-+
-+      /* Set initial unmasked IRQs to just the selected vblank pipes. */
-+      dev_priv->irq_mask_reg = ~0;
-+      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
-+              dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-+      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
-+              dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-+
-+      I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+      I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
-+      (void) I915_READ(IER);
-+
-       DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
- }
-@@ -613,10 +676,10 @@ void i915_driver_irq_uninstall(struct dr
-       if (!dev_priv)
-               return;
--      I915_WRITE16(HWSTAM, 0xffff);
--      I915_WRITE16(IMR, 0xffff);
--      I915_WRITE16(IER, 0x0);
-+      I915_WRITE(HWSTAM, 0xffff);
-+      I915_WRITE(IMR, 0xffff);
-+      I915_WRITE(IER, 0x0);
--      temp = I915_READ16(IIR);
--      I915_WRITE16(IIR, temp);
-+      temp = I915_READ(IIR);
-+      I915_WRITE(IIR, temp);
- }
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0004_i915.Track_progress_inside_of_batchbuffers_for_determining_wedgedness.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0004_i915.Track_progress_inside_of_batchbuffers_for_determining_wedgedness.patch
deleted file mode 100644 (file)
index c391d16..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From: Keith Packard <keithp@keithp.com>
-Date: Wed, 30 Jul 2008 19:21:20 +0000 (-0700)
-Subject: i915: Track progress inside of batchbuffers for determining wedgedness.
-X-Git-Tag: v2.6.12-rc2
-X-Git-Url: http://gitweb.freedesktop.org/?p=users/anholt/anholt/linux-2.6.git;a=commitdiff;h=f0740db2246e4217384e8de32de6ebb4fbd807c9
-
-i915: Track progress inside of batchbuffers for determining wedgedness.
-
-This avoids early termination for long-running commands.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
-
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -40,11 +40,15 @@ int i915_wait_ring(struct drm_device * d
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
-+      u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
-+      u32 last_acthd = I915_READ(acthd_reg);
-+      u32 acthd;
-       u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-       int i;
--      for (i = 0; i < 10000; i++) {
-+      for (i = 0; i < 100000; i++) {
-               ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-+              acthd = I915_READ(acthd_reg);
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->Size;
-@@ -55,8 +59,13 @@ int i915_wait_ring(struct drm_device * d
-               if (ring->head != last_head)
-                       i = 0;
-+              if (acthd != last_acthd)
-+                      i = 0;
-               last_head = ring->head;
-+              last_acthd = acthd;
-+              msleep_interruptible(10);
-+
-       }
-       return -EBUSY;
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0005_i915.remove_settable_use_mi_batchbuffer_start.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0005_i915.remove_settable_use_mi_batchbuffer_start.patch
deleted file mode 100644 (file)
index 12362fe..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From: Keith Packard <keithp@keithp.com>
-Date: Wed, 30 Jul 2008 19:28:47 +0000 (-0700)
-Subject: i915: remove settable use_mi_batchbuffer_start
-X-Git-Tag: v2.6.12-rc2
-X-Git-Url: http://gitweb.freedesktop.org/?p=users/anholt/anholt/linux-2.6.git;a=commitdiff;h=6fcd9a69a91c53d733870df20e095eea2b73620c
-
-i915: remove settable use_mi_batchbuffer_start
-
-The driver can know what hardware requires MI_BATCH_BUFFER vs
-MI_BATCH_BUFFER_START; there's no reason to let user mode configure this.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
-
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -159,13 +159,6 @@ static int i915_initialize(struct drm_de
-       dev_priv->current_page = 0;
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
--      /* We are using separate values as placeholders for mechanisms for
--       * private backbuffer/depthbuffer usage.
--       */
--      dev_priv->use_mi_batchbuffer_start = 0;
--      if (IS_I965G(dev)) /* 965 doesn't support older method */
--              dev_priv->use_mi_batchbuffer_start = 1;
--
-       /* Allow hardware batchbuffers unless told otherwise.
-        */
-       dev_priv->allow_batchbuffer = 1;
-@@ -486,7 +479,7 @@ static int i915_dispatch_batchbuffer(str
-                               return ret;
-               }
--              if (dev_priv->use_mi_batchbuffer_start) {
-+              if (!IS_I830(dev) && !IS_845G(dev)) {
-                       BEGIN_LP_RING(2);
-                       if (IS_I965G(dev)) {
-                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
-@@ -697,8 +690,6 @@ static int i915_setparam(struct drm_devi
-       switch (param->param) {
-       case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
--              if (!IS_I965G(dev))
--                      dev_priv->use_mi_batchbuffer_start = param->value;
-               break;
-       case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
-               dev_priv->tex_lru_log_granularity = param->value;
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -99,7 +99,6 @@ typedef struct drm_i915_private {
-       int front_offset;
-       int current_page;
-       int page_flipping;
--      int use_mi_batchbuffer_start;
-       wait_queue_head_t irq_queue;
-       atomic_t irq_received;
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0006_i915.Ignore_X_server_provided_mmio_address.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0006_i915.Ignore_X_server_provided_mmio_address.patch
deleted file mode 100644 (file)
index 397f683..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From: Keith Packard <keithp@keithp.com>
-Date: Wed, 30 Jul 2008 19:36:08 +0000 (-0700)
-Subject: i915: Ignore X server provided mmio address
-X-Git-Tag: v2.6.12-rc2
-X-Git-Url: http://gitweb.freedesktop.org/?p=users/anholt/anholt/linux-2.6.git;a=commitdiff;h=5d34a0e06e6e70b01ee070094322695b9e3f0029
-
-i915: Ignore X server provided mmio address
-
-It is already correctly detected by the kernel for use in suspend/resume.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
-
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -121,13 +121,6 @@ static int i915_initialize(struct drm_de
-               return -EINVAL;
-       }
--      dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
--      if (!dev_priv->mmio_map) {
--              i915_dma_cleanup(dev);
--              DRM_ERROR("can not find mmio map!\n");
--              return -EINVAL;
--      }
--
-       dev_priv->sarea_priv = (drm_i915_sarea_t *)
-           ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
-@@ -194,11 +187,6 @@ static int i915_dma_resume(struct drm_de
-               return -EINVAL;
-       }
--      if (!dev_priv->mmio_map) {
--              DRM_ERROR("can not find mmio map!\n");
--              return -EINVAL;
--      }
--
-       if (dev_priv->ring.map.handle == NULL) {
-               DRM_ERROR("can not ioremap virtual address for"
-                         " ring buffer\n");
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0007_i915.Initialize_hardware_status_page_at_device_load_when_possible.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0007_i915.Initialize_hardware_status_page_at_device_load_when_possible.patch
deleted file mode 100644 (file)
index cf646f0..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-From: Keith Packard <keithp@keithp.com>
-Date: Wed, 30 Jul 2008 20:03:43 +0000 (-0700)
-Subject: i915: Initialize hardware status page at device load when possible.
-X-Git-Tag: v2.6.12-rc2
-X-Git-Url: http://gitweb.freedesktop.org/?p=users/anholt/anholt/linux-2.6.git;a=commitdiff;h=ddb354254f88965f5f057e67ef775fbb4b35fef8
-
-i915: Initialize hardware status page at device load when possible.
-
-Some chips were unstable with repeated setup/teardown of the hardware status
-page.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
-
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -71,6 +71,52 @@ int i915_wait_ring(struct drm_device * d
-       return -EBUSY;
- }
-+/**
-+ * Sets up the hardware status page for devices that need a physical address
-+ * in the register.
-+ */
-+int i915_init_phys_hws(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      /* Program Hardware Status Page */
-+      dev_priv->status_page_dmah =
-+              drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
-+
-+      if (!dev_priv->status_page_dmah) {
-+              DRM_ERROR("Can not allocate hardware status page\n");
-+              return -ENOMEM;
-+      }
-+      dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
-+      dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-+
-+      memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-+
-+      I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-+      DRM_DEBUG("Enabled hardware status page\n");
-+      return 0;
-+}
-+
-+/**
-+ * Frees the hardware status page, whether it's a physical address or a virtual
-+ * address set up by the X Server.
-+ */
-+void i915_free_hws(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      if (dev_priv->status_page_dmah) {
-+              drm_pci_free(dev, dev_priv->status_page_dmah);
-+              dev_priv->status_page_dmah = NULL;
-+      }
-+
-+      if (dev_priv->status_gfx_addr) {
-+              dev_priv->status_gfx_addr = 0;
-+              drm_core_ioremapfree(&dev_priv->hws_map, dev);
-+      }
-+
-+      /* Need to rewrite hardware status page */
-+      I915_WRITE(HWS_PGA, 0x1ffff000);
-+}
-+
- void i915_kernel_lost_context(struct drm_device * dev)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-@@ -103,18 +149,9 @@ static int i915_dma_cleanup(struct drm_d
-               dev_priv->ring.map.size = 0;
-       }
--      if (dev_priv->status_page_dmah) {
--              drm_pci_free(dev, dev_priv->status_page_dmah);
--              dev_priv->status_page_dmah = NULL;
--              /* Need to rewrite hardware status page */
--              I915_WRITE(HWS_PGA, 0x1ffff000);
--      }
--
--      if (dev_priv->status_gfx_addr) {
--              dev_priv->status_gfx_addr = 0;
--              drm_core_ioremapfree(&dev_priv->hws_map, dev);
--              I915_WRITE(HWS_PGA, 0x1ffff000);
--      }
-+      /* Clear the HWS virtual address at teardown */
-+      if (I915_NEED_GFX_HWS(dev))
-+              i915_free_hws(dev);
-       return 0;
- }
-@@ -165,23 +202,6 @@ static int i915_initialize(struct drm_de
-        */
-       dev_priv->allow_batchbuffer = 1;
--      /* Program Hardware Status Page */
--      if (!I915_NEED_GFX_HWS(dev)) {
--              dev_priv->status_page_dmah =
--                      drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
--
--              if (!dev_priv->status_page_dmah) {
--                      i915_dma_cleanup(dev);
--                      DRM_ERROR("Can not allocate hardware status page\n");
--                      return -ENOMEM;
--              }
--              dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
--              dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
--
--              memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
--              I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
--      }
--      DRM_DEBUG("Enabled hardware status page\n");
-       return 0;
- }
-@@ -773,6 +793,12 @@ int i915_driver_load(struct drm_device *
-                        _DRM_KERNEL | _DRM_DRIVER,
-                        &dev_priv->mmio_map);
-+      /* Init HWS */
-+      if (!I915_NEED_GFX_HWS(dev)) {
-+              ret = i915_init_phys_hws(dev);
-+              if (ret != 0)
-+                      return ret;
-+      }
-       /* On the 945G/GM, the chipset reports the MSI capability on the
-        * integrated graphics even though the support isn't actually there
-@@ -796,6 +822,8 @@ int i915_driver_unload(struct drm_device
-       if (dev->pdev->msi_enabled)
-               pci_disable_msi(dev->pdev);
-+      i915_free_hws(dev);
-+
-       if (dev_priv->mmio_map)
-               drm_rmmap(dev, dev_priv->mmio_map);
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0008_drm.Add_GEM_graphics_execution_manager_to_i915_driver.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0008_drm.Add_GEM_graphics_execution_manager_to_i915_driver.patch
deleted file mode 100644 (file)
index e7ae851..0000000
+++ /dev/null
@@ -1,5453 +0,0 @@
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 30 Jul 2008 19:06:12 +0000 (-0700)
-Subject: drm: Add GEM ("graphics execution manager") to i915 driver.
-X-Git-Tag: v2.6.12-rc2
-X-Git-Url: http://gitweb.freedesktop.org/?p=users/anholt/anholt/linux-2.6.git;a=commitdiff;h=drm-gem-merge
-
-drm: Add GEM ("graphics execution manager") to i915 driver.
-
-GEM allows the creation of persistent buffer objects accessible by the
-graphics device through new ioctls for managing execution of commands on the
-device.  The userland API is almost entirely driver-specific to ensure that
-any driver building on this model can easily map the interface to individual
-driver requirements.
-
-GEM is used by the 2d driver for managing its internal state allocations and
-will be used for pixmap storage to reduce memory consumption and enable
-zero-copy GLX_EXT_texture_from_pixmap, and in the 3d driver is used to enable
-GL_EXT_framebuffer_object and GL_ARB_pixel_buffer_object.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
-
---- a/drivers/gpu/drm/Makefile
-+++ b/drivers/gpu/drm/Makefile
-@@ -4,8 +4,9 @@
- ccflags-y := -Iinclude/drm
--drm-y       :=        drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
--              drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
-+drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
-+              drm_context.o drm_dma.o drm_drawable.o \
-+              drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
-               drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
-               drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
-               drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
---- a/drivers/gpu/drm/drm_agpsupport.c
-+++ b/drivers/gpu/drm/drm_agpsupport.c
-@@ -33,6 +33,7 @@
- #include "drmP.h"
- #include <linux/module.h>
-+#include <asm/agp.h>
- #if __OS_HAS_AGP
-@@ -452,4 +453,52 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * 
-       return agp_unbind_memory(handle);
- }
--#endif                                /* __OS_HAS_AGP */
-+/**
-+ * Binds a collection of pages into AGP memory at the given offset, returning
-+ * the AGP memory structure containing them.
-+ *
-+ * No reference is held on the pages during this time -- it is up to the
-+ * caller to handle that.
-+ */
-+DRM_AGP_MEM *
-+drm_agp_bind_pages(struct drm_device *dev,
-+                 struct page **pages,
-+                 unsigned long num_pages,
-+                 uint32_t gtt_offset)
-+{
-+      DRM_AGP_MEM *mem;
-+      int ret, i;
-+
-+      DRM_DEBUG("\n");
-+
-+      mem = drm_agp_allocate_memory(dev->agp->bridge, num_pages,
-+                                    AGP_USER_MEMORY);
-+      if (mem == NULL) {
-+              DRM_ERROR("Failed to allocate memory for %ld pages\n",
-+                        num_pages);
-+              return NULL;
-+      }
-+
-+      for (i = 0; i < num_pages; i++)
-+              mem->memory[i] = phys_to_gart(page_to_phys(pages[i]));
-+      mem->page_count = num_pages;
-+
-+      mem->is_flushed = true;
-+      ret = drm_agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
-+      if (ret != 0) {
-+              DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
-+              agp_free_memory(mem);
-+              return NULL;
-+      }
-+
-+      return mem;
-+}
-+EXPORT_SYMBOL(drm_agp_bind_pages);
-+
-+void drm_agp_chipset_flush(struct drm_device *dev)
-+{
-+      agp_flush_chipset(dev->agp->bridge);
-+}
-+EXPORT_SYMBOL(drm_agp_chipset_flush);
-+
-+#endif /* __OS_HAS_AGP */
---- /dev/null
-+++ b/drivers/gpu/drm/drm_cache.c
-@@ -0,0 +1,76 @@
-+/**************************************************************************
-+ *
-+ * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
-+ * All Rights Reserved.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the
-+ * "Software"), to deal in the Software without restriction, including
-+ * without limitation the rights to use, copy, modify, merge, publish,
-+ * distribute, sub license, and/or sell copies of the Software, and to
-+ * permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the
-+ * next paragraph) shall be included in all copies or substantial portions
-+ * of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
-+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ **************************************************************************/
-+/*
-+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
-+ */
-+
-+#include "drmP.h"
-+
-+#if defined(CONFIG_X86)
-+static void
-+drm_clflush_page(struct page *page)
-+{
-+      uint8_t *page_virtual;
-+      unsigned int i;
-+
-+      if (unlikely(page == NULL))
-+              return;
-+
-+      page_virtual = kmap_atomic(page, KM_USER0);
-+      for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
-+              clflush(page_virtual + i);
-+      kunmap_atomic(page_virtual, KM_USER0);
-+}
-+#endif
-+
-+static void
-+drm_clflush_ipi_handler(void *null)
-+{
-+      wbinvd();
-+}
-+
-+void
-+drm_clflush_pages(struct page *pages[], unsigned long num_pages)
-+{
-+
-+#if defined(CONFIG_X86)
-+      if (cpu_has_clflush) {
-+              unsigned long i;
-+
-+              mb();
-+              for (i = 0; i < num_pages; ++i)
-+                      drm_clflush_page(*pages++);
-+              mb();
-+
-+              return;
-+      }
-+#endif
-+
-+      if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
-+              DRM_ERROR("Timed out waiting for cache flush.\n");
-+}
-+EXPORT_SYMBOL(drm_clflush_pages);
---- a/drivers/gpu/drm/drm_drv.c
-+++ b/drivers/gpu/drm/drm_drv.c
-@@ -117,6 +117,10 @@ static struct drm_ioctl_desc drm_ioctls[
-       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-+
-+      DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
- };
- #define DRM_CORE_IOCTL_COUNT  ARRAY_SIZE( drm_ioctls )
---- a/drivers/gpu/drm/drm_fops.c
-+++ b/drivers/gpu/drm/drm_fops.c
-@@ -256,6 +256,9 @@ static int drm_open_helper(struct inode 
-       INIT_LIST_HEAD(&priv->lhead);
-+      if (dev->driver->driver_features & DRIVER_GEM)
-+              drm_gem_open(dev, priv);
-+
-       if (dev->driver->open) {
-               ret = dev->driver->open(dev, priv);
-               if (ret < 0)
-@@ -400,6 +403,9 @@ int drm_release(struct inode *inode, str
-               dev->driver->reclaim_buffers(dev, file_priv);
-       }
-+      if (dev->driver->driver_features & DRIVER_GEM)
-+              drm_gem_release(dev, file_priv);
-+
-       drm_fasync(-1, filp, 0);
-       mutex_lock(&dev->ctxlist_mutex);
---- /dev/null
-+++ b/drivers/gpu/drm/drm_gem.c
-@@ -0,0 +1,420 @@
-+/*
-+ * Copyright Ã‚© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Eric Anholt <eric@anholt.net>
-+ *
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/mm.h>
-+#include <linux/uaccess.h>
-+#include <linux/fs.h>
-+#include <linux/file.h>
-+#include <linux/module.h>
-+#include <linux/mman.h>
-+#include <linux/pagemap.h>
-+#include "drmP.h"
-+
-+/** @file drm_gem.c
-+ *
-+ * This file provides some of the base ioctls and library routines for
-+ * the graphics memory manager implemented by each device driver.
-+ *
-+ * Because various devices have different requirements in terms of
-+ * synchronization and migration strategies, implementing that is left up to
-+ * the driver, and all that the general API provides should be generic --
-+ * allocating objects, reading/writing data with the cpu, freeing objects.
-+ * Even there, platform-dependent optimizations for reading/writing data with
-+ * the CPU mean we'll likely hook those out to driver-specific calls.  However,
-+ * the DRI2 implementation wants to have at least allocate/mmap be generic.
-+ *
-+ * The goal was to have swap-backed object allocation managed through
-+ * struct file.  However, file descriptors as handles to a struct file have
-+ * two major failings:
-+ * - Process limits prevent more than 1024 or so being used at a time by
-+ *   default.
-+ * - Inability to allocate high fds will aggravate the X Server's select()
-+ *   handling, and likely that of many GL client applications as well.
-+ *
-+ * This led to a plan of using our own integer IDs (called handles, following
-+ * DRM terminology) to mimic fds, and implement the fd syscalls we need as
-+ * ioctls.  The objects themselves will still include the struct file so
-+ * that we can transition to fds if the required kernel infrastructure shows
-+ * up at a later date, and as our interface with shmfs for memory allocation.
-+ */
-+
-+/**
-+ * Initialize the GEM device fields
-+ */
-+
-+int
-+drm_gem_init(struct drm_device *dev)
-+{
-+      spin_lock_init(&dev->object_name_lock);
-+      idr_init(&dev->object_name_idr);
-+      atomic_set(&dev->object_count, 0);
-+      atomic_set(&dev->object_memory, 0);
-+      atomic_set(&dev->pin_count, 0);
-+      atomic_set(&dev->pin_memory, 0);
-+      atomic_set(&dev->gtt_count, 0);
-+      atomic_set(&dev->gtt_memory, 0);
-+      return 0;
-+}
-+
-+/**
-+ * Allocate a GEM object of the specified size with shmfs backing store
-+ */
-+struct drm_gem_object *
-+drm_gem_object_alloc(struct drm_device *dev, size_t size)
-+{
-+      struct drm_gem_object *obj;
-+
-+      BUG_ON((size & (PAGE_SIZE - 1)) != 0);
-+
-+      obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
-+
-+      obj->dev = dev;
-+      obj->filp = shmem_file_setup("drm mm object", size, 0);
-+      if (IS_ERR(obj->filp)) {
-+              kfree(obj);
-+              return NULL;
-+      }
-+
-+      kref_init(&obj->refcount);
-+      kref_init(&obj->handlecount);
-+      obj->size = size;
-+      if (dev->driver->gem_init_object != NULL &&
-+          dev->driver->gem_init_object(obj) != 0) {
-+              fput(obj->filp);
-+              kfree(obj);
-+              return NULL;
-+      }
-+      atomic_inc(&dev->object_count);
-+      atomic_add(obj->size, &dev->object_memory);
-+      return obj;
-+}
-+EXPORT_SYMBOL(drm_gem_object_alloc);
-+
-+/**
-+ * Removes the mapping from handle to filp for this object.
-+ */
-+static int
-+drm_gem_handle_delete(struct drm_file *filp, int handle)
-+{
-+      struct drm_device *dev;
-+      struct drm_gem_object *obj;
-+
-+      /* This is gross. The idr system doesn't let us try a delete and
-+       * return an error code.  It just spews if you fail at deleting.
-+       * So, we have to grab a lock around finding the object and then
-+       * doing the delete on it and dropping the refcount, or the user
-+       * could race us to double-decrement the refcount and cause a
-+       * use-after-free later.  Given the frequency of our handle lookups,
-+       * we may want to use ida for number allocation and a hash table
-+       * for the pointers, anyway.
-+       */
-+      spin_lock(&filp->table_lock);
-+
-+      /* Check if we currently have a reference on the object */
-+      obj = idr_find(&filp->object_idr, handle);
-+      if (obj == NULL) {
-+              spin_unlock(&filp->table_lock);
-+              return -EINVAL;
-+      }
-+      dev = obj->dev;
-+
-+      /* Release reference and decrement refcount. */
-+      idr_remove(&filp->object_idr, handle);
-+      spin_unlock(&filp->table_lock);
-+
-+      mutex_lock(&dev->struct_mutex);
-+      drm_gem_object_handle_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+/**
-+ * Create a handle for this object. This adds a handle reference
-+ * to the object, which includes a regular reference count. Callers
-+ * will likely want to dereference the object afterwards.
-+ */
-+int
-+drm_gem_handle_create(struct drm_file *file_priv,
-+                     struct drm_gem_object *obj,
-+                     int *handlep)
-+{
-+      int     ret;
-+
-+      /*
-+       * Get the user-visible handle using idr.
-+       */
-+again:
-+      /* ensure there is space available to allocate a handle */
-+      if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0)
-+              return -ENOMEM;
-+
-+      /* do the allocation under our spinlock */
-+      spin_lock(&file_priv->table_lock);
-+      ret = idr_get_new_above(&file_priv->object_idr, obj, 1, handlep);
-+      spin_unlock(&file_priv->table_lock);
-+      if (ret == -EAGAIN)
-+              goto again;
-+
-+      if (ret != 0)
-+              return ret;
-+
-+      drm_gem_object_handle_reference(obj);
-+      return 0;
-+}
-+EXPORT_SYMBOL(drm_gem_handle_create);
-+
-+/** Returns a reference to the object named by the handle. */
-+struct drm_gem_object *
-+drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
-+                    int handle)
-+{
-+      struct drm_gem_object *obj;
-+
-+      spin_lock(&filp->table_lock);
-+
-+      /* Check if we currently have a reference on the object */
-+      obj = idr_find(&filp->object_idr, handle);
-+      if (obj == NULL) {
-+              spin_unlock(&filp->table_lock);
-+              return NULL;
-+      }
-+
-+      drm_gem_object_reference(obj);
-+
-+      spin_unlock(&filp->table_lock);
-+
-+      return obj;
-+}
-+EXPORT_SYMBOL(drm_gem_object_lookup);
-+
-+/**
-+ * Releases the handle to an mm object.
-+ */
-+int
-+drm_gem_close_ioctl(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      struct drm_gem_close *args = data;
-+      int ret;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      ret = drm_gem_handle_delete(file_priv, args->handle);
-+
-+      return ret;
-+}
-+
-+/**
-+ * Create a global name for an object, returning the name.
-+ *
-+ * Note that the name does not hold a reference; when the object
-+ * is freed, the name goes away.
-+ */
-+int
-+drm_gem_flink_ioctl(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      struct drm_gem_flink *args = data;
-+      struct drm_gem_object *obj;
-+      int ret;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EINVAL;
-+
-+again:
-+      if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
-+              return -ENOMEM;
-+
-+      spin_lock(&dev->object_name_lock);
-+      if (obj->name) {
-+              spin_unlock(&dev->object_name_lock);
-+              return -EEXIST;
-+      }
-+      ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
-+                               &obj->name);
-+      spin_unlock(&dev->object_name_lock);
-+      if (ret == -EAGAIN)
-+              goto again;
-+
-+      if (ret != 0) {
-+              mutex_lock(&dev->struct_mutex);
-+              drm_gem_object_unreference(obj);
-+              mutex_unlock(&dev->struct_mutex);
-+              return ret;
-+      }
-+
-+      /*
-+       * Leave the reference from the lookup around as the
-+       * name table now holds one
-+       */
-+      args->name = (uint64_t) obj->name;
-+
-+      return 0;
-+}
-+
-+/**
-+ * Open an object using the global name, returning a handle and the size.
-+ *
-+ * This handle (of course) holds a reference to the object, so the object
-+ * will not go away until the handle is deleted.
-+ */
-+int
-+drm_gem_open_ioctl(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_gem_open *args = data;
-+      struct drm_gem_object *obj;
-+      int ret;
-+      int handle;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      spin_lock(&dev->object_name_lock);
-+      obj = idr_find(&dev->object_name_idr, (int) args->name);
-+      if (obj)
-+              drm_gem_object_reference(obj);
-+      spin_unlock(&dev->object_name_lock);
-+      if (!obj)
-+              return -ENOENT;
-+
-+      ret = drm_gem_handle_create(file_priv, obj, &handle);
-+      mutex_lock(&dev->struct_mutex);
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      if (ret)
-+              return ret;
-+
-+      args->handle = handle;
-+      args->size = obj->size;
-+
-+      return 0;
-+}
-+
-+/**
-+ * Called at device open time, sets up the structure for handling refcounting
-+ * of mm objects.
-+ */
-+void
-+drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
-+{
-+      idr_init(&file_private->object_idr);
-+      spin_lock_init(&file_private->table_lock);
-+}
-+
-+/**
-+ * Called at device close to release the file's
-+ * handle references on objects.
-+ */
-+static int
-+drm_gem_object_release_handle(int id, void *ptr, void *data)
-+{
-+      struct drm_gem_object *obj = ptr;
-+
-+      drm_gem_object_handle_unreference(obj);
-+
-+      return 0;
-+}
-+
-+/**
-+ * Called at close time when the filp is going away.
-+ *
-+ * Releases any remaining references on objects by this filp.
-+ */
-+void
-+drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
-+{
-+      mutex_lock(&dev->struct_mutex);
-+      idr_for_each(&file_private->object_idr,
-+                   &drm_gem_object_release_handle, NULL);
-+
-+      idr_destroy(&file_private->object_idr);
-+      mutex_unlock(&dev->struct_mutex);
-+}
-+
-+/**
-+ * Called after the last reference to the object has been lost.
-+ *
-+ * Frees the object
-+ */
-+void
-+drm_gem_object_free(struct kref *kref)
-+{
-+      struct drm_gem_object *obj = (struct drm_gem_object *) kref;
-+      struct drm_device *dev = obj->dev;
-+
-+      BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-+
-+      if (dev->driver->gem_free_object != NULL)
-+              dev->driver->gem_free_object(obj);
-+
-+      fput(obj->filp);
-+      atomic_dec(&dev->object_count);
-+      atomic_sub(obj->size, &dev->object_memory);
-+      kfree(obj);
-+}
-+EXPORT_SYMBOL(drm_gem_object_free);
-+
-+/**
-+ * Called after the last handle to the object has been closed
-+ *
-+ * Removes any name for the object. Note that this must be
-+ * called before drm_gem_object_free or we'll be touching
-+ * freed memory
-+ */
-+void
-+drm_gem_object_handle_free(struct kref *kref)
-+{
-+      struct drm_gem_object *obj = container_of(kref,
-+                                                struct drm_gem_object,
-+                                                handlecount);
-+      struct drm_device *dev = obj->dev;
-+
-+      /* Remove any name for this object */
-+      spin_lock(&dev->object_name_lock);
-+      if (obj->name) {
-+              idr_remove(&dev->object_name_idr, obj->name);
-+              spin_unlock(&dev->object_name_lock);
-+              /*
-+               * The object name held a reference to this object, drop
-+               * that now.
-+               */
-+              drm_gem_object_unreference(obj);
-+      } else
-+              spin_unlock(&dev->object_name_lock);
-+
-+}
-+EXPORT_SYMBOL(drm_gem_object_handle_free);
-+
---- a/drivers/gpu/drm/drm_memory.c
-+++ b/drivers/gpu/drm/drm_memory.c
-@@ -133,6 +133,7 @@ int drm_free_agp(DRM_AGP_MEM * handle, i
- {
-       return drm_agp_free_memory(handle) ? 0 : -EINVAL;
- }
-+EXPORT_SYMBOL(drm_free_agp);
- /** Wrapper around agp_bind_memory() */
- int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
-@@ -145,6 +146,7 @@ int drm_unbind_agp(DRM_AGP_MEM * handle)
- {
-       return drm_agp_unbind_memory(handle);
- }
-+EXPORT_SYMBOL(drm_unbind_agp);
- #else  /*  __OS_HAS_AGP  */
- static inline void *agp_remap(unsigned long offset, unsigned long size,
---- a/drivers/gpu/drm/drm_mm.c
-+++ b/drivers/gpu/drm/drm_mm.c
-@@ -169,6 +169,7 @@ struct drm_mm_node *drm_mm_get_block(str
-       return child;
- }
-+EXPORT_SYMBOL(drm_mm_get_block);
- /*
-  * Put a block. Merge with the previous and / or next block if they are free.
-@@ -217,6 +218,7 @@ void drm_mm_put_block(struct drm_mm_node
-               drm_free(cur, sizeof(*cur), DRM_MEM_MM);
-       }
- }
-+EXPORT_SYMBOL(drm_mm_put_block);
- struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
-                                 unsigned long size,
-@@ -265,6 +267,7 @@ int drm_mm_clean(struct drm_mm * mm)
-       return (head->next->next == head);
- }
-+EXPORT_SYMBOL(drm_mm_search_free);
- int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
- {
-@@ -273,7 +276,7 @@ int drm_mm_init(struct drm_mm * mm, unsi
-       return drm_mm_create_tail_node(mm, start, size);
- }
--
-+EXPORT_SYMBOL(drm_mm_init);
- void drm_mm_takedown(struct drm_mm * mm)
- {
---- a/drivers/gpu/drm/drm_proc.c
-+++ b/drivers/gpu/drm/drm_proc.c
-@@ -49,6 +49,10 @@ static int drm_queues_info(char *buf, ch
-                          int request, int *eof, void *data);
- static int drm_bufs_info(char *buf, char **start, off_t offset,
-                        int request, int *eof, void *data);
-+static int drm_gem_name_info(char *buf, char **start, off_t offset,
-+                           int request, int *eof, void *data);
-+static int drm_gem_object_info(char *buf, char **start, off_t offset,
-+                             int request, int *eof, void *data);
- #if DRM_DEBUG_CODE
- static int drm_vma_info(char *buf, char **start, off_t offset,
-                       int request, int *eof, void *data);
-@@ -60,13 +64,16 @@ static int drm_vma_info(char *buf, char 
- static struct drm_proc_list {
-       const char *name;       /**< file name */
-       int (*f) (char *, char **, off_t, int, int *, void *);          /**< proc callback*/
-+      u32 driver_features; /**< Required driver features for this entry */
- } drm_proc_list[] = {
--      {"name", drm_name_info},
--      {"mem", drm_mem_info},
--      {"vm", drm_vm_info},
--      {"clients", drm_clients_info},
--      {"queues", drm_queues_info},
--      {"bufs", drm_bufs_info},
-+      {"name", drm_name_info, 0},
-+      {"mem", drm_mem_info, 0},
-+      {"vm", drm_vm_info, 0},
-+      {"clients", drm_clients_info, 0},
-+      {"queues", drm_queues_info, 0},
-+      {"bufs", drm_bufs_info, 0},
-+      {"gem_names", drm_gem_name_info, DRIVER_GEM},
-+      {"gem_objects", drm_gem_object_info, DRIVER_GEM},
- #if DRM_DEBUG_CODE
-       {"vma", drm_vma_info},
- #endif
-@@ -90,8 +97,9 @@ static struct drm_proc_list {
- int drm_proc_init(struct drm_minor *minor, int minor_id,
-                 struct proc_dir_entry *root)
- {
-+      struct drm_device *dev = minor->dev;
-       struct proc_dir_entry *ent;
--      int i, j;
-+      int i, j, ret;
-       char name[64];
-       sprintf(name, "%d", minor_id);
-@@ -102,23 +110,42 @@ int drm_proc_init(struct drm_minor *mino
-       }
-       for (i = 0; i < DRM_PROC_ENTRIES; i++) {
-+              u32 features = drm_proc_list[i].driver_features;
-+
-+              if (features != 0 &&
-+                  (dev->driver->driver_features & features) != features)
-+                      continue;
-+
-               ent = create_proc_entry(drm_proc_list[i].name,
-                                       S_IFREG | S_IRUGO, minor->dev_root);
-               if (!ent) {
-                       DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
-                                 name, drm_proc_list[i].name);
--                      for (j = 0; j < i; j++)
--                              remove_proc_entry(drm_proc_list[i].name,
--                                                minor->dev_root);
--                      remove_proc_entry(name, root);
--                      minor->dev_root = NULL;
--                      return -1;
-+                      ret = -1;
-+                      goto fail;
-               }
-               ent->read_proc = drm_proc_list[i].f;
-               ent->data = minor;
-       }
-+      if (dev->driver->proc_init) {
-+              ret = dev->driver->proc_init(minor);
-+              if (ret) {
-+                      DRM_ERROR("DRM: Driver failed to initialize "
-+                                "/proc/dri.\n");
-+                      goto fail;
-+              }
-+      }
-+
-       return 0;
-+ fail:
-+
-+      for (j = 0; j < i; j++)
-+              remove_proc_entry(drm_proc_list[i].name,
-+                                minor->dev_root);
-+      remove_proc_entry(name, root);
-+      minor->dev_root = NULL;
-+      return ret;
- }
- /**
-@@ -133,12 +160,16 @@ int drm_proc_init(struct drm_minor *mino
-  */
- int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
- {
-+      struct drm_device *dev = minor->dev;
-       int i;
-       char name[64];
-       if (!root || !minor->dev_root)
-               return 0;
-+      if (dev->driver->proc_cleanup)
-+              dev->driver->proc_cleanup(minor);
-+
-       for (i = 0; i < DRM_PROC_ENTRIES; i++)
-               remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
-       sprintf(name, "%d", minor->index);
-@@ -480,6 +511,84 @@ static int drm_clients_info(char *buf, c
-       return ret;
- }
-+struct drm_gem_name_info_data {
-+       int                     len;
-+       char                    *buf;
-+       int                     eof;
-+};
-+
-+static int drm_gem_one_name_info(int id, void *ptr, void *data)
-+{
-+      struct drm_gem_object *obj = ptr;
-+      struct drm_gem_name_info_data   *nid = data;
-+
-+      DRM_INFO("name %d size %d\n", obj->name, obj->size);
-+      if (nid->eof)
-+              return 0;
-+
-+      nid->len += sprintf(&nid->buf[nid->len],
-+                          "%6d%9d%8d%9d\n",
-+                          obj->name, obj->size,
-+                          atomic_read(&obj->handlecount.refcount),
-+                          atomic_read(&obj->refcount.refcount));
-+      if (nid->len > DRM_PROC_LIMIT) {
-+              nid->eof = 1;
-+              return 0;
-+      }
-+      return 0;
-+}
-+
-+static int drm_gem_name_info(char *buf, char **start, off_t offset,
-+                           int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      struct drm_gem_name_info_data nid;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      nid.len = sprintf(buf, "  name     size handles refcount\n");
-+      nid.buf = buf;
-+      nid.eof = 0;
-+      idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, &nid);
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      if (nid.len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return nid.len - offset;
-+}
-+
-+static int drm_gem_object_info(char *buf, char **start, off_t offset,
-+                             int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("%d objects\n", atomic_read(&dev->object_count));
-+      DRM_PROC_PRINT("%d object bytes\n", atomic_read(&dev->object_memory));
-+      DRM_PROC_PRINT("%d pinned\n", atomic_read(&dev->pin_count));
-+      DRM_PROC_PRINT("%d pin bytes\n", atomic_read(&dev->pin_memory));
-+      DRM_PROC_PRINT("%d gtt bytes\n", atomic_read(&dev->gtt_memory));
-+      DRM_PROC_PRINT("%d gtt total\n", dev->gtt_total);
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
- #if DRM_DEBUG_CODE
- static int drm__vma_info(char *buf, char **start, off_t offset, int request,
---- a/drivers/gpu/drm/drm_stub.c
-+++ b/drivers/gpu/drm/drm_stub.c
-@@ -152,6 +152,15 @@ static int drm_fill_in_dev(struct drm_de
-               goto error_out_unreg;
-       }
-+      if (driver->driver_features & DRIVER_GEM) {
-+              retcode = drm_gem_init(dev);
-+              if (retcode) {
-+                      DRM_ERROR("Cannot initialize graphics execution "
-+                                "manager (GEM)\n");
-+                      goto error_out_unreg;
-+              }
-+      }
-+
-       return 0;
-       error_out_unreg:
-@@ -317,6 +326,7 @@ int drm_put_dev(struct drm_device * dev)
- int drm_put_minor(struct drm_minor **minor_p)
- {
-       struct drm_minor *minor = *minor_p;
-+
-       DRM_DEBUG("release secondary minor %d\n", minor->index);
-       if (minor->type == DRM_MINOR_LEGACY)
---- a/drivers/gpu/drm/i915/Makefile
-+++ b/drivers/gpu/drm/i915/Makefile
-@@ -3,7 +3,11 @@
- # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
- ccflags-y := -Iinclude/drm
--i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
-+i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
-+      i915_gem.o \
-+      i915_gem_debug.o \
-+      i915_gem_proc.o \
-+      i915_gem_tiling.o
- i915-$(CONFIG_COMPAT)   += i915_ioc32.o
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -170,24 +170,31 @@ static int i915_initialize(struct drm_de
-       dev_priv->sarea_priv = (drm_i915_sarea_t *)
-           ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
--      dev_priv->ring.Start = init->ring_start;
--      dev_priv->ring.End = init->ring_end;
--      dev_priv->ring.Size = init->ring_size;
--      dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
--
--      dev_priv->ring.map.offset = init->ring_start;
--      dev_priv->ring.map.size = init->ring_size;
--      dev_priv->ring.map.type = 0;
--      dev_priv->ring.map.flags = 0;
--      dev_priv->ring.map.mtrr = 0;
-+      if (init->ring_size != 0) {
-+              if (dev_priv->ring.ring_obj != NULL) {
-+                      i915_dma_cleanup(dev);
-+                      DRM_ERROR("Client tried to initialize ringbuffer in "
-+                                "GEM mode\n");
-+                      return -EINVAL;
-+              }
--      drm_core_ioremap(&dev_priv->ring.map, dev);
-+              dev_priv->ring.Size = init->ring_size;
-+              dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
--      if (dev_priv->ring.map.handle == NULL) {
--              i915_dma_cleanup(dev);
--              DRM_ERROR("can not ioremap virtual address for"
--                        " ring buffer\n");
--              return -ENOMEM;
-+              dev_priv->ring.map.offset = init->ring_start;
-+              dev_priv->ring.map.size = init->ring_size;
-+              dev_priv->ring.map.type = 0;
-+              dev_priv->ring.map.flags = 0;
-+              dev_priv->ring.map.mtrr = 0;
-+
-+              drm_core_ioremap(&dev_priv->ring.map, dev);
-+
-+              if (dev_priv->ring.map.handle == NULL) {
-+                      i915_dma_cleanup(dev);
-+                      DRM_ERROR("can not ioremap virtual address for"
-+                                " ring buffer\n");
-+                      return -ENOMEM;
-+              }
-       }
-       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-@@ -377,9 +384,10 @@ static int i915_emit_cmds(struct drm_dev
-       return 0;
- }
--static int i915_emit_box(struct drm_device * dev,
--                       struct drm_clip_rect __user * boxes,
--                       int i, int DR1, int DR4)
-+int
-+i915_emit_box(struct drm_device *dev,
-+            struct drm_clip_rect __user *boxes,
-+            int i, int DR1, int DR4)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_clip_rect box;
-@@ -681,6 +689,9 @@ static int i915_getparam(struct drm_devi
-       case I915_PARAM_LAST_DISPATCH:
-               value = READ_BREADCRUMB(dev_priv);
-               break;
-+      case I915_PARAM_HAS_GEM:
-+              value = 1;
-+              break;
-       default:
-               DRM_ERROR("Unknown parameter %d\n", param->param);
-               return -EINVAL;
-@@ -784,6 +795,7 @@ int i915_driver_load(struct drm_device *
-       memset(dev_priv, 0, sizeof(drm_i915_private_t));
-       dev->dev_private = (void *)dev_priv;
-+      dev_priv->dev = dev;
-       /* Add register map (needed for suspend/resume) */
-       base = drm_get_resource_start(dev, mmio_bar);
-@@ -793,6 +805,8 @@ int i915_driver_load(struct drm_device *
-                        _DRM_KERNEL | _DRM_DRIVER,
-                        &dev_priv->mmio_map);
-+      i915_gem_load(dev);
-+
-       /* Init HWS */
-       if (!I915_NEED_GFX_HWS(dev)) {
-               ret = i915_init_phys_hws(dev);
-@@ -833,6 +847,25 @@ int i915_driver_unload(struct drm_device
-       return 0;
- }
-+int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
-+{
-+      struct drm_i915_file_private *i915_file_priv;
-+
-+      DRM_DEBUG("\n");
-+      i915_file_priv = (struct drm_i915_file_private *)
-+          drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
-+
-+      if (!i915_file_priv)
-+              return -ENOMEM;
-+
-+      file_priv->driver_priv = i915_file_priv;
-+
-+      i915_file_priv->mm.last_gem_seqno = 0;
-+      i915_file_priv->mm.last_gem_throttle_seqno = 0;
-+
-+      return 0;
-+}
-+
- void i915_driver_lastclose(struct drm_device * dev)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-@@ -840,6 +873,8 @@ void i915_driver_lastclose(struct drm_de
-       if (!dev_priv)
-               return;
-+      i915_gem_lastclose(dev);
-+
-       if (dev_priv->agp_heap)
-               i915_mem_takedown(&(dev_priv->agp_heap));
-@@ -852,6 +887,13 @@ void i915_driver_preclose(struct drm_dev
-       i915_mem_release(dev, file_priv, dev_priv->agp_heap);
- }
-+void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
-+{
-+      struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
-+
-+      drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
-+}
-+
- struct drm_ioctl_desc i915_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
-@@ -870,6 +912,22 @@ struct drm_ioctl_desc i915_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
-       DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
- };
- int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -542,11 +542,13 @@ static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
-           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
--          DRIVER_IRQ_VBL2,
-+          DRIVER_IRQ_VBL2 | DRIVER_GEM,
-       .load = i915_driver_load,
-       .unload = i915_driver_unload,
-+      .open = i915_driver_open,
-       .lastclose = i915_driver_lastclose,
-       .preclose = i915_driver_preclose,
-+      .postclose = i915_driver_postclose,
-       .suspend = i915_suspend,
-       .resume = i915_resume,
-       .device_is_agp = i915_driver_device_is_agp,
-@@ -559,6 +561,10 @@ static struct drm_driver driver = {
-       .reclaim_buffers = drm_core_reclaim_buffers,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-+      .proc_init = i915_gem_proc_init,
-+      .proc_cleanup = i915_gem_proc_cleanup,
-+      .gem_init_object = i915_gem_init_object,
-+      .gem_free_object = i915_gem_free_object,
-       .ioctls = i915_ioctls,
-       .fops = {
-                .owner = THIS_MODULE,
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -39,7 +39,7 @@
- #define DRIVER_NAME           "i915"
- #define DRIVER_DESC           "Intel Graphics"
--#define DRIVER_DATE           "20060119"
-+#define DRIVER_DATE           "20080730"
- /* Interface history:
-  *
-@@ -55,16 +55,23 @@
- #define DRIVER_MINOR          6
- #define DRIVER_PATCHLEVEL     0
-+#define WATCH_COHERENCY       0
-+#define WATCH_BUF     0
-+#define WATCH_EXEC    0
-+#define WATCH_LRU     0
-+#define WATCH_RELOC   0
-+#define WATCH_INACTIVE        0
-+#define WATCH_PWRITE  0
-+
- typedef struct _drm_i915_ring_buffer {
-       int tail_mask;
--      unsigned long Start;
--      unsigned long End;
-       unsigned long Size;
-       u8 *virtual_start;
-       int head;
-       int tail;
-       int space;
-       drm_local_map_t map;
-+      struct drm_gem_object *ring_obj;
- } drm_i915_ring_buffer_t;
- struct mem_block {
-@@ -83,6 +90,8 @@ typedef struct _drm_i915_vbl_swap {
- } drm_i915_vbl_swap_t;
- typedef struct drm_i915_private {
-+      struct drm_device *dev;
-+
-       drm_local_map_t *sarea;
-       drm_local_map_t *mmio_map;
-@@ -95,6 +104,7 @@ typedef struct drm_i915_private {
-       unsigned long counter;
-       unsigned int status_gfx_addr;
-       drm_local_map_t hws_map;
-+      struct drm_gem_object *hws_obj;
-       unsigned int cpp;
-       int back_offset;
-@@ -104,7 +114,6 @@ typedef struct drm_i915_private {
-       wait_queue_head_t irq_queue;
-       atomic_t irq_received;
--      atomic_t irq_emitted;
-       /** Protects user_irq_refcount and irq_mask_reg */
-       spinlock_t user_irq_lock;
-       /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
-@@ -210,8 +219,174 @@ typedef struct drm_i915_private {
-       u8 saveDACMASK;
-       u8 saveDACDATA[256*3]; /* 256 3-byte colors */
-       u8 saveCR[37];
-+
-+      struct {
-+              struct drm_mm gtt_space;
-+
-+              /**
-+               * List of objects currently involved in rendering from the
-+               * ringbuffer.
-+               *
-+               * A reference is held on the buffer while on this list.
-+               */
-+              struct list_head active_list;
-+
-+              /**
-+               * List of objects which are not in the ringbuffer but which
-+               * still have a write_domain which needs to be flushed before
-+               * unbinding.
-+               *
-+               * A reference is held on the buffer while on this list.
-+               */
-+              struct list_head flushing_list;
-+
-+              /**
-+               * LRU list of objects which are not in the ringbuffer and
-+               * are ready to unbind, but are still in the GTT.
-+               *
-+               * A reference is not held on the buffer while on this list,
-+               * as merely being GTT-bound shouldn't prevent its being
-+               * freed, and we'll pull it off the list in the free path.
-+               */
-+              struct list_head inactive_list;
-+
-+              /**
-+               * List of breadcrumbs associated with GPU requests currently
-+               * outstanding.
-+               */
-+              struct list_head request_list;
-+
-+              /**
-+               * We leave the user IRQ off as much as possible,
-+               * but this means that requests will finish and never
-+               * be retired once the system goes idle. Set a timer to
-+               * fire periodically while the ring is running. When it
-+               * fires, go retire requests.
-+               */
-+              struct delayed_work retire_work;
-+
-+              uint32_t next_gem_seqno;
-+
-+              /**
-+               * Waiting sequence number, if any
-+               */
-+              uint32_t waiting_gem_seqno;
-+
-+              /**
-+               * Last seq seen at irq time
-+               */
-+              uint32_t irq_gem_seqno;
-+
-+              /**
-+               * Flag if the X Server, and thus DRM, is not currently in
-+               * control of the device.
-+               *
-+               * This is set between LeaveVT and EnterVT.  It needs to be
-+               * replaced with a semaphore.  It also needs to be
-+               * transitioned away from for kernel modesetting.
-+               */
-+              int suspended;
-+
-+              /**
-+               * Flag if the hardware appears to be wedged.
-+               *
-+               * This is set when attempts to idle the device timeout.
-+               * It prevents command submission from occuring and makes
-+               * every pending request fail
-+               */
-+              int wedged;
-+
-+              /** Bit 6 swizzling required for X tiling */
-+              uint32_t bit_6_swizzle_x;
-+              /** Bit 6 swizzling required for Y tiling */
-+              uint32_t bit_6_swizzle_y;
-+      } mm;
- } drm_i915_private_t;
-+/** driver private structure attached to each drm_gem_object */
-+struct drm_i915_gem_object {
-+      struct drm_gem_object *obj;
-+
-+      /** Current space allocated to this object in the GTT, if any. */
-+      struct drm_mm_node *gtt_space;
-+
-+      /** This object's place on the active/flushing/inactive lists */
-+      struct list_head list;
-+
-+      /**
-+       * This is set if the object is on the active or flushing lists
-+       * (has pending rendering), and is not set if it's on inactive (ready
-+       * to be unbound).
-+       */
-+      int active;
-+
-+      /**
-+       * This is set if the object has been written to since last bound
-+       * to the GTT
-+       */
-+      int dirty;
-+
-+      /** AGP memory structure for our GTT binding. */
-+      DRM_AGP_MEM *agp_mem;
-+
-+      struct page **page_list;
-+
-+      /**
-+       * Current offset of the object in GTT space.
-+       *
-+       * This is the same as gtt_space->start
-+       */
-+      uint32_t gtt_offset;
-+
-+      /** Boolean whether this object has a valid gtt offset. */
-+      int gtt_bound;
-+
-+      /** How many users have pinned this object in GTT space */
-+      int pin_count;
-+
-+      /** Breadcrumb of last rendering to the buffer. */
-+      uint32_t last_rendering_seqno;
-+
-+      /** Current tiling mode for the object. */
-+      uint32_t tiling_mode;
-+
-+      /**
-+       * Flagging of which individual pages are valid in GEM_DOMAIN_CPU when
-+       * GEM_DOMAIN_CPU is not in the object's read domain.
-+       */
-+      uint8_t *page_cpu_valid;
-+};
-+
-+/**
-+ * Request queue structure.
-+ *
-+ * The request queue allows us to note sequence numbers that have been emitted
-+ * and may be associated with active buffers to be retired.
-+ *
-+ * By keeping this list, we can avoid having to do questionable
-+ * sequence-number comparisons on buffer last_rendering_seqnos, and associate
-+ * an emission time with seqnos for tracking how far ahead of the GPU we are.
-+ */
-+struct drm_i915_gem_request {
-+      /** GEM sequence number associated with this request. */
-+      uint32_t seqno;
-+
-+      /** Time at which this request was emitted, in jiffies. */
-+      unsigned long emitted_jiffies;
-+
-+      /** Cache domains that were flushed at the start of the request. */
-+      uint32_t flush_domains;
-+
-+      struct list_head list;
-+};
-+
-+struct drm_i915_file_private {
-+      struct {
-+              uint32_t last_gem_seqno;
-+              uint32_t last_gem_throttle_seqno;
-+      } mm;
-+};
-+
- extern struct drm_ioctl_desc i915_ioctls[];
- extern int i915_max_ioctl;
-@@ -219,18 +394,26 @@ extern int i915_max_ioctl;
- extern void i915_kernel_lost_context(struct drm_device * dev);
- extern int i915_driver_load(struct drm_device *, unsigned long flags);
- extern int i915_driver_unload(struct drm_device *);
-+extern int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv);
- extern void i915_driver_lastclose(struct drm_device * dev);
- extern void i915_driver_preclose(struct drm_device *dev,
-                                struct drm_file *file_priv);
-+extern void i915_driver_postclose(struct drm_device *dev,
-+                                struct drm_file *file_priv);
- extern int i915_driver_device_is_agp(struct drm_device * dev);
- extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
-                             unsigned long arg);
-+extern int i915_emit_box(struct drm_device *dev,
-+                       struct drm_clip_rect __user *boxes,
-+                       int i, int DR1, int DR4);
- /* i915_irq.c */
- extern int i915_irq_emit(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
- extern int i915_irq_wait(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-+void i915_user_irq_get(struct drm_device *dev);
-+void i915_user_irq_put(struct drm_device *dev);
- extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
- extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
-@@ -257,6 +440,67 @@ extern int i915_mem_destroy_heap(struct 
- extern void i915_mem_takedown(struct mem_block **heap);
- extern void i915_mem_release(struct drm_device * dev,
-                            struct drm_file *file_priv, struct mem_block *heap);
-+/* i915_gem.c */
-+int i915_gem_init_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_create_ioctl(struct drm_device *dev, void *data,
-+                        struct drm_file *file_priv);
-+int i915_gem_pread_ioctl(struct drm_device *dev, void *data,
-+                       struct drm_file *file_priv);
-+int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
-+                        struct drm_file *file_priv);
-+int i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
-+                            struct drm_file *file_priv);
-+int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
-+                           struct drm_file *file_priv);
-+int i915_gem_execbuffer(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_pin_ioctl(struct drm_device *dev, void *data,
-+                     struct drm_file *file_priv);
-+int i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
-+                       struct drm_file *file_priv);
-+int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
-+                          struct drm_file *file_priv);
-+int i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
-+                         struct drm_file *file_priv);
-+int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
-+                         struct drm_file *file_priv);
-+int i915_gem_set_tiling(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_get_tiling(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+void i915_gem_load(struct drm_device *dev);
-+int i915_gem_proc_init(struct drm_minor *minor);
-+void i915_gem_proc_cleanup(struct drm_minor *minor);
-+int i915_gem_init_object(struct drm_gem_object *obj);
-+void i915_gem_free_object(struct drm_gem_object *obj);
-+int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
-+void i915_gem_object_unpin(struct drm_gem_object *obj);
-+void i915_gem_lastclose(struct drm_device *dev);
-+uint32_t i915_get_gem_seqno(struct drm_device *dev);
-+void i915_gem_retire_requests(struct drm_device *dev);
-+void i915_gem_retire_work_handler(struct work_struct *work);
-+void i915_gem_clflush_object(struct drm_gem_object *obj);
-+
-+/* i915_gem_tiling.c */
-+void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
-+
-+/* i915_gem_debug.c */
-+void i915_gem_dump_object(struct drm_gem_object *obj, int len,
-+                        const char *where, uint32_t mark);
-+#if WATCH_INACTIVE
-+void i915_verify_inactive(struct drm_device *dev, char *file, int line);
-+#else
-+#define i915_verify_inactive(dev, file, line)
-+#endif
-+void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle);
-+void i915_gem_dump_object(struct drm_gem_object *obj, int len,
-+                        const char *where, uint32_t mark);
-+void i915_dump_lru(struct drm_device *dev, const char *where);
- #define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
- #define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
-@@ -309,6 +553,7 @@ extern void i915_mem_release(struct drm_
-  */
- #define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
- #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, 5)
-+#define I915_GEM_HWS_INDEX            0x10
- extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -0,0 +1,2508 @@
-+/*
-+ * Copyright Ã‚© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Eric Anholt <eric@anholt.net>
-+ *
-+ */
-+
-+#include "drmP.h"
-+#include "drm.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+#include <linux/swap.h>
-+
-+static int
-+i915_gem_object_set_domain(struct drm_gem_object *obj,
-+                          uint32_t read_domains,
-+                          uint32_t write_domain);
-+static int
-+i915_gem_object_set_domain_range(struct drm_gem_object *obj,
-+                               uint64_t offset,
-+                               uint64_t size,
-+                               uint32_t read_domains,
-+                               uint32_t write_domain);
-+static int
-+i915_gem_set_domain(struct drm_gem_object *obj,
-+                  struct drm_file *file_priv,
-+                  uint32_t read_domains,
-+                  uint32_t write_domain);
-+static int i915_gem_object_get_page_list(struct drm_gem_object *obj);
-+static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
-+static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
-+
-+int
-+i915_gem_init_ioctl(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_init *args = data;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      if (args->gtt_start >= args->gtt_end ||
-+          (args->gtt_start & (PAGE_SIZE - 1)) != 0 ||
-+          (args->gtt_end & (PAGE_SIZE - 1)) != 0) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EINVAL;
-+      }
-+
-+      drm_mm_init(&dev_priv->mm.gtt_space, args->gtt_start,
-+          args->gtt_end - args->gtt_start);
-+
-+      dev->gtt_total = (uint32_t) (args->gtt_end - args->gtt_start);
-+
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+
-+/**
-+ * Creates a new mm object and returns a handle to it.
-+ */
-+int
-+i915_gem_create_ioctl(struct drm_device *dev, void *data,
-+                    struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_create *args = data;
-+      struct drm_gem_object *obj;
-+      int handle, ret;
-+
-+      args->size = roundup(args->size, PAGE_SIZE);
-+
-+      /* Allocate the new object */
-+      obj = drm_gem_object_alloc(dev, args->size);
-+      if (obj == NULL)
-+              return -ENOMEM;
-+
-+      ret = drm_gem_handle_create(file_priv, obj, &handle);
-+      mutex_lock(&dev->struct_mutex);
-+      drm_gem_object_handle_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      if (ret)
-+              return ret;
-+
-+      args->handle = handle;
-+
-+      return 0;
-+}
-+
-+/**
-+ * Reads data from the object referenced by handle.
-+ *
-+ * On error, the contents of *data are undefined.
-+ */
-+int
-+i915_gem_pread_ioctl(struct drm_device *dev, void *data,
-+                   struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_pread *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      ssize_t read;
-+      loff_t offset;
-+      int ret;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EBADF;
-+      obj_priv = obj->driver_private;
-+
-+      /* Bounds check source.
-+       *
-+       * XXX: This could use review for overflow issues...
-+       */
-+      if (args->offset > obj->size || args->size > obj->size ||
-+          args->offset + args->size > obj->size) {
-+              drm_gem_object_unreference(obj);
-+              return -EINVAL;
-+      }
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      ret = i915_gem_object_set_domain_range(obj, args->offset, args->size,
-+                                             I915_GEM_DOMAIN_CPU, 0);
-+      if (ret != 0) {
-+              drm_gem_object_unreference(obj);
-+              mutex_unlock(&dev->struct_mutex);
-+      }
-+
-+      offset = args->offset;
-+
-+      read = vfs_read(obj->filp, (char __user *)(uintptr_t)args->data_ptr,
-+                      args->size, &offset);
-+      if (read != args->size) {
-+              drm_gem_object_unreference(obj);
-+              mutex_unlock(&dev->struct_mutex);
-+              if (read < 0)
-+                      return read;
-+              else
-+                      return -EINVAL;
-+      }
-+
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+static int
-+i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-+                  struct drm_i915_gem_pwrite *args,
-+                  struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      ssize_t remain;
-+      loff_t offset;
-+      char __user *user_data;
-+      char *vaddr;
-+      int i, o, l;
-+      int ret = 0;
-+      unsigned long pfn;
-+      unsigned long unwritten;
-+
-+      user_data = (char __user *) (uintptr_t) args->data_ptr;
-+      remain = args->size;
-+      if (!access_ok(VERIFY_READ, user_data, remain))
-+              return -EFAULT;
-+
-+
-+      mutex_lock(&dev->struct_mutex);
-+      ret = i915_gem_object_pin(obj, 0);
-+      if (ret) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return ret;
-+      }
-+      ret = i915_gem_set_domain(obj, file_priv,
-+                                I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
-+      if (ret)
-+              goto fail;
-+
-+      obj_priv = obj->driver_private;
-+      offset = obj_priv->gtt_offset + args->offset;
-+      obj_priv->dirty = 1;
-+
-+      while (remain > 0) {
-+              /* Operation in this page
-+               *
-+               * i = page number
-+               * o = offset within page
-+               * l = bytes to copy
-+               */
-+              i = offset >> PAGE_SHIFT;
-+              o = offset & (PAGE_SIZE-1);
-+              l = remain;
-+              if ((o + l) > PAGE_SIZE)
-+                      l = PAGE_SIZE - o;
-+
-+              pfn = (dev->agp->base >> PAGE_SHIFT) + i;
-+
-+#ifdef DRM_KMAP_ATOMIC_PROT_PFN
-+              /* kmap_atomic can't map IO pages on non-HIGHMEM kernels
-+               */
-+              vaddr = kmap_atomic_prot_pfn(pfn, KM_USER0,
-+                                           __pgprot(__PAGE_KERNEL));
-+#if WATCH_PWRITE
-+              DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n",
-+                       i, o, l, pfn, vaddr);
-+#endif
-+              unwritten = __copy_from_user_inatomic_nocache(vaddr + o,
-+                                                            user_data, l);
-+              kunmap_atomic(vaddr, KM_USER0);
-+
-+              if (unwritten)
-+#endif
-+              {
-+                      vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
-+#if WATCH_PWRITE
-+                      DRM_INFO("pwrite slow i %d o %d l %d "
-+                               "pfn %ld vaddr %p\n",
-+                               i, o, l, pfn, vaddr);
-+#endif
-+                      if (vaddr == NULL) {
-+                              ret = -EFAULT;
-+                              goto fail;
-+                      }
-+                      unwritten = __copy_from_user(vaddr + o, user_data, l);
-+#if WATCH_PWRITE
-+                      DRM_INFO("unwritten %ld\n", unwritten);
-+#endif
-+                      iounmap(vaddr);
-+                      if (unwritten) {
-+                              ret = -EFAULT;
-+                              goto fail;
-+                      }
-+              }
-+
-+              remain -= l;
-+              user_data += l;
-+              offset += l;
-+      }
-+#if WATCH_PWRITE && 1
-+      i915_gem_clflush_object(obj);
-+      i915_gem_dump_object(obj, args->offset + args->size, __func__, ~0);
-+      i915_gem_clflush_object(obj);
-+#endif
-+
-+fail:
-+      i915_gem_object_unpin(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return ret;
-+}
-+
-+int
-+i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-+                    struct drm_i915_gem_pwrite *args,
-+                    struct drm_file *file_priv)
-+{
-+      int ret;
-+      loff_t offset;
-+      ssize_t written;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      ret = i915_gem_set_domain(obj, file_priv,
-+                                I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
-+      if (ret) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return ret;
-+      }
-+
-+      offset = args->offset;
-+
-+      written = vfs_write(obj->filp,
-+                          (char __user *)(uintptr_t) args->data_ptr,
-+                          args->size, &offset);
-+      if (written != args->size) {
-+              mutex_unlock(&dev->struct_mutex);
-+              if (written < 0)
-+                      return written;
-+              else
-+                      return -EINVAL;
-+      }
-+
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+/**
-+ * Writes data to the object referenced by handle.
-+ *
-+ * On error, the contents of the buffer that were to be modified are undefined.
-+ */
-+int
-+i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
-+                    struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_pwrite *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret = 0;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EBADF;
-+      obj_priv = obj->driver_private;
-+
-+      /* Bounds check destination.
-+       *
-+       * XXX: This could use review for overflow issues...
-+       */
-+      if (args->offset > obj->size || args->size > obj->size ||
-+          args->offset + args->size > obj->size) {
-+              drm_gem_object_unreference(obj);
-+              return -EINVAL;
-+      }
-+
-+      /* We can only do the GTT pwrite on untiled buffers, as otherwise
-+       * it would end up going through the fenced access, and we'll get
-+       * different detiling behavior between reading and writing.
-+       * pread/pwrite currently are reading and writing from the CPU
-+       * perspective, requiring manual detiling by the client.
-+       */
-+      if (obj_priv->tiling_mode == I915_TILING_NONE &&
-+          dev->gtt_total != 0)
-+              ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv);
-+      else
-+              ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv);
-+
-+#if WATCH_PWRITE
-+      if (ret)
-+              DRM_INFO("pwrite failed %d\n", ret);
-+#endif
-+
-+      drm_gem_object_unreference(obj);
-+
-+      return ret;
-+}
-+
-+/**
-+ * Called when user space prepares to use an object
-+ */
-+int
-+i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
-+                        struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_set_domain *args = data;
-+      struct drm_gem_object *obj;
-+      int ret;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EBADF;
-+
-+      mutex_lock(&dev->struct_mutex);
-+#if WATCH_BUF
-+      DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n",
-+               obj, obj->size, args->read_domains, args->write_domain);
-+#endif
-+      ret = i915_gem_set_domain(obj, file_priv,
-+                                args->read_domains, args->write_domain);
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      return ret;
-+}
-+
-+/**
-+ * Called when user space has done writes to this buffer
-+ */
-+int
-+i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
-+                    struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_sw_finish *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret = 0;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBADF;
-+      }
-+
-+#if WATCH_BUF
-+      DRM_INFO("%s: sw_finish %d (%p %d)\n",
-+               __func__, args->handle, obj, obj->size);
-+#endif
-+      obj_priv = obj->driver_private;
-+
-+      /* Pinned buffers may be scanout, so flush the cache */
-+      if ((obj->write_domain & I915_GEM_DOMAIN_CPU) && obj_priv->pin_count) {
-+              i915_gem_clflush_object(obj);
-+              drm_agp_chipset_flush(dev);
-+      }
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      return ret;
-+}
-+
-+/**
-+ * Maps the contents of an object, returning the address it is mapped
-+ * into.
-+ *
-+ * While the mapping holds a reference on the contents of the object, it doesn't
-+ * imply a ref on the object itself.
-+ */
-+int
-+i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_mmap *args = data;
-+      struct drm_gem_object *obj;
-+      loff_t offset;
-+      unsigned long addr;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EBADF;
-+
-+      offset = args->offset;
-+
-+      down_write(&current->mm->mmap_sem);
-+      addr = do_mmap(obj->filp, 0, args->size,
-+                     PROT_READ | PROT_WRITE, MAP_SHARED,
-+                     args->offset);
-+      up_write(&current->mm->mmap_sem);
-+      mutex_lock(&dev->struct_mutex);
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      if (IS_ERR((void *)addr))
-+              return addr;
-+
-+      args->addr_ptr = (uint64_t) addr;
-+
-+      return 0;
-+}
-+
-+static void
-+i915_gem_object_free_page_list(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int page_count = obj->size / PAGE_SIZE;
-+      int i;
-+
-+      if (obj_priv->page_list == NULL)
-+              return;
-+
-+
-+      for (i = 0; i < page_count; i++)
-+              if (obj_priv->page_list[i] != NULL) {
-+                      if (obj_priv->dirty)
-+                              set_page_dirty(obj_priv->page_list[i]);
-+                      mark_page_accessed(obj_priv->page_list[i]);
-+                      page_cache_release(obj_priv->page_list[i]);
-+              }
-+      obj_priv->dirty = 0;
-+
-+      drm_free(obj_priv->page_list,
-+               page_count * sizeof(struct page *),
-+               DRM_MEM_DRIVER);
-+      obj_priv->page_list = NULL;
-+}
-+
-+static void
-+i915_gem_object_move_to_active(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+      /* Add a reference if we're newly entering the active list. */
-+      if (!obj_priv->active) {
-+              drm_gem_object_reference(obj);
-+              obj_priv->active = 1;
-+      }
-+      /* Move from whatever list we were on to the tail of execution. */
-+      list_move_tail(&obj_priv->list,
-+                     &dev_priv->mm.active_list);
-+}
-+
-+
-+static void
-+i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+      if (obj_priv->pin_count != 0)
-+              list_del_init(&obj_priv->list);
-+      else
-+              list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
-+
-+      if (obj_priv->active) {
-+              obj_priv->active = 0;
-+              drm_gem_object_unreference(obj);
-+      }
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+}
-+
-+/**
-+ * Creates a new sequence number, emitting a write of it to the status page
-+ * plus an interrupt, which will trigger i915_user_interrupt_handler.
-+ *
-+ * Must be called with struct_lock held.
-+ *
-+ * Returned sequence numbers are nonzero on success.
-+ */
-+static uint32_t
-+i915_add_request(struct drm_device *dev, uint32_t flush_domains)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_request *request;
-+      uint32_t seqno;
-+      int was_empty;
-+      RING_LOCALS;
-+
-+      request = drm_calloc(1, sizeof(*request), DRM_MEM_DRIVER);
-+      if (request == NULL)
-+              return 0;
-+
-+      /* Grab the seqno we're going to make this request be, and bump the
-+       * next (skipping 0 so it can be the reserved no-seqno value).
-+       */
-+      seqno = dev_priv->mm.next_gem_seqno;
-+      dev_priv->mm.next_gem_seqno++;
-+      if (dev_priv->mm.next_gem_seqno == 0)
-+              dev_priv->mm.next_gem_seqno++;
-+
-+      BEGIN_LP_RING(4);
-+      OUT_RING(MI_STORE_DWORD_INDEX);
-+      OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-+      OUT_RING(seqno);
-+
-+      OUT_RING(MI_USER_INTERRUPT);
-+      ADVANCE_LP_RING();
-+
-+      DRM_DEBUG("%d\n", seqno);
-+
-+      request->seqno = seqno;
-+      request->emitted_jiffies = jiffies;
-+      request->flush_domains = flush_domains;
-+      was_empty = list_empty(&dev_priv->mm.request_list);
-+      list_add_tail(&request->list, &dev_priv->mm.request_list);
-+
-+      if (was_empty)
-+              schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
-+      return seqno;
-+}
-+
-+/**
-+ * Command execution barrier
-+ *
-+ * Ensures that all commands in the ring are finished
-+ * before signalling the CPU
-+ */
-+uint32_t
-+i915_retire_commands(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
-+      uint32_t flush_domains = 0;
-+      RING_LOCALS;
-+
-+      /* The sampler always gets flushed on i965 (sigh) */
-+      if (IS_I965G(dev))
-+              flush_domains |= I915_GEM_DOMAIN_SAMPLER;
-+      BEGIN_LP_RING(2);
-+      OUT_RING(cmd);
-+      OUT_RING(0); /* noop */
-+      ADVANCE_LP_RING();
-+      return flush_domains;
-+}
-+
-+/**
-+ * Moves buffers associated only with the given active seqno from the active
-+ * to inactive list, potentially freeing them.
-+ */
-+static void
-+i915_gem_retire_request(struct drm_device *dev,
-+                      struct drm_i915_gem_request *request)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      /* Move any buffers on the active list that are no longer referenced
-+       * by the ringbuffer to the flushing/inactive lists as appropriate.
-+       */
-+      while (!list_empty(&dev_priv->mm.active_list)) {
-+              struct drm_gem_object *obj;
-+              struct drm_i915_gem_object *obj_priv;
-+
-+              obj_priv = list_first_entry(&dev_priv->mm.active_list,
-+                                          struct drm_i915_gem_object,
-+                                          list);
-+              obj = obj_priv->obj;
-+
-+              /* If the seqno being retired doesn't match the oldest in the
-+               * list, then the oldest in the list must still be newer than
-+               * this seqno.
-+               */
-+              if (obj_priv->last_rendering_seqno != request->seqno)
-+                      return;
-+#if WATCH_LRU
-+              DRM_INFO("%s: retire %d moves to inactive list %p\n",
-+                       __func__, request->seqno, obj);
-+#endif
-+
-+              if (obj->write_domain != 0) {
-+                      list_move_tail(&obj_priv->list,
-+                                     &dev_priv->mm.flushing_list);
-+              } else {
-+                      i915_gem_object_move_to_inactive(obj);
-+              }
-+      }
-+
-+      if (request->flush_domains != 0) {
-+              struct drm_i915_gem_object *obj_priv, *next;
-+
-+              /* Clear the write domain and activity from any buffers
-+               * that are just waiting for a flush matching the one retired.
-+               */
-+              list_for_each_entry_safe(obj_priv, next,
-+                                       &dev_priv->mm.flushing_list, list) {
-+                      struct drm_gem_object *obj = obj_priv->obj;
-+
-+                      if (obj->write_domain & request->flush_domains) {
-+                              obj->write_domain = 0;
-+                              i915_gem_object_move_to_inactive(obj);
-+                      }
-+              }
-+
-+      }
-+}
-+
-+/**
-+ * Returns true if seq1 is later than seq2.
-+ */
-+static int
-+i915_seqno_passed(uint32_t seq1, uint32_t seq2)
-+{
-+      return (int32_t)(seq1 - seq2) >= 0;
-+}
-+
-+uint32_t
-+i915_get_gem_seqno(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
-+}
-+
-+/**
-+ * This function clears the request list as sequence numbers are passed.
-+ */
-+void
-+i915_gem_retire_requests(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      uint32_t seqno;
-+
-+      seqno = i915_get_gem_seqno(dev);
-+
-+      while (!list_empty(&dev_priv->mm.request_list)) {
-+              struct drm_i915_gem_request *request;
-+              uint32_t retiring_seqno;
-+
-+              request = list_first_entry(&dev_priv->mm.request_list,
-+                                         struct drm_i915_gem_request,
-+                                         list);
-+              retiring_seqno = request->seqno;
-+
-+              if (i915_seqno_passed(seqno, retiring_seqno) ||
-+                  dev_priv->mm.wedged) {
-+                      i915_gem_retire_request(dev, request);
-+
-+                      list_del(&request->list);
-+                      drm_free(request, sizeof(*request), DRM_MEM_DRIVER);
-+              } else
-+                      break;
-+      }
-+}
-+
-+void
-+i915_gem_retire_work_handler(struct work_struct *work)
-+{
-+      drm_i915_private_t *dev_priv;
-+      struct drm_device *dev;
-+
-+      dev_priv = container_of(work, drm_i915_private_t,
-+                              mm.retire_work.work);
-+      dev = dev_priv->dev;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      i915_gem_retire_requests(dev);
-+      if (!list_empty(&dev_priv->mm.request_list))
-+              schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
-+      mutex_unlock(&dev->struct_mutex);
-+}
-+
-+/**
-+ * Waits for a sequence number to be signaled, and cleans up the
-+ * request and object lists appropriately for that event.
-+ */
-+int
-+i915_wait_request(struct drm_device *dev, uint32_t seqno)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      int ret = 0;
-+
-+      BUG_ON(seqno == 0);
-+
-+      if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
-+              dev_priv->mm.waiting_gem_seqno = seqno;
-+              i915_user_irq_get(dev);
-+              ret = wait_event_interruptible(dev_priv->irq_queue,
-+                                             i915_seqno_passed(i915_get_gem_seqno(dev),
-+                                                               seqno) ||
-+                                             dev_priv->mm.wedged);
-+              i915_user_irq_put(dev);
-+              dev_priv->mm.waiting_gem_seqno = 0;
-+      }
-+      if (dev_priv->mm.wedged)
-+              ret = -EIO;
-+
-+      if (ret && ret != -ERESTARTSYS)
-+              DRM_ERROR("%s returns %d (awaiting %d at %d)\n",
-+                        __func__, ret, seqno, i915_get_gem_seqno(dev));
-+
-+      /* Directly dispatch request retiring.  While we have the work queue
-+       * to handle this, the waiter on a request often wants an associated
-+       * buffer to have made it to the inactive list, and we would need
-+       * a separate wait queue to handle that.
-+       */
-+      if (ret == 0)
-+              i915_gem_retire_requests(dev);
-+
-+      return ret;
-+}
-+
-+static void
-+i915_gem_flush(struct drm_device *dev,
-+             uint32_t invalidate_domains,
-+             uint32_t flush_domains)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      uint32_t cmd;
-+      RING_LOCALS;
-+
-+#if WATCH_EXEC
-+      DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
-+                invalidate_domains, flush_domains);
-+#endif
-+
-+      if (flush_domains & I915_GEM_DOMAIN_CPU)
-+              drm_agp_chipset_flush(dev);
-+
-+      if ((invalidate_domains | flush_domains) & ~(I915_GEM_DOMAIN_CPU |
-+                                                   I915_GEM_DOMAIN_GTT)) {
-+              /*
-+               * read/write caches:
-+               *
-+               * I915_GEM_DOMAIN_RENDER is always invalidated, but is
-+               * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
-+               * also flushed at 2d versus 3d pipeline switches.
-+               *
-+               * read-only caches:
-+               *
-+               * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
-+               * MI_READ_FLUSH is set, and is always flushed on 965.
-+               *
-+               * I915_GEM_DOMAIN_COMMAND may not exist?
-+               *
-+               * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
-+               * invalidated when MI_EXE_FLUSH is set.
-+               *
-+               * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
-+               * invalidated with every MI_FLUSH.
-+               *
-+               * TLBs:
-+               *
-+               * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
-+               * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
-+               * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
-+               * are flushed at any MI_FLUSH.
-+               */
-+
-+              cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
-+              if ((invalidate_domains|flush_domains) &
-+                  I915_GEM_DOMAIN_RENDER)
-+                      cmd &= ~MI_NO_WRITE_FLUSH;
-+              if (!IS_I965G(dev)) {
-+                      /*
-+                       * On the 965, the sampler cache always gets flushed
-+                       * and this bit is reserved.
-+                       */
-+                      if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
-+                              cmd |= MI_READ_FLUSH;
-+              }
-+              if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
-+                      cmd |= MI_EXE_FLUSH;
-+
-+#if WATCH_EXEC
-+              DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
-+#endif
-+              BEGIN_LP_RING(2);
-+              OUT_RING(cmd);
-+              OUT_RING(0); /* noop */
-+              ADVANCE_LP_RING();
-+      }
-+}
-+
-+/**
-+ * Ensures that all rendering to the object has completed and the object is
-+ * safe to unbind from the GTT or access from the CPU.
-+ */
-+static int
-+i915_gem_object_wait_rendering(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int ret;
-+
-+      /* If there are writes queued to the buffer, flush and
-+       * create a new seqno to wait for.
-+       */
-+      if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) {
-+              uint32_t write_domain = obj->write_domain;
-+#if WATCH_BUF
-+              DRM_INFO("%s: flushing object %p from write domain %08x\n",
-+                        __func__, obj, write_domain);
-+#endif
-+              i915_gem_flush(dev, 0, write_domain);
-+
-+              i915_gem_object_move_to_active(obj);
-+              obj_priv->last_rendering_seqno = i915_add_request(dev,
-+                                                                write_domain);
-+              BUG_ON(obj_priv->last_rendering_seqno == 0);
-+#if WATCH_LRU
-+              DRM_INFO("%s: flush moves to exec list %p\n", __func__, obj);
-+#endif
-+      }
-+
-+      /* If there is rendering queued on the buffer being evicted, wait for
-+       * it.
-+       */
-+      if (obj_priv->active) {
-+#if WATCH_BUF
-+              DRM_INFO("%s: object %p wait for seqno %08x\n",
-+                        __func__, obj, obj_priv->last_rendering_seqno);
-+#endif
-+              ret = i915_wait_request(dev, obj_priv->last_rendering_seqno);
-+              if (ret != 0)
-+                      return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-+ * Unbinds an object from the GTT aperture.
-+ */
-+static int
-+i915_gem_object_unbind(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int ret = 0;
-+
-+#if WATCH_BUF
-+      DRM_INFO("%s:%d %p\n", __func__, __LINE__, obj);
-+      DRM_INFO("gtt_space %p\n", obj_priv->gtt_space);
-+#endif
-+      if (obj_priv->gtt_space == NULL)
-+              return 0;
-+
-+      if (obj_priv->pin_count != 0) {
-+              DRM_ERROR("Attempting to unbind pinned buffer\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Wait for any rendering to complete
-+       */
-+      ret = i915_gem_object_wait_rendering(obj);
-+      if (ret) {
-+              DRM_ERROR("wait_rendering failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* Move the object to the CPU domain to ensure that
-+       * any possible CPU writes while it's not in the GTT
-+       * are flushed when we go to remap it. This will
-+       * also ensure that all pending GPU writes are finished
-+       * before we unbind.
-+       */
-+      ret = i915_gem_object_set_domain(obj, I915_GEM_DOMAIN_CPU,
-+                                       I915_GEM_DOMAIN_CPU);
-+      if (ret) {
-+              DRM_ERROR("set_domain failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      if (obj_priv->agp_mem != NULL) {
-+              drm_unbind_agp(obj_priv->agp_mem);
-+              drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE);
-+              obj_priv->agp_mem = NULL;
-+      }
-+
-+      BUG_ON(obj_priv->active);
-+
-+      i915_gem_object_free_page_list(obj);
-+
-+      if (obj_priv->gtt_space) {
-+              atomic_dec(&dev->gtt_count);
-+              atomic_sub(obj->size, &dev->gtt_memory);
-+
-+              drm_mm_put_block(obj_priv->gtt_space);
-+              obj_priv->gtt_space = NULL;
-+      }
-+
-+      /* Remove ourselves from the LRU list if present. */
-+      if (!list_empty(&obj_priv->list))
-+              list_del_init(&obj_priv->list);
-+
-+      return 0;
-+}
-+
-+static int
-+i915_gem_evict_something(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret = 0;
-+
-+      for (;;) {
-+              /* If there's an inactive buffer available now, grab it
-+               * and be done.
-+               */
-+              if (!list_empty(&dev_priv->mm.inactive_list)) {
-+                      obj_priv = list_first_entry(&dev_priv->mm.inactive_list,
-+                                                  struct drm_i915_gem_object,
-+                                                  list);
-+                      obj = obj_priv->obj;
-+                      BUG_ON(obj_priv->pin_count != 0);
-+#if WATCH_LRU
-+                      DRM_INFO("%s: evicting %p\n", __func__, obj);
-+#endif
-+                      BUG_ON(obj_priv->active);
-+
-+                      /* Wait on the rendering and unbind the buffer. */
-+                      ret = i915_gem_object_unbind(obj);
-+                      break;
-+              }
-+
-+              /* If we didn't get anything, but the ring is still processing
-+               * things, wait for one of those things to finish and hopefully
-+               * leave us a buffer to evict.
-+               */
-+              if (!list_empty(&dev_priv->mm.request_list)) {
-+                      struct drm_i915_gem_request *request;
-+
-+                      request = list_first_entry(&dev_priv->mm.request_list,
-+                                                 struct drm_i915_gem_request,
-+                                                 list);
-+
-+                      ret = i915_wait_request(dev, request->seqno);
-+                      if (ret)
-+                              break;
-+
-+                      /* if waiting caused an object to become inactive,
-+                       * then loop around and wait for it. Otherwise, we
-+                       * assume that waiting freed and unbound something,
-+                       * so there should now be some space in the GTT
-+                       */
-+                      if (!list_empty(&dev_priv->mm.inactive_list))
-+                              continue;
-+                      break;
-+              }
-+
-+              /* If we didn't have anything on the request list but there
-+               * are buffers awaiting a flush, emit one and try again.
-+               * When we wait on it, those buffers waiting for that flush
-+               * will get moved to inactive.
-+               */
-+              if (!list_empty(&dev_priv->mm.flushing_list)) {
-+                      obj_priv = list_first_entry(&dev_priv->mm.flushing_list,
-+                                                  struct drm_i915_gem_object,
-+                                                  list);
-+                      obj = obj_priv->obj;
-+
-+                      i915_gem_flush(dev,
-+                                     obj->write_domain,
-+                                     obj->write_domain);
-+                      i915_add_request(dev, obj->write_domain);
-+
-+                      obj = NULL;
-+                      continue;
-+              }
-+
-+              DRM_ERROR("inactive empty %d request empty %d "
-+                        "flushing empty %d\n",
-+                        list_empty(&dev_priv->mm.inactive_list),
-+                        list_empty(&dev_priv->mm.request_list),
-+                        list_empty(&dev_priv->mm.flushing_list));
-+              /* If we didn't do any of the above, there's nothing to be done
-+               * and we just can't fit it in.
-+               */
-+              return -ENOMEM;
-+      }
-+      return ret;
-+}
-+
-+static int
-+i915_gem_object_get_page_list(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int page_count, i;
-+      struct address_space *mapping;
-+      struct inode *inode;
-+      struct page *page;
-+      int ret;
-+
-+      if (obj_priv->page_list)
-+              return 0;
-+
-+      /* Get the list of pages out of our struct file.  They'll be pinned
-+       * at this point until we release them.
-+       */
-+      page_count = obj->size / PAGE_SIZE;
-+      BUG_ON(obj_priv->page_list != NULL);
-+      obj_priv->page_list = drm_calloc(page_count, sizeof(struct page *),
-+                                       DRM_MEM_DRIVER);
-+      if (obj_priv->page_list == NULL) {
-+              DRM_ERROR("Faled to allocate page list\n");
-+              return -ENOMEM;
-+      }
-+
-+      inode = obj->filp->f_path.dentry->d_inode;
-+      mapping = inode->i_mapping;
-+      for (i = 0; i < page_count; i++) {
-+              page = read_mapping_page(mapping, i, NULL);
-+              if (IS_ERR(page)) {
-+                      ret = PTR_ERR(page);
-+                      DRM_ERROR("read_mapping_page failed: %d\n", ret);
-+                      i915_gem_object_free_page_list(obj);
-+                      return ret;
-+              }
-+              obj_priv->page_list[i] = page;
-+      }
-+      return 0;
-+}
-+
-+/**
-+ * Finds free space in the GTT aperture and binds the object there.
-+ */
-+static int
-+i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
-+{
-+      struct drm_device *dev = obj->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      struct drm_mm_node *free_space;
-+      int page_count, ret;
-+
-+      if (alignment == 0)
-+              alignment = PAGE_SIZE;
-+      if (alignment & (PAGE_SIZE - 1)) {
-+              DRM_ERROR("Invalid object alignment requested %u\n", alignment);
-+              return -EINVAL;
-+      }
-+
-+ search_free:
-+      free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
-+                                      obj->size, alignment, 0);
-+      if (free_space != NULL) {
-+              obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
-+                                                     alignment);
-+              if (obj_priv->gtt_space != NULL) {
-+                      obj_priv->gtt_space->private = obj;
-+                      obj_priv->gtt_offset = obj_priv->gtt_space->start;
-+              }
-+      }
-+      if (obj_priv->gtt_space == NULL) {
-+              /* If the gtt is empty and we're still having trouble
-+               * fitting our object in, we're out of memory.
-+               */
-+#if WATCH_LRU
-+              DRM_INFO("%s: GTT full, evicting something\n", __func__);
-+#endif
-+              if (list_empty(&dev_priv->mm.inactive_list) &&
-+                  list_empty(&dev_priv->mm.flushing_list) &&
-+                  list_empty(&dev_priv->mm.active_list)) {
-+                      DRM_ERROR("GTT full, but LRU list empty\n");
-+                      return -ENOMEM;
-+              }
-+
-+              ret = i915_gem_evict_something(dev);
-+              if (ret != 0) {
-+                      DRM_ERROR("Failed to evict a buffer %d\n", ret);
-+                      return ret;
-+              }
-+              goto search_free;
-+      }
-+
-+#if WATCH_BUF
-+      DRM_INFO("Binding object of size %d at 0x%08x\n",
-+               obj->size, obj_priv->gtt_offset);
-+#endif
-+      ret = i915_gem_object_get_page_list(obj);
-+      if (ret) {
-+              drm_mm_put_block(obj_priv->gtt_space);
-+              obj_priv->gtt_space = NULL;
-+              return ret;
-+      }
-+
-+      page_count = obj->size / PAGE_SIZE;
-+      /* Create an AGP memory structure pointing at our pages, and bind it
-+       * into the GTT.
-+       */
-+      obj_priv->agp_mem = drm_agp_bind_pages(dev,
-+                                             obj_priv->page_list,
-+                                             page_count,
-+                                             obj_priv->gtt_offset);
-+      if (obj_priv->agp_mem == NULL) {
-+              i915_gem_object_free_page_list(obj);
-+              drm_mm_put_block(obj_priv->gtt_space);
-+              obj_priv->gtt_space = NULL;
-+              return -ENOMEM;
-+      }
-+      atomic_inc(&dev->gtt_count);
-+      atomic_add(obj->size, &dev->gtt_memory);
-+
-+      /* Assert that the object is not currently in any GPU domain. As it
-+       * wasn't in the GTT, there shouldn't be any way it could have been in
-+       * a GPU cache
-+       */
-+      BUG_ON(obj->read_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
-+      BUG_ON(obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
-+
-+      return 0;
-+}
-+
-+void
-+i915_gem_clflush_object(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object      *obj_priv = obj->driver_private;
-+
-+      /* If we don't have a page list set up, then we're not pinned
-+       * to GPU, and we can ignore the cache flush because it'll happen
-+       * again at bind time.
-+       */
-+      if (obj_priv->page_list == NULL)
-+              return;
-+
-+      drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE);
-+}
-+
-+/*
-+ * Set the next domain for the specified object. This
-+ * may not actually perform the necessary flushing/invaliding though,
-+ * as that may want to be batched with other set_domain operations
-+ *
-+ * This is (we hope) the only really tricky part of gem. The goal
-+ * is fairly simple -- track which caches hold bits of the object
-+ * and make sure they remain coherent. A few concrete examples may
-+ * help to explain how it works. For shorthand, we use the notation
-+ * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the
-+ * a pair of read and write domain masks.
-+ *
-+ * Case 1: the batch buffer
-+ *
-+ *    1. Allocated
-+ *    2. Written by CPU
-+ *    3. Mapped to GTT
-+ *    4. Read by GPU
-+ *    5. Unmapped from GTT
-+ *    6. Freed
-+ *
-+ *    Let's take these a step at a time
-+ *
-+ *    1. Allocated
-+ *            Pages allocated from the kernel may still have
-+ *            cache contents, so we set them to (CPU, CPU) always.
-+ *    2. Written by CPU (using pwrite)
-+ *            The pwrite function calls set_domain (CPU, CPU) and
-+ *            this function does nothing (as nothing changes)
-+ *    3. Mapped by GTT
-+ *            This function asserts that the object is not
-+ *            currently in any GPU-based read or write domains
-+ *    4. Read by GPU
-+ *            i915_gem_execbuffer calls set_domain (COMMAND, 0).
-+ *            As write_domain is zero, this function adds in the
-+ *            current read domains (CPU+COMMAND, 0).
-+ *            flush_domains is set to CPU.
-+ *            invalidate_domains is set to COMMAND
-+ *            clflush is run to get data out of the CPU caches
-+ *            then i915_dev_set_domain calls i915_gem_flush to
-+ *            emit an MI_FLUSH and drm_agp_chipset_flush
-+ *    5. Unmapped from GTT
-+ *            i915_gem_object_unbind calls set_domain (CPU, CPU)
-+ *            flush_domains and invalidate_domains end up both zero
-+ *            so no flushing/invalidating happens
-+ *    6. Freed
-+ *            yay, done
-+ *
-+ * Case 2: The shared render buffer
-+ *
-+ *    1. Allocated
-+ *    2. Mapped to GTT
-+ *    3. Read/written by GPU
-+ *    4. set_domain to (CPU,CPU)
-+ *    5. Read/written by CPU
-+ *    6. Read/written by GPU
-+ *
-+ *    1. Allocated
-+ *            Same as last example, (CPU, CPU)
-+ *    2. Mapped to GTT
-+ *            Nothing changes (assertions find that it is not in the GPU)
-+ *    3. Read/written by GPU
-+ *            execbuffer calls set_domain (RENDER, RENDER)
-+ *            flush_domains gets CPU
-+ *            invalidate_domains gets GPU
-+ *            clflush (obj)
-+ *            MI_FLUSH and drm_agp_chipset_flush
-+ *    4. set_domain (CPU, CPU)
-+ *            flush_domains gets GPU
-+ *            invalidate_domains gets CPU
-+ *            wait_rendering (obj) to make sure all drawing is complete.
-+ *            This will include an MI_FLUSH to get the data from GPU
-+ *            to memory
-+ *            clflush (obj) to invalidate the CPU cache
-+ *            Another MI_FLUSH in i915_gem_flush (eliminate this somehow?)
-+ *    5. Read/written by CPU
-+ *            cache lines are loaded and dirtied
-+ *    6. Read written by GPU
-+ *            Same as last GPU access
-+ *
-+ * Case 3: The constant buffer
-+ *
-+ *    1. Allocated
-+ *    2. Written by CPU
-+ *    3. Read by GPU
-+ *    4. Updated (written) by CPU again
-+ *    5. Read by GPU
-+ *
-+ *    1. Allocated
-+ *            (CPU, CPU)
-+ *    2. Written by CPU
-+ *            (CPU, CPU)
-+ *    3. Read by GPU
-+ *            (CPU+RENDER, 0)
-+ *            flush_domains = CPU
-+ *            invalidate_domains = RENDER
-+ *            clflush (obj)
-+ *            MI_FLUSH
-+ *            drm_agp_chipset_flush
-+ *    4. Updated (written) by CPU again
-+ *            (CPU, CPU)
-+ *            flush_domains = 0 (no previous write domain)
-+ *            invalidate_domains = 0 (no new read domains)
-+ *    5. Read by GPU
-+ *            (CPU+RENDER, 0)
-+ *            flush_domains = CPU
-+ *            invalidate_domains = RENDER
-+ *            clflush (obj)
-+ *            MI_FLUSH
-+ *            drm_agp_chipset_flush
-+ */
-+static int
-+i915_gem_object_set_domain(struct drm_gem_object *obj,
-+                          uint32_t read_domains,
-+                          uint32_t write_domain)
-+{
-+      struct drm_device               *dev = obj->dev;
-+      struct drm_i915_gem_object      *obj_priv = obj->driver_private;
-+      uint32_t                        invalidate_domains = 0;
-+      uint32_t                        flush_domains = 0;
-+      int                             ret;
-+
-+#if WATCH_BUF
-+      DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
-+               __func__, obj,
-+               obj->read_domains, read_domains,
-+               obj->write_domain, write_domain);
-+#endif
-+      /*
-+       * If the object isn't moving to a new write domain,
-+       * let the object stay in multiple read domains
-+       */
-+      if (write_domain == 0)
-+              read_domains |= obj->read_domains;
-+      else
-+              obj_priv->dirty = 1;
-+
-+      /*
-+       * Flush the current write domain if
-+       * the new read domains don't match. Invalidate
-+       * any read domains which differ from the old
-+       * write domain
-+       */
-+      if (obj->write_domain && obj->write_domain != read_domains) {
-+              flush_domains |= obj->write_domain;
-+              invalidate_domains |= read_domains & ~obj->write_domain;
-+      }
-+      /*
-+       * Invalidate any read caches which may have
-+       * stale data. That is, any new read domains.
-+       */
-+      invalidate_domains |= read_domains & ~obj->read_domains;
-+      if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) {
-+#if WATCH_BUF
-+              DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n",
-+                       __func__, flush_domains, invalidate_domains);
-+#endif
-+              /*
-+               * If we're invaliding the CPU cache and flushing a GPU cache,
-+               * then pause for rendering so that the GPU caches will be
-+               * flushed before the cpu cache is invalidated
-+               */
-+              if ((invalidate_domains & I915_GEM_DOMAIN_CPU) &&
-+                  (flush_domains & ~(I915_GEM_DOMAIN_CPU |
-+                                     I915_GEM_DOMAIN_GTT))) {
-+                      ret = i915_gem_object_wait_rendering(obj);
-+                      if (ret)
-+                              return ret;
-+              }
-+              i915_gem_clflush_object(obj);
-+      }
-+
-+      if ((write_domain | flush_domains) != 0)
-+              obj->write_domain = write_domain;
-+
-+      /* If we're invalidating the CPU domain, clear the per-page CPU
-+       * domain list as well.
-+       */
-+      if (obj_priv->page_cpu_valid != NULL &&
-+          (obj->read_domains & I915_GEM_DOMAIN_CPU) &&
-+          ((read_domains & I915_GEM_DOMAIN_CPU) == 0)) {
-+              memset(obj_priv->page_cpu_valid, 0, obj->size / PAGE_SIZE);
-+      }
-+      obj->read_domains = read_domains;
-+
-+      dev->invalidate_domains |= invalidate_domains;
-+      dev->flush_domains |= flush_domains;
-+#if WATCH_BUF
-+      DRM_INFO("%s: read %08x write %08x invalidate %08x flush %08x\n",
-+               __func__,
-+               obj->read_domains, obj->write_domain,
-+               dev->invalidate_domains, dev->flush_domains);
-+#endif
-+      return 0;
-+}
-+
-+/**
-+ * Set the read/write domain on a range of the object.
-+ *
-+ * Currently only implemented for CPU reads, otherwise drops to normal
-+ * i915_gem_object_set_domain().
-+ */
-+static int
-+i915_gem_object_set_domain_range(struct drm_gem_object *obj,
-+                               uint64_t offset,
-+                               uint64_t size,
-+                               uint32_t read_domains,
-+                               uint32_t write_domain)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int ret, i;
-+
-+      if (obj->read_domains & I915_GEM_DOMAIN_CPU)
-+              return 0;
-+
-+      if (read_domains != I915_GEM_DOMAIN_CPU ||
-+          write_domain != 0)
-+              return i915_gem_object_set_domain(obj,
-+                                                read_domains, write_domain);
-+
-+      /* Wait on any GPU rendering to the object to be flushed. */
-+      if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) {
-+              ret = i915_gem_object_wait_rendering(obj);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      if (obj_priv->page_cpu_valid == NULL) {
-+              obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE,
-+                                                    DRM_MEM_DRIVER);
-+      }
-+
-+      /* Flush the cache on any pages that are still invalid from the CPU's
-+       * perspective.
-+       */
-+      for (i = offset / PAGE_SIZE; i < (offset + size - 1) / PAGE_SIZE; i++) {
-+              if (obj_priv->page_cpu_valid[i])
-+                      continue;
-+
-+              drm_clflush_pages(obj_priv->page_list + i, 1);
-+
-+              obj_priv->page_cpu_valid[i] = 1;
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-+ * Once all of the objects have been set in the proper domain,
-+ * perform the necessary flush and invalidate operations.
-+ *
-+ * Returns the write domains flushed, for use in flush tracking.
-+ */
-+static uint32_t
-+i915_gem_dev_set_domain(struct drm_device *dev)
-+{
-+      uint32_t flush_domains = dev->flush_domains;
-+
-+      /*
-+       * Now that all the buffers are synced to the proper domains,
-+       * flush and invalidate the collected domains
-+       */
-+      if (dev->invalidate_domains | dev->flush_domains) {
-+#if WATCH_EXEC
-+              DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
-+                        __func__,
-+                       dev->invalidate_domains,
-+                       dev->flush_domains);
-+#endif
-+              i915_gem_flush(dev,
-+                             dev->invalidate_domains,
-+                             dev->flush_domains);
-+              dev->invalidate_domains = 0;
-+              dev->flush_domains = 0;
-+      }
-+
-+      return flush_domains;
-+}
-+
-+/**
-+ * Pin an object to the GTT and evaluate the relocations landing in it.
-+ */
-+static int
-+i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
-+                               struct drm_file *file_priv,
-+                               struct drm_i915_gem_exec_object *entry)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_relocation_entry reloc;
-+      struct drm_i915_gem_relocation_entry __user *relocs;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int i, ret;
-+      uint32_t last_reloc_offset = -1;
-+      void *reloc_page = NULL;
-+
-+      /* Choose the GTT offset for our buffer and put it there. */
-+      ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
-+      if (ret)
-+              return ret;
-+
-+      entry->offset = obj_priv->gtt_offset;
-+
-+      relocs = (struct drm_i915_gem_relocation_entry __user *)
-+               (uintptr_t) entry->relocs_ptr;
-+      /* Apply the relocations, using the GTT aperture to avoid cache
-+       * flushing requirements.
-+       */
-+      for (i = 0; i < entry->relocation_count; i++) {
-+              struct drm_gem_object *target_obj;
-+              struct drm_i915_gem_object *target_obj_priv;
-+              uint32_t reloc_val, reloc_offset, *reloc_entry;
-+              int ret;
-+
-+              ret = copy_from_user(&reloc, relocs + i, sizeof(reloc));
-+              if (ret != 0) {
-+                      i915_gem_object_unpin(obj);
-+                      return ret;
-+              }
-+
-+              target_obj = drm_gem_object_lookup(obj->dev, file_priv,
-+                                                 reloc.target_handle);
-+              if (target_obj == NULL) {
-+                      i915_gem_object_unpin(obj);
-+                      return -EBADF;
-+              }
-+              target_obj_priv = target_obj->driver_private;
-+
-+              /* The target buffer should have appeared before us in the
-+               * exec_object list, so it should have a GTT space bound by now.
-+               */
-+              if (target_obj_priv->gtt_space == NULL) {
-+                      DRM_ERROR("No GTT space found for object %d\n",
-+                                reloc.target_handle);
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return -EINVAL;
-+              }
-+
-+              if (reloc.offset > obj->size - 4) {
-+                      DRM_ERROR("Relocation beyond object bounds: "
-+                                "obj %p target %d offset %d size %d.\n",
-+                                obj, reloc.target_handle,
-+                                (int) reloc.offset, (int) obj->size);
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return -EINVAL;
-+              }
-+              if (reloc.offset & 3) {
-+                      DRM_ERROR("Relocation not 4-byte aligned: "
-+                                "obj %p target %d offset %d.\n",
-+                                obj, reloc.target_handle,
-+                                (int) reloc.offset);
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return -EINVAL;
-+              }
-+
-+              if (reloc.write_domain && target_obj->pending_write_domain &&
-+                  reloc.write_domain != target_obj->pending_write_domain) {
-+                      DRM_ERROR("Write domain conflict: "
-+                                "obj %p target %d offset %d "
-+                                "new %08x old %08x\n",
-+                                obj, reloc.target_handle,
-+                                (int) reloc.offset,
-+                                reloc.write_domain,
-+                                target_obj->pending_write_domain);
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return -EINVAL;
-+              }
-+
-+#if WATCH_RELOC
-+              DRM_INFO("%s: obj %p offset %08x target %d "
-+                       "read %08x write %08x gtt %08x "
-+                       "presumed %08x delta %08x\n",
-+                       __func__,
-+                       obj,
-+                       (int) reloc.offset,
-+                       (int) reloc.target_handle,
-+                       (int) reloc.read_domains,
-+                       (int) reloc.write_domain,
-+                       (int) target_obj_priv->gtt_offset,
-+                       (int) reloc.presumed_offset,
-+                       reloc.delta);
-+#endif
-+
-+              target_obj->pending_read_domains |= reloc.read_domains;
-+              target_obj->pending_write_domain |= reloc.write_domain;
-+
-+              /* If the relocation already has the right value in it, no
-+               * more work needs to be done.
-+               */
-+              if (target_obj_priv->gtt_offset == reloc.presumed_offset) {
-+                      drm_gem_object_unreference(target_obj);
-+                      continue;
-+              }
-+
-+              /* Now that we're going to actually write some data in,
-+               * make sure that any rendering using this buffer's contents
-+               * is completed.
-+               */
-+              i915_gem_object_wait_rendering(obj);
-+
-+              /* As we're writing through the gtt, flush
-+               * any CPU writes before we write the relocations
-+               */
-+              if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
-+                      i915_gem_clflush_object(obj);
-+                      drm_agp_chipset_flush(dev);
-+                      obj->write_domain = 0;
-+              }
-+
-+              /* Map the page containing the relocation we're going to
-+               * perform.
-+               */
-+              reloc_offset = obj_priv->gtt_offset + reloc.offset;
-+              if (reloc_page == NULL ||
-+                  (last_reloc_offset & ~(PAGE_SIZE - 1)) !=
-+                  (reloc_offset & ~(PAGE_SIZE - 1))) {
-+                      if (reloc_page != NULL)
-+                              iounmap(reloc_page);
-+
-+                      reloc_page = ioremap(dev->agp->base +
-+                                           (reloc_offset & ~(PAGE_SIZE - 1)),
-+                                           PAGE_SIZE);
-+                      last_reloc_offset = reloc_offset;
-+                      if (reloc_page == NULL) {
-+                              drm_gem_object_unreference(target_obj);
-+                              i915_gem_object_unpin(obj);
-+                              return -ENOMEM;
-+                      }
-+              }
-+
-+              reloc_entry = (uint32_t *)((char *)reloc_page +
-+                                         (reloc_offset & (PAGE_SIZE - 1)));
-+              reloc_val = target_obj_priv->gtt_offset + reloc.delta;
-+
-+#if WATCH_BUF
-+              DRM_INFO("Applied relocation: %p@0x%08x %08x -> %08x\n",
-+                        obj, (unsigned int) reloc.offset,
-+                        readl(reloc_entry), reloc_val);
-+#endif
-+              writel(reloc_val, reloc_entry);
-+
-+              /* Write the updated presumed offset for this entry back out
-+               * to the user.
-+               */
-+              reloc.presumed_offset = target_obj_priv->gtt_offset;
-+              ret = copy_to_user(relocs + i, &reloc, sizeof(reloc));
-+              if (ret != 0) {
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return ret;
-+              }
-+
-+              drm_gem_object_unreference(target_obj);
-+      }
-+
-+      if (reloc_page != NULL)
-+              iounmap(reloc_page);
-+
-+#if WATCH_BUF
-+      if (0)
-+              i915_gem_dump_object(obj, 128, __func__, ~0);
-+#endif
-+      return 0;
-+}
-+
-+/** Dispatch a batchbuffer to the ring
-+ */
-+static int
-+i915_dispatch_gem_execbuffer(struct drm_device *dev,
-+                            struct drm_i915_gem_execbuffer *exec,
-+                            uint64_t exec_offset)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_clip_rect __user *boxes = (struct drm_clip_rect __user *)
-+                                           (uintptr_t) exec->cliprects_ptr;
-+      int nbox = exec->num_cliprects;
-+      int i = 0, count;
-+      uint32_t        exec_start, exec_len;
-+      RING_LOCALS;
-+
-+      exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
-+      exec_len = (uint32_t) exec->batch_len;
-+
-+      if ((exec_start | exec_len) & 0x7) {
-+              DRM_ERROR("alignment\n");
-+              return -EINVAL;
-+      }
-+
-+      if (!exec_start)
-+              return -EINVAL;
-+
-+      count = nbox ? nbox : 1;
-+
-+      for (i = 0; i < count; i++) {
-+              if (i < nbox) {
-+                      int ret = i915_emit_box(dev, boxes, i,
-+                                              exec->DR1, exec->DR4);
-+                      if (ret)
-+                              return ret;
-+              }
-+
-+              if (IS_I830(dev) || IS_845G(dev)) {
-+                      BEGIN_LP_RING(4);
-+                      OUT_RING(MI_BATCH_BUFFER);
-+                      OUT_RING(exec_start | MI_BATCH_NON_SECURE);
-+                      OUT_RING(exec_start + exec_len - 4);
-+                      OUT_RING(0);
-+                      ADVANCE_LP_RING();
-+              } else {
-+                      BEGIN_LP_RING(2);
-+                      if (IS_I965G(dev)) {
-+                              OUT_RING(MI_BATCH_BUFFER_START |
-+                                       (2 << 6) |
-+                                       MI_BATCH_NON_SECURE_I965);
-+                              OUT_RING(exec_start);
-+                      } else {
-+                              OUT_RING(MI_BATCH_BUFFER_START |
-+                                       (2 << 6));
-+                              OUT_RING(exec_start | MI_BATCH_NON_SECURE);
-+                      }
-+                      ADVANCE_LP_RING();
-+              }
-+      }
-+
-+      /* XXX breadcrumb */
-+      return 0;
-+}
-+
-+/* Throttle our rendering by waiting until the ring has completed our requests
-+ * emitted over 20 msec ago.
-+ *
-+ * This should get us reasonable parallelism between CPU and GPU but also
-+ * relatively low latency when blocking on a particular request to finish.
-+ */
-+static int
-+i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
-+{
-+      struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
-+      int ret = 0;
-+      uint32_t seqno;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      seqno = i915_file_priv->mm.last_gem_throttle_seqno;
-+      i915_file_priv->mm.last_gem_throttle_seqno =
-+              i915_file_priv->mm.last_gem_seqno;
-+      if (seqno)
-+              ret = i915_wait_request(dev, seqno);
-+      mutex_unlock(&dev->struct_mutex);
-+      return ret;
-+}
-+
-+int
-+i915_gem_execbuffer(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
-+      struct drm_i915_gem_execbuffer *args = data;
-+      struct drm_i915_gem_exec_object *exec_list = NULL;
-+      struct drm_gem_object **object_list = NULL;
-+      struct drm_gem_object *batch_obj;
-+      int ret, i, pinned = 0;
-+      uint64_t exec_offset;
-+      uint32_t seqno, flush_domains, pre_flush_domains;
-+
-+#if WATCH_EXEC
-+      DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-+                (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-+#endif
-+
-+      /* Copy in the exec list from userland */
-+      exec_list = drm_calloc(sizeof(*exec_list), args->buffer_count,
-+                             DRM_MEM_DRIVER);
-+      object_list = drm_calloc(sizeof(*object_list), args->buffer_count,
-+                               DRM_MEM_DRIVER);
-+      if (exec_list == NULL || object_list == NULL) {
-+              DRM_ERROR("Failed to allocate exec or object list "
-+                        "for %d buffers\n",
-+                        args->buffer_count);
-+              ret = -ENOMEM;
-+              goto pre_mutex_err;
-+      }
-+      ret = copy_from_user(exec_list,
-+                           (struct drm_i915_relocation_entry __user *)
-+                           (uintptr_t) args->buffers_ptr,
-+                           sizeof(*exec_list) * args->buffer_count);
-+      if (ret != 0) {
-+              DRM_ERROR("copy %d exec entries failed %d\n",
-+                        args->buffer_count, ret);
-+              goto pre_mutex_err;
-+      }
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      if (dev_priv->mm.wedged) {
-+              DRM_ERROR("Execbuf while wedged\n");
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EIO;
-+      }
-+
-+      if (dev_priv->mm.suspended) {
-+              DRM_ERROR("Execbuf while VT-switched.\n");
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBUSY;
-+      }
-+
-+      /* Zero the gloabl flush/invalidate flags. These
-+       * will be modified as each object is bound to the
-+       * gtt
-+       */
-+      dev->invalidate_domains = 0;
-+      dev->flush_domains = 0;
-+
-+      /* Look up object handles and perform the relocations */
-+      for (i = 0; i < args->buffer_count; i++) {
-+              object_list[i] = drm_gem_object_lookup(dev, file_priv,
-+                                                     exec_list[i].handle);
-+              if (object_list[i] == NULL) {
-+                      DRM_ERROR("Invalid object handle %d at index %d\n",
-+                                 exec_list[i].handle, i);
-+                      ret = -EBADF;
-+                      goto err;
-+              }
-+
-+              object_list[i]->pending_read_domains = 0;
-+              object_list[i]->pending_write_domain = 0;
-+              ret = i915_gem_object_pin_and_relocate(object_list[i],
-+                                                     file_priv,
-+                                                     &exec_list[i]);
-+              if (ret) {
-+                      DRM_ERROR("object bind and relocate failed %d\n", ret);
-+                      goto err;
-+              }
-+              pinned = i + 1;
-+      }
-+
-+      /* Set the pending read domains for the batch buffer to COMMAND */
-+      batch_obj = object_list[args->buffer_count-1];
-+      batch_obj->pending_read_domains = I915_GEM_DOMAIN_COMMAND;
-+      batch_obj->pending_write_domain = 0;
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      for (i = 0; i < args->buffer_count; i++) {
-+              struct drm_gem_object *obj = object_list[i];
-+              struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+              if (obj_priv->gtt_space == NULL) {
-+                      /* We evicted the buffer in the process of validating
-+                       * our set of buffers in.  We could try to recover by
-+                       * kicking them everything out and trying again from
-+                       * the start.
-+                       */
-+                      ret = -ENOMEM;
-+                      goto err;
-+              }
-+
-+              /* make sure all previous memory operations have passed */
-+              ret = i915_gem_object_set_domain(obj,
-+                                               obj->pending_read_domains,
-+                                               obj->pending_write_domain);
-+              if (ret)
-+                      goto err;
-+      }
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      /* Flush/invalidate caches and chipset buffer */
-+      flush_domains = i915_gem_dev_set_domain(dev);
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+#if WATCH_COHERENCY
-+      for (i = 0; i < args->buffer_count; i++) {
-+              i915_gem_object_check_coherency(object_list[i],
-+                                              exec_list[i].handle);
-+      }
-+#endif
-+
-+      exec_offset = exec_list[args->buffer_count - 1].offset;
-+
-+#if WATCH_EXEC
-+      i915_gem_dump_object(object_list[args->buffer_count - 1],
-+                            args->batch_len,
-+                            __func__,
-+                            ~0);
-+#endif
-+
-+      pre_flush_domains = flush_domains;
-+
-+      /* Exec the batchbuffer */
-+      ret = i915_dispatch_gem_execbuffer(dev, args, exec_offset);
-+      if (ret) {
-+              DRM_ERROR("dispatch failed %d\n", ret);
-+              goto err;
-+      }
-+
-+      /*
-+       * Ensure that the commands in the batch buffer are
-+       * finished before the interrupt fires
-+       */
-+      flush_domains |= i915_retire_commands(dev);
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      /*
-+       * Get a seqno representing the execution of the current buffer,
-+       * which we can wait on.  We would like to mitigate these interrupts,
-+       * likely by only creating seqnos occasionally (so that we have
-+       * *some* interrupts representing completion of buffers that we can
-+       * wait on when trying to clear up gtt space).
-+       */
-+      seqno = i915_add_request(dev, flush_domains);
-+      BUG_ON(seqno == 0);
-+      i915_file_priv->mm.last_gem_seqno = seqno;
-+      for (i = 0; i < args->buffer_count; i++) {
-+              struct drm_gem_object *obj = object_list[i];
-+              struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+              if (pre_flush_domains & obj->pending_write_domain &
-+                  ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) {
-+                      /* If we had a batchbuffer that resulted in a GPU
-+                       * domain being flushed before execution, followed by
-+                       * execution that resulted in the write_domain being
-+                       * set, then when that request is retired the
-+                       * write_domain would be incorrectly cleared.  We're not
-+                       * sure that this can be triggered.
-+                       */
-+                      DRM_ERROR("Going to lose the write domain on "
-+                                "obj %d size %d\n",
-+                                exec_list[i].handle, obj->size);
-+              }
-+
-+              i915_gem_object_move_to_active(obj);
-+              obj_priv->last_rendering_seqno = seqno;
-+#if WATCH_LRU
-+              DRM_INFO("%s: move to exec list %p\n", __func__, obj);
-+#endif
-+      }
-+#if WATCH_LRU
-+      i915_dump_lru(dev, __func__);
-+#endif
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      /* Copy the new buffer offsets back to the user's exec list. */
-+      ret = copy_to_user((struct drm_i915_relocation_entry __user *)
-+                         (uintptr_t) args->buffers_ptr,
-+                         exec_list,
-+                         sizeof(*exec_list) * args->buffer_count);
-+      if (ret)
-+              DRM_ERROR("failed to copy %d exec entries "
-+                        "back to user (%d)\n",
-+                         args->buffer_count, ret);
-+err:
-+      if (object_list != NULL) {
-+              for (i = 0; i < pinned; i++)
-+                      i915_gem_object_unpin(object_list[i]);
-+
-+              for (i = 0; i < args->buffer_count; i++)
-+                      drm_gem_object_unreference(object_list[i]);
-+      }
-+      mutex_unlock(&dev->struct_mutex);
-+
-+pre_mutex_err:
-+      drm_free(object_list, sizeof(*object_list) * args->buffer_count,
-+               DRM_MEM_DRIVER);
-+      drm_free(exec_list, sizeof(*exec_list) * args->buffer_count,
-+               DRM_MEM_DRIVER);
-+
-+      return ret;
-+}
-+
-+int
-+i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int ret;
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+      if (obj_priv->gtt_space == NULL) {
-+              ret = i915_gem_object_bind_to_gtt(obj, alignment);
-+              if (ret != 0) {
-+                      DRM_ERROR("Failure to bind: %d", ret);
-+                      return ret;
-+              }
-+      }
-+      obj_priv->pin_count++;
-+
-+      /* If the object is not active and not pending a flush,
-+       * remove it from the inactive list
-+       */
-+      if (obj_priv->pin_count == 1) {
-+              atomic_inc(&dev->pin_count);
-+              atomic_add(obj->size, &dev->pin_memory);
-+              if (!obj_priv->active &&
-+                  (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
-+                                         I915_GEM_DOMAIN_GTT)) == 0 &&
-+                  !list_empty(&obj_priv->list))
-+                      list_del_init(&obj_priv->list);
-+      }
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      return 0;
-+}
-+
-+void
-+i915_gem_object_unpin(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+      obj_priv->pin_count--;
-+      BUG_ON(obj_priv->pin_count < 0);
-+      BUG_ON(obj_priv->gtt_space == NULL);
-+
-+      /* If the object is no longer pinned, and is
-+       * neither active nor being flushed, then stick it on
-+       * the inactive list
-+       */
-+      if (obj_priv->pin_count == 0) {
-+              if (!obj_priv->active &&
-+                  (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
-+                                         I915_GEM_DOMAIN_GTT)) == 0)
-+                      list_move_tail(&obj_priv->list,
-+                                     &dev_priv->mm.inactive_list);
-+              atomic_dec(&dev->pin_count);
-+              atomic_sub(obj->size, &dev->pin_memory);
-+      }
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+}
-+
-+int
-+i915_gem_pin_ioctl(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_pin *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL) {
-+              DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n",
-+                        args->handle);
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBADF;
-+      }
-+      obj_priv = obj->driver_private;
-+
-+      ret = i915_gem_object_pin(obj, args->alignment);
-+      if (ret != 0) {
-+              drm_gem_object_unreference(obj);
-+              mutex_unlock(&dev->struct_mutex);
-+              return ret;
-+      }
-+
-+      /* XXX - flush the CPU caches for pinned objects
-+       * as the X server doesn't manage domains yet
-+       */
-+      if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
-+              i915_gem_clflush_object(obj);
-+              drm_agp_chipset_flush(dev);
-+              obj->write_domain = 0;
-+      }
-+      args->offset = obj_priv->gtt_offset;
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+int
-+i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
-+                   struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_pin *args = data;
-+      struct drm_gem_object *obj;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL) {
-+              DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n",
-+                        args->handle);
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBADF;
-+      }
-+
-+      i915_gem_object_unpin(obj);
-+
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      return 0;
-+}
-+
-+int
-+i915_gem_busy_ioctl(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_busy *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL) {
-+              DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n",
-+                        args->handle);
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBADF;
-+      }
-+
-+      obj_priv = obj->driver_private;
-+      args->busy = obj_priv->active;
-+
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      return 0;
-+}
-+
-+int
-+i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv)
-+{
-+    return i915_gem_ring_throttle(dev, file_priv);
-+}
-+
-+int i915_gem_init_object(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER);
-+      if (obj_priv == NULL)
-+              return -ENOMEM;
-+
-+      /*
-+       * We've just allocated pages from the kernel,
-+       * so they've just been written by the CPU with
-+       * zeros. They'll need to be clflushed before we
-+       * use them with the GPU.
-+       */
-+      obj->write_domain = I915_GEM_DOMAIN_CPU;
-+      obj->read_domains = I915_GEM_DOMAIN_CPU;
-+
-+      obj->driver_private = obj_priv;
-+      obj_priv->obj = obj;
-+      INIT_LIST_HEAD(&obj_priv->list);
-+      return 0;
-+}
-+
-+void i915_gem_free_object(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+      while (obj_priv->pin_count > 0)
-+              i915_gem_object_unpin(obj);
-+
-+      i915_gem_object_unbind(obj);
-+
-+      drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
-+      drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
-+}
-+
-+static int
-+i915_gem_set_domain(struct drm_gem_object *obj,
-+                  struct drm_file *file_priv,
-+                  uint32_t read_domains,
-+                  uint32_t write_domain)
-+{
-+      struct drm_device *dev = obj->dev;
-+      int ret;
-+      uint32_t flush_domains;
-+
-+      BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-+
-+      ret = i915_gem_object_set_domain(obj, read_domains, write_domain);
-+      if (ret)
-+              return ret;
-+      flush_domains = i915_gem_dev_set_domain(obj->dev);
-+
-+      if (flush_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT))
-+              (void) i915_add_request(dev, flush_domains);
-+
-+      return 0;
-+}
-+
-+/** Unbinds all objects that are on the given buffer list. */
-+static int
-+i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
-+{
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret;
-+
-+      while (!list_empty(head)) {
-+              obj_priv = list_first_entry(head,
-+                                          struct drm_i915_gem_object,
-+                                          list);
-+              obj = obj_priv->obj;
-+
-+              if (obj_priv->pin_count != 0) {
-+                      DRM_ERROR("Pinned object in unbind list\n");
-+                      mutex_unlock(&dev->struct_mutex);
-+                      return -EINVAL;
-+              }
-+
-+              ret = i915_gem_object_unbind(obj);
-+              if (ret != 0) {
-+                      DRM_ERROR("Error unbinding object in LeaveVT: %d\n",
-+                                ret);
-+                      mutex_unlock(&dev->struct_mutex);
-+                      return ret;
-+              }
-+      }
-+
-+
-+      return 0;
-+}
-+
-+static int
-+i915_gem_idle(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      uint32_t seqno, cur_seqno, last_seqno;
-+      int stuck;
-+
-+      if (dev_priv->mm.suspended)
-+              return 0;
-+
-+      /* Hack!  Don't let anybody do execbuf while we don't control the chip.
-+       * We need to replace this with a semaphore, or something.
-+       */
-+      dev_priv->mm.suspended = 1;
-+
-+      i915_kernel_lost_context(dev);
-+
-+      /* Flush the GPU along with all non-CPU write domains
-+       */
-+      i915_gem_flush(dev, ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT),
-+                     ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
-+      seqno = i915_add_request(dev, ~(I915_GEM_DOMAIN_CPU |
-+                                      I915_GEM_DOMAIN_GTT));
-+
-+      if (seqno == 0) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return -ENOMEM;
-+      }
-+
-+      dev_priv->mm.waiting_gem_seqno = seqno;
-+      last_seqno = 0;
-+      stuck = 0;
-+      for (;;) {
-+              cur_seqno = i915_get_gem_seqno(dev);
-+              if (i915_seqno_passed(cur_seqno, seqno))
-+                      break;
-+              if (last_seqno == cur_seqno) {
-+                      if (stuck++ > 100) {
-+                              DRM_ERROR("hardware wedged\n");
-+                              dev_priv->mm.wedged = 1;
-+                              DRM_WAKEUP(&dev_priv->irq_queue);
-+                              break;
-+                      }
-+              }
-+              msleep(10);
-+              last_seqno = cur_seqno;
-+      }
-+      dev_priv->mm.waiting_gem_seqno = 0;
-+
-+      i915_gem_retire_requests(dev);
-+
-+      /* Active and flushing should now be empty as we've
-+       * waited for a sequence higher than any pending execbuffer
-+       */
-+      BUG_ON(!list_empty(&dev_priv->mm.active_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
-+
-+      /* Request should now be empty as we've also waited
-+       * for the last request in the list
-+       */
-+      BUG_ON(!list_empty(&dev_priv->mm.request_list));
-+
-+      /* Move all buffers out of the GTT. */
-+      i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
-+
-+      BUG_ON(!list_empty(&dev_priv->mm.active_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.request_list));
-+      return 0;
-+}
-+
-+static int
-+i915_gem_init_hws(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret;
-+
-+      /* If we need a physical address for the status page, it's already
-+       * initialized at driver load time.
-+       */
-+      if (!I915_NEED_GFX_HWS(dev))
-+              return 0;
-+
-+      obj = drm_gem_object_alloc(dev, 4096);
-+      if (obj == NULL) {
-+              DRM_ERROR("Failed to allocate status page\n");
-+              return -ENOMEM;
-+      }
-+      obj_priv = obj->driver_private;
-+
-+      ret = i915_gem_object_pin(obj, 4096);
-+      if (ret != 0) {
-+              drm_gem_object_unreference(obj);
-+              return ret;
-+      }
-+
-+      dev_priv->status_gfx_addr = obj_priv->gtt_offset;
-+      dev_priv->hws_map.offset = dev->agp->base + obj_priv->gtt_offset;
-+      dev_priv->hws_map.size = 4096;
-+      dev_priv->hws_map.type = 0;
-+      dev_priv->hws_map.flags = 0;
-+      dev_priv->hws_map.mtrr = 0;
-+
-+      drm_core_ioremap(&dev_priv->hws_map, dev);
-+      if (dev_priv->hws_map.handle == NULL) {
-+              DRM_ERROR("Failed to map status page.\n");
-+              memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-+              drm_gem_object_unreference(obj);
-+              return -EINVAL;
-+      }
-+      dev_priv->hws_obj = obj;
-+      dev_priv->hw_status_page = dev_priv->hws_map.handle;
-+      memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-+      I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-+      DRM_DEBUG("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
-+
-+      return 0;
-+}
-+
-+static int
-+i915_gem_init_ringbuffer(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret;
-+
-+      ret = i915_gem_init_hws(dev);
-+      if (ret != 0)
-+              return ret;
-+
-+      obj = drm_gem_object_alloc(dev, 128 * 1024);
-+      if (obj == NULL) {
-+              DRM_ERROR("Failed to allocate ringbuffer\n");
-+              return -ENOMEM;
-+      }
-+      obj_priv = obj->driver_private;
-+
-+      ret = i915_gem_object_pin(obj, 4096);
-+      if (ret != 0) {
-+              drm_gem_object_unreference(obj);
-+              return ret;
-+      }
-+
-+      /* Set up the kernel mapping for the ring. */
-+      dev_priv->ring.Size = obj->size;
-+      dev_priv->ring.tail_mask = obj->size - 1;
-+
-+      dev_priv->ring.map.offset = dev->agp->base + obj_priv->gtt_offset;
-+      dev_priv->ring.map.size = obj->size;
-+      dev_priv->ring.map.type = 0;
-+      dev_priv->ring.map.flags = 0;
-+      dev_priv->ring.map.mtrr = 0;
-+
-+      drm_core_ioremap(&dev_priv->ring.map, dev);
-+      if (dev_priv->ring.map.handle == NULL) {
-+              DRM_ERROR("Failed to map ringbuffer.\n");
-+              memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
-+              drm_gem_object_unreference(obj);
-+              return -EINVAL;
-+      }
-+      dev_priv->ring.ring_obj = obj;
-+      dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-+
-+      /* Stop the ring if it's running. */
-+      I915_WRITE(PRB0_CTL, 0);
-+      I915_WRITE(PRB0_HEAD, 0);
-+      I915_WRITE(PRB0_TAIL, 0);
-+      I915_WRITE(PRB0_START, 0);
-+
-+      /* Initialize the ring. */
-+      I915_WRITE(PRB0_START, obj_priv->gtt_offset);
-+      I915_WRITE(PRB0_CTL,
-+                 ((obj->size - 4096) & RING_NR_PAGES) |
-+                 RING_NO_REPORT |
-+                 RING_VALID);
-+
-+      /* Update our cache of the ring state */
-+      i915_kernel_lost_context(dev);
-+
-+      return 0;
-+}
-+
-+static void
-+i915_gem_cleanup_ringbuffer(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      if (dev_priv->ring.ring_obj == NULL)
-+              return;
-+
-+      drm_core_ioremapfree(&dev_priv->ring.map, dev);
-+
-+      i915_gem_object_unpin(dev_priv->ring.ring_obj);
-+      drm_gem_object_unreference(dev_priv->ring.ring_obj);
-+      dev_priv->ring.ring_obj = NULL;
-+      memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
-+
-+      if (dev_priv->hws_obj != NULL) {
-+              i915_gem_object_unpin(dev_priv->hws_obj);
-+              drm_gem_object_unreference(dev_priv->hws_obj);
-+              dev_priv->hws_obj = NULL;
-+              memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-+
-+              /* Write high address into HWS_PGA when disabling. */
-+              I915_WRITE(HWS_PGA, 0x1ffff000);
-+      }
-+}
-+
-+int
-+i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
-+                     struct drm_file *file_priv)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      int ret;
-+
-+      if (dev_priv->mm.wedged) {
-+              DRM_ERROR("Reenabling wedged hardware, good luck\n");
-+              dev_priv->mm.wedged = 0;
-+      }
-+
-+      ret = i915_gem_init_ringbuffer(dev);
-+      if (ret != 0)
-+              return ret;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      BUG_ON(!list_empty(&dev_priv->mm.active_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.request_list));
-+      dev_priv->mm.suspended = 0;
-+      mutex_unlock(&dev->struct_mutex);
-+      return 0;
-+}
-+
-+int
-+i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
-+                     struct drm_file *file_priv)
-+{
-+      int ret;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      ret = i915_gem_idle(dev);
-+      if (ret == 0)
-+              i915_gem_cleanup_ringbuffer(dev);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+void
-+i915_gem_lastclose(struct drm_device *dev)
-+{
-+      int ret;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      if (dev_priv->ring.ring_obj != NULL) {
-+              ret = i915_gem_idle(dev);
-+              if (ret)
-+                      DRM_ERROR("failed to idle hardware: %d\n", ret);
-+
-+              i915_gem_cleanup_ringbuffer(dev);
-+      }
-+
-+      mutex_unlock(&dev->struct_mutex);
-+}
-+
-+void
-+i915_gem_load(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      INIT_LIST_HEAD(&dev_priv->mm.active_list);
-+      INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
-+      INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
-+      INIT_LIST_HEAD(&dev_priv->mm.request_list);
-+      INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
-+                        i915_gem_retire_work_handler);
-+      dev_priv->mm.next_gem_seqno = 1;
-+
-+      i915_gem_detect_bit_6_swizzle(dev);
-+}
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
-@@ -0,0 +1,201 @@
-+/*
-+ * Copyright Ã‚© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Keith Packard <keithp@keithp.com>
-+ *
-+ */
-+
-+#include "drmP.h"
-+#include "drm.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+
-+#if WATCH_INACTIVE
-+void
-+i915_verify_inactive(struct drm_device *dev, char *file, int line)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
-+              obj = obj_priv->obj;
-+              if (obj_priv->pin_count || obj_priv->active ||
-+                  (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
-+                                         I915_GEM_DOMAIN_GTT)))
-+                      DRM_ERROR("inactive %p (p %d a %d w %x)  %s:%d\n",
-+                                obj,
-+                                obj_priv->pin_count, obj_priv->active,
-+                                obj->write_domain, file, line);
-+      }
-+}
-+#endif /* WATCH_INACTIVE */
-+
-+
-+#if WATCH_BUF | WATCH_EXEC | WATCH_PWRITE
-+static void
-+i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end,
-+                 uint32_t bias, uint32_t mark)
-+{
-+      uint32_t *mem = kmap_atomic(page, KM_USER0);
-+      int i;
-+      for (i = start; i < end; i += 4)
-+              DRM_INFO("%08x: %08x%s\n",
-+                        (int) (bias + i), mem[i / 4],
-+                        (bias + i == mark) ? " ********" : "");
-+      kunmap_atomic(mem, KM_USER0);
-+      /* give syslog time to catch up */
-+      msleep(1);
-+}
-+
-+void
-+i915_gem_dump_object(struct drm_gem_object *obj, int len,
-+                   const char *where, uint32_t mark)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int page;
-+
-+      DRM_INFO("%s: object at offset %08x\n", where, obj_priv->gtt_offset);
-+      for (page = 0; page < (len + PAGE_SIZE-1) / PAGE_SIZE; page++) {
-+              int page_len, chunk, chunk_len;
-+
-+              page_len = len - page * PAGE_SIZE;
-+              if (page_len > PAGE_SIZE)
-+                      page_len = PAGE_SIZE;
-+
-+              for (chunk = 0; chunk < page_len; chunk += 128) {
-+                      chunk_len = page_len - chunk;
-+                      if (chunk_len > 128)
-+                              chunk_len = 128;
-+                      i915_gem_dump_page(obj_priv->page_list[page],
-+                                         chunk, chunk + chunk_len,
-+                                         obj_priv->gtt_offset +
-+                                         page * PAGE_SIZE,
-+                                         mark);
-+              }
-+      }
-+}
-+#endif
-+
-+#if WATCH_LRU
-+void
-+i915_dump_lru(struct drm_device *dev, const char *where)
-+{
-+      drm_i915_private_t              *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object      *obj_priv;
-+
-+      DRM_INFO("active list %s {\n", where);
-+      list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
-+                          list)
-+      {
-+              DRM_INFO("    %p: %08x\n", obj_priv,
-+                       obj_priv->last_rendering_seqno);
-+      }
-+      DRM_INFO("}\n");
-+      DRM_INFO("flushing list %s {\n", where);
-+      list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
-+                          list)
-+      {
-+              DRM_INFO("    %p: %08x\n", obj_priv,
-+                       obj_priv->last_rendering_seqno);
-+      }
-+      DRM_INFO("}\n");
-+      DRM_INFO("inactive %s {\n", where);
-+      list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
-+              DRM_INFO("    %p: %08x\n", obj_priv,
-+                       obj_priv->last_rendering_seqno);
-+      }
-+      DRM_INFO("}\n");
-+}
-+#endif
-+
-+
-+#if WATCH_COHERENCY
-+void
-+i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int page;
-+      uint32_t *gtt_mapping;
-+      uint32_t *backing_map = NULL;
-+      int bad_count = 0;
-+
-+      DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n",
-+               __func__, obj, obj_priv->gtt_offset, handle,
-+               obj->size / 1024);
-+
-+      gtt_mapping = ioremap(dev->agp->base + obj_priv->gtt_offset,
-+                            obj->size);
-+      if (gtt_mapping == NULL) {
-+              DRM_ERROR("failed to map GTT space\n");
-+              return;
-+      }
-+
-+      for (page = 0; page < obj->size / PAGE_SIZE; page++) {
-+              int i;
-+
-+              backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0);
-+
-+              if (backing_map == NULL) {
-+                      DRM_ERROR("failed to map backing page\n");
-+                      goto out;
-+              }
-+
-+              for (i = 0; i < PAGE_SIZE / 4; i++) {
-+                      uint32_t cpuval = backing_map[i];
-+                      uint32_t gttval = readl(gtt_mapping +
-+                                              page * 1024 + i);
-+
-+                      if (cpuval != gttval) {
-+                              DRM_INFO("incoherent CPU vs GPU at 0x%08x: "
-+                                       "0x%08x vs 0x%08x\n",
-+                                       (int)(obj_priv->gtt_offset +
-+                                             page * PAGE_SIZE + i * 4),
-+                                       cpuval, gttval);
-+                              if (bad_count++ >= 8) {
-+                                      DRM_INFO("...\n");
-+                                      goto out;
-+                              }
-+                      }
-+              }
-+              kunmap_atomic(backing_map, KM_USER0);
-+              backing_map = NULL;
-+      }
-+
-+ out:
-+      if (backing_map != NULL)
-+              kunmap_atomic(backing_map, KM_USER0);
-+      iounmap(gtt_mapping);
-+
-+      /* give syslog time to catch up */
-+      msleep(1);
-+
-+      /* Directly flush the object, since we just loaded values with the CPU
-+       * from the backing pages and we don't want to disturb the cache
-+       * management that we're trying to observe.
-+       */
-+
-+      i915_gem_clflush_object(obj);
-+}
-+#endif
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_gem_proc.c
-@@ -0,0 +1,292 @@
-+/*
-+ * Copyright Ã‚© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Eric Anholt <eric@anholt.net>
-+ *    Keith Packard <keithp@keithp.com>
-+ *
-+ */
-+
-+#include "drmP.h"
-+#include "drm.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+
-+static int i915_gem_active_info(char *buf, char **start, off_t offset,
-+                              int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Active:\n");
-+      list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
-+                          list)
-+      {
-+              struct drm_gem_object *obj = obj_priv->obj;
-+              if (obj->name) {
-+                      DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
-+                                     obj, obj->name,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              } else {
-+                      DRM_PROC_PRINT("       %p: %08x %08x %d\n",
-+                                     obj,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              }
-+      }
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static int i915_gem_flushing_info(char *buf, char **start, off_t offset,
-+                                int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Flushing:\n");
-+      list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
-+                          list)
-+      {
-+              struct drm_gem_object *obj = obj_priv->obj;
-+              if (obj->name) {
-+                      DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
-+                                     obj, obj->name,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              } else {
-+                      DRM_PROC_PRINT("       %p: %08x %08x %d\n", obj,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              }
-+      }
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static int i915_gem_inactive_info(char *buf, char **start, off_t offset,
-+                                int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Inactive:\n");
-+      list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list,
-+                          list)
-+      {
-+              struct drm_gem_object *obj = obj_priv->obj;
-+              if (obj->name) {
-+                      DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
-+                                     obj, obj->name,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              } else {
-+                      DRM_PROC_PRINT("       %p: %08x %08x %d\n", obj,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              }
-+      }
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static int i915_gem_request_info(char *buf, char **start, off_t offset,
-+                               int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_request *gem_request;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Request:\n");
-+      list_for_each_entry(gem_request, &dev_priv->mm.request_list,
-+                          list)
-+      {
-+              DRM_PROC_PRINT("    %d @ %d %08x\n",
-+                             gem_request->seqno,
-+                             (int) (jiffies - gem_request->emitted_jiffies),
-+                             gem_request->flush_domains);
-+      }
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static int i915_gem_seqno_info(char *buf, char **start, off_t offset,
-+                             int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Current sequence: %d\n", i915_get_gem_seqno(dev));
-+      DRM_PROC_PRINT("Waiter sequence:  %d\n",
-+                     dev_priv->mm.waiting_gem_seqno);
-+      DRM_PROC_PRINT("IRQ sequence:     %d\n", dev_priv->mm.irq_gem_seqno);
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+
-+static int i915_interrupt_info(char *buf, char **start, off_t offset,
-+                             int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Interrupt enable:    %08x\n",
-+                     I915_READ(IER));
-+      DRM_PROC_PRINT("Interrupt identity:  %08x\n",
-+                     I915_READ(IIR));
-+      DRM_PROC_PRINT("Interrupt mask:      %08x\n",
-+                     I915_READ(IMR));
-+      DRM_PROC_PRINT("Pipe A stat:         %08x\n",
-+                     I915_READ(PIPEASTAT));
-+      DRM_PROC_PRINT("Pipe B stat:         %08x\n",
-+                     I915_READ(PIPEBSTAT));
-+      DRM_PROC_PRINT("Interrupts received: %d\n",
-+                     atomic_read(&dev_priv->irq_received));
-+      DRM_PROC_PRINT("Current sequence:    %d\n",
-+                     i915_get_gem_seqno(dev));
-+      DRM_PROC_PRINT("Waiter sequence:     %d\n",
-+                     dev_priv->mm.waiting_gem_seqno);
-+      DRM_PROC_PRINT("IRQ sequence:        %d\n",
-+                     dev_priv->mm.irq_gem_seqno);
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static struct drm_proc_list {
-+      /** file name */
-+      const char *name;
-+      /** proc callback*/
-+      int (*f) (char *, char **, off_t, int, int *, void *);
-+} i915_gem_proc_list[] = {
-+      {"i915_gem_active", i915_gem_active_info},
-+      {"i915_gem_flushing", i915_gem_flushing_info},
-+      {"i915_gem_inactive", i915_gem_inactive_info},
-+      {"i915_gem_request", i915_gem_request_info},
-+      {"i915_gem_seqno", i915_gem_seqno_info},
-+      {"i915_gem_interrupt", i915_interrupt_info},
-+};
-+
-+#define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list)
-+
-+int i915_gem_proc_init(struct drm_minor *minor)
-+{
-+      struct proc_dir_entry *ent;
-+      int i, j;
-+
-+      for (i = 0; i < I915_GEM_PROC_ENTRIES; i++) {
-+              ent = create_proc_entry(i915_gem_proc_list[i].name,
-+                                      S_IFREG | S_IRUGO, minor->dev_root);
-+              if (!ent) {
-+                      DRM_ERROR("Cannot create /proc/dri/.../%s\n",
-+                                i915_gem_proc_list[i].name);
-+                      for (j = 0; j < i; j++)
-+                              remove_proc_entry(i915_gem_proc_list[i].name,
-+                                                minor->dev_root);
-+                      return -1;
-+              }
-+              ent->read_proc = i915_gem_proc_list[i].f;
-+              ent->data = minor;
-+      }
-+      return 0;
-+}
-+
-+void i915_gem_proc_cleanup(struct drm_minor *minor)
-+{
-+      int i;
-+
-+      if (!minor->dev_root)
-+              return;
-+
-+      for (i = 0; i < I915_GEM_PROC_ENTRIES; i++)
-+              remove_proc_entry(i915_gem_proc_list[i].name, minor->dev_root);
-+}
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
-@@ -0,0 +1,271 @@
-+/*
-+ * Copyright Ã‚© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Eric Anholt <eric@anholt.net>
-+ *
-+ */
-+
-+#include "drmP.h"
-+#include "drm.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+
-+/** @file i915_gem_tiling.c
-+ *
-+ * Support for managing tiling state of buffer objects.
-+ *
-+ * The idea behind tiling is to increase cache hit rates by rearranging
-+ * pixel data so that a group of pixel accesses are in the same cacheline.
-+ * Performance improvement from doing this on the back/depth buffer are on
-+ * the order of 30%.
-+ *
-+ * Intel architectures make this somewhat more complicated, though, by
-+ * adjustments made to addressing of data when the memory is in interleaved
-+ * mode (matched pairs of DIMMS) to improve memory bandwidth.
-+ * For interleaved memory, the CPU sends every sequential 64 bytes
-+ * to an alternate memory channel so it can get the bandwidth from both.
-+ *
-+ * The GPU also rearranges its accesses for increased bandwidth to interleaved
-+ * memory, and it matches what the CPU does for non-tiled.  However, when tiled
-+ * it does it a little differently, since one walks addresses not just in the
-+ * X direction but also Y.  So, along with alternating channels when bit
-+ * 6 of the address flips, it also alternates when other bits flip --  Bits 9
-+ * (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines)
-+ * are common to both the 915 and 965-class hardware.
-+ *
-+ * The CPU also sometimes XORs in higher bits as well, to improve
-+ * bandwidth doing strided access like we do so frequently in graphics.  This
-+ * is called "Channel XOR Randomization" in the MCH documentation.  The result
-+ * is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address
-+ * decode.
-+ *
-+ * All of this bit 6 XORing has an effect on our memory management,
-+ * as we need to make sure that the 3d driver can correctly address object
-+ * contents.
-+ *
-+ * If we don't have interleaved memory, all tiling is safe and no swizzling is
-+ * required.
-+ *
-+ * When bit 17 is XORed in, we simply refuse to tile at all.  Bit
-+ * 17 is not just a page offset, so as we page an objet out and back in,
-+ * individual pages in it will have different bit 17 addresses, resulting in
-+ * each 64 bytes being swapped with its neighbor!
-+ *
-+ * Otherwise, if interleaved, we have to tell the 3d driver what the address
-+ * swizzling it needs to do is, since it's writing with the CPU to the pages
-+ * (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the
-+ * pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling
-+ * required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order
-+ * to match what the GPU expects.
-+ */
-+
-+/**
-+ * Detects bit 6 swizzling of address lookup between IGD access and CPU
-+ * access through main memory.
-+ */
-+void
-+i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct pci_dev *bridge;
-+      uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-+      uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-+      int ret;
-+
-+      if (IS_I965G(dev) && !IS_I965GM(dev)) {
-+              uint32_t chdecmisc;
-+
-+              /* On the 965, channel interleave appears to be determined by
-+               * the flex bit.  If flex is set, then the ranks (sides of a
-+               * DIMM) of memory will be "stacked" (physical addresses walk
-+               * through one rank then move on to the next, flipping channels
-+               * or not depending on rank configuration).  The GPU in this
-+               * case does exactly the same addressing as the CPU.
-+               *
-+               * Unlike the 945, channel randomization based does not
-+               * appear to be available.
-+               *
-+               * XXX: While the G965 doesn't appear to do any interleaving
-+               * when the DIMMs are not exactly matched, the G4x chipsets
-+               * might be for "L-shaped" configurations, and will need to be
-+               * detected.
-+               *
-+               * L-shaped configuration:
-+               *
-+               * +-----+
-+               * |     |
-+               * |DIMM2|         <-- non-interleaved
-+               * +-----+
-+               * +-----+ +-----+
-+               * |     | |     |
-+               * |DIMM0| |DIMM1| <-- interleaved area
-+               * +-----+ +-----+
-+               */
-+              chdecmisc = I915_READ(CHDECMISC);
-+
-+              if (chdecmisc == 0xff) {
-+                      DRM_ERROR("Couldn't read from MCHBAR.  "
-+                                "Disabling tiling.\n");
-+              } else if (chdecmisc & CHDECMISC_FLEXMEMORY) {
-+                      swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-+                      swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-+              } else {
-+                      swizzle_x = I915_BIT_6_SWIZZLE_9_10;
-+                      swizzle_y = I915_BIT_6_SWIZZLE_9;
-+              }
-+      } else if (IS_I9XX(dev)) {
-+              uint32_t dcc;
-+
-+              /* On 915-945 and GM965, channel interleave by the CPU is
-+               * determined by DCC.  The CPU will alternate based on bit 6
-+               * in interleaved mode, and the GPU will then also alternate
-+               * on bit 6, 9, and 10 for X, but the CPU may also optionally
-+               * alternate based on bit 17 (XOR not disabled and XOR
-+               * bit == 17).
-+               */
-+              dcc = I915_READ(DCC);
-+              switch (dcc & DCC_ADDRESSING_MODE_MASK) {
-+              case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
-+              case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
-+                      swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-+                      swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-+                      break;
-+              case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
-+                      if (IS_I915G(dev) || IS_I915GM(dev) ||
-+                          dcc & DCC_CHANNEL_XOR_DISABLE) {
-+                              swizzle_x = I915_BIT_6_SWIZZLE_9_10;
-+                              swizzle_y = I915_BIT_6_SWIZZLE_9;
-+                      } else if (IS_I965GM(dev)) {
-+                              /* GM965 only does bit 11-based channel
-+                               * randomization
-+                               */
-+                              swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
-+                              swizzle_y = I915_BIT_6_SWIZZLE_9_11;
-+                      } else {
-+                              /* Bit 17 or perhaps other swizzling */
-+                              swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-+                              swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-+                      }
-+                      break;
-+              }
-+              if (dcc == 0xffffffff) {
-+                      DRM_ERROR("Couldn't read from MCHBAR.  "
-+                                "Disabling tiling.\n");
-+                      swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-+                      swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-+              }
-+      } else {
-+              /* As far as we know, the 865 doesn't have these bit 6
-+               * swizzling issues.
-+               */
-+              swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-+              swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-+      }
-+
-+      dev_priv->mm.bit_6_swizzle_x = swizzle_x;
-+      dev_priv->mm.bit_6_swizzle_y = swizzle_y;
-+}
-+
-+/**
-+ * Sets the tiling mode of an object, returning the required swizzling of
-+ * bit 6 of addresses in the object.
-+ */
-+int
-+i915_gem_set_tiling(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_set_tiling *args = data;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EINVAL;
-+      obj_priv = obj->driver_private;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      if (args->tiling_mode == I915_TILING_NONE) {
-+              obj_priv->tiling_mode = I915_TILING_NONE;
-+              args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
-+      } else {
-+              if (args->tiling_mode == I915_TILING_X)
-+                      args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
-+              else
-+                      args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
-+              /* If we can't handle the swizzling, make it untiled. */
-+              if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
-+                      args->tiling_mode = I915_TILING_NONE;
-+                      args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
-+              }
-+      }
-+      obj_priv->tiling_mode = args->tiling_mode;
-+
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      drm_gem_object_unreference(obj);
-+
-+      return 0;
-+}
-+
-+/**
-+ * Returns the current tiling mode and required bit 6 swizzling for the object.
-+ */
-+int
-+i915_gem_get_tiling(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_get_tiling *args = data;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EINVAL;
-+      obj_priv = obj->driver_private;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      args->tiling_mode = obj_priv->tiling_mode;
-+      switch (obj_priv->tiling_mode) {
-+      case I915_TILING_X:
-+              args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
-+              break;
-+      case I915_TILING_Y:
-+              args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
-+              break;
-+      case I915_TILING_NONE:
-+              args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
-+              break;
-+      default:
-+              DRM_ERROR("unknown tiling mode\n");
-+      }
-+
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      drm_gem_object_unreference(obj);
-+
-+      return 0;
-+}
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -281,8 +281,10 @@ irqreturn_t i915_driver_irq_handler(DRM_
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
--      if (iir & I915_USER_INTERRUPT)
-+      if (iir & I915_USER_INTERRUPT) {
-+              dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
-               DRM_WAKEUP(&dev_priv->irq_queue);
-+      }
-       if (iir & (I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
-                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)) {
-@@ -343,7 +345,7 @@ static int i915_emit_irq(struct drm_devi
-       return dev_priv->counter;
- }
--static void i915_user_irq_get(struct drm_device *dev)
-+void i915_user_irq_get(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-@@ -353,7 +355,7 @@ static void i915_user_irq_get(struct drm
-       spin_unlock(&dev_priv->user_irq_lock);
- }
--static void i915_user_irq_put(struct drm_device *dev)
-+void i915_user_irq_put(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
---- a/drivers/gpu/drm/i915/i915_reg.h
-+++ b/drivers/gpu/drm/i915/i915_reg.h
-@@ -25,19 +25,6 @@
- #ifndef _I915_REG_H_
- #define _I915_REG_H_
--/* MCH MMIO space */
--/** 915-945 and GM965 MCH register controlling DRAM channel access */
--#define DCC           0x200
--#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL            (0 << 0)
--#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC   (1 << 0)
--#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED  (2 << 0)
--#define DCC_ADDRESSING_MODE_MASK                      (3 << 0)
--#define DCC_CHANNEL_XOR_DISABLE                               (1 << 10)
--
--/** 965 MCH register controlling DRAM channel configuration */
--#define CHDECMISC             0x111
--#define CHDECMISC_FLEXMEMORY          (1 << 1)
--
- /*
-  * The Bridge device's PCI config space has information about the
-  * fb aperture size and the amount of pre-reserved memory.
-@@ -516,6 +503,30 @@
- #define PALETTE_A             0x0a000
- #define PALETTE_B             0x0a800
-+/* MCH MMIO space */
-+
-+/*
-+ * MCHBAR mirror.
-+ *
-+ * This mirrors the MCHBAR MMIO space whose location is determined by
-+ * device 0 function 0's pci config register 0x44 or 0x48 and matches it in
-+ * every way.  It is not accessible from the CP register read instructions.
-+ *
-+ */
-+/** 915-945 and GM965 MCH register controlling DRAM channel access */
-+#define MCHBAR_MIRROR_BASE    0x10000
-+
-+#define DCC                   0x10200
-+#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL            (0 << 0)
-+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC   (1 << 0)
-+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED  (2 << 0)
-+#define DCC_ADDRESSING_MODE_MASK                      (3 << 0)
-+#define DCC_CHANNEL_XOR_DISABLE                               (1 << 10)
-+
-+/** 965 MCH register controlling DRAM channel configuration */
-+#define CHDECMISC             0x10111
-+#define CHDECMISC_FLEXMEMORY          (1 << 1)
-+
- /*
-  * Overlay regs
-  */
---- a/include/drm/drm.h
-+++ b/include/drm/drm.h
-@@ -573,6 +573,34 @@ struct drm_set_version {
-       int drm_dd_minor;
- };
-+/** DRM_IOCTL_GEM_CLOSE ioctl argument type */
-+struct drm_gem_close {
-+      /** Handle of the object to be closed. */
-+      uint32_t handle;
-+      uint32_t pad;
-+};
-+
-+/** DRM_IOCTL_GEM_FLINK ioctl argument type */
-+struct drm_gem_flink {
-+      /** Handle for the object being named */
-+      uint32_t handle;
-+
-+      /** Returned global name */
-+      uint32_t name;
-+};
-+
-+/** DRM_IOCTL_GEM_OPEN ioctl argument type */
-+struct drm_gem_open {
-+      /** Name of object being opened */
-+      uint32_t name;
-+
-+      /** Returned handle for the object */
-+      uint32_t handle;
-+
-+      /** Returned size of the object */
-+      uint64_t size;
-+};
-+
- #define DRM_IOCTL_BASE                        'd'
- #define DRM_IO(nr)                    _IO(DRM_IOCTL_BASE,nr)
- #define DRM_IOR(nr,type)              _IOR(DRM_IOCTL_BASE,nr,type)
-@@ -587,6 +615,9 @@ struct drm_set_version {
- #define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
- #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
- #define DRM_IOCTL_SET_VERSION         DRM_IOWR(0x07, struct drm_set_version)
-+#define DRM_IOCTL_GEM_CLOSE           DRM_IOW (0x09, struct drm_gem_close)
-+#define DRM_IOCTL_GEM_FLINK           DRM_IOWR(0x0a, struct drm_gem_flink)
-+#define DRM_IOCTL_GEM_OPEN            DRM_IOWR(0x0b, struct drm_gem_open)
- #define DRM_IOCTL_SET_UNIQUE          DRM_IOW( 0x10, struct drm_unique)
- #define DRM_IOCTL_AUTH_MAGIC          DRM_IOW( 0x11, struct drm_auth)
---- a/include/drm/drmP.h
-+++ b/include/drm/drmP.h
-@@ -104,6 +104,7 @@ struct drm_device;
- #define DRIVER_DMA_QUEUE   0x200
- #define DRIVER_FB_DMA      0x400
- #define DRIVER_IRQ_VBL2    0x800
-+#define DRIVER_GEM         0x1000
- /***********************************************************************/
- /** \name Begin the DRM... */
-@@ -387,6 +388,10 @@ struct drm_file {
-       struct drm_minor *minor;
-       int remove_auth_on_close;
-       unsigned long lock_count;
-+      /** Mapping of mm object handles to object pointers. */
-+      struct idr object_idr;
-+      /** Lock for synchronization of access to object_idr. */
-+      spinlock_t table_lock;
-       struct file *filp;
-       void *driver_priv;
- };
-@@ -558,6 +563,56 @@ struct drm_ati_pcigart_info {
- };
- /**
-+ * This structure defines the drm_mm memory object, which will be used by the
-+ * DRM for its buffer objects.
-+ */
-+struct drm_gem_object {
-+      /** Reference count of this object */
-+      struct kref refcount;
-+
-+      /** Handle count of this object. Each handle also holds a reference */
-+      struct kref handlecount;
-+
-+      /** Related drm device */
-+      struct drm_device *dev;
-+
-+      /** File representing the shmem storage */
-+      struct file *filp;
-+
-+      /**
-+       * Size of the object, in bytes.  Immutable over the object's
-+       * lifetime.
-+       */
-+      size_t size;
-+
-+      /**
-+       * Global name for this object, starts at 1. 0 means unnamed.
-+       * Access is covered by the object_name_lock in the related drm_device
-+       */
-+      int name;
-+
-+      /**
-+       * Memory domains. These monitor which caches contain read/write data
-+       * related to the object. When transitioning from one set of domains
-+       * to another, the driver is called to ensure that caches are suitably
-+       * flushed and invalidated
-+       */
-+      uint32_t read_domains;
-+      uint32_t write_domain;
-+
-+      /**
-+       * While validating an exec operation, the
-+       * new read/write domain values are computed here.
-+       * They will be transferred to the above values
-+       * at the point that any cache flushing occurs
-+       */
-+      uint32_t pending_read_domains;
-+      uint32_t pending_write_domain;
-+
-+      void *driver_private;
-+};
-+
-+/**
-  * DRM driver structure. This structure represent the common code for
-  * a family of cards. There will one drm_device for each card present
-  * in this family
-@@ -614,6 +669,18 @@ struct drm_driver {
-       void (*set_version) (struct drm_device *dev,
-                            struct drm_set_version *sv);
-+      int (*proc_init)(struct drm_minor *minor);
-+      void (*proc_cleanup)(struct drm_minor *minor);
-+
-+      /**
-+       * Driver-specific constructor for drm_gem_objects, to set up
-+       * obj->driver_private.
-+       *
-+       * Returns 0 on success.
-+       */
-+      int (*gem_init_object) (struct drm_gem_object *obj);
-+      void (*gem_free_object) (struct drm_gem_object *obj);
-+
-       int major;
-       int minor;
-       int patchlevel;
-@@ -771,6 +838,22 @@ struct drm_device {
-       spinlock_t drw_lock;
-       struct idr drw_idr;
-       /*@} */
-+
-+      /** \name GEM information */
-+      /*@{ */
-+      spinlock_t object_name_lock;
-+      struct idr object_name_idr;
-+      atomic_t object_count;
-+      atomic_t object_memory;
-+      atomic_t pin_count;
-+      atomic_t pin_memory;
-+      atomic_t gtt_count;
-+      atomic_t gtt_memory;
-+      uint32_t gtt_total;
-+      uint32_t invalidate_domains;    /* domains pending invalidation */
-+      uint32_t flush_domains;         /* domains pending flush */
-+      /*@} */
-+
- };
- static __inline__ int drm_core_check_feature(struct drm_device *dev,
-@@ -867,6 +950,10 @@ extern void *drm_realloc(void *oldpt, si
- extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
- extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
- extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
-+extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
-+                                     struct page **pages,
-+                                     unsigned long num_pages,
-+                                     uint32_t gtt_offset);
- extern int drm_unbind_agp(DRM_AGP_MEM * handle);
-                               /* Misc. IOCTL support (drm_ioctl.h) */
-@@ -929,6 +1016,9 @@ extern int drm_getmagic(struct drm_devic
- extern int drm_authmagic(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-+/* Cache management (drm_cache.c) */
-+void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
-+
-                               /* Locking IOCTL support (drm_lock.h) */
- extern int drm_lock(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv);
-@@ -1026,6 +1116,7 @@ extern DRM_AGP_MEM *drm_agp_allocate_mem
- extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
- extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
- extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
-+extern void drm_agp_chipset_flush(struct drm_device *dev);
-                               /* Stub support (drm_stub.h) */
- extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
-@@ -1088,6 +1179,66 @@ extern unsigned long drm_mm_tail_space(s
- extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
- extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
-+/* Graphics Execution Manager library functions (drm_gem.c) */
-+int drm_gem_init(struct drm_device *dev);
-+void drm_gem_object_free(struct kref *kref);
-+struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
-+                                          size_t size);
-+void drm_gem_object_handle_free(struct kref *kref);
-+
-+static inline void
-+drm_gem_object_reference(struct drm_gem_object *obj)
-+{
-+      kref_get(&obj->refcount);
-+}
-+
-+static inline void
-+drm_gem_object_unreference(struct drm_gem_object *obj)
-+{
-+      if (obj == NULL)
-+              return;
-+
-+      kref_put(&obj->refcount, drm_gem_object_free);
-+}
-+
-+int drm_gem_handle_create(struct drm_file *file_priv,
-+                        struct drm_gem_object *obj,
-+                        int *handlep);
-+
-+static inline void
-+drm_gem_object_handle_reference(struct drm_gem_object *obj)
-+{
-+      drm_gem_object_reference(obj);
-+      kref_get(&obj->handlecount);
-+}
-+
-+static inline void
-+drm_gem_object_handle_unreference(struct drm_gem_object *obj)
-+{
-+      if (obj == NULL)
-+              return;
-+
-+      /*
-+       * Must bump handle count first as this may be the last
-+       * ref, in which case the object would disappear before we
-+       * checked for a name
-+       */
-+      kref_put(&obj->handlecount, drm_gem_object_handle_free);
-+      drm_gem_object_unreference(obj);
-+}
-+
-+struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
-+                                           struct drm_file *filp,
-+                                           int handle);
-+int drm_gem_close_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int drm_gem_flink_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int drm_gem_open_ioctl(struct drm_device *dev, void *data,
-+                     struct drm_file *file_priv);
-+void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
-+void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
-+
- extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
- extern void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev);
- extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
---- a/include/drm/i915_drm.h
-+++ b/include/drm/i915_drm.h
-@@ -143,6 +143,22 @@ typedef struct _drm_i915_sarea {
- #define DRM_I915_GET_VBLANK_PIPE      0x0e
- #define DRM_I915_VBLANK_SWAP  0x0f
- #define DRM_I915_HWS_ADDR     0x11
-+#define DRM_I915_GEM_INIT     0x13
-+#define DRM_I915_GEM_EXECBUFFER       0x14
-+#define DRM_I915_GEM_PIN      0x15
-+#define DRM_I915_GEM_UNPIN    0x16
-+#define DRM_I915_GEM_BUSY     0x17
-+#define DRM_I915_GEM_THROTTLE 0x18
-+#define DRM_I915_GEM_ENTERVT  0x19
-+#define DRM_I915_GEM_LEAVEVT  0x1a
-+#define DRM_I915_GEM_CREATE   0x1b
-+#define DRM_I915_GEM_PREAD    0x1c
-+#define DRM_I915_GEM_PWRITE   0x1d
-+#define DRM_I915_GEM_MMAP     0x1e
-+#define DRM_I915_GEM_SET_DOMAIN       0x1f
-+#define DRM_I915_GEM_SW_FINISH        0x20
-+#define DRM_I915_GEM_SET_TILING       0x21
-+#define DRM_I915_GEM_GET_TILING       0x22
- #define DRM_IOCTL_I915_INIT           DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
- #define DRM_IOCTL_I915_FLUSH          DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
-@@ -160,6 +176,20 @@ typedef struct _drm_i915_sarea {
- #define DRM_IOCTL_I915_SET_VBLANK_PIPE        DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
- #define DRM_IOCTL_I915_GET_VBLANK_PIPE        DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
- #define DRM_IOCTL_I915_VBLANK_SWAP    DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
-+#define DRM_IOCTL_I915_GEM_PIN                DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
-+#define DRM_IOCTL_I915_GEM_UNPIN      DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
-+#define DRM_IOCTL_I915_GEM_BUSY               DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
-+#define DRM_IOCTL_I915_GEM_THROTTLE   DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
-+#define DRM_IOCTL_I915_GEM_ENTERVT    DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
-+#define DRM_IOCTL_I915_GEM_LEAVEVT    DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
-+#define DRM_IOCTL_I915_GEM_CREATE     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create)
-+#define DRM_IOCTL_I915_GEM_PREAD      DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread)
-+#define DRM_IOCTL_I915_GEM_PWRITE     DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
-+#define DRM_IOCTL_I915_GEM_MMAP               DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
-+#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
-+#define DRM_IOCTL_I915_GEM_SW_FINISH  DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
-+#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
-+#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
- /* Allow drivers to submit batchbuffers directly to hardware, relying
-  * on the security mechanisms provided by hardware.
-@@ -200,6 +230,7 @@ typedef struct drm_i915_irq_wait {
- #define I915_PARAM_IRQ_ACTIVE            1
- #define I915_PARAM_ALLOW_BATCHBUFFER     2
- #define I915_PARAM_LAST_DISPATCH         3
-+#define I915_PARAM_HAS_GEM               5
- typedef struct drm_i915_getparam {
-       int param;
-@@ -267,4 +298,305 @@ typedef struct drm_i915_hws_addr {
-       uint64_t addr;
- } drm_i915_hws_addr_t;
-+struct drm_i915_gem_init {
-+      /**
-+       * Beginning offset in the GTT to be managed by the DRM memory
-+       * manager.
-+       */
-+      uint64_t gtt_start;
-+      /**
-+       * Ending offset in the GTT to be managed by the DRM memory
-+       * manager.
-+       */
-+      uint64_t gtt_end;
-+};
-+
-+struct drm_i915_gem_create {
-+      /**
-+       * Requested size for the object.
-+       *
-+       * The (page-aligned) allocated size for the object will be returned.
-+       */
-+      uint64_t size;
-+      /**
-+       * Returned handle for the object.
-+       *
-+       * Object handles are nonzero.
-+       */
-+      uint32_t handle;
-+      uint32_t pad;
-+};
-+
-+struct drm_i915_gem_pread {
-+      /** Handle for the object being read. */
-+      uint32_t handle;
-+      uint32_t pad;
-+      /** Offset into the object to read from */
-+      uint64_t offset;
-+      /** Length of data to read */
-+      uint64_t size;
-+      /**
-+       * Pointer to write the data into.
-+       *
-+       * This is a fixed-size type for 32/64 compatibility.
-+       */
-+      uint64_t data_ptr;
-+};
-+
-+struct drm_i915_gem_pwrite {
-+      /** Handle for the object being written to. */
-+      uint32_t handle;
-+      uint32_t pad;
-+      /** Offset into the object to write to */
-+      uint64_t offset;
-+      /** Length of data to write */
-+      uint64_t size;
-+      /**
-+       * Pointer to read the data from.
-+       *
-+       * This is a fixed-size type for 32/64 compatibility.
-+       */
-+      uint64_t data_ptr;
-+};
-+
-+struct drm_i915_gem_mmap {
-+      /** Handle for the object being mapped. */
-+      uint32_t handle;
-+      uint32_t pad;
-+      /** Offset in the object to map. */
-+      uint64_t offset;
-+      /**
-+       * Length of data to map.
-+       *
-+       * The value will be page-aligned.
-+       */
-+      uint64_t size;
-+      /**
-+       * Returned pointer the data was mapped at.
-+       *
-+       * This is a fixed-size type for 32/64 compatibility.
-+       */
-+      uint64_t addr_ptr;
-+};
-+
-+struct drm_i915_gem_set_domain {
-+      /** Handle for the object */
-+      uint32_t handle;
-+
-+      /** New read domains */
-+      uint32_t read_domains;
-+
-+      /** New write domain */
-+      uint32_t write_domain;
-+};
-+
-+struct drm_i915_gem_sw_finish {
-+      /** Handle for the object */
-+      uint32_t handle;
-+};
-+
-+struct drm_i915_gem_relocation_entry {
-+      /**
-+       * Handle of the buffer being pointed to by this relocation entry.
-+       *
-+       * It's appealing to make this be an index into the mm_validate_entry
-+       * list to refer to the buffer, but this allows the driver to create
-+       * a relocation list for state buffers and not re-write it per
-+       * exec using the buffer.
-+       */
-+      uint32_t target_handle;
-+
-+      /**
-+       * Value to be added to the offset of the target buffer to make up
-+       * the relocation entry.
-+       */
-+      uint32_t delta;
-+
-+      /** Offset in the buffer the relocation entry will be written into */
-+      uint64_t offset;
-+
-+      /**
-+       * Offset value of the target buffer that the relocation entry was last
-+       * written as.
-+       *
-+       * If the buffer has the same offset as last time, we can skip syncing
-+       * and writing the relocation.  This value is written back out by
-+       * the execbuffer ioctl when the relocation is written.
-+       */
-+      uint64_t presumed_offset;
-+
-+      /**
-+       * Target memory domains read by this operation.
-+       */
-+      uint32_t read_domains;
-+
-+      /**
-+       * Target memory domains written by this operation.
-+       *
-+       * Note that only one domain may be written by the whole
-+       * execbuffer operation, so that where there are conflicts,
-+       * the application will get -EINVAL back.
-+       */
-+      uint32_t write_domain;
-+};
-+
-+/** @{
-+ * Intel memory domains
-+ *
-+ * Most of these just align with the various caches in
-+ * the system and are used to flush and invalidate as
-+ * objects end up cached in different domains.
-+ */
-+/** CPU cache */
-+#define I915_GEM_DOMAIN_CPU           0x00000001
-+/** Render cache, used by 2D and 3D drawing */
-+#define I915_GEM_DOMAIN_RENDER                0x00000002
-+/** Sampler cache, used by texture engine */
-+#define I915_GEM_DOMAIN_SAMPLER               0x00000004
-+/** Command queue, used to load batch buffers */
-+#define I915_GEM_DOMAIN_COMMAND               0x00000008
-+/** Instruction cache, used by shader programs */
-+#define I915_GEM_DOMAIN_INSTRUCTION   0x00000010
-+/** Vertex address cache */
-+#define I915_GEM_DOMAIN_VERTEX                0x00000020
-+/** GTT domain - aperture and scanout */
-+#define I915_GEM_DOMAIN_GTT           0x00000040
-+/** @} */
-+
-+struct drm_i915_gem_exec_object {
-+      /**
-+       * User's handle for a buffer to be bound into the GTT for this
-+       * operation.
-+       */
-+      uint32_t handle;
-+
-+      /** Number of relocations to be performed on this buffer */
-+      uint32_t relocation_count;
-+      /**
-+       * Pointer to array of struct drm_i915_gem_relocation_entry containing
-+       * the relocations to be performed in this buffer.
-+       */
-+      uint64_t relocs_ptr;
-+
-+      /** Required alignment in graphics aperture */
-+      uint64_t alignment;
-+
-+      /**
-+       * Returned value of the updated offset of the object, for future
-+       * presumed_offset writes.
-+       */
-+      uint64_t offset;
-+};
-+
-+struct drm_i915_gem_execbuffer {
-+      /**
-+       * List of buffers to be validated with their relocations to be
-+       * performend on them.
-+       *
-+       * This is a pointer to an array of struct drm_i915_gem_validate_entry.
-+       *
-+       * These buffers must be listed in an order such that all relocations
-+       * a buffer is performing refer to buffers that have already appeared
-+       * in the validate list.
-+       */
-+      uint64_t buffers_ptr;
-+      uint32_t buffer_count;
-+
-+      /** Offset in the batchbuffer to start execution from. */
-+      uint32_t batch_start_offset;
-+      /** Bytes used in batchbuffer from batch_start_offset */
-+      uint32_t batch_len;
-+      uint32_t DR1;
-+      uint32_t DR4;
-+      uint32_t num_cliprects;
-+      /** This is a struct drm_clip_rect *cliprects */
-+      uint64_t cliprects_ptr;
-+};
-+
-+struct drm_i915_gem_pin {
-+      /** Handle of the buffer to be pinned. */
-+      uint32_t handle;
-+      uint32_t pad;
-+
-+      /** alignment required within the aperture */
-+      uint64_t alignment;
-+
-+      /** Returned GTT offset of the buffer. */
-+      uint64_t offset;
-+};
-+
-+struct drm_i915_gem_unpin {
-+      /** Handle of the buffer to be unpinned. */
-+      uint32_t handle;
-+      uint32_t pad;
-+};
-+
-+struct drm_i915_gem_busy {
-+      /** Handle of the buffer to check for busy */
-+      uint32_t handle;
-+
-+      /** Return busy status (1 if busy, 0 if idle) */
-+      uint32_t busy;
-+};
-+
-+#define I915_TILING_NONE      0
-+#define I915_TILING_X         1
-+#define I915_TILING_Y         2
-+
-+#define I915_BIT_6_SWIZZLE_NONE               0
-+#define I915_BIT_6_SWIZZLE_9          1
-+#define I915_BIT_6_SWIZZLE_9_10               2
-+#define I915_BIT_6_SWIZZLE_9_11               3
-+#define I915_BIT_6_SWIZZLE_9_10_11    4
-+/* Not seen by userland */
-+#define I915_BIT_6_SWIZZLE_UNKNOWN    5
-+
-+struct drm_i915_gem_set_tiling {
-+      /** Handle of the buffer to have its tiling state updated */
-+      uint32_t handle;
-+
-+      /**
-+       * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
-+       * I915_TILING_Y).
-+       *
-+       * This value is to be set on request, and will be updated by the
-+       * kernel on successful return with the actual chosen tiling layout.
-+       *
-+       * The tiling mode may be demoted to I915_TILING_NONE when the system
-+       * has bit 6 swizzling that can't be managed correctly by GEM.
-+       *
-+       * Buffer contents become undefined when changing tiling_mode.
-+       */
-+      uint32_t tiling_mode;
-+
-+      /**
-+       * Stride in bytes for the object when in I915_TILING_X or
-+       * I915_TILING_Y.
-+       */
-+      uint32_t stride;
-+
-+      /**
-+       * Returned address bit 6 swizzling required for CPU access through
-+       * mmap mapping.
-+       */
-+      uint32_t swizzle_mode;
-+};
-+
-+struct drm_i915_gem_get_tiling {
-+      /** Handle of the buffer to get tiling state for. */
-+      uint32_t handle;
-+
-+      /**
-+       * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
-+       * I915_TILING_Y).
-+       */
-+      uint32_t tiling_mode;
-+
-+      /**
-+       * Returned address bit 6 swizzling required for CPU access through
-+       * mmap mapping.
-+       */
-+      uint32_t swizzle_mode;
-+};
-+
- #endif                                /* _I915_DRM_H_ */
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch
deleted file mode 100644 (file)
index 4de9839..0000000
+++ /dev/null
@@ -1,6727 +0,0 @@
-diff -uNr a/fs/Kconfig b/fs/Kconfig
---- a/fs/Kconfig       2008-07-28 19:40:31.000000000 -0700
-+++ b/fs/Kconfig       2008-08-13 16:19:56.000000000 -0700
-@@ -1348,6 +1348,56 @@
-         If unsure, say N.
-+config SQUASHFS
-+      tristate "SquashFS 3.3 - Squashed file system support"
-+      select ZLIB_INFLATE
-+      help
-+        Saying Y here includes support for SquashFS 3.3 (a Compressed
-+        Read-Only File System).  Squashfs is a highly compressed read-only
-+        filesystem for Linux.  It uses zlib compression to compress both
-+        files, inodes and directories.  Inodes in the system are very small
-+        and all blocks are packed to minimise data overhead. Block sizes
-+        greater than 4K are supported up to a maximum of 1 Mbytes (default
-+        block size 128K).  SquashFS 3.3 supports 64 bit filesystems and files
-+        (larger than 4GB), full uid/gid information, hard links and timestamps.  
-+
-+        Squashfs is intended for general read-only filesystem use, for
-+        archival use (i.e. in cases where a .tar.gz file may be used), and in
-+        embedded systems where low overhead is needed.  Further information
-+        and filesystem tools are available from http://squashfs.sourceforge.net.
-+
-+        If you want to compile this as a module ( = code which can be
-+        inserted in and removed from the running kernel whenever you want),
-+        say M here and read <file:Documentation/modules.txt>.  The module
-+        will be called squashfs.  Note that the root file system (the one
-+        containing the directory /) cannot be compiled as a module.
-+
-+        If unsure, say N.
-+
-+config SQUASHFS_EMBEDDED
-+
-+      bool "Additional option for memory-constrained systems" 
-+      depends on SQUASHFS
-+      default n
-+      help
-+        Saying Y here allows you to specify cache size.
-+
-+        If unsure, say N.
-+
-+config SQUASHFS_FRAGMENT_CACHE_SIZE
-+      int "Number of fragments cached" if SQUASHFS_EMBEDDED
-+      depends on SQUASHFS
-+      default "3"
-+      help
-+        By default SquashFS caches the last 3 fragments read from
-+        the filesystem.  Increasing this amount may mean SquashFS
-+        has to re-read fragments less often from disk, at the expense
-+        of extra system memory.  Decreasing this amount will mean
-+        SquashFS uses less memory at the expense of extra reads from disk.
-+
-+        Note there must be at least one cached fragment.  Anything
-+        much more than three will probably not make much difference.
-+
- config VXFS_FS
-       tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
-       depends on BLOCK
-diff -uNr a/fs/Kconfig.orig b/fs/Kconfig.orig
---- a/fs/Kconfig.orig  1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/Kconfig.orig  2008-07-28 19:40:31.000000000 -0700
-@@ -0,0 +1,2097 @@
-+#
-+# File system configuration
-+#
-+
-+menu "File systems"
-+
-+if BLOCK
-+
-+config EXT2_FS
-+      tristate "Second extended fs support"
-+      help
-+        Ext2 is a standard Linux file system for hard disks.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called ext2.
-+
-+        If unsure, say Y.
-+
-+config EXT2_FS_XATTR
-+      bool "Ext2 extended attributes"
-+      depends on EXT2_FS
-+      help
-+        Extended attributes are name:value pairs associated with inodes by
-+        the kernel or by users (see the attr(5) manual page, or visit
-+        <http://acl.bestbits.at/> for details).
-+
-+        If unsure, say N.
-+
-+config EXT2_FS_POSIX_ACL
-+      bool "Ext2 POSIX Access Control Lists"
-+      depends on EXT2_FS_XATTR
-+      select FS_POSIX_ACL
-+      help
-+        Posix Access Control Lists (ACLs) support permissions for users and
-+        groups beyond the owner/group/world scheme.
-+
-+        To learn more about Access Control Lists, visit the Posix ACLs for
-+        Linux website <http://acl.bestbits.at/>.
-+
-+        If you don't know what Access Control Lists are, say N
-+
-+config EXT2_FS_SECURITY
-+      bool "Ext2 Security Labels"
-+      depends on EXT2_FS_XATTR
-+      help
-+        Security labels support alternative access control models
-+        implemented by security modules like SELinux.  This option
-+        enables an extended attribute handler for file security
-+        labels in the ext2 filesystem.
-+
-+        If you are not using a security module that requires using
-+        extended attributes for file security labels, say N.
-+
-+config EXT2_FS_XIP
-+      bool "Ext2 execute in place support"
-+      depends on EXT2_FS && MMU
-+      help
-+        Execute in place can be used on memory-backed block devices. If you
-+        enable this option, you can select to mount block devices which are
-+        capable of this feature without using the page cache.
-+
-+        If you do not use a block device that is capable of using this,
-+        or if unsure, say N.
-+
-+config FS_XIP
-+# execute in place
-+      bool
-+      depends on EXT2_FS_XIP
-+      default y
-+
-+config EXT3_FS
-+      tristate "Ext3 journalling file system support"
-+      select JBD
-+      help
-+        This is the journalling version of the Second extended file system
-+        (often called ext3), the de facto standard Linux file system
-+        (method to organize files on a storage device) for hard disks.
-+
-+        The journalling code included in this driver means you do not have
-+        to run e2fsck (file system checker) on your file systems after a
-+        crash.  The journal keeps track of any changes that were being made
-+        at the time the system crashed, and can ensure that your file system
-+        is consistent without the need for a lengthy check.
-+
-+        Other than adding the journal to the file system, the on-disk format
-+        of ext3 is identical to ext2.  It is possible to freely switch
-+        between using the ext3 driver and the ext2 driver, as long as the
-+        file system has been cleanly unmounted, or e2fsck is run on the file
-+        system.
-+
-+        To add a journal on an existing ext2 file system or change the
-+        behavior of ext3 file systems, you can use the tune2fs utility ("man
-+        tune2fs").  To modify attributes of files and directories on ext3
-+        file systems, use chattr ("man chattr").  You need to be using
-+        e2fsprogs version 1.20 or later in order to create ext3 journals
-+        (available at <http://sourceforge.net/projects/e2fsprogs/>).
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called ext3.
-+
-+config EXT3_FS_XATTR
-+      bool "Ext3 extended attributes"
-+      depends on EXT3_FS
-+      default y
-+      help
-+        Extended attributes are name:value pairs associated with inodes by
-+        the kernel or by users (see the attr(5) manual page, or visit
-+        <http://acl.bestbits.at/> for details).
-+
-+        If unsure, say N.
-+
-+        You need this for POSIX ACL support on ext3.
-+
-+config EXT3_FS_POSIX_ACL
-+      bool "Ext3 POSIX Access Control Lists"
-+      depends on EXT3_FS_XATTR
-+      select FS_POSIX_ACL
-+      help
-+        Posix Access Control Lists (ACLs) support permissions for users and
-+        groups beyond the owner/group/world scheme.
-+
-+        To learn more about Access Control Lists, visit the Posix ACLs for
-+        Linux website <http://acl.bestbits.at/>.
-+
-+        If you don't know what Access Control Lists are, say N
-+
-+config EXT3_FS_SECURITY
-+      bool "Ext3 Security Labels"
-+      depends on EXT3_FS_XATTR
-+      help
-+        Security labels support alternative access control models
-+        implemented by security modules like SELinux.  This option
-+        enables an extended attribute handler for file security
-+        labels in the ext3 filesystem.
-+
-+        If you are not using a security module that requires using
-+        extended attributes for file security labels, say N.
-+
-+config EXT4DEV_FS
-+      tristate "Ext4dev/ext4 extended fs support development (EXPERIMENTAL)"
-+      depends on EXPERIMENTAL
-+      select JBD2
-+      select CRC16
-+      help
-+        Ext4dev is a predecessor filesystem of the next generation
-+        extended fs ext4, based on ext3 filesystem code. It will be
-+        renamed ext4 fs later, once ext4dev is mature and stabilized.
-+
-+        Unlike the change from ext2 filesystem to ext3 filesystem,
-+        the on-disk format of ext4dev is not the same as ext3 any more:
-+        it is based on extent maps and it supports 48-bit physical block
-+        numbers. These combined on-disk format changes will allow
-+        ext4dev/ext4 to handle more than 16 TB filesystem volumes --
-+        a hard limit that ext3 cannot overcome without changing the
-+        on-disk format.
-+
-+        Other than extent maps and 48-bit block numbers, ext4dev also is
-+        likely to have other new features such as persistent preallocation,
-+        high resolution time stamps, and larger file support etc.  These
-+        features will be added to ext4dev gradually.
-+
-+        To compile this file system support as a module, choose M here. The
-+        module will be called ext4dev.
-+
-+        If unsure, say N.
-+
-+config EXT4DEV_FS_XATTR
-+      bool "Ext4dev extended attributes"
-+      depends on EXT4DEV_FS
-+      default y
-+      help
-+        Extended attributes are name:value pairs associated with inodes by
-+        the kernel or by users (see the attr(5) manual page, or visit
-+        <http://acl.bestbits.at/> for details).
-+
-+        If unsure, say N.
-+
-+        You need this for POSIX ACL support on ext4dev/ext4.
-+
-+config EXT4DEV_FS_POSIX_ACL
-+      bool "Ext4dev POSIX Access Control Lists"
-+      depends on EXT4DEV_FS_XATTR
-+      select FS_POSIX_ACL
-+      help
-+        POSIX Access Control Lists (ACLs) support permissions for users and
-+        groups beyond the owner/group/world scheme.
-+
-+        To learn more about Access Control Lists, visit the POSIX ACLs for
-+        Linux website <http://acl.bestbits.at/>.
-+
-+        If you don't know what Access Control Lists are, say N
-+
-+config EXT4DEV_FS_SECURITY
-+      bool "Ext4dev Security Labels"
-+      depends on EXT4DEV_FS_XATTR
-+      help
-+        Security labels support alternative access control models
-+        implemented by security modules like SELinux.  This option
-+        enables an extended attribute handler for file security
-+        labels in the ext4dev/ext4 filesystem.
-+
-+        If you are not using a security module that requires using
-+        extended attributes for file security labels, say N.
-+
-+config JBD
-+      tristate
-+      help
-+        This is a generic journalling layer for block devices.  It is
-+        currently used by the ext3 and OCFS2 file systems, but it could
-+        also be used to add journal support to other file systems or block
-+        devices such as RAID or LVM.
-+
-+        If you are using the ext3 or OCFS2 file systems, you need to
-+        say Y here. If you are not using ext3 OCFS2 then you will probably
-+        want to say N.
-+
-+        To compile this device as a module, choose M here: the module will be
-+        called jbd.  If you are compiling ext3 or OCFS2 into the kernel,
-+        you cannot compile this code as a module.
-+
-+config JBD_DEBUG
-+      bool "JBD (ext3) debugging support"
-+      depends on JBD && DEBUG_FS
-+      help
-+        If you are using the ext3 journaled file system (or potentially any
-+        other file system/device using JBD), this option allows you to
-+        enable debugging output while the system is running, in order to
-+        help track down any problems you are having.  By default the
-+        debugging output will be turned off.
-+
-+        If you select Y here, then you will be able to turn on debugging
-+        with "echo N > /sys/kernel/debug/jbd/jbd-debug", where N is a
-+        number between 1 and 5, the higher the number, the more debugging
-+        output is generated.  To turn debugging off again, do
-+        "echo 0 > /sys/kernel/debug/jbd/jbd-debug".
-+
-+config JBD2
-+      tristate
-+      select CRC32
-+      help
-+        This is a generic journaling layer for block devices that support
-+        both 32-bit and 64-bit block numbers.  It is currently used by
-+        the ext4dev/ext4 filesystem, but it could also be used to add
-+        journal support to other file systems or block devices such
-+        as RAID or LVM.
-+
-+        If you are using ext4dev/ext4, you need to say Y here. If you are not
-+        using ext4dev/ext4 then you will probably want to say N.
-+
-+        To compile this device as a module, choose M here. The module will be
-+        called jbd2.  If you are compiling ext4dev/ext4 into the kernel,
-+        you cannot compile this code as a module.
-+
-+config JBD2_DEBUG
-+      bool "JBD2 (ext4dev/ext4) debugging support"
-+      depends on JBD2 && DEBUG_FS
-+      help
-+        If you are using the ext4dev/ext4 journaled file system (or
-+        potentially any other filesystem/device using JBD2), this option
-+        allows you to enable debugging output while the system is running,
-+        in order to help track down any problems you are having.
-+        By default, the debugging output will be turned off.
-+
-+        If you select Y here, then you will be able to turn on debugging
-+        with "echo N > /sys/kernel/debug/jbd2/jbd2-debug", where N is a
-+        number between 1 and 5. The higher the number, the more debugging
-+        output is generated.  To turn debugging off again, do
-+        "echo 0 > /sys/kernel/debug/jbd2/jbd2-debug".
-+
-+config FS_MBCACHE
-+# Meta block cache for Extended Attributes (ext2/ext3/ext4)
-+      tristate
-+      depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR
-+      default y if EXT2_FS=y || EXT3_FS=y || EXT4DEV_FS=y
-+      default m if EXT2_FS=m || EXT3_FS=m || EXT4DEV_FS=m
-+
-+config REISERFS_FS
-+      tristate "Reiserfs support"
-+      help
-+        Stores not just filenames but the files themselves in a balanced
-+        tree.  Uses journalling.
-+
-+        Balanced trees are more efficient than traditional file system
-+        architectural foundations.
-+
-+        In general, ReiserFS is as fast as ext2, but is very efficient with
-+        large directories and small files.  Additional patches are needed
-+        for NFS and quotas, please see <http://www.namesys.com/> for links.
-+
-+        It is more easily extended to have features currently found in
-+        database and keyword search systems than block allocation based file
-+        systems are.  The next version will be so extended, and will support
-+        plugins consistent with our motto ``It takes more than a license to
-+        make source code open.''
-+
-+        Read <http://www.namesys.com/> to learn more about reiserfs.
-+
-+        Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com.
-+
-+        If you like it, you can pay us to add new features to it that you
-+        need, buy a support contract, or pay us to port it to another OS.
-+
-+config REISERFS_CHECK
-+      bool "Enable reiserfs debug mode"
-+      depends on REISERFS_FS
-+      help
-+        If you set this to Y, then ReiserFS will perform every check it can
-+        possibly imagine of its internal consistency throughout its
-+        operation.  It will also go substantially slower.  More than once we
-+        have forgotten that this was on, and then gone despondent over the
-+        latest benchmarks.:-) Use of this option allows our team to go all
-+        out in checking for consistency when debugging without fear of its
-+        effect on end users.  If you are on the verge of sending in a bug
-+        report, say Y and you might get a useful error message.  Almost
-+        everyone should say N.
-+
-+config REISERFS_PROC_INFO
-+      bool "Stats in /proc/fs/reiserfs"
-+      depends on REISERFS_FS && PROC_FS
-+      help
-+        Create under /proc/fs/reiserfs a hierarchy of files, displaying
-+        various ReiserFS statistics and internal data at the expense of
-+        making your kernel or module slightly larger (+8 KB). This also
-+        increases the amount of kernel memory required for each mount.
-+        Almost everyone but ReiserFS developers and people fine-tuning
-+        reiserfs or tracing problems should say N.
-+
-+config REISERFS_FS_XATTR
-+      bool "ReiserFS extended attributes"
-+      depends on REISERFS_FS
-+      help
-+        Extended attributes are name:value pairs associated with inodes by
-+        the kernel or by users (see the attr(5) manual page, or visit
-+        <http://acl.bestbits.at/> for details).
-+
-+        If unsure, say N.
-+
-+config REISERFS_FS_POSIX_ACL
-+      bool "ReiserFS POSIX Access Control Lists"
-+      depends on REISERFS_FS_XATTR
-+      select FS_POSIX_ACL
-+      help
-+        Posix Access Control Lists (ACLs) support permissions for users and
-+        groups beyond the owner/group/world scheme.
-+
-+        To learn more about Access Control Lists, visit the Posix ACLs for
-+        Linux website <http://acl.bestbits.at/>.
-+
-+        If you don't know what Access Control Lists are, say N
-+
-+config REISERFS_FS_SECURITY
-+      bool "ReiserFS Security Labels"
-+      depends on REISERFS_FS_XATTR
-+      help
-+        Security labels support alternative access control models
-+        implemented by security modules like SELinux.  This option
-+        enables an extended attribute handler for file security
-+        labels in the ReiserFS filesystem.
-+
-+        If you are not using a security module that requires using
-+        extended attributes for file security labels, say N.
-+
-+config JFS_FS
-+      tristate "JFS filesystem support"
-+      select NLS
-+      help
-+        This is a port of IBM's Journaled Filesystem .  More information is
-+        available in the file <file:Documentation/filesystems/jfs.txt>.
-+
-+        If you do not intend to use the JFS filesystem, say N.
-+
-+config JFS_POSIX_ACL
-+      bool "JFS POSIX Access Control Lists"
-+      depends on JFS_FS
-+      select FS_POSIX_ACL
-+      help
-+        Posix Access Control Lists (ACLs) support permissions for users and
-+        groups beyond the owner/group/world scheme.
-+
-+        To learn more about Access Control Lists, visit the Posix ACLs for
-+        Linux website <http://acl.bestbits.at/>.
-+
-+        If you don't know what Access Control Lists are, say N
-+
-+config JFS_SECURITY
-+      bool "JFS Security Labels"
-+      depends on JFS_FS
-+      help
-+        Security labels support alternative access control models
-+        implemented by security modules like SELinux.  This option
-+        enables an extended attribute handler for file security
-+        labels in the jfs filesystem.
-+
-+        If you are not using a security module that requires using
-+        extended attributes for file security labels, say N.
-+
-+config JFS_DEBUG
-+      bool "JFS debugging"
-+      depends on JFS_FS
-+      help
-+        If you are experiencing any problems with the JFS filesystem, say
-+        Y here.  This will result in additional debugging messages to be
-+        written to the system log.  Under normal circumstances, this
-+        results in very little overhead.
-+
-+config JFS_STATISTICS
-+      bool "JFS statistics"
-+      depends on JFS_FS
-+      help
-+        Enabling this option will cause statistics from the JFS file system
-+        to be made available to the user in the /proc/fs/jfs/ directory.
-+
-+config FS_POSIX_ACL
-+# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4)
-+#
-+# NOTE: you can implement Posix ACLs without these helpers (XFS does).
-+#     Never use this symbol for ifdefs.
-+#
-+      bool
-+      default n
-+
-+source "fs/xfs/Kconfig"
-+source "fs/gfs2/Kconfig"
-+
-+config OCFS2_FS
-+      tristate "OCFS2 file system support"
-+      depends on NET && SYSFS
-+      select CONFIGFS_FS
-+      select JBD
-+      select CRC32
-+      help
-+        OCFS2 is a general purpose extent based shared disk cluster file
-+        system with many similarities to ext3. It supports 64 bit inode
-+        numbers, and has automatically extending metadata groups which may
-+        also make it attractive for non-clustered use.
-+
-+        You'll want to install the ocfs2-tools package in order to at least
-+        get "mount.ocfs2".
-+
-+        Project web page:    http://oss.oracle.com/projects/ocfs2
-+        Tools web page:      http://oss.oracle.com/projects/ocfs2-tools
-+        OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/
-+
-+        For more information on OCFS2, see the file
-+        <file:Documentation/filesystems/ocfs2.txt>.
-+
-+config OCFS2_FS_O2CB
-+      tristate "O2CB Kernelspace Clustering"
-+      depends on OCFS2_FS
-+      default y
-+      help
-+        OCFS2 includes a simple kernelspace clustering package, the OCFS2
-+        Cluster Base.  It only requires a very small userspace component
-+        to configure it. This comes with the standard ocfs2-tools package.
-+        O2CB is limited to maintaining a cluster for OCFS2 file systems.
-+        It cannot manage any other cluster applications.
-+
-+        It is always safe to say Y here, as the clustering method is
-+        run-time selectable.
-+
-+config OCFS2_FS_USERSPACE_CLUSTER
-+      tristate "OCFS2 Userspace Clustering"
-+      depends on OCFS2_FS && DLM
-+      default y
-+      help
-+        This option will allow OCFS2 to use userspace clustering services
-+        in conjunction with the DLM in fs/dlm.  If you are using a
-+        userspace cluster manager, say Y here.
-+
-+        It is safe to say Y, as the clustering method is run-time
-+        selectable.
-+
-+config OCFS2_FS_STATS
-+      bool "OCFS2 statistics"
-+      depends on OCFS2_FS
-+      default y
-+      help
-+        This option allows some fs statistics to be captured. Enabling
-+        this option may increase the memory consumption.
-+
-+config OCFS2_DEBUG_MASKLOG
-+      bool "OCFS2 logging support"
-+      depends on OCFS2_FS
-+      default y
-+      help
-+        The ocfs2 filesystem has an extensive logging system.  The system
-+        allows selection of events to log via files in /sys/o2cb/logmask/.
-+        This option will enlarge your kernel, but it allows debugging of
-+        ocfs2 filesystem issues.
-+
-+config OCFS2_DEBUG_FS
-+      bool "OCFS2 expensive checks"
-+      depends on OCFS2_FS
-+      default n
-+      help
-+        This option will enable expensive consistency checks. Enable
-+        this option for debugging only as it is likely to decrease
-+        performance of the filesystem.
-+
-+endif # BLOCK
-+
-+config DNOTIFY
-+      bool "Dnotify support"
-+      default y
-+      help
-+        Dnotify is a directory-based per-fd file change notification system
-+        that uses signals to communicate events to user-space.  There exist
-+        superior alternatives, but some applications may still rely on
-+        dnotify.
-+
-+        If unsure, say Y.
-+
-+config INOTIFY
-+      bool "Inotify file change notification support"
-+      default y
-+      ---help---
-+        Say Y here to enable inotify support.  Inotify is a file change
-+        notification system and a replacement for dnotify.  Inotify fixes
-+        numerous shortcomings in dnotify and introduces several new features
-+        including multiple file events, one-shot support, and unmount
-+        notification.
-+
-+        For more information, see <file:Documentation/filesystems/inotify.txt>
-+
-+        If unsure, say Y.
-+
-+config INOTIFY_USER
-+      bool "Inotify support for userspace"
-+      depends on INOTIFY
-+      default y
-+      ---help---
-+        Say Y here to enable inotify support for userspace, including the
-+        associated system calls.  Inotify allows monitoring of both files and
-+        directories via a single open fd.  Events are read from the file
-+        descriptor, which is also select()- and poll()-able.
-+
-+        For more information, see <file:Documentation/filesystems/inotify.txt>
-+
-+        If unsure, say Y.
-+
-+config QUOTA
-+      bool "Quota support"
-+      help
-+        If you say Y here, you will be able to set per user limits for disk
-+        usage (also called disk quotas). Currently, it works for the
-+        ext2, ext3, and reiserfs file system. ext3 also supports journalled
-+        quotas for which you don't need to run quotacheck(8) after an unclean
-+        shutdown.
-+        For further details, read the Quota mini-HOWTO, available from
-+        <http://www.tldp.org/docs.html#howto>, or the documentation provided
-+        with the quota tools. Probably the quota support is only useful for
-+        multi user systems. If unsure, say N.
-+
-+config QUOTA_NETLINK_INTERFACE
-+      bool "Report quota messages through netlink interface"
-+      depends on QUOTA && NET
-+      help
-+        If you say Y here, quota warnings (about exceeding softlimit, reaching
-+        hardlimit, etc.) will be reported through netlink interface. If unsure,
-+        say Y.
-+
-+config PRINT_QUOTA_WARNING
-+      bool "Print quota warnings to console (OBSOLETE)"
-+      depends on QUOTA
-+      default y
-+      help
-+        If you say Y here, quota warnings (about exceeding softlimit, reaching
-+        hardlimit, etc.) will be printed to the process' controlling terminal.
-+        Note that this behavior is currently deprecated and may go away in
-+        future. Please use notification via netlink socket instead.
-+
-+config QFMT_V1
-+      tristate "Old quota format support"
-+      depends on QUOTA
-+      help
-+        This quota format was (is) used by kernels earlier than 2.4.22. If
-+        you have quota working and you don't want to convert to new quota
-+        format say Y here.
-+
-+config QFMT_V2
-+      tristate "Quota format v2 support"
-+      depends on QUOTA
-+      help
-+        This quota format allows using quotas with 32-bit UIDs/GIDs. If you
-+        need this functionality say Y here.
-+
-+config QUOTACTL
-+      bool
-+      depends on XFS_QUOTA || QUOTA
-+      default y
-+
-+config AUTOFS_FS
-+      tristate "Kernel automounter support"
-+      help
-+        The automounter is a tool to automatically mount remote file systems
-+        on demand. This implementation is partially kernel-based to reduce
-+        overhead in the already-mounted case; this is unlike the BSD
-+        automounter (amd), which is a pure user space daemon.
-+
-+        To use the automounter you need the user-space tools from the autofs
-+        package; you can find the location in <file:Documentation/Changes>.
-+        You also want to answer Y to "NFS file system support", below.
-+
-+        If you want to use the newer version of the automounter with more
-+        features, say N here and say Y to "Kernel automounter v4 support",
-+        below.
-+
-+        To compile this support as a module, choose M here: the module will be
-+        called autofs.
-+
-+        If you are not a part of a fairly large, distributed network, you
-+        probably do not need an automounter, and can say N here.
-+
-+config AUTOFS4_FS
-+      tristate "Kernel automounter version 4 support (also supports v3)"
-+      help
-+        The automounter is a tool to automatically mount remote file systems
-+        on demand. This implementation is partially kernel-based to reduce
-+        overhead in the already-mounted case; this is unlike the BSD
-+        automounter (amd), which is a pure user space daemon.
-+
-+        To use the automounter you need the user-space tools from
-+        <ftp://ftp.kernel.org/pub/linux/daemons/autofs/v4/>; you also
-+        want to answer Y to "NFS file system support", below.
-+
-+        To compile this support as a module, choose M here: the module will be
-+        called autofs4.  You will need to add "alias autofs autofs4" to your
-+        modules configuration file.
-+
-+        If you are not a part of a fairly large, distributed network or
-+        don't have a laptop which needs to dynamically reconfigure to the
-+        local network, you probably do not need an automounter, and can say
-+        N here.
-+
-+config FUSE_FS
-+      tristate "Filesystem in Userspace support"
-+      help
-+        With FUSE it is possible to implement a fully functional filesystem
-+        in a userspace program.
-+
-+        There's also companion library: libfuse.  This library along with
-+        utilities is available from the FUSE homepage:
-+        <http://fuse.sourceforge.net/>
-+
-+        See <file:Documentation/filesystems/fuse.txt> for more information.
-+        See <file:Documentation/Changes> for needed library/utility version.
-+
-+        If you want to develop a userspace FS, or if you want to use
-+        a filesystem based on FUSE, answer Y or M.
-+
-+config GENERIC_ACL
-+      bool
-+      select FS_POSIX_ACL
-+
-+if BLOCK
-+menu "CD-ROM/DVD Filesystems"
-+
-+config ISO9660_FS
-+      tristate "ISO 9660 CDROM file system support"
-+      help
-+        This is the standard file system used on CD-ROMs.  It was previously
-+        known as "High Sierra File System" and is called "hsfs" on other
-+        Unix systems.  The so-called Rock-Ridge extensions which allow for
-+        long Unix filenames and symbolic links are also supported by this
-+        driver.  If you have a CD-ROM drive and want to do more with it than
-+        just listen to audio CDs and watch its LEDs, say Y (and read
-+        <file:Documentation/filesystems/isofs.txt> and the CD-ROM-HOWTO,
-+        available from <http://www.tldp.org/docs.html#howto>), thereby
-+        enlarging your kernel by about 27 KB; otherwise say N.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called isofs.
-+
-+config JOLIET
-+      bool "Microsoft Joliet CDROM extensions"
-+      depends on ISO9660_FS
-+      select NLS
-+      help
-+        Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system
-+        which allows for long filenames in unicode format (unicode is the
-+        new 16 bit character code, successor to ASCII, which encodes the
-+        characters of almost all languages of the world; see
-+        <http://www.unicode.org/> for more information).  Say Y here if you
-+        want to be able to read Joliet CD-ROMs under Linux.
-+
-+config ZISOFS
-+      bool "Transparent decompression extension"
-+      depends on ISO9660_FS
-+      select ZLIB_INFLATE
-+      help
-+        This is a Linux-specific extension to RockRidge which lets you store
-+        data in compressed form on a CD-ROM and have it transparently
-+        decompressed when the CD-ROM is accessed.  See
-+        <http://www.kernel.org/pub/linux/utils/fs/zisofs/> for the tools
-+        necessary to create such a filesystem.  Say Y here if you want to be
-+        able to read such compressed CD-ROMs.
-+
-+config UDF_FS
-+      tristate "UDF file system support"
-+      select CRC_ITU_T
-+      help
-+        This is the new file system used on some CD-ROMs and DVDs. Say Y if
-+        you intend to mount DVD discs or CDRW's written in packet mode, or
-+        if written to by other UDF utilities, such as DirectCD.
-+        Please read <file:Documentation/filesystems/udf.txt>.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called udf.
-+
-+        If unsure, say N.
-+
-+config UDF_NLS
-+      bool
-+      default y
-+      depends on (UDF_FS=m && NLS) || (UDF_FS=y && NLS=y)
-+
-+endmenu
-+endif # BLOCK
-+
-+if BLOCK
-+menu "DOS/FAT/NT Filesystems"
-+
-+config FAT_FS
-+      tristate
-+      select NLS
-+      help
-+        If you want to use one of the FAT-based file systems (the MS-DOS and
-+        VFAT (Windows 95) file systems), then you must say Y or M here
-+        to include FAT support. You will then be able to mount partitions or
-+        diskettes with FAT-based file systems and transparently access the
-+        files on them, i.e. MSDOS files will look and behave just like all
-+        other Unix files.
-+
-+        This FAT support is not a file system in itself, it only provides
-+        the foundation for the other file systems. You will have to say Y or
-+        M to at least one of "MSDOS fs support" or "VFAT fs support" in
-+        order to make use of it.
-+
-+        Another way to read and write MSDOS floppies and hard drive
-+        partitions from within Linux (but not transparently) is with the
-+        mtools ("man mtools") program suite. You don't need to say Y here in
-+        order to do that.
-+
-+        If you need to move large files on floppies between a DOS and a
-+        Linux box, say Y here, mount the floppy under Linux with an MSDOS
-+        file system and use GNU tar's M option. GNU tar is a program
-+        available for Unix and DOS ("man tar" or "info tar").
-+
-+        The FAT support will enlarge your kernel by about 37 KB. If unsure,
-+        say Y.
-+
-+        To compile this as a module, choose M here: the module will be called
-+        fat.  Note that if you compile the FAT support as a module, you
-+        cannot compile any of the FAT-based file systems into the kernel
-+        -- they will have to be modules as well.
-+
-+config MSDOS_FS
-+      tristate "MSDOS fs support"
-+      select FAT_FS
-+      help
-+        This allows you to mount MSDOS partitions of your hard drive (unless
-+        they are compressed; to access compressed MSDOS partitions under
-+        Linux, you can either use the DOS emulator DOSEMU, described in the
-+        DOSEMU-HOWTO, available from
-+        <http://www.tldp.org/docs.html#howto>, or try dmsdosfs in
-+        <ftp://ibiblio.org/pub/Linux/system/filesystems/dosfs/>. If you
-+        intend to use dosemu with a non-compressed MSDOS partition, say Y
-+        here) and MSDOS floppies. This means that file access becomes
-+        transparent, i.e. the MSDOS files look and behave just like all
-+        other Unix files.
-+
-+        If you have Windows 95 or Windows NT installed on your MSDOS
-+        partitions, you should use the VFAT file system (say Y to "VFAT fs
-+        support" below), or you will not be able to see the long filenames
-+        generated by Windows 95 / Windows NT.
-+
-+        This option will enlarge your kernel by about 7 KB. If unsure,
-+        answer Y. This will only work if you said Y to "DOS FAT fs support"
-+        as well. To compile this as a module, choose M here: the module will
-+        be called msdos.
-+
-+config VFAT_FS
-+      tristate "VFAT (Windows-95) fs support"
-+      select FAT_FS
-+      help
-+        This option provides support for normal Windows file systems with
-+        long filenames.  That includes non-compressed FAT-based file systems
-+        used by Windows 95, Windows 98, Windows NT 4.0, and the Unix
-+        programs from the mtools package.
-+
-+        The VFAT support enlarges your kernel by about 10 KB and it only
-+        works if you said Y to the "DOS FAT fs support" above.  Please read
-+        the file <file:Documentation/filesystems/vfat.txt> for details.  If
-+        unsure, say Y.
-+
-+        To compile this as a module, choose M here: the module will be called
-+        vfat.
-+
-+config FAT_DEFAULT_CODEPAGE
-+      int "Default codepage for FAT"
-+      depends on MSDOS_FS || VFAT_FS
-+      default 437
-+      help
-+        This option should be set to the codepage of your FAT filesystems.
-+        It can be overridden with the "codepage" mount option.
-+        See <file:Documentation/filesystems/vfat.txt> for more information.
-+
-+config FAT_DEFAULT_IOCHARSET
-+      string "Default iocharset for FAT"
-+      depends on VFAT_FS
-+      default "iso8859-1"
-+      help
-+        Set this to the default input/output character set you'd
-+        like FAT to use. It should probably match the character set
-+        that most of your FAT filesystems use, and can be overridden
-+        with the "iocharset" mount option for FAT filesystems.
-+        Note that "utf8" is not recommended for FAT filesystems.
-+        If unsure, you shouldn't set "utf8" here.
-+        See <file:Documentation/filesystems/vfat.txt> for more information.
-+
-+config NTFS_FS
-+      tristate "NTFS file system support"
-+      select NLS
-+      help
-+        NTFS is the file system of Microsoft Windows NT, 2000, XP and 2003.
-+
-+        Saying Y or M here enables read support.  There is partial, but
-+        safe, write support available.  For write support you must also
-+        say Y to "NTFS write support" below.
-+
-+        There are also a number of user-space tools available, called
-+        ntfsprogs.  These include ntfsundelete and ntfsresize, that work
-+        without NTFS support enabled in the kernel.
-+
-+        This is a rewrite from scratch of Linux NTFS support and replaced
-+        the old NTFS code starting with Linux 2.5.11.  A backport to
-+        the Linux 2.4 kernel series is separately available as a patch
-+        from the project web site.
-+
-+        For more information see <file:Documentation/filesystems/ntfs.txt>
-+        and <http://www.linux-ntfs.org/>.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called ntfs.
-+
-+        If you are not using Windows NT, 2000, XP or 2003 in addition to
-+        Linux on your computer it is safe to say N.
-+
-+config NTFS_DEBUG
-+      bool "NTFS debugging support"
-+      depends on NTFS_FS
-+      help
-+        If you are experiencing any problems with the NTFS file system, say
-+        Y here.  This will result in additional consistency checks to be
-+        performed by the driver as well as additional debugging messages to
-+        be written to the system log.  Note that debugging messages are
-+        disabled by default.  To enable them, supply the option debug_msgs=1
-+        at the kernel command line when booting the kernel or as an option
-+        to insmod when loading the ntfs module.  Once the driver is active,
-+        you can enable debugging messages by doing (as root):
-+        echo 1 > /proc/sys/fs/ntfs-debug
-+        Replacing the "1" with "0" would disable debug messages.
-+
-+        If you leave debugging messages disabled, this results in little
-+        overhead, but enabling debug messages results in very significant
-+        slowdown of the system.
-+
-+        When reporting bugs, please try to have available a full dump of
-+        debugging messages while the misbehaviour was occurring.
-+
-+config NTFS_RW
-+      bool "NTFS write support"
-+      depends on NTFS_FS
-+      help
-+        This enables the partial, but safe, write support in the NTFS driver.
-+
-+        The only supported operation is overwriting existing files, without
-+        changing the file length.  No file or directory creation, deletion or
-+        renaming is possible.  Note only non-resident files can be written to
-+        so you may find that some very small files (<500 bytes or so) cannot
-+        be written to.
-+
-+        While we cannot guarantee that it will not damage any data, we have
-+        so far not received a single report where the driver would have
-+        damaged someones data so we assume it is perfectly safe to use.
-+
-+        Note:  While write support is safe in this version (a rewrite from
-+        scratch of the NTFS support), it should be noted that the old NTFS
-+        write support, included in Linux 2.5.10 and before (since 1997),
-+        is not safe.
-+
-+        This is currently useful with TopologiLinux.  TopologiLinux is run
-+        on top of any DOS/Microsoft Windows system without partitioning your
-+        hard disk.  Unlike other Linux distributions TopologiLinux does not
-+        need its own partition.  For more information see
-+        <http://topologi-linux.sourceforge.net/>
-+
-+        It is perfectly safe to say N here.
-+
-+endmenu
-+endif # BLOCK
-+
-+menu "Pseudo filesystems"
-+
-+source "fs/proc/Kconfig"
-+
-+config SYSFS
-+      bool "sysfs file system support" if EMBEDDED
-+      default y
-+      help
-+      The sysfs filesystem is a virtual filesystem that the kernel uses to
-+      export internal kernel objects, their attributes, and their
-+      relationships to one another.
-+
-+      Users can use sysfs to ascertain useful information about the running
-+      kernel, such as the devices the kernel has discovered on each bus and
-+      which driver each is bound to. sysfs can also be used to tune devices
-+      and other kernel subsystems.
-+
-+      Some system agents rely on the information in sysfs to operate.
-+      /sbin/hotplug uses device and object attributes in sysfs to assist in
-+      delegating policy decisions, like persistently naming devices.
-+
-+      sysfs is currently used by the block subsystem to mount the root
-+      partition.  If sysfs is disabled you must specify the boot device on
-+      the kernel boot command line via its major and minor numbers.  For
-+      example, "root=03:01" for /dev/hda1.
-+
-+      Designers of embedded systems may wish to say N here to conserve space.
-+
-+config TMPFS
-+      bool "Virtual memory file system support (former shm fs)"
-+      help
-+        Tmpfs is a file system which keeps all files in virtual memory.
-+
-+        Everything in tmpfs is temporary in the sense that no files will be
-+        created on your hard drive. The files live in memory and swap
-+        space. If you unmount a tmpfs instance, everything stored therein is
-+        lost.
-+
-+        See <file:Documentation/filesystems/tmpfs.txt> for details.
-+
-+config TMPFS_POSIX_ACL
-+      bool "Tmpfs POSIX Access Control Lists"
-+      depends on TMPFS
-+      select GENERIC_ACL
-+      help
-+        POSIX Access Control Lists (ACLs) support permissions for users and
-+        groups beyond the owner/group/world scheme.
-+
-+        To learn more about Access Control Lists, visit the POSIX ACLs for
-+        Linux website <http://acl.bestbits.at/>.
-+
-+        If you don't know what Access Control Lists are, say N.
-+
-+config HUGETLBFS
-+      bool "HugeTLB file system support"
-+      depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \
-+                 (S390 && 64BIT) || BROKEN
-+      help
-+        hugetlbfs is a filesystem backing for HugeTLB pages, based on
-+        ramfs. For architectures that support it, say Y here and read
-+        <file:Documentation/vm/hugetlbpage.txt> for details.
-+
-+        If unsure, say N.
-+
-+config HUGETLB_PAGE
-+      def_bool HUGETLBFS
-+
-+config CONFIGFS_FS
-+      tristate "Userspace-driven configuration filesystem"
-+      depends on SYSFS
-+      help
-+        configfs is a ram-based filesystem that provides the converse
-+        of sysfs's functionality. Where sysfs is a filesystem-based
-+        view of kernel objects, configfs is a filesystem-based manager
-+        of kernel objects, or config_items.
-+
-+        Both sysfs and configfs can and should exist together on the
-+        same system. One is not a replacement for the other.
-+
-+endmenu
-+
-+menu "Miscellaneous filesystems"
-+
-+config ADFS_FS
-+      tristate "ADFS file system support (EXPERIMENTAL)"
-+      depends on BLOCK && EXPERIMENTAL
-+      help
-+        The Acorn Disc Filing System is the standard file system of the
-+        RiscOS operating system which runs on Acorn's ARM-based Risc PC
-+        systems and the Acorn Archimedes range of machines. If you say Y
-+        here, Linux will be able to read from ADFS partitions on hard drives
-+        and from ADFS-formatted floppy discs. If you also want to be able to
-+        write to those devices, say Y to "ADFS write support" below.
-+
-+        The ADFS partition should be the first partition (i.e.,
-+        /dev/[hs]d?1) on each of your drives. Please read the file
-+        <file:Documentation/filesystems/adfs.txt> for further details.
-+
-+        To compile this code as a module, choose M here: the module will be
-+        called adfs.
-+
-+        If unsure, say N.
-+
-+config ADFS_FS_RW
-+      bool "ADFS write support (DANGEROUS)"
-+      depends on ADFS_FS
-+      help
-+        If you say Y here, you will be able to write to ADFS partitions on
-+        hard drives and ADFS-formatted floppy disks. This is experimental
-+        codes, so if you're unsure, say N.
-+
-+config AFFS_FS
-+      tristate "Amiga FFS file system support (EXPERIMENTAL)"
-+      depends on BLOCK && EXPERIMENTAL
-+      help
-+        The Fast File System (FFS) is the common file system used on hard
-+        disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20).  Say Y
-+        if you want to be able to read and write files from and to an Amiga
-+        FFS partition on your hard drive.  Amiga floppies however cannot be
-+        read with this driver due to an incompatibility of the floppy
-+        controller used in an Amiga and the standard floppy controller in
-+        PCs and workstations. Read <file:Documentation/filesystems/affs.txt>
-+        and <file:fs/affs/Changes>.
-+
-+        With this driver you can also mount disk files used by Bernd
-+        Schmidt's Un*X Amiga Emulator
-+        (<http://www.freiburg.linux.de/~uae/>).
-+        If you want to do this, you will also need to say Y or M to "Loop
-+        device support", above.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called affs.  If unsure, say N.
-+
-+config ECRYPT_FS
-+      tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
-+      depends on EXPERIMENTAL && KEYS && CRYPTO && NET
-+      help
-+        Encrypted filesystem that operates on the VFS layer.  See
-+        <file:Documentation/filesystems/ecryptfs.txt> to learn more about
-+        eCryptfs.  Userspace components are required and can be
-+        obtained from <http://ecryptfs.sf.net>.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called ecryptfs.
-+
-+config HFS_FS
-+      tristate "Apple Macintosh file system support (EXPERIMENTAL)"
-+      depends on BLOCK && EXPERIMENTAL
-+      select NLS
-+      help
-+        If you say Y here, you will be able to mount Macintosh-formatted
-+        floppy disks and hard drive partitions with full read-write access.
-+        Please read <file:Documentation/filesystems/hfs.txt> to learn about
-+        the available mount options.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called hfs.
-+
-+config HFSPLUS_FS
-+      tristate "Apple Extended HFS file system support"
-+      depends on BLOCK
-+      select NLS
-+      select NLS_UTF8
-+      help
-+        If you say Y here, you will be able to mount extended format
-+        Macintosh-formatted hard drive partitions with full read-write access.
-+
-+        This file system is often called HFS+ and was introduced with
-+        MacOS 8. It includes all Mac specific filesystem data such as
-+        data forks and creator codes, but it also has several UNIX
-+        style features such as file ownership and permissions.
-+
-+config BEFS_FS
-+      tristate "BeOS file system (BeFS) support (read only) (EXPERIMENTAL)"
-+      depends on BLOCK && EXPERIMENTAL
-+      select NLS
-+      help
-+        The BeOS File System (BeFS) is the native file system of Be, Inc's
-+        BeOS. Notable features include support for arbitrary attributes
-+        on files and directories, and database-like indices on selected
-+        attributes. (Also note that this driver doesn't make those features
-+        available at this time). It is a 64 bit filesystem, so it supports
-+        extremely large volumes and files.
-+
-+        If you use this filesystem, you should also say Y to at least one
-+        of the NLS (native language support) options below.
-+
-+        If you don't know what this is about, say N.
-+
-+        To compile this as a module, choose M here: the module will be
-+        called befs.
-+
-+config BEFS_DEBUG
-+      bool "Debug BeFS"
-+      depends on BEFS_FS
-+      help
-+        If you say Y here, you can use the 'debug' mount option to enable
-+        debugging output from the driver.
-+
-+config BFS_FS
-+      tristate "BFS file system support (EXPERIMENTAL)"
-+      depends on BLOCK && EXPERIMENTAL
-+      help
-+        Boot File System (BFS) is a file system used under SCO UnixWare to
-+        allow the bootloader access to the kernel image and other important
-+        files during the boot process.  It is usually mounted under /stand
-+        and corresponds to the slice marked as "STAND" in the UnixWare
-+        partition.  You should say Y if you want to read or write the files
-+        on your /stand slice from within Linux.  You then also need to say Y
-+        to "UnixWare slices support", below.  More information about the BFS
-+        file system is contained in the file
-+        <file:Documentation/filesystems/bfs.txt>.
-+
-+        If you don't know what this is about, say N.
-+
-+        To compile this as a module, choose M here: the module will be called
-+        bfs.  Note that the file system of your root partition (the one
-+        containing the directory /) cannot be compiled as a module.
-+
-+
-+
-+config EFS_FS
-+      tristate "EFS file system support (read only) (EXPERIMENTAL)"
-+      depends on BLOCK && EXPERIMENTAL
-+      help
-+        EFS is an older file system used for non-ISO9660 CD-ROMs and hard
-+        disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer
-+        uses the XFS file system for hard disk partitions however).
-+
-+        This implementation only offers read-only access. If you don't know
-+        what all this is about, it's safe to say N. For more information
-+        about EFS see its home page at <http://aeschi.ch.eu.org/efs/>.
-+
-+        To compile the EFS file system support as a module, choose M here: the
-+        module will be called efs.
-+
-+config JFFS2_FS
-+      tristate "Journalling Flash File System v2 (JFFS2) support"
-+      select CRC32
-+      depends on MTD
-+      help
-+        JFFS2 is the second generation of the Journalling Flash File System
-+        for use on diskless embedded devices. It provides improved wear
-+        levelling, compression and support for hard links. You cannot use
-+        this on normal block devices, only on 'MTD' devices.
-+
-+        Further information on the design and implementation of JFFS2 is
-+        available at <http://sources.redhat.com/jffs2/>.
-+
-+config JFFS2_FS_DEBUG
-+      int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)"
-+      depends on JFFS2_FS
-+      default "0"
-+      help
-+        This controls the amount of debugging messages produced by the JFFS2
-+        code. Set it to zero for use in production systems. For evaluation,
-+        testing and debugging, it's advisable to set it to one. This will
-+        enable a few assertions and will print debugging messages at the
-+        KERN_DEBUG loglevel, where they won't normally be visible. Level 2
-+        is unlikely to be useful - it enables extra debugging in certain
-+        areas which at one point needed debugging, but when the bugs were
-+        located and fixed, the detailed messages were relegated to level 2.
-+
-+        If reporting bugs, please try to have available a full dump of the
-+        messages at debug level 1 while the misbehaviour was occurring.
-+
-+config JFFS2_FS_WRITEBUFFER
-+      bool "JFFS2 write-buffering support"
-+      depends on JFFS2_FS
-+      default y
-+      help
-+        This enables the write-buffering support in JFFS2.
-+
-+        This functionality is required to support JFFS2 on the following
-+        types of flash devices:
-+          - NAND flash
-+          - NOR flash with transparent ECC
-+          - DataFlash
-+
-+config JFFS2_FS_WBUF_VERIFY
-+      bool "Verify JFFS2 write-buffer reads"
-+      depends on JFFS2_FS_WRITEBUFFER
-+      default n
-+      help
-+        This causes JFFS2 to read back every page written through the
-+        write-buffer, and check for errors.
-+
-+config JFFS2_SUMMARY
-+      bool "JFFS2 summary support (EXPERIMENTAL)"
-+      depends on JFFS2_FS && EXPERIMENTAL
-+      default n
-+      help
-+        This feature makes it possible to use summary information
-+        for faster filesystem mount.
-+
-+        The summary information can be inserted into a filesystem image
-+        by the utility 'sumtool'.
-+
-+        If unsure, say 'N'.
-+
-+config JFFS2_FS_XATTR
-+      bool "JFFS2 XATTR support (EXPERIMENTAL)"
-+      depends on JFFS2_FS && EXPERIMENTAL
-+      default n
-+      help
-+        Extended attributes are name:value pairs associated with inodes by
-+        the kernel or by users (see the attr(5) manual page, or visit
-+        <http://acl.bestbits.at/> for details).
-+
-+        If unsure, say N.
-+
-+config JFFS2_FS_POSIX_ACL
-+      bool "JFFS2 POSIX Access Control Lists"
-+      depends on JFFS2_FS_XATTR
-+      default y
-+      select FS_POSIX_ACL
-+      help
-+        Posix Access Control Lists (ACLs) support permissions for users and
-+        groups beyond the owner/group/world scheme.
-+
-+        To learn more about Access Control Lists, visit the Posix ACLs for
-+        Linux website <http://acl.bestbits.at/>.
-+
-+        If you don't know what Access Control Lists are, say N
-+
-+config JFFS2_FS_SECURITY
-+      bool "JFFS2 Security Labels"
-+      depends on JFFS2_FS_XATTR
-+      default y
-+      help
-+        Security labels support alternative access control models
-+        implemented by security modules like SELinux.  This option
-+        enables an extended attribute handler for file security
-+        labels in the jffs2 filesystem.
-+
-+        If you are not using a security module that requires using
-+        extended attributes for file security labels, say N.
-+
-+config JFFS2_COMPRESSION_OPTIONS
-+      bool "Advanced compression options for JFFS2"
-+      depends on JFFS2_FS
-+      default n
-+      help
-+        Enabling this option allows you to explicitly choose which
-+        compression modules, if any, are enabled in JFFS2. Removing
-+        compressors can mean you cannot read existing file systems,
-+        and enabling experimental compressors can mean that you
-+        write a file system which cannot be read by a standard kernel.
-+
-+        If unsure, you should _definitely_ say 'N'.
-+
-+config JFFS2_ZLIB
-+      bool "JFFS2 ZLIB compression support" if JFFS2_COMPRESSION_OPTIONS
-+      select ZLIB_INFLATE
-+      select ZLIB_DEFLATE
-+      depends on JFFS2_FS
-+      default y
-+      help
-+        Zlib is designed to be a free, general-purpose, legally unencumbered,
-+        lossless data-compression library for use on virtually any computer
-+        hardware and operating system. See <http://www.gzip.org/zlib/> for
-+        further information.
-+
-+        Say 'Y' if unsure.
-+
-+config JFFS2_LZO
-+      bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS
-+      select LZO_COMPRESS
-+      select LZO_DECOMPRESS
-+      depends on JFFS2_FS
-+      default n
-+      help
-+        minilzo-based compression. Generally works better than Zlib.
-+
-+        This feature was added in July, 2007. Say 'N' if you need
-+        compatibility with older bootloaders or kernels.
-+
-+config JFFS2_RTIME
-+      bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
-+      depends on JFFS2_FS
-+      default y
-+      help
-+        Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
-+
-+config JFFS2_RUBIN
-+      bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
-+      depends on JFFS2_FS
-+      default n
-+      help
-+        RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
-+
-+choice
-+      prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
-+      default JFFS2_CMODE_PRIORITY
-+      depends on JFFS2_FS
-+      help
-+        You can set here the default compression mode of JFFS2 from
-+        the available compression modes. Don't touch if unsure.
-+
-+config JFFS2_CMODE_NONE
-+      bool "no compression"
-+      help
-+        Uses no compression.
-+
-+config JFFS2_CMODE_PRIORITY
-+      bool "priority"
-+      help
-+        Tries the compressors in a predefined order and chooses the first
-+        successful one.
-+
-+config JFFS2_CMODE_SIZE
-+      bool "size (EXPERIMENTAL)"
-+      help
-+        Tries all compressors and chooses the one which has the smallest
-+        result.
-+
-+config JFFS2_CMODE_FAVOURLZO
-+      bool "Favour LZO"
-+      help
-+        Tries all compressors and chooses the one which has the smallest
-+        result but gives some preference to LZO (which has faster
-+        decompression) at the expense of size.
-+
-+endchoice
-+
-+# UBIFS File system configuration
-+source "fs/ubifs/Kconfig"
-+
-+config CRAMFS
-+      tristate "Compressed ROM file system support (cramfs)"
-+      depends on BLOCK
-+      select ZLIB_INFLATE
-+      help
-+        Saying Y here includes support for CramFs (Compressed ROM File
-+        System).  CramFs is designed to be a simple, small, and compressed
-+        file system for ROM based embedded systems.  CramFs is read-only,
-+        limited to 256MB file systems (with 16MB files), and doesn't support
-+        16/32 bits uid/gid, hard links and timestamps.
-+
-+        See <file:Documentation/filesystems/cramfs.txt> and
-+        <file:fs/cramfs/README> for further information.
-+
-+        To compile this as a module, choose M here: the module will be called
-+        cramfs.  Note that the root file system (the one containing the
-+        directory /) cannot be compiled as a module.
-+
-+        If unsure, say N.
-+
-+config VXFS_FS
-+      tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
-+      depends on BLOCK
-+      help
-+        FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
-+        file system format.  VERITAS VxFS(TM) is the standard file system
-+        of SCO UnixWare (and possibly others) and optionally available
-+        for Sunsoft Solaris, HP-UX and many other operating systems.
-+        Currently only readonly access is supported.
-+
-+        NOTE: the file system type as used by mount(1), mount(2) and
-+        fstab(5) is 'vxfs' as it describes the file system format, not
-+        the actual driver.
-+
-+        To compile this as a module, choose M here: the module will be
-+        called freevxfs.  If unsure, say N.
-+
-+config MINIX_FS
-+      tristate "Minix file system support"
-+      depends on BLOCK
-+      help
-+        Minix is a simple operating system used in many classes about OS's.
-+        The minix file system (method to organize files on a hard disk
-+        partition or a floppy disk) was the original file system for Linux,
-+        but has been superseded by the second extended file system ext2fs.
-+        You don't want to use the minix file system on your hard disk
-+        because of certain built-in restrictions, but it is sometimes found
-+        on older Linux floppy disks.  This option will enlarge your kernel
-+        by about 28 KB. If unsure, say N.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called minix.  Note that the file system of your root
-+        partition (the one containing the directory /) cannot be compiled as
-+        a module.
-+
-+config OMFS_FS
-+      tristate "SonicBlue Optimized MPEG File System support"
-+      depends on BLOCK
-+      select CRC_ITU_T
-+      help
-+        This is the proprietary file system used by the Rio Karma music
-+        player and ReplayTV DVR.  Despite the name, this filesystem is not
-+        more efficient than a standard FS for MPEG files, in fact likely
-+        the opposite is true.  Say Y if you have either of these devices
-+        and wish to mount its disk.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called omfs.  If unsure, say N.
-+
-+config HPFS_FS
-+      tristate "OS/2 HPFS file system support"
-+      depends on BLOCK
-+      help
-+        OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
-+        is the file system used for organizing files on OS/2 hard disk
-+        partitions. Say Y if you want to be able to read files from and
-+        write files to an OS/2 HPFS partition on your hard drive. OS/2
-+        floppies however are in regular MSDOS format, so you don't need this
-+        option in order to be able to read them. Read
-+        <file:Documentation/filesystems/hpfs.txt>.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called hpfs.  If unsure, say N.
-+
-+
-+config QNX4FS_FS
-+      tristate "QNX4 file system support (read only)"
-+      depends on BLOCK
-+      help
-+        This is the file system used by the real-time operating systems
-+        QNX 4 and QNX 6 (the latter is also called QNX RTP).
-+        Further information is available at <http://www.qnx.com/>.
-+        Say Y if you intend to mount QNX hard disks or floppies.
-+        Unless you say Y to "QNX4FS read-write support" below, you will
-+        only be able to read these file systems.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called qnx4.
-+
-+        If you don't know whether you need it, then you don't need it:
-+        answer N.
-+
-+config QNX4FS_RW
-+      bool "QNX4FS write support (DANGEROUS)"
-+      depends on QNX4FS_FS && EXPERIMENTAL && BROKEN
-+      help
-+        Say Y if you want to test write support for QNX4 file systems.
-+
-+        It's currently broken, so for now:
-+        answer N.
-+
-+config ROMFS_FS
-+      tristate "ROM file system support"
-+      depends on BLOCK
-+      ---help---
-+        This is a very small read-only file system mainly intended for
-+        initial ram disks of installation disks, but it could be used for
-+        other read-only media as well.  Read
-+        <file:Documentation/filesystems/romfs.txt> for details.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called romfs.  Note that the file system of your
-+        root partition (the one containing the directory /) cannot be a
-+        module.
-+
-+        If you don't know whether you need it, then you don't need it:
-+        answer N.
-+
-+
-+config SYSV_FS
-+      tristate "System V/Xenix/V7/Coherent file system support"
-+      depends on BLOCK
-+      help
-+        SCO, Xenix and Coherent are commercial Unix systems for Intel
-+        machines, and Version 7 was used on the DEC PDP-11. Saying Y
-+        here would allow you to read from their floppies and hard disk
-+        partitions.
-+
-+        If you have floppies or hard disk partitions like that, it is likely
-+        that they contain binaries from those other Unix systems; in order
-+        to run these binaries, you will want to install linux-abi which is
-+        a set of kernel modules that lets you run SCO, Xenix, Wyse,
-+        UnixWare, Dell Unix and System V programs under Linux.  It is
-+        available via FTP (user: ftp) from
-+        <ftp://ftp.openlinux.org/pub/people/hch/linux-abi/>).
-+        NOTE: that will work only for binaries from Intel-based systems;
-+        PDP ones will have to wait until somebody ports Linux to -11 ;-)
-+
-+        If you only intend to mount files from some other Unix over the
-+        network using NFS, you don't need the System V file system support
-+        (but you need NFS file system support obviously).
-+
-+        Note that this option is generally not needed for floppies, since a
-+        good portable way to transport files and directories between unixes
-+        (and even other operating systems) is given by the tar program ("man
-+        tar" or preferably "info tar").  Note also that this option has
-+        nothing whatsoever to do with the option "System V IPC". Read about
-+        the System V file system in
-+        <file:Documentation/filesystems/sysv-fs.txt>.
-+        Saying Y here will enlarge your kernel by about 27 KB.
-+
-+        To compile this as a module, choose M here: the module will be called
-+        sysv.
-+
-+        If you haven't heard about all of this before, it's safe to say N.
-+
-+
-+config UFS_FS
-+      tristate "UFS file system support (read only)"
-+      depends on BLOCK
-+      help
-+        BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
-+        OpenBSD and NeXTstep) use a file system called UFS. Some System V
-+        Unixes can create and mount hard disk partitions and diskettes using
-+        this file system as well. Saying Y here will allow you to read from
-+        these partitions; if you also want to write to them, say Y to the
-+        experimental "UFS file system write support", below. Please read the
-+        file <file:Documentation/filesystems/ufs.txt> for more information.
-+
-+          The recently released UFS2 variant (used in FreeBSD 5.x) is
-+          READ-ONLY supported.
-+
-+        Note that this option is generally not needed for floppies, since a
-+        good portable way to transport files and directories between unixes
-+        (and even other operating systems) is given by the tar program ("man
-+        tar" or preferably "info tar").
-+
-+        When accessing NeXTstep files, you may need to convert them from the
-+        NeXT character set to the Latin1 character set; use the program
-+        recode ("info recode") for this purpose.
-+
-+        To compile the UFS file system support as a module, choose M here: the
-+        module will be called ufs.
-+
-+        If you haven't heard about all of this before, it's safe to say N.
-+
-+config UFS_FS_WRITE
-+      bool "UFS file system write support (DANGEROUS)"
-+      depends on UFS_FS && EXPERIMENTAL
-+      help
-+        Say Y here if you want to try writing to UFS partitions. This is
-+        experimental, so you should back up your UFS partitions beforehand.
-+
-+config UFS_DEBUG
-+      bool "UFS debugging"
-+      depends on UFS_FS
-+      help
-+        If you are experiencing any problems with the UFS filesystem, say
-+        Y here.  This will result in _many_ additional debugging messages to be
-+        written to the system log.
-+
-+endmenu
-+
-+menuconfig NETWORK_FILESYSTEMS
-+      bool "Network File Systems"
-+      default y
-+      depends on NET
-+      ---help---
-+        Say Y here to get to see options for network filesystems and
-+        filesystem-related networking code, such as NFS daemon and
-+        RPCSEC security modules.
-+
-+        This option alone does not add any kernel code.
-+
-+        If you say N, all options in this submenu will be skipped and
-+        disabled; if unsure, say Y here.
-+
-+if NETWORK_FILESYSTEMS
-+
-+config NFS_FS
-+      tristate "NFS client support"
-+      depends on INET
-+      select LOCKD
-+      select SUNRPC
-+      select NFS_ACL_SUPPORT if NFS_V3_ACL
-+      help
-+        Choose Y here if you want to access files residing on other
-+        computers using Sun's Network File System protocol.  To compile
-+        this file system support as a module, choose M here: the module
-+        will be called nfs.
-+
-+        To mount file systems exported by NFS servers, you also need to
-+        install the user space mount.nfs command which can be found in
-+        the Linux nfs-utils package, available from http://linux-nfs.org/.
-+        Information about using the mount command is available in the
-+        mount(8) man page.  More detail about the Linux NFS client
-+        implementation is available via the nfs(5) man page.
-+
-+        Below you can choose which versions of the NFS protocol are
-+        available in the kernel to mount NFS servers.  Support for NFS
-+        version 2 (RFC 1094) is always available when NFS_FS is selected.
-+
-+        To configure a system which mounts its root file system via NFS
-+        at boot time, say Y here, select "Kernel level IP
-+        autoconfiguration" in the NETWORK menu, and select "Root file
-+        system on NFS" below.  You cannot compile this file system as a
-+        module in this case.
-+
-+        If unsure, say N.
-+
-+config NFS_V3
-+      bool "NFS client support for NFS version 3"
-+      depends on NFS_FS
-+      help
-+        This option enables support for version 3 of the NFS protocol
-+        (RFC 1813) in the kernel's NFS client.
-+
-+        If unsure, say Y.
-+
-+config NFS_V3_ACL
-+      bool "NFS client support for the NFSv3 ACL protocol extension"
-+      depends on NFS_V3
-+      help
-+        Some NFS servers support an auxiliary NFSv3 ACL protocol that
-+        Sun added to Solaris but never became an official part of the
-+        NFS version 3 protocol.  This protocol extension allows
-+        applications on NFS clients to manipulate POSIX Access Control
-+        Lists on files residing on NFS servers.  NFS servers enforce
-+        ACLs on local files whether this protocol is available or not.
-+
-+        Choose Y here if your NFS server supports the Solaris NFSv3 ACL
-+        protocol extension and you want your NFS client to allow
-+        applications to access and modify ACLs on files on the server.
-+
-+        Most NFS servers don't support the Solaris NFSv3 ACL protocol
-+        extension.  You can choose N here or specify the "noacl" mount
-+        option to prevent your NFS client from trying to use the NFSv3
-+        ACL protocol.
-+
-+        If unsure, say N.
-+
-+config NFS_V4
-+      bool "NFS client support for NFS version 4 (EXPERIMENTAL)"
-+      depends on NFS_FS && EXPERIMENTAL
-+      select RPCSEC_GSS_KRB5
-+      help
-+        This option enables support for version 4 of the NFS protocol
-+        (RFC 3530) in the kernel's NFS client.
-+
-+        To mount NFS servers using NFSv4, you also need to install user
-+        space programs which can be found in the Linux nfs-utils package,
-+        available from http://linux-nfs.org/.
-+
-+        If unsure, say N.
-+
-+config ROOT_NFS
-+      bool "Root file system on NFS"
-+      depends on NFS_FS=y && IP_PNP
-+      help
-+        If you want your system to mount its root file system via NFS,
-+        choose Y here.  This is common practice for managing systems
-+        without local permanent storage.  For details, read
-+        <file:Documentation/filesystems/nfsroot.txt>.
-+
-+        Most people say N here.
-+
-+config NFSD
-+      tristate "NFS server support"
-+      depends on INET
-+      select LOCKD
-+      select SUNRPC
-+      select EXPORTFS
-+      select NFS_ACL_SUPPORT if NFSD_V2_ACL
-+      help
-+        Choose Y here if you want to allow other computers to access
-+        files residing on this system using Sun's Network File System
-+        protocol.  To compile the NFS server support as a module,
-+        choose M here: the module will be called nfsd.
-+
-+        You may choose to use a user-space NFS server instead, in which
-+        case you can choose N here.
-+
-+        To export local file systems using NFS, you also need to install
-+        user space programs which can be found in the Linux nfs-utils
-+        package, available from http://linux-nfs.org/.  More detail about
-+        the Linux NFS server implementation is available via the
-+        exports(5) man page.
-+
-+        Below you can choose which versions of the NFS protocol are
-+        available to clients mounting the NFS server on this system.
-+        Support for NFS version 2 (RFC 1094) is always available when
-+        CONFIG_NFSD is selected.
-+
-+        If unsure, say N.
-+
-+config NFSD_V2_ACL
-+      bool
-+      depends on NFSD
-+
-+config NFSD_V3
-+      bool "NFS server support for NFS version 3"
-+      depends on NFSD
-+      help
-+        This option enables support in your system's NFS server for
-+        version 3 of the NFS protocol (RFC 1813).
-+
-+        If unsure, say Y.
-+
-+config NFSD_V3_ACL
-+      bool "NFS server support for the NFSv3 ACL protocol extension"
-+      depends on NFSD_V3
-+      select NFSD_V2_ACL
-+      help
-+        Solaris NFS servers support an auxiliary NFSv3 ACL protocol that
-+        never became an official part of the NFS version 3 protocol.
-+        This protocol extension allows applications on NFS clients to
-+        manipulate POSIX Access Control Lists on files residing on NFS
-+        servers.  NFS servers enforce POSIX ACLs on local files whether
-+        this protocol is available or not.
-+
-+        This option enables support in your system's NFS server for the
-+        NFSv3 ACL protocol extension allowing NFS clients to manipulate
-+        POSIX ACLs on files exported by your system's NFS server.  NFS
-+        clients which support the Solaris NFSv3 ACL protocol can then
-+        access and modify ACLs on your NFS server.
-+
-+        To store ACLs on your NFS server, you also need to enable ACL-
-+        related CONFIG options for your local file systems of choice.
-+
-+        If unsure, say N.
-+
-+config NFSD_V4
-+      bool "NFS server support for NFS version 4 (EXPERIMENTAL)"
-+      depends on NFSD && PROC_FS && EXPERIMENTAL
-+      select NFSD_V3
-+      select FS_POSIX_ACL
-+      select RPCSEC_GSS_KRB5
-+      help
-+        This option enables support in your system's NFS server for
-+        version 4 of the NFS protocol (RFC 3530).
-+
-+        To export files using NFSv4, you need to install additional user
-+        space programs which can be found in the Linux nfs-utils package,
-+        available from http://linux-nfs.org/.
-+
-+        If unsure, say N.
-+
-+config LOCKD
-+      tristate
-+
-+config LOCKD_V4
-+      bool
-+      depends on NFSD_V3 || NFS_V3
-+      default y
-+
-+config EXPORTFS
-+      tristate
-+
-+config NFS_ACL_SUPPORT
-+      tristate
-+      select FS_POSIX_ACL
-+
-+config NFS_COMMON
-+      bool
-+      depends on NFSD || NFS_FS
-+      default y
-+
-+config SUNRPC
-+      tristate
-+
-+config SUNRPC_GSS
-+      tristate
-+
-+config SUNRPC_XPRT_RDMA
-+      tristate
-+      depends on SUNRPC && INFINIBAND && EXPERIMENTAL
-+      default SUNRPC && INFINIBAND
-+      help
-+        This option enables an RPC client transport capability that
-+        allows the NFS client to mount servers via an RDMA-enabled
-+        transport.
-+
-+        To compile RPC client RDMA transport support as a module,
-+        choose M here: the module will be called xprtrdma.
-+
-+        If unsure, say N.
-+
-+config RPCSEC_GSS_KRB5
-+      tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)"
-+      depends on SUNRPC && EXPERIMENTAL
-+      select SUNRPC_GSS
-+      select CRYPTO
-+      select CRYPTO_MD5
-+      select CRYPTO_DES
-+      select CRYPTO_CBC
-+      help
-+        Choose Y here to enable Secure RPC using the Kerberos version 5
-+        GSS-API mechanism (RFC 1964).
-+
-+        Secure RPC calls with Kerberos require an auxiliary user-space
-+        daemon which may be found in the Linux nfs-utils package
-+        available from http://linux-nfs.org/.  In addition, user-space
-+        Kerberos support should be installed.
-+
-+        If unsure, say N.
-+
-+config RPCSEC_GSS_SPKM3
-+      tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)"
-+      depends on SUNRPC && EXPERIMENTAL
-+      select SUNRPC_GSS
-+      select CRYPTO
-+      select CRYPTO_MD5
-+      select CRYPTO_DES
-+      select CRYPTO_CAST5
-+      select CRYPTO_CBC
-+      help
-+        Choose Y here to enable Secure RPC using the SPKM3 public key
-+        GSS-API mechansim (RFC 2025).
-+
-+        Secure RPC calls with SPKM3 require an auxiliary userspace
-+        daemon which may be found in the Linux nfs-utils package
-+        available from http://linux-nfs.org/.
-+
-+        If unsure, say N.
-+
-+config SMB_FS
-+      tristate "SMB file system support (OBSOLETE, please use CIFS)"
-+      depends on INET
-+      select NLS
-+      help
-+        SMB (Server Message Block) is the protocol Windows for Workgroups
-+        (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share
-+        files and printers over local networks.  Saying Y here allows you to
-+        mount their file systems (often called "shares" in this context) and
-+        access them just like any other Unix directory.  Currently, this
-+        works only if the Windows machines use TCP/IP as the underlying
-+        transport protocol, and not NetBEUI.  For details, read
-+        <file:Documentation/filesystems/smbfs.txt> and the SMB-HOWTO,
-+        available from <http://www.tldp.org/docs.html#howto>.
-+
-+        Note: if you just want your box to act as an SMB *server* and make
-+        files and printing services available to Windows clients (which need
-+        to have a TCP/IP stack), you don't need to say Y here; you can use
-+        the program SAMBA (available from <ftp://ftp.samba.org/pub/samba/>)
-+        for that.
-+
-+        General information about how to connect Linux, Windows machines and
-+        Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
-+
-+        To compile the SMB support as a module, choose M here:
-+        the module will be called smbfs.  Most people say N, however.
-+
-+config SMB_NLS_DEFAULT
-+      bool "Use a default NLS"
-+      depends on SMB_FS
-+      help
-+        Enabling this will make smbfs use nls translations by default. You
-+        need to specify the local charset (CONFIG_NLS_DEFAULT) in the nls
-+        settings and you need to give the default nls for the SMB server as
-+        CONFIG_SMB_NLS_REMOTE.
-+
-+        The nls settings can be changed at mount time, if your smbmount
-+        supports that, using the codepage and iocharset parameters.
-+
-+        smbmount from samba 2.2.0 or later supports this.
-+
-+config SMB_NLS_REMOTE
-+      string "Default Remote NLS Option"
-+      depends on SMB_NLS_DEFAULT
-+      default "cp437"
-+      help
-+        This setting allows you to specify a default value for which
-+        codepage the server uses. If this field is left blank no
-+        translations will be done by default. The local codepage/charset
-+        default to CONFIG_NLS_DEFAULT.
-+
-+        The nls settings can be changed at mount time, if your smbmount
-+        supports that, using the codepage and iocharset parameters.
-+
-+        smbmount from samba 2.2.0 or later supports this.
-+
-+config CIFS
-+      tristate "CIFS support (advanced network filesystem, SMBFS successor)"
-+      depends on INET
-+      select NLS
-+      help
-+        This is the client VFS module for the Common Internet File System
-+        (CIFS) protocol which is the successor to the Server Message Block 
-+        (SMB) protocol, the native file sharing mechanism for most early
-+        PC operating systems.  The CIFS protocol is fully supported by 
-+        file servers such as Windows 2000 (including Windows 2003, NT 4  
-+        and Windows XP) as well by Samba (which provides excellent CIFS
-+        server support for Linux and many other operating systems). Limited
-+        support for OS/2 and Windows ME and similar servers is provided as
-+        well.
-+
-+        The cifs module provides an advanced network file system
-+        client for mounting to CIFS compliant servers.  It includes
-+        support for DFS (hierarchical name space), secure per-user
-+        session establishment via Kerberos or NTLM or NTLMv2,
-+        safe distributed caching (oplock), optional packet
-+        signing, Unicode and other internationalization improvements.
-+        If you need to mount to Samba or Windows from this machine, say Y.
-+
-+config CIFS_STATS
-+        bool "CIFS statistics"
-+        depends on CIFS
-+        help
-+          Enabling this option will cause statistics for each server share
-+        mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
-+
-+config CIFS_STATS2
-+      bool "Extended statistics"
-+      depends on CIFS_STATS
-+      help
-+        Enabling this option will allow more detailed statistics on SMB
-+        request timing to be displayed in /proc/fs/cifs/DebugData and also
-+        allow optional logging of slow responses to dmesg (depending on the
-+        value of /proc/fs/cifs/cifsFYI, see fs/cifs/README for more details).
-+        These additional statistics may have a minor effect on performance
-+        and memory utilization.
-+
-+        Unless you are a developer or are doing network performance analysis
-+        or tuning, say N.
-+
-+config CIFS_WEAK_PW_HASH
-+      bool "Support legacy servers which use weaker LANMAN security"
-+      depends on CIFS
-+      help
-+        Modern CIFS servers including Samba and most Windows versions
-+        (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
-+        security mechanisms. These hash the password more securely
-+        than the mechanisms used in the older LANMAN version of the
-+        SMB protocol but LANMAN based authentication is needed to
-+        establish sessions with some old SMB servers.
-+
-+        Enabling this option allows the cifs module to mount to older
-+        LANMAN based servers such as OS/2 and Windows 95, but such
-+        mounts may be less secure than mounts using NTLM or more recent
-+        security mechanisms if you are on a public network.  Unless you
-+        have a need to access old SMB servers (and are on a private
-+        network) you probably want to say N.  Even if this support
-+        is enabled in the kernel build, LANMAN authentication will not be
-+        used automatically. At runtime LANMAN mounts are disabled but
-+        can be set to required (or optional) either in
-+        /proc/fs/cifs (see fs/cifs/README for more detail) or via an
-+        option on the mount command. This support is disabled by
-+        default in order to reduce the possibility of a downgrade
-+        attack.
-+
-+        If unsure, say N.
-+
-+config CIFS_XATTR
-+        bool "CIFS extended attributes"
-+        depends on CIFS
-+        help
-+          Extended attributes are name:value pairs associated with inodes by
-+          the kernel or by users (see the attr(5) manual page, or visit
-+          <http://acl.bestbits.at/> for details).  CIFS maps the name of
-+          extended attributes beginning with the user namespace prefix
-+          to SMB/CIFS EAs. EAs are stored on Windows servers without the
-+          user namespace prefix, but their names are seen by Linux cifs clients
-+          prefaced by the user namespace prefix. The system namespace
-+          (used by some filesystems to store ACLs) is not supported at
-+          this time.
-+
-+          If unsure, say N.
-+
-+config CIFS_POSIX
-+        bool "CIFS POSIX Extensions"
-+        depends on CIFS_XATTR
-+        help
-+          Enabling this option will cause the cifs client to attempt to
-+        negotiate a newer dialect with servers, such as Samba 3.0.5
-+        or later, that optionally can handle more POSIX like (rather
-+        than Windows like) file behavior.  It also enables
-+        support for POSIX ACLs (getfacl and setfacl) to servers
-+        (such as Samba 3.10 and later) which can negotiate
-+        CIFS POSIX ACL support.  If unsure, say N.
-+
-+config CIFS_DEBUG2
-+      bool "Enable additional CIFS debugging routines"
-+      depends on CIFS
-+      help
-+         Enabling this option adds a few more debugging routines
-+         to the cifs code which slightly increases the size of
-+         the cifs module and can cause additional logging of debug
-+         messages in some error paths, slowing performance. This
-+         option can be turned off unless you are debugging
-+         cifs problems.  If unsure, say N.
-+
-+config CIFS_EXPERIMENTAL
-+        bool "CIFS Experimental Features (EXPERIMENTAL)"
-+        depends on CIFS && EXPERIMENTAL
-+        help
-+          Enables cifs features under testing. These features are
-+          experimental and currently include DFS support and directory 
-+          change notification ie fcntl(F_DNOTIFY), as well as the upcall
-+          mechanism which will be used for Kerberos session negotiation
-+          and uid remapping.  Some of these features also may depend on 
-+          setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental
-+          (which is disabled by default). See the file fs/cifs/README 
-+          for more details.  If unsure, say N.
-+
-+config CIFS_UPCALL
-+        bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
-+        depends on CIFS_EXPERIMENTAL
-+        depends on KEYS
-+        help
-+          Enables an upcall mechanism for CIFS which accesses
-+          userspace helper utilities to provide SPNEGO packaged (RFC 4178)
-+          Kerberos tickets which are needed to mount to certain secure servers
-+          (for which more secure Kerberos authentication is required). If
-+          unsure, say N.
-+
-+config CIFS_DFS_UPCALL
-+        bool "DFS feature support (EXPERIMENTAL)"
-+        depends on CIFS_EXPERIMENTAL
-+        depends on KEYS
-+        help
-+          Enables an upcall mechanism for CIFS which contacts userspace
-+          helper utilities to provide server name resolution (host names to
-+          IP addresses) which is needed for implicit mounts of DFS junction
-+          points. If unsure, say N.
-+
-+config NCP_FS
-+      tristate "NCP file system support (to mount NetWare volumes)"
-+      depends on IPX!=n || INET
-+      help
-+        NCP (NetWare Core Protocol) is a protocol that runs over IPX and is
-+        used by Novell NetWare clients to talk to file servers.  It is to
-+        IPX what NFS is to TCP/IP, if that helps.  Saying Y here allows you
-+        to mount NetWare file server volumes and to access them just like
-+        any other Unix directory.  For details, please read the file
-+        <file:Documentation/filesystems/ncpfs.txt> in the kernel source and
-+        the IPX-HOWTO from <http://www.tldp.org/docs.html#howto>.
-+
-+        You do not have to say Y here if you want your Linux box to act as a
-+        file *server* for Novell NetWare clients.
-+
-+        General information about how to connect Linux, Windows machines and
-+        Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
-+
-+        To compile this as a module, choose M here: the module will be called
-+        ncpfs.  Say N unless you are connected to a Novell network.
-+
-+source "fs/ncpfs/Kconfig"
-+
-+config CODA_FS
-+      tristate "Coda file system support (advanced network fs)"
-+      depends on INET
-+      help
-+        Coda is an advanced network file system, similar to NFS in that it
-+        enables you to mount file systems of a remote server and access them
-+        with regular Unix commands as if they were sitting on your hard
-+        disk.  Coda has several advantages over NFS: support for
-+        disconnected operation (e.g. for laptops), read/write server
-+        replication, security model for authentication and encryption,
-+        persistent client caches and write back caching.
-+
-+        If you say Y here, your Linux box will be able to act as a Coda
-+        *client*.  You will need user level code as well, both for the
-+        client and server.  Servers are currently user level, i.e. they need
-+        no kernel support.  Please read
-+        <file:Documentation/filesystems/coda.txt> and check out the Coda
-+        home page <http://www.coda.cs.cmu.edu/>.
-+
-+        To compile the coda client support as a module, choose M here: the
-+        module will be called coda.
-+
-+config AFS_FS
-+      tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
-+      depends on INET && EXPERIMENTAL
-+      select AF_RXRPC
-+      help
-+        If you say Y here, you will get an experimental Andrew File System
-+        driver. It currently only supports unsecured read-only AFS access.
-+
-+        See <file:Documentation/filesystems/afs.txt> for more information.
-+
-+        If unsure, say N.
-+
-+config AFS_DEBUG
-+      bool "AFS dynamic debugging"
-+      depends on AFS_FS
-+      help
-+        Say Y here to make runtime controllable debugging messages appear.
-+
-+        See <file:Documentation/filesystems/afs.txt> for more information.
-+
-+        If unsure, say N.
-+
-+config 9P_FS
-+      tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
-+      depends on INET && NET_9P && EXPERIMENTAL
-+      help
-+        If you say Y here, you will get experimental support for
-+        Plan 9 resource sharing via the 9P2000 protocol.
-+
-+        See <http://v9fs.sf.net> for more information.
-+
-+        If unsure, say N.
-+
-+endif # NETWORK_FILESYSTEMS
-+
-+if BLOCK
-+menu "Partition Types"
-+
-+source "fs/partitions/Kconfig"
-+
-+endmenu
-+endif
-+
-+source "fs/nls/Kconfig"
-+source "fs/dlm/Kconfig"
-+
-+endmenu
-diff -uNr a/fs/Makefile b/fs/Makefile
---- a/fs/Makefile      2008-07-28 19:40:31.000000000 -0700
-+++ b/fs/Makefile      2008-08-13 16:18:09.000000000 -0700
-@@ -74,6 +74,7 @@
- obj-$(CONFIG_JBD2)            += jbd2/
- obj-$(CONFIG_EXT2_FS)         += ext2/
- obj-$(CONFIG_CRAMFS)          += cramfs/
-+obj-$(CONFIG_SQUASHFS)                += squashfs/
- obj-y                         += ramfs/
- obj-$(CONFIG_HUGETLBFS)               += hugetlbfs/
- obj-$(CONFIG_CODA_FS)         += coda/
-diff -uNr a/fs/squashfs/block.c b/fs/squashfs/block.c
---- a/fs/squashfs/block.c      1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/block.c      2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,314 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * block.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+static struct buffer_head *get_block_length(struct super_block *s,
-+                              int *cur_index, int *offset, int *c_byte)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      unsigned short temp;
-+      struct buffer_head *bh;
-+
-+      if (!(bh = sb_bread(s, *cur_index)))
-+              goto out;
-+
-+      if (msblk->devblksize - *offset == 1) {
-+              if (msblk->swap)
-+                      ((unsigned char *) &temp)[1] = *((unsigned char *)
-+                              (bh->b_data + *offset));
-+              else
-+                      ((unsigned char *) &temp)[0] = *((unsigned char *)
-+                              (bh->b_data + *offset));
-+              brelse(bh);
-+              if (!(bh = sb_bread(s, ++(*cur_index))))
-+                      goto out;
-+              if (msblk->swap)
-+                      ((unsigned char *) &temp)[0] = *((unsigned char *)
-+                              bh->b_data); 
-+              else
-+                      ((unsigned char *) &temp)[1] = *((unsigned char *)
-+                              bh->b_data); 
-+              *c_byte = temp;
-+              *offset = 1;
-+      } else {
-+              if (msblk->swap) {
-+                      ((unsigned char *) &temp)[1] = *((unsigned char *)
-+                              (bh->b_data + *offset));
-+                      ((unsigned char *) &temp)[0] = *((unsigned char *)
-+                              (bh->b_data + *offset + 1)); 
-+              } else {
-+                      ((unsigned char *) &temp)[0] = *((unsigned char *)
-+                              (bh->b_data + *offset));
-+                      ((unsigned char *) &temp)[1] = *((unsigned char *)
-+                              (bh->b_data + *offset + 1)); 
-+              }
-+              *c_byte = temp;
-+              *offset += 2;
-+      }
-+
-+      if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
-+              if (*offset == msblk->devblksize) {
-+                      brelse(bh);
-+                      if (!(bh = sb_bread(s, ++(*cur_index))))
-+                              goto out;
-+                      *offset = 0;
-+              }
-+              if (*((unsigned char *) (bh->b_data + *offset)) !=
-+                                              SQUASHFS_MARKER_BYTE) {
-+                      ERROR("Metadata block marker corrupt @ %x\n",
-+                                              *cur_index);
-+                      brelse(bh);
-+                      goto out;
-+              }
-+              (*offset)++;
-+      }
-+      return bh;
-+
-+out:
-+      return NULL;
-+}
-+
-+
-+unsigned int squashfs_read_data(struct super_block *s, char *buffer,
-+                      long long index, unsigned int length,
-+                      long long *next_index, int srclength)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      struct buffer_head **bh;
-+      unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
-+      unsigned int cur_index = index >> msblk->devblksize_log2;
-+      int bytes, avail_bytes, b = 0, k = 0;
-+      unsigned int compressed;
-+      unsigned int c_byte = length;
-+
-+      bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) *
-+                                                              sizeof(struct buffer_head *), GFP_KERNEL);
-+      if (bh == NULL)
-+              goto read_failure;
-+
-+      if (c_byte) {
-+              bytes = -offset;
-+              compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
-+              c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
-+
-+              TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index,
-+                                      compressed ? "" : "un", (unsigned int) c_byte, srclength);
-+
-+              if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)
-+                      goto read_failure;
-+
-+              for (b = 0; bytes < (int) c_byte; b++, cur_index++) {
-+                      bh[b] = sb_getblk(s, cur_index);
-+                      if (bh[b] == NULL)
-+                              goto block_release;
-+                      bytes += msblk->devblksize;
-+              }
-+              ll_rw_block(READ, b, bh);
-+      } else {
-+              if (index < 0 || (index + 2) > sblk->bytes_used)
-+                      goto read_failure;
-+
-+              bh[0] = get_block_length(s, &cur_index, &offset, &c_byte);
-+              if (bh[0] == NULL)
-+                      goto read_failure;
-+              b = 1;
-+
-+              bytes = msblk->devblksize - offset;
-+              compressed = SQUASHFS_COMPRESSED(c_byte);
-+              c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
-+
-+              TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
-+                                      ? "" : "un", (unsigned int) c_byte);
-+
-+              if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)
-+                      goto block_release;
-+
-+              for (; bytes < c_byte; b++) {
-+                      bh[b] = sb_getblk(s, ++cur_index);
-+                      if (bh[b] == NULL)
-+                              goto block_release;
-+                      bytes += msblk->devblksize;
-+              }
-+              ll_rw_block(READ, b - 1, bh + 1);
-+      }
-+
-+      if (compressed) {
-+              int zlib_err = 0;
-+
-+              /*
-+              * uncompress block
-+              */
-+
-+              mutex_lock(&msblk->read_data_mutex);
-+
-+              msblk->stream.next_out = buffer;
-+              msblk->stream.avail_out = srclength;
-+
-+              for (bytes = 0; k < b; k++) {
-+                      avail_bytes = min(c_byte - bytes, msblk->devblksize - offset);
-+
-+                      wait_on_buffer(bh[k]);
-+                      if (!buffer_uptodate(bh[k]))
-+                              goto release_mutex;
-+
-+                      msblk->stream.next_in = bh[k]->b_data + offset;
-+                      msblk->stream.avail_in = avail_bytes;
-+
-+                      if (k == 0) {
-+                              zlib_err = zlib_inflateInit(&msblk->stream);
-+                              if (zlib_err != Z_OK) {
-+                                      ERROR("zlib_inflateInit returned unexpected result 0x%x,"
-+                                              " srclength %d\n", zlib_err, srclength);
-+                                      goto release_mutex;
-+                              }
-+
-+                              if (avail_bytes == 0) {
-+                                      offset = 0;
-+                                      brelse(bh[k]);
-+                                      continue;
-+                              }
-+                      }
-+
-+                      zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH);
-+                      if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) {
-+                              ERROR("zlib_inflate returned unexpected result 0x%x,"
-+                                      " srclength %d, avail_in %d, avail_out %d\n", zlib_err,
-+                                      srclength, msblk->stream.avail_in, msblk->stream.avail_out);
-+                              goto release_mutex;
-+                      }
-+
-+                      bytes += avail_bytes;
-+                      offset = 0;
-+                      brelse(bh[k]);
-+              }
-+
-+              if (zlib_err != Z_STREAM_END)
-+                      goto release_mutex;
-+
-+              zlib_err = zlib_inflateEnd(&msblk->stream);
-+              if (zlib_err != Z_OK) {
-+                      ERROR("zlib_inflateEnd returned unexpected result 0x%x,"
-+                              " srclength %d\n", zlib_err, srclength);
-+                      goto release_mutex;
-+              }
-+              bytes = msblk->stream.total_out;
-+              mutex_unlock(&msblk->read_data_mutex);
-+      } else {
-+              int i;
-+
-+              for(i = 0; i < b; i++) {
-+                      wait_on_buffer(bh[i]);
-+                      if (!buffer_uptodate(bh[i]))
-+                              goto block_release;
-+              }
-+
-+              for (bytes = 0; k < b; k++) {
-+                      avail_bytes = min(c_byte - bytes, msblk->devblksize - offset);
-+
-+                      memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);
-+                      bytes += avail_bytes;
-+                      offset = 0;
-+                      brelse(bh[k]);
-+              }
-+      }
-+
-+      if (next_index)
-+              *next_index = index + c_byte + (length ? 0 :
-+                              (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2));
-+
-+      kfree(bh);
-+      return bytes;
-+
-+release_mutex:
-+      mutex_unlock(&msblk->read_data_mutex);
-+
-+block_release:
-+      for (; k < b; k++)
-+              brelse(bh[k]);
-+
-+read_failure:
-+      ERROR("sb_bread failed reading block 0x%x\n", cur_index);
-+      kfree(bh);
-+      return 0;
-+}
-+
-+
-+int squashfs_get_cached_block(struct super_block *s, void *buffer,
-+                              long long block, unsigned int offset,
-+                              int length, long long *next_block,
-+                              unsigned int *next_offset)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      int bytes, return_length = length;
-+      struct squashfs_cache_entry *entry;
-+
-+      TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
-+
-+      while (1) {
-+              entry = squashfs_cache_get(s, msblk->block_cache, block, 0);
-+              bytes = entry->length - offset;
-+
-+              if (entry->error || bytes < 1) {
-+                      return_length = 0;
-+                      goto finish;
-+              } else if (bytes >= length) {
-+                      if (buffer)
-+                              memcpy(buffer, entry->data + offset, length);
-+                      if (entry->length - offset == length) {
-+                              *next_block = entry->next_index;
-+                              *next_offset = 0;
-+                      } else {
-+                              *next_block = block;
-+                              *next_offset = offset + length;
-+                      }
-+                      goto finish;
-+              } else {
-+                      if (buffer) {
-+                              memcpy(buffer, entry->data + offset, bytes);
-+                              buffer = (char *) buffer + bytes;
-+                      }
-+                      block = entry->next_index;
-+                      squashfs_cache_put(msblk->block_cache, entry);
-+                      length -= bytes;
-+                      offset = 0;
-+              }
-+      }
-+
-+finish:
-+      squashfs_cache_put(msblk->block_cache, entry);
-+      return return_length;
-+}
-diff -uNr a/fs/squashfs/cache.c b/fs/squashfs/cache.c
---- a/fs/squashfs/cache.c      1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/cache.c      2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,189 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * cache.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s,
-+      struct squashfs_cache *cache, long long block, int length)
-+{
-+      int i, n;
-+      struct squashfs_cache_entry *entry;
-+
-+      spin_lock(&cache->lock);
-+
-+      while (1) {
-+              for (i = 0; i < cache->entries && cache->entry[i].block != block; i++);
-+
-+              if (i == cache->entries) {
-+                      if (cache->unused_blks == 0) {
-+                              cache->waiting ++;
-+                              spin_unlock(&cache->lock);
-+                              wait_event(cache->wait_queue, cache->unused_blks);
-+                              spin_lock(&cache->lock);
-+                              cache->waiting --;
-+                              continue;
-+                      }
-+
-+                      i = cache->next_blk;
-+                      for (n = 0; n < cache->entries; n++) {
-+                              if (cache->entry[i].locked == 0)
-+                                      break;
-+                              i = (i + 1) % cache->entries;
-+                      }
-+
-+                      cache->next_blk = (i + 1) % cache->entries;
-+                      entry = &cache->entry[i];
-+
-+                      cache->unused_blks --;
-+                      entry->block = block;
-+                      entry->locked = 1;
-+                      entry->pending = 1;
-+                      entry->waiting = 0;
-+                      entry->error = 0;
-+                      spin_unlock(&cache->lock);
-+
-+                      entry->length = squashfs_read_data(s, entry->data,
-+                              block, length, &entry->next_index, cache->block_size);
-+
-+                      spin_lock(&cache->lock);
-+
-+                      if (entry->length == 0)
-+                              entry->error = 1;
-+
-+                      entry->pending = 0;
-+                      spin_unlock(&cache->lock);
-+                      if (entry->waiting)
-+                              wake_up_all(&entry->wait_queue);
-+                      goto out;
-+              }
-+
-+              entry = &cache->entry[i];
-+              if (entry->locked == 0)
-+                      cache->unused_blks --;
-+              entry->locked++;
-+
-+              if (entry->pending) {
-+                      entry->waiting ++;
-+                      spin_unlock(&cache->lock);
-+                      wait_event(entry->wait_queue, !entry->pending);
-+                      goto out;
-+              }
-+
-+              spin_unlock(&cache->lock);
-+              goto out;
-+      }
-+
-+out:
-+      TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i,
-+              cache->name, entry->block, entry->locked, entry->error);
-+      if (entry->error)
-+              ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block);
-+      return entry;
-+}
-+
-+
-+void squashfs_cache_put(struct squashfs_cache *cache,
-+                              struct squashfs_cache_entry *entry)
-+{
-+      spin_lock(&cache->lock);
-+      entry->locked --;
-+      if (entry->locked == 0) {
-+              cache->unused_blks ++;
-+              spin_unlock(&cache->lock);
-+              if (cache->waiting)
-+                      wake_up(&cache->wait_queue);
-+      } else
-+              spin_unlock(&cache->lock);
-+}
-+
-+
-+void squashfs_cache_delete(struct squashfs_cache *cache)
-+{
-+      int i;
-+
-+      if (cache == NULL)
-+              return;
-+
-+      for (i = 0; i < cache->entries; i++)
-+              if (cache->entry[i].data) {
-+                      if (cache->use_vmalloc)
-+                              vfree(cache->entry[i].data);
-+                      else
-+                              kfree(cache->entry[i].data);
-+              }
-+
-+      kfree(cache);
-+}
-+
-+
-+struct squashfs_cache *squashfs_cache_init(char *name, int entries,
-+      int block_size, int use_vmalloc)
-+{
-+      int i;
-+      struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) +
-+                      entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL);
-+      if (cache == NULL) {
-+              ERROR("Failed to allocate %s cache\n", name);
-+              goto failed;
-+      }
-+
-+      cache->next_blk = 0;
-+      cache->unused_blks = entries;
-+      cache->entries = entries;
-+      cache->block_size = block_size;
-+      cache->use_vmalloc = use_vmalloc;
-+      cache->name = name;
-+      cache->waiting = 0;
-+      spin_lock_init(&cache->lock);
-+      init_waitqueue_head(&cache->wait_queue);
-+
-+      for (i = 0; i < entries; i++) {
-+              init_waitqueue_head(&cache->entry[i].wait_queue);
-+              cache->entry[i].block = SQUASHFS_INVALID_BLK;
-+              cache->entry[i].data = use_vmalloc ? vmalloc(block_size) :
-+                              kmalloc(block_size, GFP_KERNEL);
-+              if (cache->entry[i].data == NULL) {
-+                      ERROR("Failed to allocate %s cache entry\n", name);
-+                      goto cleanup;
-+              }
-+      }
-+
-+      return cache;
-+
-+cleanup:
-+      squashfs_cache_delete(cache);
-+failed:
-+      return NULL;
-+}
-diff -uNr a/fs/squashfs/dir.c b/fs/squashfs/dir.c
---- a/fs/squashfs/dir.c        1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/dir.c        2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,216 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * dir.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+
-+static const unsigned char squashfs_filetype_table[] = {
-+      DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
-+};
-+
-+static int get_dir_index_using_offset(struct super_block *s,
-+                              long long *next_block, unsigned int *next_offset,
-+                              long long index_start, unsigned int index_offset, int i_count,
-+                              long long f_pos)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      int i, length = 0;
-+      struct squashfs_dir_index index;
-+
-+      TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
-+                                      i_count, (unsigned int) f_pos);
-+
-+      f_pos -= 3;
-+      if (f_pos == 0)
-+              goto finish;
-+
-+      for (i = 0; i < i_count; i++) {
-+              if (msblk->swap) {
-+                      struct squashfs_dir_index sindex;
-+                      squashfs_get_cached_block(s, &sindex, index_start, index_offset,
-+                                      sizeof(sindex), &index_start, &index_offset);
-+                      SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
-+              } else
-+                      squashfs_get_cached_block(s, &index, index_start, index_offset,
-+                                      sizeof(index), &index_start, &index_offset);
-+
-+              if (index.index > f_pos)
-+                      break;
-+
-+              squashfs_get_cached_block(s, NULL, index_start, index_offset,
-+                                      index.size + 1, &index_start, &index_offset);
-+
-+              length = index.index;
-+              *next_block = index.start_block + sblk->directory_table_start;
-+      }
-+
-+      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
-+
-+finish:
-+      return length + 3;
-+}
-+
-+
-+static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
-+{
-+      struct inode *i = file->f_dentry->d_inode;
-+      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      long long next_block = SQUASHFS_I(i)->start_block +
-+              sblk->directory_table_start;
-+      int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count;
-+      struct squashfs_dir_header dirh;
-+      struct squashfs_dir_entry *dire;
-+
-+      TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
-+
-+      dire = kmalloc(sizeof(struct squashfs_dir_entry) +
-+              SQUASHFS_NAME_LEN + 1, GFP_KERNEL);
-+      if (dire == NULL) {
-+              ERROR("Failed to allocate squashfs_dir_entry\n");
-+              goto finish;
-+      }
-+
-+      while(file->f_pos < 3) {
-+              char *name;
-+              int size, i_ino;
-+
-+              if(file->f_pos == 0) {
-+                      name = ".";
-+                      size = 1;
-+                      i_ino = i->i_ino;
-+              } else {
-+                      name = "..";
-+                      size = 2;
-+                      i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
-+              }
-+              TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
-+                              (unsigned int) dirent, name, size, (int)
-+                              file->f_pos, i_ino, squashfs_filetype_table[1]);
-+
-+              if (filldir(dirent, name, size, file->f_pos, i_ino,
-+                              squashfs_filetype_table[1]) < 0) {
-+                              TRACE("Filldir returned less than 0\n");
-+                      goto finish;
-+              }
-+              file->f_pos += size;
-+      }
-+
-+      length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
-+                              SQUASHFS_I(i)->u.s2.directory_index_start,
-+                              SQUASHFS_I(i)->u.s2.directory_index_offset,
-+                              SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos);
-+
-+      while (length < i_size_read(i)) {
-+              /* read directory header */
-+              if (msblk->swap) {
-+                      struct squashfs_dir_header sdirh;
-+                      
-+                      if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block,
-+                                       next_offset, sizeof(sdirh), &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += sizeof(sdirh);
-+                      SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
-+              } else {
-+                      if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block,
-+                                      next_offset, sizeof(dirh), &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += sizeof(dirh);
-+              }
-+
-+              dir_count = dirh.count + 1;
-+              while (dir_count--) {
-+                      if (msblk->swap) {
-+                              struct squashfs_dir_entry sdire;
-+                              if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block,
-+                                              next_offset, sizeof(sdire), &next_block, &next_offset))
-+                                      goto failed_read;
-+                              
-+                              length += sizeof(sdire);
-+                              SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
-+                      } else {
-+                              if (!squashfs_get_cached_block(i->i_sb, dire, next_block,
-+                                              next_offset, sizeof(*dire), &next_block, &next_offset))
-+                                      goto failed_read;
-+
-+                              length += sizeof(*dire);
-+                      }
-+
-+                      if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block,
-+                                              next_offset, dire->size + 1, &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += dire->size + 1;
-+
-+                      if (file->f_pos >= length)
-+                              continue;
-+
-+                      dire->name[dire->size + 1] = '\0';
-+
-+                      TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
-+                                      (unsigned int) dirent, dire->name, dire->size + 1,
-+                                      (int) file->f_pos, dirh.start_block, dire->offset,
-+                                      dirh.inode_number + dire->inode_number,
-+                                      squashfs_filetype_table[dire->type]);
-+
-+                      if (filldir(dirent, dire->name, dire->size + 1, file->f_pos,
-+                                      dirh.inode_number + dire->inode_number,
-+                                      squashfs_filetype_table[dire->type]) < 0) {
-+                              TRACE("Filldir returned less than 0\n");
-+                              goto finish;
-+                      }
-+                      file->f_pos = length;
-+              }
-+      }
-+
-+finish:
-+      kfree(dire);
-+      return 0;
-+
-+failed_read:
-+      ERROR("Unable to read directory block [%llx:%x]\n", next_block,
-+              next_offset);
-+      kfree(dire);
-+      return 0;
-+}
-+
-+
-+const struct file_operations squashfs_dir_ops = {
-+      .read = generic_read_dir,
-+      .readdir = squashfs_readdir
-+};
-diff -uNr a/fs/squashfs/export.c b/fs/squashfs/export.c
---- a/fs/squashfs/export.c     1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/export.c     2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,171 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * export.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];
-+      int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);
-+      squashfs_inode_t inode;
-+
-+      TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);
-+
-+      if (msblk->swap) {
-+              squashfs_inode_t sinode;
-+
-+              if (!squashfs_get_cached_block(s, &sinode, start, offset,
-+                                      sizeof(sinode), &start, &offset))
-+                      goto out;
-+              SQUASHFS_SWAP_INODE_T((&inode), &sinode);
-+      } else if (!squashfs_get_cached_block(s, &inode, start, offset,
-+                                      sizeof(inode), &start, &offset))
-+                      goto out;
-+
-+      TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);
-+
-+      return inode;
-+
-+out:
-+      return SQUASHFS_INVALID_BLK;
-+}
-+
-+
-+static struct dentry *squashfs_export_iget(struct super_block *s,
-+      unsigned int inode_number)
-+{
-+      squashfs_inode_t inode;
-+      struct inode *i;
-+      struct dentry *dentry;
-+
-+      TRACE("Entered squashfs_export_iget\n");
-+
-+      inode = squashfs_inode_lookup(s, inode_number);
-+      if(inode == SQUASHFS_INVALID_BLK) {
-+              dentry = ERR_PTR(-ENOENT);
-+              goto failure;
-+      }
-+
-+      i = squashfs_iget(s, inode, inode_number);
-+      if(i == NULL) {
-+              dentry = ERR_PTR(-EACCES);
-+              goto failure;
-+      }
-+
-+      dentry = d_alloc_anon(i);
-+      if (dentry == NULL) {
-+              iput(i);
-+              dentry = ERR_PTR(-ENOMEM);
-+      }
-+
-+failure:
-+      return dentry;
-+}
-+
-+
-+static struct dentry *squashfs_fh_to_dentry(struct super_block *s,
-+              struct fid *fid, int fh_len, int fh_type)
-+{
-+      if((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) ||
-+                      fh_len < 2)
-+              return NULL;
-+
-+      return squashfs_export_iget(s, fid->i32.ino);
-+}
-+
-+
-+static struct dentry *squashfs_fh_to_parent(struct super_block *s,
-+              struct fid *fid, int fh_len, int fh_type)
-+{
-+      if(fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4)
-+              return NULL;
-+
-+      return squashfs_export_iget(s, fid->i32.parent_ino);
-+}
-+
-+
-+static struct dentry *squashfs_get_parent(struct dentry *child)
-+{
-+      struct inode *i = child->d_inode;
-+
-+      TRACE("Entered squashfs_get_parent\n");
-+
-+      return squashfs_export_iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);
-+}
-+
-+
-+int read_inode_lookup_table(struct super_block *s)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);
-+
-+      TRACE("In read_inode_lookup_table, length %d\n", length);
-+
-+      /* Allocate inode lookup table */
-+      msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL);
-+      if (msblk->inode_lookup_table == NULL) {
-+              ERROR("Failed to allocate inode lookup table\n");
-+              return 0;
-+      }
-+   
-+      if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,
-+                      sblk->lookup_table_start, length |
-+                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
-+              ERROR("unable to read inode lookup table\n");
-+              return 0;
-+      }
-+
-+      if (msblk->swap) {
-+              int i;
-+              long long block;
-+
-+              for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {
-+                      SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),
-+                                              &msblk->inode_lookup_table[i], 1);
-+                      msblk->inode_lookup_table[i] = block;
-+              }
-+      }
-+
-+      return 1;
-+}
-+
-+
-+const struct export_operations squashfs_export_ops = {
-+      .fh_to_dentry = squashfs_fh_to_dentry,
-+      .fh_to_parent = squashfs_fh_to_parent,
-+      .get_parent = squashfs_get_parent
-+};
-diff -uNr a/fs/squashfs/file.c b/fs/squashfs/file.c
---- a/fs/squashfs/file.c       1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/file.c       2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,430 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * file.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+
-+static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
-+{
-+      struct meta_index *meta = NULL;
-+      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
-+      int i;
-+
-+      mutex_lock(&msblk->meta_index_mutex);
-+
-+      TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
-+
-+      if (msblk->meta_index == NULL)
-+              goto not_allocated;
-+
-+      for (i = 0; i < SQUASHFS_META_NUMBER; i ++) {
-+              if (msblk->meta_index[i].inode_number == inode->i_ino &&
-+                              msblk->meta_index[i].offset >= offset &&
-+                              msblk->meta_index[i].offset <= index &&
-+                              msblk->meta_index[i].locked == 0) {
-+                      TRACE("locate_meta_index: entry %d, offset %d\n", i,
-+                                      msblk->meta_index[i].offset);
-+                      meta = &msblk->meta_index[i];
-+                      offset = meta->offset;
-+              }
-+      }
-+
-+      if (meta)
-+              meta->locked = 1;
-+
-+not_allocated:
-+      mutex_unlock(&msblk->meta_index_mutex);
-+
-+      return meta;
-+}
-+
-+
-+static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
-+{
-+      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
-+      struct meta_index *meta = NULL;
-+      int i;
-+
-+      mutex_lock(&msblk->meta_index_mutex);
-+
-+      TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
-+
-+      if (msblk->meta_index == NULL) {
-+              msblk->meta_index = kmalloc(sizeof(struct meta_index) *
-+                                      SQUASHFS_META_NUMBER, GFP_KERNEL);
-+              if (msblk->meta_index == NULL) {
-+                      ERROR("Failed to allocate meta_index\n");
-+                      goto failed;
-+              }
-+              for (i = 0; i < SQUASHFS_META_NUMBER; i++) {
-+                      msblk->meta_index[i].inode_number = 0;
-+                      msblk->meta_index[i].locked = 0;
-+              }
-+              msblk->next_meta_index = 0;
-+      }
-+
-+      for (i = SQUASHFS_META_NUMBER; i &&
-+                      msblk->meta_index[msblk->next_meta_index].locked; i --)
-+              msblk->next_meta_index = (msblk->next_meta_index + 1) %
-+                      SQUASHFS_META_NUMBER;
-+
-+      if (i == 0) {
-+              TRACE("empty_meta_index: failed!\n");
-+              goto failed;
-+      }
-+
-+      TRACE("empty_meta_index: returned meta entry %d, %p\n",
-+                      msblk->next_meta_index,
-+                      &msblk->meta_index[msblk->next_meta_index]);
-+
-+      meta = &msblk->meta_index[msblk->next_meta_index];
-+      msblk->next_meta_index = (msblk->next_meta_index + 1) %
-+                      SQUASHFS_META_NUMBER;
-+
-+      meta->inode_number = inode->i_ino;
-+      meta->offset = offset;
-+      meta->skip = skip;
-+      meta->entries = 0;
-+      meta->locked = 1;
-+
-+failed:
-+      mutex_unlock(&msblk->meta_index_mutex);
-+      return meta;
-+}
-+
-+
-+static void release_meta_index(struct inode *inode, struct meta_index *meta)
-+{
-+      meta->locked = 0;
-+      smp_mb();
-+}
-+
-+
-+static int read_block_index(struct super_block *s, int blocks, char *block_list,
-+                              long long *start_block, int *offset)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      unsigned int *block_listp;
-+      int block = 0;
-+      
-+      if (msblk->swap) {
-+              char sblock_list[blocks << 2];
-+
-+              if (!squashfs_get_cached_block(s, sblock_list, *start_block,
-+                              *offset, blocks << 2, start_block, offset)) {
-+                      ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset);
-+                      goto failure;
-+              }
-+              SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
-+                              ((unsigned int *)sblock_list), blocks);
-+      } else {
-+              if (!squashfs_get_cached_block(s, block_list, *start_block,
-+                              *offset, blocks << 2, start_block, offset)) {
-+                      ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset);
-+                      goto failure;
-+              }
-+      }
-+
-+      for (block_listp = (unsigned int *) block_list; blocks;
-+                              block_listp++, blocks --)
-+              block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
-+
-+      return block;
-+
-+failure:
-+      return -1;
-+}
-+
-+
-+#define SIZE 256
-+
-+static inline int calculate_skip(int blocks) {
-+      int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
-+      return skip >= 7 ? 7 : skip + 1;
-+}
-+
-+
-+static int get_meta_index(struct inode *inode, int index,
-+              long long *index_block, int *index_offset,
-+              long long *data_block, char *block_list)
-+{
-+      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
-+      int offset = 0;
-+      struct meta_index *meta;
-+      struct meta_entry *meta_entry;
-+      long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
-+      int cur_offset = SQUASHFS_I(inode)->offset;
-+      long long cur_data_block = SQUASHFS_I(inode)->start_block;
-+      int i;
-+ 
-+      index /= SQUASHFS_META_INDEXES * skip;
-+
-+      while (offset < index) {
-+              meta = locate_meta_index(inode, index, offset + 1);
-+
-+              if (meta == NULL) {
-+                      meta = empty_meta_index(inode, offset + 1, skip);
-+                      if (meta == NULL)
-+                              goto all_done;
-+              } else {
-+                      if(meta->entries == 0)
-+                              goto failed;
-+                      /* XXX */
-+                      offset = index < meta->offset + meta->entries ? index :
-+                              meta->offset + meta->entries - 1;
-+                      /* XXX */
-+                      meta_entry = &meta->meta_entry[offset - meta->offset];
-+                      cur_index_block = meta_entry->index_block + sblk->inode_table_start;
-+                      cur_offset = meta_entry->offset;
-+                      cur_data_block = meta_entry->data_block;
-+                      TRACE("get_meta_index: offset %d, meta->offset %d, "
-+                              "meta->entries %d\n", offset, meta->offset, meta->entries);
-+                      TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
-+                              " data_block 0x%llx\n", cur_index_block,
-+                              cur_offset, cur_data_block);
-+              }
-+
-+              for (i = meta->offset + meta->entries; i <= index &&
-+                              i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
-+                      int blocks = skip * SQUASHFS_META_INDEXES;
-+
-+                      while (blocks) {
-+                              int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks;
-+                              int res = read_block_index(inode->i_sb, block, block_list,
-+                                      &cur_index_block, &cur_offset);
-+
-+                              if (res == -1)
-+                                      goto failed;
-+
-+                              cur_data_block += res;
-+                              blocks -= block;
-+                      }
-+
-+                      meta_entry = &meta->meta_entry[i - meta->offset];
-+                      meta_entry->index_block = cur_index_block - sblk->inode_table_start;
-+                      meta_entry->offset = cur_offset;
-+                      meta_entry->data_block = cur_data_block;
-+                      meta->entries ++;
-+                      offset ++;
-+              }
-+
-+              TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
-+                              meta->offset, meta->entries);
-+
-+              release_meta_index(inode, meta);
-+      }
-+
-+all_done:
-+      *index_block = cur_index_block;
-+      *index_offset = cur_offset;
-+      *data_block = cur_data_block;
-+
-+      return offset * SQUASHFS_META_INDEXES * skip;
-+
-+failed:
-+      release_meta_index(inode, meta);
-+      return -1;
-+}
-+
-+
-+long long read_blocklist(struct inode *inode, int index,
-+                              int readahead_blks, char *block_list,
-+                              unsigned short **block_p, unsigned int *bsize)
-+{
-+      long long block_ptr;
-+      int offset;
-+      long long block;
-+      int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
-+              block_list);
-+
-+      TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
-+                     " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block);
-+
-+      if(res == -1)
-+              goto failure;
-+
-+      index -= res;
-+
-+      while (index) {
-+              int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
-+              int res = read_block_index(inode->i_sb, blocks, block_list,
-+                      &block_ptr, &offset);
-+              if (res == -1)
-+                      goto failure;
-+              block += res;
-+              index -= blocks;
-+      }
-+
-+      if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1)
-+              goto failure;
-+      *bsize = *((unsigned int *) block_list);
-+
-+      return block;
-+
-+failure:
-+      return 0;
-+}
-+
-+
-+static int squashfs_readpage(struct file *file, struct page *page)
-+{
-+      struct inode *inode = page->mapping->host;
-+      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      unsigned char *block_list = NULL;
-+      long long block;
-+      unsigned int bsize, i;
-+      int bytes;
-+      int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
-+      void *pageaddr;
-+      struct squashfs_cache_entry *fragment = NULL;
-+      char *data_ptr = msblk->read_page;
-+      
-+      int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
-+      int start_index = page->index & ~mask;
-+      int end_index = start_index | mask;
-+      int file_end = i_size_read(inode) >> sblk->block_log;
-+      int sparse = 0;
-+
-+      TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
-+                                      page->index, SQUASHFS_I(inode)->start_block);
-+
-+      if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
-+                                      PAGE_CACHE_SHIFT))
-+              goto out;
-+
-+      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
-+                                      || index < file_end) {
-+              block_list = kmalloc(SIZE, GFP_KERNEL);
-+              if (block_list == NULL) {
-+                      ERROR("Failed to allocate block_list\n");
-+                      goto error_out;
-+              }
-+
-+              block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize);
-+              if (block == 0)
-+                      goto error_out;
-+
-+              if (bsize == 0) { /* hole */
-+                      bytes = index == file_end ?
-+                              (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size;
-+                      sparse = 1;
-+              } else {
-+                      mutex_lock(&msblk->read_page_mutex);
-+              
-+                      bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
-+                              bsize, NULL, sblk->block_size);
-+
-+                      if (bytes == 0) {
-+                              ERROR("Unable to read page, block %llx, size %x\n", block, bsize);
-+                              mutex_unlock(&msblk->read_page_mutex);
-+                              goto error_out;
-+                      }
-+              }
-+      } else {
-+              fragment = get_cached_fragment(inode->i_sb,
-+                                      SQUASHFS_I(inode)-> u.s1.fragment_start_block,
-+                                      SQUASHFS_I(inode)->u.s1.fragment_size);
-+
-+              if (fragment->error) {
-+                      ERROR("Unable to read page, block %llx, size %x\n",
-+                                      SQUASHFS_I(inode)->u.s1.fragment_start_block,
-+                                      (int) SQUASHFS_I(inode)->u.s1.fragment_size);
-+                      release_cached_fragment(msblk, fragment);
-+                      goto error_out;
-+              }
-+              bytes = i_size_read(inode) & (sblk->block_size - 1);
-+              data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset;
-+      }
-+
-+      for (i = start_index; i <= end_index && bytes > 0; i++,
-+                                              bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) {
-+              struct page *push_page;
-+              int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE);
-+
-+              TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail);
-+
-+              push_page = (i == page->index) ? page :
-+                      grab_cache_page_nowait(page->mapping, i);
-+
-+              if (!push_page)
-+                      continue;
-+
-+              if (PageUptodate(push_page))
-+                      goto skip_page;
-+
-+              pageaddr = kmap_atomic(push_page, KM_USER0);
-+              memcpy(pageaddr, data_ptr, avail);
-+              memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
-+              kunmap_atomic(pageaddr, KM_USER0);
-+              flush_dcache_page(push_page);
-+              SetPageUptodate(push_page);
-+skip_page:
-+              unlock_page(push_page);
-+              if(i != page->index)
-+                      page_cache_release(push_page);
-+      }
-+
-+      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
-+                                      || index < file_end) {
-+              if (!sparse)
-+                      mutex_unlock(&msblk->read_page_mutex);
-+              kfree(block_list);
-+      } else
-+              release_cached_fragment(msblk, fragment);
-+
-+      return 0;
-+
-+error_out:
-+      SetPageError(page);
-+out:
-+      pageaddr = kmap_atomic(page, KM_USER0);
-+      memset(pageaddr, 0, PAGE_CACHE_SIZE);
-+      kunmap_atomic(pageaddr, KM_USER0);
-+      flush_dcache_page(page);
-+      if (!PageError(page))
-+              SetPageUptodate(page);
-+      unlock_page(page);
-+
-+      kfree(block_list);
-+      return 0;
-+}
-+
-+
-+const struct address_space_operations squashfs_aops = {
-+      .readpage = squashfs_readpage
-+};
-diff -uNr a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c
---- a/fs/squashfs/fragment.c   1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/fragment.c   2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,122 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * fragment.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+
-+int get_fragment_location(struct super_block *s, unsigned int fragment,
-+                              long long *fragment_start_block,
-+                              unsigned int *fragment_size)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      long long start_block =
-+              msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
-+      int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
-+      struct squashfs_fragment_entry fragment_entry;
-+
-+      if (msblk->swap) {
-+              struct squashfs_fragment_entry sfragment_entry;
-+
-+              if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset,
-+                                       sizeof(sfragment_entry), &start_block, &offset))
-+                      goto out;
-+              SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
-+      } else
-+              if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset,
-+                                       sizeof(fragment_entry), &start_block, &offset))
-+                      goto out;
-+
-+      *fragment_start_block = fragment_entry.start_block;
-+      *fragment_size = fragment_entry.size;
-+
-+      return 1;
-+
-+out:
-+      return 0;
-+}
-+
-+
-+void release_cached_fragment(struct squashfs_sb_info *msblk,
-+                              struct squashfs_cache_entry *fragment)
-+{
-+      squashfs_cache_put(msblk->fragment_cache, fragment);
-+}
-+
-+
-+struct squashfs_cache_entry *get_cached_fragment(struct super_block *s,
-+                              long long start_block, int length)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+
-+      return squashfs_cache_get(s, msblk->fragment_cache, start_block, length);
-+}
-+
-+
-+int read_fragment_index_table(struct super_block *s)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);
-+
-+      if(length == 0)
-+              return 1;
-+
-+      /* Allocate fragment index table */
-+      msblk->fragment_index = kmalloc(length, GFP_KERNEL);
-+      if (msblk->fragment_index == NULL) {
-+              ERROR("Failed to allocate fragment index table\n");
-+              return 0;
-+      }
-+   
-+      if (!squashfs_read_data(s, (char *) msblk->fragment_index,
-+                      sblk->fragment_table_start, length |
-+                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
-+              ERROR("unable to read fragment index table\n");
-+              return 0;
-+      }
-+
-+      if (msblk->swap) {
-+              int i;
-+              long long fragment;
-+
-+              for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {
-+                      SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
-+                                              &msblk->fragment_index[i], 1);
-+                      msblk->fragment_index[i] = fragment;
-+              }
-+      }
-+
-+      return 1;
-+}
-diff -uNr a/fs/squashfs/id.c b/fs/squashfs/id.c
---- a/fs/squashfs/id.c 1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/id.c 2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,97 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * id.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+
-+int get_id(struct super_block *s, unsigned int index, unsigned int *id)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      long long start_block = msblk->id_table[SQUASHFS_ID_BLOCK(index)];
-+      int offset = SQUASHFS_ID_BLOCK_OFFSET(index);
-+
-+      if (msblk->swap) {
-+              unsigned int sid;
-+
-+              if (!squashfs_get_cached_block(s, &sid, start_block, offset,
-+                                       sizeof(unsigned int), &start_block, &offset))
-+                      goto out;
-+              SQUASHFS_SWAP_INTS((&sid), id, 1);
-+      } else
-+              if (!squashfs_get_cached_block(s, id, start_block, offset,
-+                                       sizeof(unsigned int), &start_block, &offset))
-+                      goto out;
-+
-+      return 1;
-+
-+out:
-+      return 0;
-+}
-+
-+
-+int read_id_index_table(struct super_block *s)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      unsigned int length = SQUASHFS_ID_BLOCK_BYTES(sblk->no_ids);
-+
-+      TRACE("In read_id_index_table, length %d\n", length);
-+
-+      /* Allocate id index table */
-+      msblk->id_table = kmalloc(length, GFP_KERNEL);
-+      if (msblk->id_table == NULL) {
-+              ERROR("Failed to allocate id index table\n");
-+              return 0;
-+      }
-+   
-+      if (!squashfs_read_data(s, (char *) msblk->id_table,
-+                      sblk->id_table_start, length |
-+                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
-+              ERROR("unable to read id index table\n");
-+              return 0;
-+      }
-+
-+      if (msblk->swap) {
-+              int i;
-+              long long block;
-+
-+              for (i = 0; i < SQUASHFS_ID_BLOCKS(sblk->no_ids); i++) {
-+                      SQUASHFS_SWAP_ID_BLOCKS((&block), &msblk->id_table[i], 1);
-+                      msblk->id_table[i] = block;
-+              }
-+      }
-+
-+      return 1;
-+}
-diff -uNr a/fs/squashfs/inode.c b/fs/squashfs/inode.c
---- a/fs/squashfs/inode.c      1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/inode.c      2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,340 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * inode.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+
-+static int squashfs_new_inode(struct super_block *s, struct inode *i,
-+                              struct squashfs_base_inode_header *inodeb)
-+{
-+      if(get_id(s, inodeb->uid, &i->i_uid) == 0)
-+              goto out;
-+      if(get_id(s, inodeb->guid, &i->i_gid) == 0)
-+              goto out;
-+
-+      i->i_ino = inodeb->inode_number;
-+      i->i_mtime.tv_sec = inodeb->mtime;
-+      i->i_atime.tv_sec = inodeb->mtime;
-+      i->i_ctime.tv_sec = inodeb->mtime;
-+      i->i_mode = inodeb->mode;
-+      i->i_size = 0;
-+
-+      return 1;
-+
-+out:
-+      return 0;
-+}
-+
-+
-+struct inode *squashfs_iget(struct super_block *s,
-+                              squashfs_inode_t inode, unsigned int inode_number)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct inode *i = iget_locked(s, inode_number);
-+
-+      TRACE("Entered squashfs_iget\n");
-+
-+      if(i && (i->i_state & I_NEW)) {
-+              (msblk->read_inode)(i, inode);
-+              unlock_new_inode(i);
-+      }
-+
-+      return i;
-+}
-+
-+
-+int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)
-+{
-+      struct super_block *s = i->i_sb;
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start;
-+      unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
-+      long long next_block;
-+      unsigned int next_offset;
-+      union squashfs_inode_header id, sid;
-+      struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base;
-+
-+      TRACE("Entered squashfs_read_inode\n");
-+
-+      if (msblk->swap) {
-+              if (!squashfs_get_cached_block(s, sinodeb, block, offset,
-+                                      sizeof(*sinodeb), &next_block, &next_offset))
-+                      goto failed_read;
-+              SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb));
-+      } else
-+              if (!squashfs_get_cached_block(s, inodeb, block, offset,
-+                                      sizeof(*inodeb), &next_block, &next_offset))
-+                      goto failed_read;
-+
-+      if(squashfs_new_inode(s, i, inodeb) == 0)
-+                      goto failed_read;
-+
-+      switch(inodeb->inode_type) {
-+              case SQUASHFS_FILE_TYPE: {
-+                      unsigned int frag_size;
-+                      long long frag_blk;
-+                      struct squashfs_reg_inode_header *inodep = &id.reg;
-+                      struct squashfs_reg_inode_header *sinodep = &sid.reg;
-+                              
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
-+                      } else
-+                              if (!squashfs_get_cached_block(s, inodep, block, offset,
-+                                              sizeof(*inodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+
-+                      frag_blk = SQUASHFS_INVALID_BLK;
-+
-+                      if (inodep->fragment != SQUASHFS_INVALID_FRAG)
-+                                      if(!get_fragment_location(s, inodep->fragment, &frag_blk,
-+                                                                                              &frag_size))
-+                                              goto failed_read;
-+                              
-+                      i->i_nlink = 1;
-+                      i->i_size = inodep->file_size;
-+                      i->i_fop = &generic_ro_fops;
-+                      i->i_mode |= S_IFREG;
-+                      i->i_blocks = ((i->i_size - 1) >> 9) + 1;
-+                      SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
-+                      SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
-+                      SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
-+                      SQUASHFS_I(i)->start_block = inodep->start_block;
-+                      SQUASHFS_I(i)->u.s1.block_list_start = next_block;
-+                      SQUASHFS_I(i)->offset = next_offset;
-+                      i->i_data.a_ops = &squashfs_aops;
-+
-+                      TRACE("File inode %x:%x, start_block %llx, "
-+                                      "block_list_start %llx, offset %x\n",
-+                                      SQUASHFS_INODE_BLK(inode), offset,
-+                                      inodep->start_block, next_block,
-+                                      next_offset);
-+                      break;
-+              }
-+              case SQUASHFS_LREG_TYPE: {
-+                      unsigned int frag_size;
-+                      long long frag_blk;
-+                      struct squashfs_lreg_inode_header *inodep = &id.lreg;
-+                      struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
-+                              
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
-+                      } else
-+                              if (!squashfs_get_cached_block(s, inodep, block, offset,
-+                                              sizeof(*inodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+
-+                      frag_blk = SQUASHFS_INVALID_BLK;
-+
-+                      if (inodep->fragment != SQUASHFS_INVALID_FRAG)
-+                              if (!get_fragment_location(s, inodep->fragment, &frag_blk,
-+                                                                                               &frag_size))
-+                                      goto failed_read;
-+                              
-+                      i->i_nlink = inodep->nlink;
-+                      i->i_size = inodep->file_size;
-+                      i->i_fop = &generic_ro_fops;
-+                      i->i_mode |= S_IFREG;
-+                      i->i_blocks = ((inodep->file_size - inodep->sparse - 1) >> 9) + 1;
-+                              
-+                      SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
-+                      SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
-+                      SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
-+                      SQUASHFS_I(i)->start_block = inodep->start_block;
-+                      SQUASHFS_I(i)->u.s1.block_list_start = next_block;
-+                      SQUASHFS_I(i)->offset = next_offset;
-+                      i->i_data.a_ops = &squashfs_aops;
-+
-+                      TRACE("File inode %x:%x, start_block %llx, "
-+                                      "block_list_start %llx, offset %x\n",
-+                                      SQUASHFS_INODE_BLK(inode), offset,
-+                                      inodep->start_block, next_block,
-+                                      next_offset);
-+                      break;
-+              }
-+              case SQUASHFS_DIR_TYPE: {
-+                      struct squashfs_dir_inode_header *inodep = &id.dir;
-+                      struct squashfs_dir_inode_header *sinodep = &sid.dir;
-+
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
-+                      } else
-+                              if (!squashfs_get_cached_block(s, inodep, block, offset,
-+                                              sizeof(*inodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+
-+                      i->i_nlink = inodep->nlink;
-+                      i->i_size = inodep->file_size;
-+                      i->i_op = &squashfs_dir_inode_ops;
-+                      i->i_fop = &squashfs_dir_ops;
-+                      i->i_mode |= S_IFDIR;
-+                      SQUASHFS_I(i)->start_block = inodep->start_block;
-+                      SQUASHFS_I(i)->offset = inodep->offset;
-+                      SQUASHFS_I(i)->u.s2.directory_index_count = 0;
-+                      SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
-+
-+                      TRACE("Directory inode %x:%x, start_block %x, offset "
-+                                      "%x\n", SQUASHFS_INODE_BLK(inode),
-+                                      offset, inodep->start_block,
-+                                      inodep->offset);
-+                      break;
-+              }
-+              case SQUASHFS_LDIR_TYPE: {
-+                      struct squashfs_ldir_inode_header *inodep = &id.ldir;
-+                      struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
-+
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep);
-+                      } else
-+                              if (!squashfs_get_cached_block(s, inodep, block, offset,
-+                                              sizeof(*inodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+
-+                      i->i_nlink = inodep->nlink;
-+                      i->i_size = inodep->file_size;
-+                      i->i_op = &squashfs_dir_inode_ops;
-+                      i->i_fop = &squashfs_dir_ops;
-+                      i->i_mode |= S_IFDIR;
-+                      SQUASHFS_I(i)->start_block = inodep->start_block;
-+                      SQUASHFS_I(i)->offset = inodep->offset;
-+                      SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
-+                      SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset;
-+                      SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count;
-+                      SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
-+
-+                      TRACE("Long directory inode %x:%x, start_block %x, offset %x\n",
-+                                      SQUASHFS_INODE_BLK(inode), offset,
-+                                      inodep->start_block, inodep->offset);
-+                      break;
-+              }
-+              case SQUASHFS_SYMLINK_TYPE: {
-+                      struct squashfs_symlink_inode_header *inodep = &id.symlink;
-+                      struct squashfs_symlink_inode_header *sinodep = &sid.symlink;
-+      
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep);
-+                      } else
-+                              if (!squashfs_get_cached_block(s, inodep, block, offset,
-+                                              sizeof(*inodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+
-+                      i->i_nlink = inodep->nlink;
-+                      i->i_size = inodep->symlink_size;
-+                      i->i_op = &page_symlink_inode_operations;
-+                      i->i_data.a_ops = &squashfs_symlink_aops;
-+                      i->i_mode |= S_IFLNK;
-+                      SQUASHFS_I(i)->start_block = next_block;
-+                      SQUASHFS_I(i)->offset = next_offset;
-+
-+                      TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n",
-+                                      SQUASHFS_INODE_BLK(inode), offset,
-+                                      next_block, next_offset);
-+                      break;
-+               }
-+               case SQUASHFS_BLKDEV_TYPE:
-+               case SQUASHFS_CHRDEV_TYPE: {
-+                      struct squashfs_dev_inode_header *inodep = &id.dev;
-+                      struct squashfs_dev_inode_header *sinodep = &sid.dev;
-+
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
-+                      } else  
-+                              if (!squashfs_get_cached_block(s, inodep, block, offset,
-+                                              sizeof(*inodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+
-+                      i->i_nlink = inodep->nlink;
-+                      i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ?
-+                                      S_IFCHR : S_IFBLK;
-+                      init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev));
-+
-+                      TRACE("Device inode %x:%x, rdev %x\n",
-+                                      SQUASHFS_INODE_BLK(inode), offset, inodep->rdev);
-+                      break;
-+               }
-+               case SQUASHFS_FIFO_TYPE:
-+               case SQUASHFS_SOCKET_TYPE: {
-+                      struct squashfs_ipc_inode_header *inodep = &id.ipc;
-+                      struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
-+
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
-+                      } else  
-+                              if (!squashfs_get_cached_block(s, inodep, block, offset,
-+                                              sizeof(*inodep), &next_block, &next_offset))
-+                                      goto failed_read;
-+
-+                      i->i_nlink = inodep->nlink;
-+                      i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
-+                                                      ? S_IFIFO : S_IFSOCK;
-+                      init_special_inode(i, i->i_mode, 0);
-+                      break;
-+               }
-+               default:
-+                      ERROR("Unknown inode type %d in squashfs_iget!\n",
-+                                      inodeb->inode_type);
-+                      goto failed_read1;
-+      }
-+      
-+      return 1;
-+
-+failed_read:
-+      ERROR("Unable to read inode [%llx:%x]\n", block, offset);
-+
-+failed_read1:
-+      make_bad_inode(i);
-+      return 0;
-+}
-diff -uNr a/fs/squashfs/Makefile b/fs/squashfs/Makefile
---- a/fs/squashfs/Makefile     1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/Makefile     2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,8 @@
-+#
-+# Makefile for the linux squashfs routines.
-+#
-+
-+obj-$(CONFIG_SQUASHFS) += squashfs.o
-+squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
-+squashfs-y += namei.o super.o symlink.o
-+#squashfs-y += squashfs2_0.o
-diff -uNr a/fs/squashfs/namei.c b/fs/squashfs/namei.c
---- a/fs/squashfs/namei.c      1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/namei.c      2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,200 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * namei.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+
-+static int get_dir_index_using_name(struct super_block *s,
-+                              long long *next_block, unsigned int *next_offset,
-+                              long long index_start, unsigned int index_offset, int i_count,
-+                              const char *name, int size)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      int i, length = 0;
-+      struct squashfs_dir_index *index;
-+      char *str;
-+
-+      TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
-+
-+      str = kmalloc(sizeof(struct squashfs_dir_index) +
-+              (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL);
-+      if (str == NULL) {
-+              ERROR("Failed to allocate squashfs_dir_index\n");
-+              goto failure;
-+      }
-+
-+      index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);
-+      strncpy(str, name, size);
-+      str[size] = '\0';
-+
-+      for (i = 0; i < i_count; i++) {
-+              if (msblk->swap) {
-+                      struct squashfs_dir_index sindex;
-+                      squashfs_get_cached_block(s, &sindex, index_start, index_offset,
-+                              sizeof(sindex), &index_start, &index_offset);
-+                      SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
-+              } else
-+                      squashfs_get_cached_block(s, index, index_start, index_offset,
-+                              sizeof(struct squashfs_dir_index), &index_start, &index_offset);
-+
-+              squashfs_get_cached_block(s, index->name, index_start, index_offset,
-+                                      index->size + 1, &index_start, &index_offset);
-+
-+              index->name[index->size + 1] = '\0';
-+
-+              if (strcmp(index->name, str) > 0)
-+                      break;
-+
-+              length = index->index;
-+              *next_block = index->start_block + sblk->directory_table_start;
-+      }
-+
-+      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
-+      kfree(str);
-+
-+failure:
-+      return length + 3;
-+}
-+
-+              
-+static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
-+                              struct nameidata *nd)
-+{
-+      const unsigned char *name = dentry->d_name.name;
-+      int len = dentry->d_name.len;
-+      struct inode *inode = NULL;
-+      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      long long next_block = SQUASHFS_I(i)->start_block +
-+                              sblk->directory_table_start;
-+      int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count;
-+      struct squashfs_dir_header dirh;
-+      struct squashfs_dir_entry *dire;
-+
-+      TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
-+
-+      dire = kmalloc(sizeof(struct squashfs_dir_entry) +
-+              SQUASHFS_NAME_LEN + 1, GFP_KERNEL);
-+      if (dire == NULL) {
-+              ERROR("Failed to allocate squashfs_dir_entry\n");
-+              goto exit_lookup;
-+      }
-+
-+      if (len > SQUASHFS_NAME_LEN)
-+              goto exit_lookup;
-+
-+      length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
-+                              SQUASHFS_I(i)->u.s2.directory_index_start,
-+                              SQUASHFS_I(i)->u.s2.directory_index_offset,
-+                              SQUASHFS_I(i)->u.s2.directory_index_count, name, len);
-+
-+      while (length < i_size_read(i)) {
-+              /* read directory header */
-+              if (msblk->swap) {
-+                      struct squashfs_dir_header sdirh;
-+                      if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block,
-+                                       next_offset, sizeof(sdirh), &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += sizeof(sdirh);
-+                      SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
-+              } else {
-+                      if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block,
-+                                      next_offset, sizeof(dirh), &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += sizeof(dirh);
-+              }
-+
-+              dir_count = dirh.count + 1;
-+              while (dir_count--) {
-+                      if (msblk->swap) {
-+                              struct squashfs_dir_entry sdire;
-+                              if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block,
-+                                              next_offset, sizeof(sdire), &next_block, &next_offset))
-+                                      goto failed_read;
-+                              
-+                              length += sizeof(sdire);
-+                              SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
-+                      } else {
-+                              if (!squashfs_get_cached_block(i->i_sb, dire, next_block,
-+                                              next_offset, sizeof(*dire), &next_block, &next_offset))
-+                                      goto failed_read;
-+
-+                              length += sizeof(*dire);
-+                      }
-+
-+                      if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block,
-+                                      next_offset, dire->size + 1, &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += dire->size + 1;
-+
-+                      if (name[0] < dire->name[0])
-+                              goto exit_lookup;
-+
-+                      if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
-+                              squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,
-+                                                              dire->offset);
-+
-+                              TRACE("calling squashfs_iget for directory entry %s, inode"
-+                                      "  %x:%x, %d\n", name, dirh.start_block, dire->offset,
-+                                      dirh.inode_number + dire->inode_number);
-+
-+                              inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);
-+
-+                              goto exit_lookup;
-+                      }
-+              }
-+      }
-+
-+exit_lookup:
-+      kfree(dire);
-+      if (inode)
-+              return d_splice_alias(inode, dentry);
-+      d_add(dentry, inode);
-+      return ERR_PTR(0);
-+
-+failed_read:
-+      ERROR("Unable to read directory block [%llx:%x]\n", next_block,
-+              next_offset);
-+      goto exit_lookup;
-+}
-+
-+
-+const struct inode_operations squashfs_dir_inode_ops = {
-+      .lookup = squashfs_lookup
-+};
-diff -uNr a/fs/squashfs/squashfs2_0.c b/fs/squashfs/squashfs2_0.c
---- a/fs/squashfs/squashfs2_0.c        1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/squashfs2_0.c        2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,740 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * squashfs2_0.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+
-+#include "squashfs.h"
-+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
-+static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
-+                              struct nameidata *);
-+
-+static struct file_operations squashfs_dir_ops_2 = {
-+      .read = generic_read_dir,
-+      .readdir = squashfs_readdir_2
-+};
-+
-+static struct inode_operations squashfs_dir_inode_ops_2 = {
-+      .lookup = squashfs_lookup_2
-+};
-+
-+static unsigned char squashfs_filetype_table[] = {
-+      DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
-+};
-+
-+static int read_fragment_index_table_2(struct super_block *s)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+
-+      if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
-+                                      (sblk->fragments), GFP_KERNEL))) {
-+              ERROR("Failed to allocate uid/gid table\n");
-+              return 0;
-+      }
-+   
-+      if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
-+                                      !squashfs_read_data(s, (char *)
-+                                      msblk->fragment_index_2,
-+                                      sblk->fragment_table_start,
-+                                      SQUASHFS_FRAGMENT_INDEX_BYTES_2
-+                                      (sblk->fragments) |
-+                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
-+              ERROR("unable to read fragment index table\n");
-+              return 0;
-+      }
-+
-+      if (msblk->swap) {
-+              int i;
-+              unsigned int fragment;
-+
-+              for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
-+                                                                      i++) {
-+                      SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
-+                                              &msblk->fragment_index_2[i], 1);
-+                      msblk->fragment_index_2[i] = fragment;
-+              }
-+      }
-+
-+      return 1;
-+}
-+
-+
-+static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
-+                              long long *fragment_start_block,
-+                              unsigned int *fragment_size)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      long long start_block =
-+              msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
-+      int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
-+      struct squashfs_fragment_entry_2 fragment_entry;
-+
-+      if (msblk->swap) {
-+              struct squashfs_fragment_entry_2 sfragment_entry;
-+
-+              if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
-+                                      start_block, offset,
-+                                      sizeof(sfragment_entry), &start_block,
-+                                      &offset))
-+                      goto out;
-+              SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
-+      } else
-+              if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
-+                                      start_block, offset,
-+                                      sizeof(fragment_entry), &start_block,
-+                                      &offset))
-+                      goto out;
-+
-+      *fragment_start_block = fragment_entry.start_block;
-+      *fragment_size = fragment_entry.size;
-+
-+      return 1;
-+
-+out:
-+      return 0;
-+}
-+
-+
-+static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
-+              struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
-+{
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+
-+      i->i_ino = ino;
-+      i->i_mtime.tv_sec = sblk->mkfs_time;
-+      i->i_atime.tv_sec = sblk->mkfs_time;
-+      i->i_ctime.tv_sec = sblk->mkfs_time;
-+      i->i_uid = msblk->uid[inodeb->uid];
-+      i->i_mode = inodeb->mode;
-+      i->i_nlink = 1;
-+      i->i_size = 0;
-+      if (inodeb->guid == SQUASHFS_GUIDS)
-+              i->i_gid = i->i_uid;
-+      else
-+              i->i_gid = msblk->guid[inodeb->guid];
-+}
-+
-+
-+static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)
-+{
-+      struct super_block *s = i->i_sb;
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      unsigned int block = SQUASHFS_INODE_BLK(inode) +
-+              sblk->inode_table_start;
-+      unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
-+      unsigned int ino = SQUASHFS_MK_VFS_INODE(block -
-+              sblk->inode_table_start, offset);
-+      long long next_block;
-+      unsigned int next_offset;
-+      union squashfs_inode_header_2 id, sid;
-+      struct squashfs_base_inode_header_2 *inodeb = &id.base,
-+                                        *sinodeb = &sid.base;
-+
-+      TRACE("Entered squashfs_read_inode_2\n");
-+
-+      if (msblk->swap) {
-+              if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
-+                                      offset, sizeof(*sinodeb), &next_block,
-+                                      &next_offset))
-+                      goto failed_read;
-+              SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
-+                                      sizeof(*sinodeb));
-+      } else
-+              if (!squashfs_get_cached_block(s, (char *) inodeb, block,
-+                                      offset, sizeof(*inodeb), &next_block,
-+                                      &next_offset))
-+                      goto failed_read;
-+
-+      squashfs_new_inode(msblk, i, inodeb, ino);
-+
-+      switch(inodeb->inode_type) {
-+              case SQUASHFS_FILE_TYPE: {
-+                      struct squashfs_reg_inode_header_2 *inodep = &id.reg;
-+                      struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
-+                      long long frag_blk;
-+                      unsigned int frag_size = 0;
-+                              
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
-+                      } else
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              inodep, block, offset,
-+                                              sizeof(*inodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+
-+                      frag_blk = SQUASHFS_INVALID_BLK;
-+                      if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
-+                                      !get_fragment_location_2(s,
-+                                      inodep->fragment, &frag_blk, &frag_size))
-+                              goto failed_read;
-+                              
-+                      i->i_size = inodep->file_size;
-+                      i->i_fop = &generic_ro_fops;
-+                      i->i_mode |= S_IFREG;
-+                      i->i_mtime.tv_sec = inodep->mtime;
-+                      i->i_atime.tv_sec = inodep->mtime;
-+                      i->i_ctime.tv_sec = inodep->mtime;
-+                      i->i_blocks = ((i->i_size - 1) >> 9) + 1;
-+                      SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
-+                      SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
-+                      SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
-+                      SQUASHFS_I(i)->start_block = inodep->start_block;
-+                      SQUASHFS_I(i)->u.s1.block_list_start = next_block;
-+                      SQUASHFS_I(i)->offset = next_offset;
-+                      i->i_data.a_ops = &squashfs_aops;
-+
-+                      TRACE("File inode %x:%x, start_block %x, "
-+                                      "block_list_start %llx, offset %x\n",
-+                                      SQUASHFS_INODE_BLK(inode), offset,
-+                                      inodep->start_block, next_block,
-+                                      next_offset);
-+                      break;
-+              }
-+              case SQUASHFS_DIR_TYPE: {
-+                      struct squashfs_dir_inode_header_2 *inodep = &id.dir;
-+                      struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
-+
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
-+                      } else
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              inodep, block, offset,
-+                                              sizeof(*inodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+
-+                      i->i_size = inodep->file_size;
-+                      i->i_op = &squashfs_dir_inode_ops_2;
-+                      i->i_fop = &squashfs_dir_ops_2;
-+                      i->i_mode |= S_IFDIR;
-+                      i->i_mtime.tv_sec = inodep->mtime;
-+                      i->i_atime.tv_sec = inodep->mtime;
-+                      i->i_ctime.tv_sec = inodep->mtime;
-+                      SQUASHFS_I(i)->start_block = inodep->start_block;
-+                      SQUASHFS_I(i)->offset = inodep->offset;
-+                      SQUASHFS_I(i)->u.s2.directory_index_count = 0;
-+                      SQUASHFS_I(i)->u.s2.parent_inode = 0;
-+
-+                      TRACE("Directory inode %x:%x, start_block %x, offset "
-+                                      "%x\n", SQUASHFS_INODE_BLK(inode),
-+                                      offset, inodep->start_block,
-+                                      inodep->offset);
-+                      break;
-+              }
-+              case SQUASHFS_LDIR_TYPE: {
-+                      struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
-+                      struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
-+
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
-+                                              sinodep);
-+                      } else
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              inodep, block, offset,
-+                                              sizeof(*inodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+
-+                      i->i_size = inodep->file_size;
-+                      i->i_op = &squashfs_dir_inode_ops_2;
-+                      i->i_fop = &squashfs_dir_ops_2;
-+                      i->i_mode |= S_IFDIR;
-+                      i->i_mtime.tv_sec = inodep->mtime;
-+                      i->i_atime.tv_sec = inodep->mtime;
-+                      i->i_ctime.tv_sec = inodep->mtime;
-+                      SQUASHFS_I(i)->start_block = inodep->start_block;
-+                      SQUASHFS_I(i)->offset = inodep->offset;
-+                      SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
-+                      SQUASHFS_I(i)->u.s2.directory_index_offset =
-+                                                              next_offset;
-+                      SQUASHFS_I(i)->u.s2.directory_index_count =
-+                                                              inodep->i_count;
-+                      SQUASHFS_I(i)->u.s2.parent_inode = 0;
-+
-+                      TRACE("Long directory inode %x:%x, start_block %x, "
-+                                      "offset %x\n",
-+                                      SQUASHFS_INODE_BLK(inode), offset,
-+                                      inodep->start_block, inodep->offset);
-+                      break;
-+              }
-+              case SQUASHFS_SYMLINK_TYPE: {
-+                      struct squashfs_symlink_inode_header_2 *inodep =
-+                                                              &id.symlink;
-+                      struct squashfs_symlink_inode_header_2 *sinodep =
-+                                                              &sid.symlink;
-+      
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
-+                                                              sinodep);
-+                      } else
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              inodep, block, offset,
-+                                              sizeof(*inodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+
-+                      i->i_size = inodep->symlink_size;
-+                      i->i_op = &page_symlink_inode_operations;
-+                      i->i_data.a_ops = &squashfs_symlink_aops;
-+                      i->i_mode |= S_IFLNK;
-+                      SQUASHFS_I(i)->start_block = next_block;
-+                      SQUASHFS_I(i)->offset = next_offset;
-+
-+                      TRACE("Symbolic link inode %x:%x, start_block %llx, "
-+                                      "offset %x\n",
-+                                      SQUASHFS_INODE_BLK(inode), offset,
-+                                      next_block, next_offset);
-+                      break;
-+               }
-+               case SQUASHFS_BLKDEV_TYPE:
-+               case SQUASHFS_CHRDEV_TYPE: {
-+                      struct squashfs_dev_inode_header_2 *inodep = &id.dev;
-+                      struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
-+
-+                      if (msblk->swap) {
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              sinodep, block, offset,
-+                                              sizeof(*sinodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+                              SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
-+                      } else  
-+                              if (!squashfs_get_cached_block(s, (char *)
-+                                              inodep, block, offset,
-+                                              sizeof(*inodep), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+
-+                      i->i_mode |= (inodeb->inode_type ==
-+                                      SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :
-+                                      S_IFBLK;
-+                      init_special_inode(i, i->i_mode,
-+                                      old_decode_dev(inodep->rdev));
-+
-+                      TRACE("Device inode %x:%x, rdev %x\n",
-+                                      SQUASHFS_INODE_BLK(inode), offset,
-+                                      inodep->rdev);
-+                      break;
-+               }
-+               case SQUASHFS_FIFO_TYPE:
-+               case SQUASHFS_SOCKET_TYPE: {
-+
-+                      i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
-+                                                      ? S_IFIFO : S_IFSOCK;
-+                      init_special_inode(i, i->i_mode, 0);
-+                      break;
-+               }
-+               default:
-+                      ERROR("Unknown inode type %d in squashfs_iget!\n",
-+                                      inodeb->inode_type);
-+                      goto failed_read1;
-+      }
-+      
-+      return 1;
-+
-+failed_read:
-+      ERROR("Unable to read inode [%x:%x]\n", block, offset);
-+
-+failed_read1:
-+      return 0;
-+}
-+
-+
-+static int get_dir_index_using_offset(struct super_block *s, long long 
-+                              *next_block, unsigned int *next_offset,
-+                              long long index_start,
-+                              unsigned int index_offset, int i_count,
-+                              long long f_pos)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      int i, length = 0;
-+      struct squashfs_dir_index_2 index;
-+
-+      TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
-+                                      i_count, (unsigned int) f_pos);
-+
-+      if (f_pos == 0)
-+              goto finish;
-+
-+      for (i = 0; i < i_count; i++) {
-+              if (msblk->swap) {
-+                      struct squashfs_dir_index_2 sindex;
-+                      squashfs_get_cached_block(s, (char *) &sindex,
-+                                      index_start, index_offset,
-+                                      sizeof(sindex), &index_start,
-+                                      &index_offset);
-+                      SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
-+              } else
-+                      squashfs_get_cached_block(s, (char *) &index,
-+                                      index_start, index_offset,
-+                                      sizeof(index), &index_start,
-+                                      &index_offset);
-+
-+              if (index.index > f_pos)
-+                      break;
-+
-+              squashfs_get_cached_block(s, NULL, index_start, index_offset,
-+                                      index.size + 1, &index_start,
-+                                      &index_offset);
-+
-+              length = index.index;
-+              *next_block = index.start_block + sblk->directory_table_start;
-+      }
-+
-+      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
-+
-+finish:
-+      return length;
-+}
-+
-+
-+static int get_dir_index_using_name(struct super_block *s, long long
-+                              *next_block, unsigned int *next_offset,
-+                              long long index_start,
-+                              unsigned int index_offset, int i_count,
-+                              const char *name, int size)
-+{
-+      struct squashfs_sb_info *msblk = s->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      int i, length = 0;
-+      struct squashfs_dir_index_2 *index;
-+      char *str;
-+
-+      TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
-+
-+      if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
-+              (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
-+              ERROR("Failed to allocate squashfs_dir_index\n");
-+              goto failure;
-+      }
-+
-+      index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);
-+      strncpy(str, name, size);
-+      str[size] = '\0';
-+
-+      for (i = 0; i < i_count; i++) {
-+              if (msblk->swap) {
-+                      struct squashfs_dir_index_2 sindex;
-+                      squashfs_get_cached_block(s, (char *) &sindex,
-+                                      index_start, index_offset,
-+                                      sizeof(sindex), &index_start,
-+                                      &index_offset);
-+                      SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
-+              } else
-+                      squashfs_get_cached_block(s, (char *) index,
-+                                      index_start, index_offset,
-+                                      sizeof(struct squashfs_dir_index_2),
-+                                      &index_start, &index_offset);
-+
-+              squashfs_get_cached_block(s, index->name, index_start,
-+                                      index_offset, index->size + 1,
-+                                      &index_start, &index_offset);
-+
-+              index->name[index->size + 1] = '\0';
-+
-+              if (strcmp(index->name, str) > 0)
-+                      break;
-+
-+              length = index->index;
-+              *next_block = index->start_block + sblk->directory_table_start;
-+      }
-+
-+      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
-+      kfree(str);
-+failure:
-+      return length;
-+}
-+
-+              
-+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
-+{
-+      struct inode *i = file->f_dentry->d_inode;
-+      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      long long next_block = SQUASHFS_I(i)->start_block +
-+              sblk->directory_table_start;
-+      int next_offset = SQUASHFS_I(i)->offset, length = 0,
-+              dir_count;
-+      struct squashfs_dir_header_2 dirh;
-+      struct squashfs_dir_entry_2 *dire;
-+
-+      TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
-+
-+      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
-+              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
-+              ERROR("Failed to allocate squashfs_dir_entry\n");
-+              goto finish;
-+      }
-+
-+      length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
-+                              SQUASHFS_I(i)->u.s2.directory_index_start,
-+                              SQUASHFS_I(i)->u.s2.directory_index_offset,
-+                              SQUASHFS_I(i)->u.s2.directory_index_count,
-+                              file->f_pos);
-+
-+      while (length < i_size_read(i)) {
-+              /* read directory header */
-+              if (msblk->swap) {
-+                      struct squashfs_dir_header_2 sdirh;
-+                      
-+                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
-+                                      next_block, next_offset, sizeof(sdirh),
-+                                      &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += sizeof(sdirh);
-+                      SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
-+              } else {
-+                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
-+                                      next_block, next_offset, sizeof(dirh),
-+                                      &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += sizeof(dirh);
-+              }
-+
-+              dir_count = dirh.count + 1;
-+              while (dir_count--) {
-+                      if (msblk->swap) {
-+                              struct squashfs_dir_entry_2 sdire;
-+                              if (!squashfs_get_cached_block(i->i_sb, (char *)
-+                                              &sdire, next_block, next_offset,
-+                                              sizeof(sdire), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+                              
-+                              length += sizeof(sdire);
-+                              SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
-+                      } else {
-+                              if (!squashfs_get_cached_block(i->i_sb, (char *)
-+                                              dire, next_block, next_offset,
-+                                              sizeof(*dire), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+
-+                              length += sizeof(*dire);
-+                      }
-+
-+                      if (!squashfs_get_cached_block(i->i_sb, dire->name,
-+                                              next_block, next_offset,
-+                                              dire->size + 1, &next_block,
-+                                              &next_offset))
-+                              goto failed_read;
-+
-+                      length += dire->size + 1;
-+
-+                      if (file->f_pos >= length)
-+                              continue;
-+
-+                      dire->name[dire->size + 1] = '\0';
-+
-+                      TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
-+                                      (unsigned int) dirent, dire->name,
-+                                      dire->size + 1, (int) file->f_pos,
-+                                      dirh.start_block, dire->offset,
-+                                      squashfs_filetype_table[dire->type]);
-+
-+                      if (filldir(dirent, dire->name, dire->size + 1,
-+                                      file->f_pos, SQUASHFS_MK_VFS_INODE(
-+                                      dirh.start_block, dire->offset),
-+                                      squashfs_filetype_table[dire->type])
-+                                      < 0) {
-+                              TRACE("Filldir returned less than 0\n");
-+                              goto finish;
-+                      }
-+                      file->f_pos = length;
-+              }
-+      }
-+
-+finish:
-+      kfree(dire);
-+      return 0;
-+
-+failed_read:
-+      ERROR("Unable to read directory block [%llx:%x]\n", next_block,
-+              next_offset);
-+      kfree(dire);
-+      return 0;
-+}
-+
-+
-+static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
-+                              struct nameidata *nd)
-+{
-+      const unsigned char *name = dentry->d_name.name;
-+      int len = dentry->d_name.len;
-+      struct inode *inode = NULL;
-+      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+      long long next_block = SQUASHFS_I(i)->start_block +
-+                              sblk->directory_table_start;
-+      int next_offset = SQUASHFS_I(i)->offset, length = 0,
-+                              dir_count;
-+      struct squashfs_dir_header_2 dirh;
-+      struct squashfs_dir_entry_2 *dire;
-+      int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
-+
-+      TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);
-+
-+      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
-+              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
-+              ERROR("Failed to allocate squashfs_dir_entry\n");
-+              goto exit_loop;
-+      }
-+
-+      if (len > SQUASHFS_NAME_LEN)
-+              goto exit_loop;
-+
-+      length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
-+                              SQUASHFS_I(i)->u.s2.directory_index_start,
-+                              SQUASHFS_I(i)->u.s2.directory_index_offset,
-+                              SQUASHFS_I(i)->u.s2.directory_index_count, name,
-+                              len);
-+
-+      while (length < i_size_read(i)) {
-+              /* read directory header */
-+              if (msblk->swap) {
-+                      struct squashfs_dir_header_2 sdirh;
-+                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
-+                                      next_block, next_offset, sizeof(sdirh),
-+                                      &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += sizeof(sdirh);
-+                      SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
-+              } else {
-+                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
-+                                      next_block, next_offset, sizeof(dirh),
-+                                      &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += sizeof(dirh);
-+              }
-+
-+              dir_count = dirh.count + 1;
-+              while (dir_count--) {
-+                      if (msblk->swap) {
-+                              struct squashfs_dir_entry_2 sdire;
-+                              if (!squashfs_get_cached_block(i->i_sb, (char *)
-+                                              &sdire, next_block,next_offset,
-+                                              sizeof(sdire), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+                              
-+                              length += sizeof(sdire);
-+                              SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
-+                      } else {
-+                              if (!squashfs_get_cached_block(i->i_sb, (char *)
-+                                              dire, next_block,next_offset,
-+                                              sizeof(*dire), &next_block,
-+                                              &next_offset))
-+                                      goto failed_read;
-+
-+                              length += sizeof(*dire);
-+                      }
-+
-+                      if (!squashfs_get_cached_block(i->i_sb, dire->name,
-+                                      next_block, next_offset, dire->size + 1,
-+                                      &next_block, &next_offset))
-+                              goto failed_read;
-+
-+                      length += dire->size + 1;
-+
-+                      if (sorted && name[0] < dire->name[0])
-+                              goto exit_loop;
-+
-+                      if ((len == dire->size + 1) && !strncmp(name,
-+                                              dire->name, len)) {
-+                              squashfs_inode_t ino =
-+                                      SQUASHFS_MKINODE(dirh.start_block,
-+                                      dire->offset);
-+                              unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,
-+                                      dire->offset);
-+
-+                              TRACE("calling squashfs_iget for directory "
-+                                      "entry %s, inode %x:%x, %lld\n", name,
-+                                      dirh.start_block, dire->offset, ino);
-+
-+                              inode = squashfs_iget(i->i_sb, ino, inode_number);
-+
-+                              goto exit_loop;
-+                      }
-+              }
-+      }
-+
-+exit_loop:
-+      kfree(dire);
-+      d_add(dentry, inode);
-+      return ERR_PTR(0);
-+
-+failed_read:
-+      ERROR("Unable to read directory block [%llx:%x]\n", next_block,
-+              next_offset);
-+      goto exit_loop;
-+}
-+
-+
-+int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
-+{
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+
-+      msblk->read_inode = squashfs_read_inode_2;
-+      msblk->read_fragment_index_table = read_fragment_index_table_2;
-+
-+      sblk->bytes_used = sblk->bytes_used_2;
-+      sblk->uid_start = sblk->uid_start_2;
-+      sblk->guid_start = sblk->guid_start_2;
-+      sblk->inode_table_start = sblk->inode_table_start_2;
-+      sblk->directory_table_start = sblk->directory_table_start_2;
-+      sblk->fragment_table_start = sblk->fragment_table_start_2;
-+
-+      return 1;
-+}
-diff -uNr a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
---- a/fs/squashfs/squashfs.h   1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/squashfs.h   2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,122 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * squashfs.h
-+ */
-+
-+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
-+#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
-+#endif
-+
-+#ifdef SQUASHFS_TRACE
-+#define TRACE(s, args...)     printk(KERN_NOTICE "SQUASHFS: "s, ## args)
-+#else
-+#define TRACE(s, args...)     {}
-+#endif
-+
-+#define ERROR(s, args...)     printk(KERN_ERR "SQUASHFS error: "s, ## args)
-+
-+#define SERROR(s, args...)    do { \
-+                              if (!silent) \
-+                              printk(KERN_ERR "SQUASHFS error: "s, ## args);\
-+                              } while(0)
-+
-+#define WARNING(s, args...)   printk(KERN_WARNING "SQUASHFS: "s, ## args)
-+
-+static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
-+{
-+      return list_entry(inode, struct squashfs_inode_info, vfs_inode);
-+}
-+
-+/* block.c */
-+extern unsigned int squashfs_read_data(struct super_block *, char *,
-+                              long long, unsigned int, long long *, int);
-+extern int squashfs_get_cached_block(struct super_block *, void *,
-+                              long long, unsigned int, int, long long *, unsigned int *);
-+
-+/* cache.c */
-+extern struct squashfs_cache_entry *squashfs_cache_get(struct super_block *,
-+      struct squashfs_cache *, long long, int);
-+extern void squashfs_cache_put(struct squashfs_cache *,
-+                              struct squashfs_cache_entry *);
-+extern void squashfs_cache_delete(struct squashfs_cache *);
-+extern struct squashfs_cache *squashfs_cache_init(char *, int, int, int);
-+
-+/* export.c */
-+extern int read_inode_lookup_table(struct super_block *);
-+
-+/* file.c */
-+extern long long read_blocklist(struct inode *, int, int, char *,
-+                              unsigned short **, unsigned int *);
-+
-+/* fragment.c */
-+extern int get_fragment_location(struct super_block *, unsigned int,
-+                              long long *, unsigned int *);
-+extern void release_cached_fragment(struct squashfs_sb_info *,
-+                              struct squashfs_cache_entry *);
-+extern struct squashfs_cache_entry *get_cached_fragment(struct super_block *,
-+                              long long, int);
-+extern int read_fragment_index_table(struct super_block *);
-+
-+/* id.c */
-+extern int get_id(struct super_block *, unsigned int, unsigned int *);
-+extern int read_id_index_table(struct super_block *);
-+
-+/* inode.c */
-+extern struct inode *squashfs_iget(struct super_block *, squashfs_inode_t,
-+                      unsigned int);
-+extern int squashfs_read_inode(struct inode *, squashfs_inode_t);
-+
-+/*
-+ * Inodes and files operations
-+ */
-+
-+/* dir.c */
-+extern const struct file_operations squashfs_dir_ops;
-+
-+/* export.c */
-+extern const struct export_operations squashfs_export_ops;
-+
-+/* file.c */
-+extern const struct address_space_operations squashfs_aops;
-+
-+/* namei.c */
-+extern const struct inode_operations squashfs_dir_inode_ops;
-+
-+/* symlink.c */
-+extern const struct address_space_operations squashfs_symlink_aops;
-+
-+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
-+extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
-+#else
-+static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
-+{
-+      return 0;
-+}
-+#endif
-+
-+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
-+extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
-+#else
-+static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
-+{
-+      return 0;
-+}
-+#endif
-diff -uNr a/fs/squashfs/super.c b/fs/squashfs/super.c
---- a/fs/squashfs/super.c      1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/super.c      2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,381 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * super.c
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+#include <linux/module.h>
-+#include <linux/zlib.h>
-+#include <linux/fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/vmalloc.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/exportfs.h>
-+
-+#include "squashfs.h"
-+
-+static struct file_system_type squashfs_fs_type;
-+static struct super_operations squashfs_super_ops;
-+
-+static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
-+{
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+
-+      msblk->read_inode = squashfs_read_inode;
-+      msblk->read_blocklist = read_blocklist;
-+      msblk->read_fragment_index_table = read_fragment_index_table;
-+
-+      if (sblk->s_major == 1) {
-+              if (!squashfs_1_0_supported(msblk)) {
-+                      SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
-+                              "are unsupported\n");
-+                      SERROR("Please recompile with Squashfs 1.0 support enabled\n");
-+                      return 0;
-+              }
-+      } else if (sblk->s_major == 2) {
-+              if (!squashfs_2_0_supported(msblk)) {
-+                      SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
-+                              "are unsupported\n");
-+                      SERROR("Please recompile with Squashfs 2.0 support enabled\n");
-+                      return 0;
-+              }
-+      } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
-+                      SQUASHFS_MINOR) {
-+              SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
-+                              "filesystem\n", sblk->s_major, sblk->s_minor);
-+              SERROR("Please update your kernel\n");
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+
-+static int squashfs_fill_super(struct super_block *s, void *data, int silent)
-+{
-+      struct squashfs_sb_info *msblk;
-+      struct squashfs_super_block *sblk;
-+      char b[BDEVNAME_SIZE];
-+      struct inode *root;
-+
-+      TRACE("Entered squashfs_fill_superblock\n");
-+
-+      s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL);
-+      if (s->s_fs_info == NULL) {
-+              ERROR("Failed to allocate superblock\n");
-+              goto failure;
-+      }
-+      msblk = s->s_fs_info;
-+
-+      msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize());
-+      if (msblk->stream.workspace == NULL) {
-+              ERROR("Failed to allocate zlib workspace\n");
-+              goto failure;
-+      }
-+      sblk = &msblk->sblk;
-+      
-+      msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
-+      msblk->devblksize_log2 = ffz(~msblk->devblksize);
-+
-+      mutex_init(&msblk->read_data_mutex);
-+      mutex_init(&msblk->read_page_mutex);
-+      mutex_init(&msblk->meta_index_mutex);
-+      
-+      /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not
-+       * beyond filesystem end.  As we're using squashfs_read_data to read sblk here,
-+       * first set sblk->bytes_used to a useful value */
-+      sblk->bytes_used = sizeof(struct squashfs_super_block);
-+      if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
-+                                      sizeof(struct squashfs_super_block) |
-+                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {
-+              SERROR("unable to read superblock\n");
-+              goto failed_mount;
-+      }
-+
-+      /* Check it is a SQUASHFS superblock */
-+      if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
-+              if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
-+                      struct squashfs_super_block ssblk;
-+
-+                      WARNING("Mounting a different endian SQUASHFS filesystem on %s\n",
-+                              bdevname(s->s_bdev, b));
-+
-+                      //SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
-+                      memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
-+                      msblk->swap = 1;
-+              } else  {
-+                      SERROR("Can't find a SQUASHFS superblock on %s\n",
-+                                                      bdevname(s->s_bdev, b));
-+                      goto failed_mount;
-+              }
-+      }
-+
-+      /* Check the MAJOR & MINOR versions */
-+      if(!supported_squashfs_filesystem(msblk, silent))
-+              goto failed_mount;
-+
-+      /* Check the filesystem does not extend beyond the end of the
-+         block device */
-+      if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))
-+              goto failed_mount;
-+
-+      /* Check the root inode for sanity */
-+      if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)
-+              goto failed_mount;
-+
-+      TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
-+      TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags)
-+                                      ? "un" : "");
-+      TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
-+                                      ? "un" : "");
-+      TRACE("Check data is %spresent in the filesystem\n",
-+                                      SQUASHFS_CHECK_DATA(sblk->flags) ?  "" : "not ");
-+      TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
-+      TRACE("Block size %d\n", sblk->block_size);
-+      TRACE("Number of inodes %d\n", sblk->inodes);
-+      if (sblk->s_major > 1)
-+              TRACE("Number of fragments %d\n", sblk->fragments);
-+      TRACE("Number of ids %d\n", sblk->no_ids);
-+      TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
-+      TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
-+      if (sblk->s_major > 1)
-+              TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start);
-+      TRACE("sblk->id_table_start %llx\n", sblk->id_table_start);
-+
-+      s->s_maxbytes = MAX_LFS_FILESIZE;
-+      s->s_flags |= MS_RDONLY;
-+      s->s_op = &squashfs_super_ops;
-+
-+      msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS,
-+              SQUASHFS_METADATA_SIZE, 0);
-+      if (msblk->block_cache == NULL)
-+              goto failed_mount;
-+
-+      /* Allocate read_page block */
-+      msblk->read_page = vmalloc(sblk->block_size);
-+      if (msblk->read_page == NULL) {
-+              ERROR("Failed to allocate read_page block\n");
-+              goto failed_mount;
-+      }
-+
-+      /* Allocate and read id index table */
-+      if (read_id_index_table(s) == 0)
-+              goto failed_mount;
-+
-+      if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
-+              goto allocate_root;
-+
-+      msblk->fragment_cache = squashfs_cache_init("fragment",
-+              SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1);
-+      if (msblk->fragment_cache == NULL)
-+              goto failed_mount;
-+
-+      /* Allocate and read fragment index table */
-+      if (msblk->read_fragment_index_table(s) == 0)
-+              goto failed_mount;
-+
-+      if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)
-+              goto allocate_root;
-+
-+      /* Allocate and read inode lookup table */
-+      if (read_inode_lookup_table(s) == 0)
-+              goto failed_mount;
-+
-+      s->s_export_op = &squashfs_export_ops;
-+
-+allocate_root:
-+      root = new_inode(s);
-+      if ((msblk->read_inode)(root, sblk->root_inode) == 0)
-+              goto failed_mount;
-+      insert_inode_hash(root);
-+
-+      s->s_root = d_alloc_root(root);
-+      if (s->s_root == NULL) {
-+              ERROR("Root inode create failed\n");
-+              iput(root);
-+              goto failed_mount;
-+      }
-+
-+      TRACE("Leaving squashfs_fill_super\n");
-+      return 0;
-+
-+failed_mount:
-+      kfree(msblk->inode_lookup_table);
-+      kfree(msblk->fragment_index);
-+      squashfs_cache_delete(msblk->fragment_cache);
-+      kfree(msblk->id_table);
-+      vfree(msblk->read_page);
-+      squashfs_cache_delete(msblk->block_cache);
-+      kfree(msblk->fragment_index_2);
-+      vfree(msblk->stream.workspace);
-+      kfree(s->s_fs_info);
-+      s->s_fs_info = NULL;
-+      return -EINVAL;
-+
-+failure:
-+      return -ENOMEM;
-+}
-+
-+
-+static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-+{
-+      struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
-+      struct squashfs_super_block *sblk = &msblk->sblk;
-+
-+      TRACE("Entered squashfs_statfs\n");
-+
-+      buf->f_type = SQUASHFS_MAGIC;
-+      buf->f_bsize = sblk->block_size;
-+      buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
-+      buf->f_bfree = buf->f_bavail = 0;
-+      buf->f_files = sblk->inodes;
-+      buf->f_ffree = 0;
-+      buf->f_namelen = SQUASHFS_NAME_LEN;
-+
-+      return 0;
-+}
-+
-+
-+static int squashfs_remount(struct super_block *s, int *flags, char *data)
-+{
-+      *flags |= MS_RDONLY;
-+      return 0;
-+}
-+
-+
-+static void squashfs_put_super(struct super_block *s)
-+{
-+      if (s->s_fs_info) {
-+              struct squashfs_sb_info *sbi = s->s_fs_info;
-+              squashfs_cache_delete(sbi->block_cache);
-+              squashfs_cache_delete(sbi->fragment_cache);
-+              vfree(sbi->read_page);
-+              kfree(sbi->id_table);
-+              kfree(sbi->fragment_index);
-+              kfree(sbi->fragment_index_2);
-+              kfree(sbi->meta_index);
-+              vfree(sbi->stream.workspace);
-+              kfree(s->s_fs_info);
-+              s->s_fs_info = NULL;
-+      }
-+}
-+
-+
-+static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
-+                              const char *dev_name, void *data, struct vfsmount *mnt)
-+{
-+      return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
-+                              mnt);
-+}
-+
-+
-+static struct kmem_cache * squashfs_inode_cachep;
-+
-+
-+static void init_once(void *foo)
-+{
-+      struct squashfs_inode_info *ei = foo;
-+
-+      inode_init_once(&ei->vfs_inode);
-+}
-+
-+
-+static int __init init_inodecache(void)
-+{
-+      squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
-+          sizeof(struct squashfs_inode_info), 0,
-+              SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once);
-+      if (squashfs_inode_cachep == NULL)
-+              return -ENOMEM;
-+      return 0;
-+}
-+
-+
-+static void destroy_inodecache(void)
-+{
-+      kmem_cache_destroy(squashfs_inode_cachep);
-+}
-+
-+
-+static int __init init_squashfs_fs(void)
-+{
-+      int err = init_inodecache();
-+      if (err)
-+              goto out;
-+
-+      printk(KERN_INFO "squashfs: version 4.0-CVS (2008/07/27) "
-+              "Phillip Lougher\n");
-+
-+      err = register_filesystem(&squashfs_fs_type);
-+      if (err)
-+              destroy_inodecache();
-+
-+out:
-+      return err;
-+}
-+
-+
-+static void __exit exit_squashfs_fs(void)
-+{
-+      unregister_filesystem(&squashfs_fs_type);
-+      destroy_inodecache();
-+}
-+
-+
-+static struct inode *squashfs_alloc_inode(struct super_block *sb)
-+{
-+      struct squashfs_inode_info *ei;
-+      ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
-+      return ei ? &ei->vfs_inode : NULL;
-+}
-+
-+
-+static void squashfs_destroy_inode(struct inode *inode)
-+{
-+      kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
-+}
-+
-+
-+static struct file_system_type squashfs_fs_type = {
-+      .owner = THIS_MODULE,
-+      .name = "squashfs",
-+      .get_sb = squashfs_get_sb,
-+      .kill_sb = kill_block_super,
-+      .fs_flags = FS_REQUIRES_DEV
-+};
-+
-+static struct super_operations squashfs_super_ops = {
-+      .alloc_inode = squashfs_alloc_inode,
-+      .destroy_inode = squashfs_destroy_inode,
-+      .statfs = squashfs_statfs,
-+      .put_super = squashfs_put_super,
-+      .remount_fs = squashfs_remount
-+};
-+
-+module_init(init_squashfs_fs);
-+module_exit(exit_squashfs_fs);
-+MODULE_DESCRIPTION("squashfs 4.0-CVS, a compressed read-only filesystem");
-+MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
-+MODULE_LICENSE("GPL");
-diff -uNr a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
---- a/fs/squashfs/symlink.c    1969-12-31 16:00:00.000000000 -0800
-+++ b/fs/squashfs/symlink.c    2008-08-13 16:14:50.000000000 -0700
-@@ -0,0 +1,85 @@
-+/*
-+ * Squashfs - a compressed read only filesystem for Linux
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * symlink.c
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/vfs.h>
-+#include <linux/zlib.h>
-+#include <linux/buffer_head.h>
-+#include <linux/squashfs_fs.h>
-+#include <linux/squashfs_fs_sb.h>
-+#include <linux/squashfs_fs_i.h>
-+
-+#include "squashfs.h"
-+
-+static int squashfs_symlink_readpage(struct file *file, struct page *page)
-+{
-+      struct inode *inode = page->mapping->host;
-+      int index = page->index << PAGE_CACHE_SHIFT;
-+      long long block = SQUASHFS_I(inode)->start_block;
-+      int offset = SQUASHFS_I(inode)->offset;
-+      void *pageaddr = kmap(page);
-+      int length, bytes, avail_bytes;
-+
-+      TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
-+                              "%llx, offset %x\n", page->index,
-+                              SQUASHFS_I(inode)->start_block,
-+                              SQUASHFS_I(inode)->offset);
-+
-+      for (length = 0; length < index; length += bytes) {
-+              bytes = squashfs_get_cached_block(inode->i_sb, NULL, block,
-+                              offset, PAGE_CACHE_SIZE, &block, &offset);
-+              if (bytes == 0) {
-+                      ERROR("Unable to read symbolic link [%llx:%x]\n",
-+                              block, offset);
-+                      goto skip_read;
-+              }
-+      }
-+
-+      if (length != index) {
-+              ERROR("(squashfs_symlink_readpage) length != index\n");
-+              bytes = 0;
-+              goto skip_read;
-+      }
-+
-+      avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE);
-+
-+      bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset,
-+                              avail_bytes, &block, &offset);
-+      if (bytes == 0)
-+              ERROR("Unable to read symbolic link [%llx:%x]\n", block,
-+                              offset);
-+
-+skip_read:
-+      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
-+      kunmap(page);
-+      flush_dcache_page(page);
-+      SetPageUptodate(page);
-+      unlock_page(page);
-+
-+      return 0;
-+}
-+
-+
-+const struct address_space_operations squashfs_symlink_aops = {
-+      .readpage = squashfs_symlink_readpage
-+};
-diff -uNr a/include/linux/squashfs_fs.h b/include/linux/squashfs_fs.h
---- a/include/linux/squashfs_fs.h      1969-12-31 16:00:00.000000000 -0800
-+++ b/include/linux/squashfs_fs.h      2008-08-13 16:16:05.000000000 -0700
-@@ -0,0 +1,949 @@
-+#ifndef SQUASHFS_FS
-+#define SQUASHFS_FS
-+/*
-+ * Squashfs
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * squashfs_fs.h
-+ */
-+
-+#if 0
-+#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
-+#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
-+#endif
-+#endif
-+
-+#define SQUASHFS_CACHED_FRAGMENTS     CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE     
-+#define SQUASHFS_MAJOR                        4
-+#define SQUASHFS_MINOR                        0
-+#define SQUASHFS_MAGIC                        0x73717368
-+#define SQUASHFS_MAGIC_SWAP           0x68737173
-+#define SQUASHFS_START                        0
-+
-+/* size of metadata (inode and directory) blocks */
-+#define SQUASHFS_METADATA_SIZE                8192
-+#define SQUASHFS_METADATA_LOG         13
-+
-+/* default size of data blocks */
-+#define SQUASHFS_FILE_SIZE            131072
-+#define SQUASHFS_FILE_LOG             17
-+
-+#define SQUASHFS_FILE_MAX_SIZE                1048576
-+
-+/* Max number of uids and gids */
-+#define SQUASHFS_IDS                  65536
-+
-+/* Max length of filename (not 255) */
-+#define SQUASHFS_NAME_LEN             256
-+
-+#define SQUASHFS_INVALID              ((long long) 0xffffffffffff)
-+#define SQUASHFS_INVALID_FRAG         ((unsigned int) 0xffffffff)
-+#define SQUASHFS_INVALID_BLK          ((long long) -1)
-+#define SQUASHFS_USED_BLK             ((long long) -2)
-+
-+/* Filesystem flags */
-+#define SQUASHFS_NOI                  0
-+#define SQUASHFS_NOD                  1
-+#define SQUASHFS_CHECK                        2
-+#define SQUASHFS_NOF                  3
-+#define SQUASHFS_NO_FRAG              4
-+#define SQUASHFS_ALWAYS_FRAG          5
-+#define SQUASHFS_DUPLICATE            6
-+#define SQUASHFS_EXPORT                       7
-+
-+#define SQUASHFS_BIT(flag, bit)               ((flag >> bit) & 1)
-+
-+#define SQUASHFS_UNCOMPRESSED_INODES(flags)   SQUASHFS_BIT(flags, \
-+                                              SQUASHFS_NOI)
-+
-+#define SQUASHFS_UNCOMPRESSED_DATA(flags)     SQUASHFS_BIT(flags, \
-+                                              SQUASHFS_NOD)
-+
-+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)        SQUASHFS_BIT(flags, \
-+                                              SQUASHFS_NOF)
-+
-+#define SQUASHFS_NO_FRAGMENTS(flags)          SQUASHFS_BIT(flags, \
-+                                              SQUASHFS_NO_FRAG)
-+
-+#define SQUASHFS_ALWAYS_FRAGMENTS(flags)      SQUASHFS_BIT(flags, \
-+                                              SQUASHFS_ALWAYS_FRAG)
-+
-+#define SQUASHFS_DUPLICATES(flags)            SQUASHFS_BIT(flags, \
-+                                              SQUASHFS_DUPLICATE)
-+
-+#define SQUASHFS_EXPORTABLE(flags)            SQUASHFS_BIT(flags, \
-+                                              SQUASHFS_EXPORT)
-+
-+#define SQUASHFS_CHECK_DATA(flags)            SQUASHFS_BIT(flags, \
-+                                              SQUASHFS_CHECK)
-+
-+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
-+              duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \
-+              | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
-+              (duplicate_checking << 6) | (exportable << 7))
-+
-+/* Max number of types and file types */
-+#define SQUASHFS_DIR_TYPE             1
-+#define SQUASHFS_FILE_TYPE            2
-+#define SQUASHFS_SYMLINK_TYPE         3
-+#define SQUASHFS_BLKDEV_TYPE          4
-+#define SQUASHFS_CHRDEV_TYPE          5
-+#define SQUASHFS_FIFO_TYPE            6
-+#define SQUASHFS_SOCKET_TYPE          7
-+#define SQUASHFS_LDIR_TYPE            8
-+#define SQUASHFS_LREG_TYPE            9
-+
-+/* 1.0 filesystem type definitions */
-+#define SQUASHFS_TYPES                        5
-+#define SQUASHFS_IPC_TYPE             0
-+
-+/* Flag whether block is compressed or uncompressed, bit is set if block is
-+ * uncompressed */
-+#define SQUASHFS_COMPRESSED_BIT               (1 << 15)
-+
-+#define SQUASHFS_COMPRESSED_SIZE(B)   (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
-+              (B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)
-+
-+#define SQUASHFS_COMPRESSED(B)                (!((B) & SQUASHFS_COMPRESSED_BIT))
-+
-+#define SQUASHFS_COMPRESSED_BIT_BLOCK         (1 << 24)
-+
-+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)     ((B) & \
-+      ~SQUASHFS_COMPRESSED_BIT_BLOCK)
-+
-+#define SQUASHFS_COMPRESSED_BLOCK(B)  (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
-+
-+/*
-+ * Inode number ops.  Inodes consist of a compressed block number, and an
-+ * uncompressed  offset within that block
-+ */
-+#define SQUASHFS_INODE_BLK(a)         ((unsigned int) ((a) >> 16))
-+
-+#define SQUASHFS_INODE_OFFSET(a)      ((unsigned int) ((a) & 0xffff))
-+
-+#define SQUASHFS_MKINODE(A, B)                ((squashfs_inode_t)(((squashfs_inode_t) (A)\
-+                                      << 16) + (B)))
-+
-+/* Compute 32 bit VFS inode number from squashfs inode number */
-+#define SQUASHFS_MK_VFS_INODE(a, b)   ((unsigned int) (((a) << 8) + \
-+                                      ((b) >> 2) + 1))
-+/* XXX */
-+
-+/* Translate between VFS mode and squashfs mode */
-+#define SQUASHFS_MODE(a)              ((a) & 0xfff)
-+
-+/* fragment and fragment table defines */
-+#define SQUASHFS_FRAGMENT_BYTES(A)    ((A) * sizeof(struct squashfs_fragment_entry))
-+
-+#define SQUASHFS_FRAGMENT_INDEX(A)    (SQUASHFS_FRAGMENT_BYTES(A) / \
-+                                      SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)     (SQUASHFS_FRAGMENT_BYTES(A) % \
-+                                              SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_FRAGMENT_INDEXES(A)  ((SQUASHFS_FRAGMENT_BYTES(A) + \
-+                                      SQUASHFS_METADATA_SIZE - 1) / \
-+                                      SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)      (SQUASHFS_FRAGMENT_INDEXES(A) *\
-+                                              sizeof(long long))
-+
-+/* inode lookup table defines */
-+#define SQUASHFS_LOOKUP_BYTES(A)      ((A) * sizeof(squashfs_inode_t))
-+
-+#define SQUASHFS_LOOKUP_BLOCK(A)              (SQUASHFS_LOOKUP_BYTES(A) / \
-+                                              SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A)               (SQUASHFS_LOOKUP_BYTES(A) % \
-+                                              SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_LOOKUP_BLOCKS(A)     ((SQUASHFS_LOOKUP_BYTES(A) + \
-+                                      SQUASHFS_METADATA_SIZE - 1) / \
-+                                      SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_LOOKUP_BLOCK_BYTES(A)        (SQUASHFS_LOOKUP_BLOCKS(A) *\
-+                                      sizeof(long long))
-+
-+/* uid lookup table defines */
-+#define SQUASHFS_ID_BYTES(A)  ((A) * sizeof(unsigned int))
-+
-+#define SQUASHFS_ID_BLOCK(A)          (SQUASHFS_ID_BYTES(A) / \
-+                                              SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_ID_BLOCK_OFFSET(A)           (SQUASHFS_ID_BYTES(A) % \
-+                                              SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_ID_BLOCKS(A) ((SQUASHFS_ID_BYTES(A) + \
-+                                      SQUASHFS_METADATA_SIZE - 1) / \
-+                                      SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_ID_BLOCK_BYTES(A)    (SQUASHFS_ID_BLOCKS(A) *\
-+                                      sizeof(long long))
-+
-+/* cached data constants for filesystem */
-+#define SQUASHFS_CACHED_BLKS          8
-+
-+#define SQUASHFS_MAX_FILE_SIZE_LOG    64
-+
-+#define SQUASHFS_MAX_FILE_SIZE                ((long long) 1 << \
-+                                      (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
-+
-+#define SQUASHFS_MARKER_BYTE          0xff
-+
-+/* meta index cache */
-+#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
-+#define SQUASHFS_META_ENTRIES 31
-+#define SQUASHFS_META_NUMBER  8
-+#define SQUASHFS_SLOTS                4
-+
-+struct meta_entry {
-+      long long               data_block;
-+      unsigned int            index_block;
-+      unsigned short          offset;
-+      unsigned short          pad;
-+};
-+
-+struct meta_index {
-+      unsigned int            inode_number;
-+      unsigned int            offset;
-+      unsigned short          entries;
-+      unsigned short          skip;
-+      unsigned short          locked;
-+      unsigned short          pad;
-+      struct meta_entry       meta_entry[SQUASHFS_META_ENTRIES];
-+};
-+
-+
-+/*
-+ * definitions for structures on disk
-+ */
-+
-+typedef long long             squashfs_block_t;
-+typedef long long             squashfs_inode_t;
-+
-+#define COMPRESSION_ZLIB 1
-+
-+struct squashfs_super_block {
-+      unsigned int            s_magic;
-+      unsigned int            inodes;
-+      unsigned int            mkfs_time /* time of filesystem creation */;
-+      unsigned int            block_size;
-+      unsigned int            fragments;
-+      unsigned short          compression;
-+      unsigned short          block_log;
-+      unsigned short          flags;
-+      unsigned short          no_ids;
-+      unsigned short          s_major;
-+      unsigned short          s_minor;
-+      squashfs_inode_t        root_inode;
-+      long long               bytes_used;
-+      long long               id_table_start;
-+      long long               xattr_table_start;
-+      long long               inode_table_start;
-+      long long               directory_table_start;
-+      long long               fragment_table_start;
-+      long long               lookup_table_start;
-+};
-+
-+struct squashfs_dir_index {
-+      unsigned int            index;
-+      unsigned int            start_block;
-+      unsigned int            size;
-+      unsigned char           name[0];
-+};
-+
-+#define SQUASHFS_BASE_INODE_HEADER            \
-+      unsigned short          inode_type;     \
-+      unsigned short          mode;   \
-+      unsigned short          uid;            \
-+      unsigned short          guid;           \
-+      unsigned int            mtime;          \
-+      unsigned int            inode_number;
-+
-+struct squashfs_base_inode_header {
-+      SQUASHFS_BASE_INODE_HEADER;
-+};
-+
-+struct squashfs_ipc_inode_header {
-+      SQUASHFS_BASE_INODE_HEADER;
-+      unsigned int            nlink;
-+};
-+
-+struct squashfs_dev_inode_header {
-+      SQUASHFS_BASE_INODE_HEADER;
-+      unsigned int            nlink;
-+      unsigned int            rdev;
-+};
-+      
-+struct squashfs_symlink_inode_header {
-+      SQUASHFS_BASE_INODE_HEADER;
-+      unsigned int            nlink;
-+      unsigned int            symlink_size;
-+      char                    symlink[0];
-+};
-+
-+struct squashfs_reg_inode_header {
-+      SQUASHFS_BASE_INODE_HEADER;
-+      unsigned int            start_block;
-+      unsigned int            fragment;
-+      unsigned int            offset;
-+      unsigned int            file_size;
-+      unsigned short          block_list[0];
-+};
-+
-+struct squashfs_lreg_inode_header {
-+      SQUASHFS_BASE_INODE_HEADER;
-+      squashfs_block_t        start_block;
-+      long long               file_size;
-+      long long               sparse;
-+      unsigned int            nlink;
-+      unsigned int            fragment;
-+      unsigned int            offset;
-+      unsigned int            xattr;
-+      unsigned short          block_list[0];
-+};
-+
-+struct squashfs_dir_inode_header {
-+      SQUASHFS_BASE_INODE_HEADER;
-+      unsigned int            start_block;
-+      unsigned int            nlink;
-+      unsigned short          file_size;
-+      unsigned short          offset;
-+      unsigned int            parent_inode;
-+};
-+
-+struct squashfs_ldir_inode_header {
-+      SQUASHFS_BASE_INODE_HEADER;
-+      unsigned int            nlink;
-+      unsigned int            file_size;
-+      unsigned int            start_block;
-+      unsigned int            parent_inode;
-+      unsigned short          i_count;
-+      unsigned short          offset;
-+      struct squashfs_dir_index       index[0];
-+};
-+
-+union squashfs_inode_header {
-+      struct squashfs_base_inode_header       base;
-+      struct squashfs_dev_inode_header        dev;
-+      struct squashfs_symlink_inode_header    symlink;
-+      struct squashfs_reg_inode_header        reg;
-+      struct squashfs_lreg_inode_header       lreg;
-+      struct squashfs_dir_inode_header        dir;
-+      struct squashfs_ldir_inode_header       ldir;
-+      struct squashfs_ipc_inode_header        ipc;
-+};
-+      
-+struct squashfs_dir_entry {
-+      unsigned short          offset;
-+      short                   inode_number;
-+      unsigned short          type;
-+      unsigned short          size;
-+      char                    name[0];
-+};
-+
-+struct squashfs_dir_header {
-+      unsigned int            count;
-+      unsigned int            start_block;
-+      unsigned int            inode_number;
-+};
-+
-+struct squashfs_fragment_entry {
-+      long long               start_block;
-+      unsigned int            size;
-+      unsigned int            unused;
-+};
-+
-+extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
-+extern int squashfs_uncompress_init(void);
-+extern int squashfs_uncompress_exit(void);
-+
-+/*
-+ * macros to convert each packed bitfield structure from little endian to big
-+ * endian and vice versa.  These are needed when creating or using a filesystem
-+ * on a machine with different byte ordering to the target architecture.
-+ *
-+ */
-+
-+#define SQUASHFS_SWAP_START \
-+      int bits;\
-+      int b_pos;\
-+      unsigned long long val;\
-+      unsigned char *s;\
-+      unsigned char *d;
-+
-+#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
-+      SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
-+      SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
-+      SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
-+      SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
-+      SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
-+      SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
-+      SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
-+      SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
-+      SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
-+      SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
-+      SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
-+      SQUASHFS_SWAP((s)->flags, d, 288, 8);\
-+      SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
-+      SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
-+      SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
-+      SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
-+      SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
-+      SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
-+      SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
-+      SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
-+      SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
-+      SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
-+      SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
-+      SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
-+      SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
-+      SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\
-+}
-+
-+#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
-+      SQUASHFS_MEMSET(s, d, n);\
-+      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
-+      SQUASHFS_SWAP((s)->mode, d, 4, 12);\
-+      SQUASHFS_SWAP((s)->uid, d, 16, 8);\
-+      SQUASHFS_SWAP((s)->guid, d, 24, 8);\
-+      SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
-+      SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
-+
-+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
-+}
-+
-+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
-+                      sizeof(struct squashfs_ipc_inode_header))\
-+      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
-+                      sizeof(struct squashfs_dev_inode_header)); \
-+      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
-+      SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
-+}
-+
-+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
-+                      sizeof(struct squashfs_symlink_inode_header));\
-+      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
-+      SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
-+}
-+
-+#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
-+                      sizeof(struct squashfs_reg_inode_header));\
-+      SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
-+      SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
-+      SQUASHFS_SWAP((s)->offset, d, 192, 32);\
-+      SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
-+                      sizeof(struct squashfs_lreg_inode_header));\
-+      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
-+      SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
-+      SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
-+      SQUASHFS_SWAP((s)->offset, d, 224, 32);\
-+      SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
-+}
-+
-+#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
-+                      sizeof(struct squashfs_dir_inode_header));\
-+      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
-+      SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
-+      SQUASHFS_SWAP((s)->offset, d, 147, 13);\
-+      SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
-+      SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
-+                      sizeof(struct squashfs_ldir_inode_header));\
-+      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
-+      SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
-+      SQUASHFS_SWAP((s)->offset, d, 155, 13);\
-+      SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
-+      SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
-+      SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
-+      SQUASHFS_SWAP((s)->index, d, 0, 32);\
-+      SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
-+      SQUASHFS_SWAP((s)->size, d, 64, 8);\
-+}
-+
-+#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
-+      SQUASHFS_SWAP((s)->count, d, 0, 8);\
-+      SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
-+      SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
-+      SQUASHFS_SWAP((s)->offset, d, 0, 13);\
-+      SQUASHFS_SWAP((s)->type, d, 13, 3);\
-+      SQUASHFS_SWAP((s)->size, d, 16, 8);\
-+      SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
-+}
-+
-+#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
-+      SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
-+      SQUASHFS_SWAP((s)->size, d, 64, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)
-+
-+#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
-+      int entry;\
-+      int bit_position;\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, n * 2);\
-+      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
-+                      16)\
-+              SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
-+}
-+
-+#define SQUASHFS_SWAP_INTS(s, d, n) {\
-+      int entry;\
-+      int bit_position;\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, n * 4);\
-+      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
-+                      32)\
-+              SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
-+      int entry;\
-+      int bit_position;\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, n * 8);\
-+      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
-+                      64)\
-+              SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
-+}
-+
-+#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
-+      int entry;\
-+      int bit_position;\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, n * bits / 8);\
-+      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
-+                      bits)\
-+              SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
-+}
-+
-+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
-+#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
-+#define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
-+
-+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
-+
-+struct squashfs_base_inode_header_1 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:4; /* index into uid table */
-+      unsigned int            guid:4; /* index into guid table */
-+} __attribute__ ((packed));
-+
-+struct squashfs_ipc_inode_header_1 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:4; /* index into uid table */
-+      unsigned int            guid:4; /* index into guid table */
-+      unsigned int            type:4;
-+      unsigned int            offset:4;
-+} __attribute__ ((packed));
-+
-+struct squashfs_dev_inode_header_1 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:4; /* index into uid table */
-+      unsigned int            guid:4; /* index into guid table */
-+      unsigned short          rdev;
-+} __attribute__ ((packed));
-+      
-+struct squashfs_symlink_inode_header_1 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:4; /* index into uid table */
-+      unsigned int            guid:4; /* index into guid table */
-+      unsigned short          symlink_size;
-+      char                    symlink[0];
-+} __attribute__ ((packed));
-+
-+struct squashfs_reg_inode_header_1 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:4; /* index into uid table */
-+      unsigned int            guid:4; /* index into guid table */
-+      unsigned int            mtime;
-+      unsigned int            start_block;
-+      unsigned int            file_size:32;
-+      unsigned short          block_list[0];
-+} __attribute__ ((packed));
-+
-+struct squashfs_dir_inode_header_1 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:4; /* index into uid table */
-+      unsigned int            guid:4; /* index into guid table */
-+      unsigned int            file_size:19;
-+      unsigned int            offset:13;
-+      unsigned int            mtime;
-+      unsigned int            start_block:24;
-+} __attribute__  ((packed));
-+
-+union squashfs_inode_header_1 {
-+      struct squashfs_base_inode_header_1     base;
-+      struct squashfs_dev_inode_header_1      dev;
-+      struct squashfs_symlink_inode_header_1  symlink;
-+      struct squashfs_reg_inode_header_1      reg;
-+      struct squashfs_dir_inode_header_1      dir;
-+      struct squashfs_ipc_inode_header_1      ipc;
-+};
-+
-+#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
-+      SQUASHFS_MEMSET(s, d, n);\
-+      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
-+      SQUASHFS_SWAP((s)->mode, d, 4, 12);\
-+      SQUASHFS_SWAP((s)->uid, d, 16, 4);\
-+      SQUASHFS_SWAP((s)->guid, d, 20, 4);
-+
-+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
-+}
-+
-+#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
-+                      sizeof(struct squashfs_ipc_inode_header_1));\
-+      SQUASHFS_SWAP((s)->type, d, 24, 4);\
-+      SQUASHFS_SWAP((s)->offset, d, 28, 4);\
-+}
-+
-+#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
-+                      sizeof(struct squashfs_dev_inode_header_1));\
-+      SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
-+}
-+
-+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
-+                      sizeof(struct squashfs_symlink_inode_header_1));\
-+      SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
-+}
-+
-+#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
-+                      sizeof(struct squashfs_reg_inode_header_1));\
-+      SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
-+      SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
-+      SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
-+                      sizeof(struct squashfs_dir_inode_header_1));\
-+      SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
-+      SQUASHFS_SWAP((s)->offset, d, 43, 13);\
-+      SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
-+      SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
-+}
-+
-+#endif
-+
-+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
-+
-+struct squashfs_dir_index_2 {
-+      unsigned int            index:27;
-+      unsigned int            start_block:29;
-+      unsigned char           size;
-+      unsigned char           name[0];
-+} __attribute__ ((packed));
-+
-+struct squashfs_base_inode_header_2 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:8; /* index into uid table */
-+      unsigned int            guid:8; /* index into guid table */
-+} __attribute__ ((packed));
-+
-+struct squashfs_ipc_inode_header_2 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:8; /* index into uid table */
-+      unsigned int            guid:8; /* index into guid table */
-+} __attribute__ ((packed));
-+
-+struct squashfs_dev_inode_header_2 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:8; /* index into uid table */
-+      unsigned int            guid:8; /* index into guid table */
-+      unsigned short          rdev;
-+} __attribute__ ((packed));
-+      
-+struct squashfs_symlink_inode_header_2 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:8; /* index into uid table */
-+      unsigned int            guid:8; /* index into guid table */
-+      unsigned short          symlink_size;
-+      char                    symlink[0];
-+} __attribute__ ((packed));
-+
-+struct squashfs_reg_inode_header_2 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:8; /* index into uid table */
-+      unsigned int            guid:8; /* index into guid table */
-+      unsigned int            mtime;
-+      unsigned int            start_block;
-+      unsigned int            fragment;
-+      unsigned int            offset;
-+      unsigned int            file_size:32;
-+      unsigned short          block_list[0];
-+} __attribute__ ((packed));
-+
-+struct squashfs_dir_inode_header_2 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:8; /* index into uid table */
-+      unsigned int            guid:8; /* index into guid table */
-+      unsigned int            file_size:19;
-+      unsigned int            offset:13;
-+      unsigned int            mtime;
-+      unsigned int            start_block:24;
-+} __attribute__  ((packed));
-+
-+struct squashfs_ldir_inode_header_2 {
-+      unsigned int            inode_type:4;
-+      unsigned int            mode:12; /* protection */
-+      unsigned int            uid:8; /* index into uid table */
-+      unsigned int            guid:8; /* index into guid table */
-+      unsigned int            file_size:27;
-+      unsigned int            offset:13;
-+      unsigned int            mtime;
-+      unsigned int            start_block:24;
-+      unsigned int            i_count:16;
-+      struct squashfs_dir_index_2     index[0];
-+} __attribute__  ((packed));
-+
-+union squashfs_inode_header_2 {
-+      struct squashfs_base_inode_header_2     base;
-+      struct squashfs_dev_inode_header_2      dev;
-+      struct squashfs_symlink_inode_header_2  symlink;
-+      struct squashfs_reg_inode_header_2      reg;
-+      struct squashfs_dir_inode_header_2      dir;
-+      struct squashfs_ldir_inode_header_2     ldir;
-+      struct squashfs_ipc_inode_header_2      ipc;
-+};
-+      
-+struct squashfs_dir_header_2 {
-+      unsigned int            count:8;
-+      unsigned int            start_block:24;
-+} __attribute__ ((packed));
-+
-+struct squashfs_dir_entry_2 {
-+      unsigned int            offset:13;
-+      unsigned int            type:3;
-+      unsigned int            size:8;
-+      char                    name[0];
-+} __attribute__ ((packed));
-+
-+struct squashfs_fragment_entry_2 {
-+      unsigned int            start_block;
-+      unsigned int            size;
-+} __attribute__ ((packed));
-+
-+#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
-+      SQUASHFS_MEMSET(s, d, n);\
-+      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
-+      SQUASHFS_SWAP((s)->mode, d, 4, 12);\
-+      SQUASHFS_SWAP((s)->uid, d, 16, 8);\
-+      SQUASHFS_SWAP((s)->guid, d, 24, 8);\
-+
-+#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
-+}
-+
-+#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
-+      SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
-+
-+#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
-+                      sizeof(struct squashfs_dev_inode_header_2)); \
-+      SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
-+}
-+
-+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
-+                      sizeof(struct squashfs_symlink_inode_header_2));\
-+      SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
-+}
-+
-+#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
-+                      sizeof(struct squashfs_reg_inode_header_2));\
-+      SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
-+      SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
-+      SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
-+      SQUASHFS_SWAP((s)->offset, d, 128, 32);\
-+      SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
-+                      sizeof(struct squashfs_dir_inode_header_2));\
-+      SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
-+      SQUASHFS_SWAP((s)->offset, d, 51, 13);\
-+      SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
-+      SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
-+}
-+
-+#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
-+                      sizeof(struct squashfs_ldir_inode_header_2));\
-+      SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
-+      SQUASHFS_SWAP((s)->offset, d, 59, 13);\
-+      SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
-+      SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
-+      SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
-+}
-+
-+#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
-+      SQUASHFS_SWAP((s)->index, d, 0, 27);\
-+      SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
-+      SQUASHFS_SWAP((s)->size, d, 56, 8);\
-+}
-+#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
-+      SQUASHFS_SWAP((s)->count, d, 0, 8);\
-+      SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
-+}
-+
-+#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
-+      SQUASHFS_SWAP((s)->offset, d, 0, 13);\
-+      SQUASHFS_SWAP((s)->type, d, 13, 3);\
-+      SQUASHFS_SWAP((s)->size, d, 16, 8);\
-+}
-+
-+#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
-+      SQUASHFS_SWAP_START\
-+      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
-+      SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
-+      SQUASHFS_SWAP((s)->size, d, 32, 32);\
-+}
-+
-+#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
-+
-+/* fragment and fragment table defines */
-+#define SQUASHFS_FRAGMENT_BYTES_2(A)  (A * sizeof(struct squashfs_fragment_entry_2))
-+
-+#define SQUASHFS_FRAGMENT_INDEX_2(A)  (SQUASHFS_FRAGMENT_BYTES_2(A) / \
-+                                      SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)   (SQUASHFS_FRAGMENT_BYTES_2(A) % \
-+                                              SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_FRAGMENT_INDEXES_2(A)        ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
-+                                      SQUASHFS_METADATA_SIZE - 1) / \
-+                                      SQUASHFS_METADATA_SIZE)
-+
-+#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)    (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
-+                                              sizeof(int))
-+
-+#endif
-+
-+#ifdef __KERNEL__
-+
-+/*
-+ * macros used to swap each structure entry, taking into account
-+ * bitfields and different bitfield placing conventions on differing
-+ * architectures
-+ */
-+
-+#include <asm/byteorder.h>
-+
-+#ifdef __BIG_ENDIAN
-+      /* convert from little endian to big endian */
-+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
-+              tbits, b_pos)
-+#else
-+      /* convert from big endian to little endian */ 
-+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
-+              tbits, 64 - tbits - b_pos)
-+#endif
-+
-+#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
-+      b_pos = pos % 8;\
-+      val = 0;\
-+      s = (unsigned char *)p + (pos / 8);\
-+      d = ((unsigned char *) &val) + 7;\
-+      for(bits = 0; bits < (tbits + b_pos); bits += 8) \
-+              *d-- = *s++;\
-+      value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
-+}
-+
-+#define SQUASHFS_MEMSET(s, d, n)      memset(s, 0, n);
-+
-+#endif
-+#endif
-diff -uNr a/include/linux/squashfs_fs_i.h b/include/linux/squashfs_fs_i.h
---- a/include/linux/squashfs_fs_i.h    1969-12-31 16:00:00.000000000 -0800
-+++ b/include/linux/squashfs_fs_i.h    2008-08-13 16:16:05.000000000 -0700
-@@ -0,0 +1,45 @@
-+#ifndef SQUASHFS_FS_I
-+#define SQUASHFS_FS_I
-+/*
-+ * Squashfs
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * squashfs_fs_i.h
-+ */
-+
-+struct squashfs_inode_info {
-+      long long       start_block;
-+      unsigned int    offset;
-+      union {
-+              struct {
-+                      long long       fragment_start_block;
-+                      unsigned int    fragment_size;
-+                      unsigned int    fragment_offset;
-+                      long long       block_list_start;
-+              } s1;
-+              struct {
-+                      long long       directory_index_start;
-+                      unsigned int    directory_index_offset;
-+                      unsigned int    directory_index_count;
-+                      unsigned int    parent_inode;
-+              } s2;
-+      } u;
-+      struct inode    vfs_inode;
-+};
-+#endif
-diff -uNr a/include/linux/squashfs_fs_sb.h b/include/linux/squashfs_fs_sb.h
---- a/include/linux/squashfs_fs_sb.h   1969-12-31 16:00:00.000000000 -0800
-+++ b/include/linux/squashfs_fs_sb.h   2008-08-13 16:16:05.000000000 -0700
-@@ -0,0 +1,78 @@
-+#ifndef SQUASHFS_FS_SB
-+#define SQUASHFS_FS_SB
-+/*
-+ * Squashfs
-+ *
-+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+ * Phillip Lougher <phillip@lougher.demon.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * squashfs_fs_sb.h
-+ */
-+
-+#include <linux/squashfs_fs.h>
-+
-+struct squashfs_cache_entry {
-+      long long       block;
-+      int             length;
-+      int             locked;
-+      long long       next_index;
-+      char            pending;
-+      char            error;
-+      int             waiting;
-+      wait_queue_head_t       wait_queue;
-+      char            *data;
-+};
-+
-+struct squashfs_cache {
-+      char *name;
-+      int entries;
-+      int block_size;
-+      int next_blk;
-+      int waiting;
-+      int unused_blks;
-+      int use_vmalloc;
-+      spinlock_t lock;
-+      wait_queue_head_t wait_queue;
-+      struct squashfs_cache_entry entry[0];
-+};
-+
-+struct squashfs_sb_info {
-+      struct squashfs_super_block     sblk;
-+      int                     devblksize;
-+      int                     devblksize_log2;
-+      int                     swap;
-+      struct squashfs_cache   *block_cache;
-+      struct squashfs_cache   *fragment_cache;
-+      int                     next_meta_index;
-+      unsigned int            *id_table;
-+      long long               *fragment_index;
-+      unsigned int            *fragment_index_2;
-+      char                    *read_page;
-+      struct mutex            read_data_mutex;
-+      struct mutex            read_page_mutex;
-+      struct mutex            meta_index_mutex;
-+      struct meta_index       *meta_index;
-+      z_stream                stream;
-+      long long               *inode_lookup_table;
-+      int                     (*read_inode)(struct inode *i,  squashfs_inode_t \
-+                              inode);
-+      long long               (*read_blocklist)(struct inode *inode, int \
-+                              index, int readahead_blks, char *block_list, \
-+                              unsigned short **block_p, unsigned int *bsize);
-+      int                     (*read_fragment_index_table)(struct super_block *s);
-+};
-+#endif
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0010_unionfs-2.4_for_2.6.27-rc1.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0010_unionfs-2.4_for_2.6.27-rc1.patch
deleted file mode 100644 (file)
index 8a2e83a..0000000
+++ /dev/null
@@ -1,11320 +0,0 @@
-diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
-index 52cd611..bc6b437 100644
---- a/Documentation/filesystems/00-INDEX
-+++ b/Documentation/filesystems/00-INDEX
-@@ -106,6 +106,8 @@ udf.txt
-       - info and mount options for the UDF filesystem.
- ufs.txt
-       - info on the ufs filesystem.
-+unionfs/
-+      - info on the unionfs filesystem
- vfat.txt
-       - info on using the VFAT filesystem used in Windows NT and Windows 95
- vfs.txt
-diff --git a/Documentation/filesystems/unionfs/00-INDEX b/Documentation/filesystems/unionfs/00-INDEX
-new file mode 100644
-index 0000000..96fdf67
---- /dev/null
-+++ b/Documentation/filesystems/unionfs/00-INDEX
-@@ -0,0 +1,10 @@
-+00-INDEX
-+      - this file.
-+concepts.txt
-+      - A brief introduction of concepts.
-+issues.txt
-+      - A summary of known issues with unionfs.
-+rename.txt
-+      - Information regarding rename operations.
-+usage.txt
-+      - Usage information and examples.
-diff --git a/Documentation/filesystems/unionfs/concepts.txt b/Documentation/filesystems/unionfs/concepts.txt
-new file mode 100644
-index 0000000..b853788
---- /dev/null
-+++ b/Documentation/filesystems/unionfs/concepts.txt
-@@ -0,0 +1,287 @@
-+Unionfs 2.x CONCEPTS:
-+=====================
-+
-+This file describes the concepts needed by a namespace unification file
-+system.
-+
-+
-+Branch Priority:
-+================
-+
-+Each branch is assigned a unique priority - starting from 0 (highest
-+priority).  No two branches can have the same priority.
-+
-+
-+Branch Mode:
-+============
-+
-+Each branch is assigned a mode - read-write or read-only. This allows
-+directories on media mounted read-write to be used in a read-only manner.
-+
-+
-+Whiteouts:
-+==========
-+
-+A whiteout removes a file name from the namespace. Whiteouts are needed when
-+one attempts to remove a file on a read-only branch.
-+
-+Suppose we have a two-branch union, where branch 0 is read-write and branch
-+1 is read-only. And a file 'foo' on branch 1:
-+
-+./b0/
-+./b1/
-+./b1/foo
-+
-+The unified view would simply be:
-+
-+./union/
-+./union/foo
-+
-+Since 'foo' is stored on a read-only branch, it cannot be removed. A
-+whiteout is used to remove the name 'foo' from the unified namespace. Again,
-+since branch 1 is read-only, the whiteout cannot be created there. So, we
-+try on a higher priority (lower numerically) branch and create the whiteout
-+there.
-+
-+./b0/
-+./b0/.wh.foo
-+./b1/
-+./b1/foo
-+
-+Later, when Unionfs traverses branches (due to lookup or readdir), it
-+eliminate 'foo' from the namespace (as well as the whiteout itself.)
-+
-+
-+Opaque Directories:
-+===================
-+
-+Assume we have a unionfs mount comprising of two branches.  Branch 0 is
-+empty; branch 1 has the directory /a and file /a/f.  Let's say we mount a
-+union of branch 0 as read-write and branch 1 as read-only.  Now, let's say
-+we try to perform the following operation in the union:
-+
-+      rm -fr a
-+
-+Because branch 1 is not writable, we cannot physically remove the file /a/f
-+or the directory /a.  So instead, we will create a whiteout in branch 0
-+named /.wh.a, masking out the name "a" from branch 1.  Next, let's say we
-+try to create a directory named "a" as follows:
-+
-+      mkdir a
-+
-+Because we have a whiteout for "a" already, Unionfs behaves as if "a"
-+doesn't exist, and thus will delete the whiteout and replace it with an
-+actual directory named "a".
-+
-+The problem now is that if you try to "ls" in the union, Unionfs will
-+perform is normal directory name unification, for *all* directories named
-+"a" in all branches.  This will cause the file /a/f from branch 1 to
-+re-appear in the union's namespace, which violates Unix semantics.
-+
-+To avoid this problem, we have a different form of whiteouts for
-+directories, called "opaque directories" (same as BSD Union Mount does).
-+Whenever we replace a whiteout with a directory, that directory is marked as
-+opaque.  In Unionfs 2.x, it means that we create a file named
-+/a/.wh.__dir_opaque in branch 0, after having created directory /a there.
-+When unionfs notices that a directory is opaque, it stops all namespace
-+operations (including merging readdir contents) at that opaque directory.
-+This prevents re-exposing names from masked out directories.
-+
-+
-+Duplicate Elimination:
-+======================
-+
-+It is possible for files on different branches to have the same name.
-+Unionfs then has to select which instance of the file to show to the user.
-+Given the fact that each branch has a priority associated with it, the
-+simplest solution is to take the instance from the highest priority
-+(numerically lowest value) and "hide" the others.
-+
-+
-+Unlinking:
-+=========
-+
-+Unlink operation on non-directory instances is optimized to remove the
-+maximum possible objects in case multiple underlying branches have the same
-+file name.  The unlink operation will first try to delete file instances
-+from highest priority branch and then move further to delete from remaining
-+branches in order of their decreasing priority.  Consider a case (F..D..F),
-+where F is a file and D is a directory of the same name; here, some
-+intermediate branch could have an empty directory instance with the same
-+name, so this operation also tries to delete this directory instance and
-+proceed further to delete from next possible lower priority branch.  The
-+unionfs unlink operation will smoothly delete the files with same name from
-+all possible underlying branches.  In case if some error occurs, it creates
-+whiteout in highest priority branch that will hide file instance in rest of
-+the branches.  An error could occur either if an unlink operations in any of
-+the underlying branch failed or if a branch has no write permission.
-+
-+This unlinking policy is known as "delete all" and it has the benefit of
-+overall reducing the number of inodes used by duplicate files, and further
-+reducing the total number of inodes consumed by whiteouts.  The cost is of
-+extra processing, but testing shows this extra processing is well worth the
-+savings.
-+
-+
-+Copyup:
-+=======
-+
-+When a change is made to the contents of a file's data or meta-data, they
-+have to be stored somewhere.  The best way is to create a copy of the
-+original file on a branch that is writable, and then redirect the write
-+though to this copy.  The copy must be made on a higher priority branch so
-+that lookup and readdir return this newer "version" of the file rather than
-+the original (see duplicate elimination).
-+
-+An entire unionfs mount can be read-only or read-write.  If it's read-only,
-+then none of the branches will be written to, even if some of the branches
-+are physically writeable.  If the unionfs mount is read-write, then the
-+leftmost (highest priority) branch must be writeable (for copyup to take
-+place); the remaining branches can be any mix of read-write and read-only.
-+
-+In a writeable mount, unionfs will create new files/dir in the leftmost
-+branch.  If one tries to modify a file in a read-only branch/media, unionfs
-+will copyup the file to the leftmost branch and modify it there.  If you try
-+to modify a file from a writeable branch which is not the leftmost branch,
-+then unionfs will modify it in that branch; this is useful if you, say,
-+unify differnet packages (e.g., apache, sendmail, ftpd, etc.) and you want
-+changes to specific package files to remain logically in the directory where
-+they came from.
-+
-+Cache Coherency:
-+================
-+
-+Unionfs users often want to be able to modify files and directories directly
-+on the lower branches, and have those changes be visible at the Unionfs
-+level.  This means that data (e.g., pages) and meta-data (dentries, inodes,
-+open files, etc.) have to be synchronized between the upper and lower
-+layers.  In other words, the newest changes from a layer below have to be
-+propagated to the Unionfs layer above.  If the two layers are not in sync, a
-+cache incoherency ensues, which could lead to application failures and even
-+oopses.  The Linux kernel, however, has a rather limited set of mechanisms
-+to ensure this inter-layer cache coherency---so Unionfs has to do most of
-+the hard work on its own.
-+
-+Maintaining Invariants:
-+
-+The way Unionfs ensures cache coherency is as follows.  At each entry point
-+to a Unionfs file system method, we call a utility function to validate the
-+primary objects of this method.  Generally, we call unionfs_file_revalidate
-+on open files, and __unionfs_d_revalidate_chain on dentries (which also
-+validates inodes).  These utility functions check to see whether the upper
-+Unionfs object is in sync with any of the lower objects that it represents.
-+The checks we perform include whether the Unionfs superblock has a newer
-+generation number, or if any of the lower objects mtime's or ctime's are
-+newer.  (Note: generation numbers change when branch-management commands are
-+issued, so in a way, maintaining cache coherency is also very important for
-+branch-management.)  If indeed we determine that any Unionfs object is no
-+longer in sync with its lower counterparts, then we rebuild that object
-+similarly to how we do so for branch-management.
-+
-+While rebuilding Unionfs's objects, we also purge any page mappings and
-+truncate inode pages (see fs/unionfs/dentry.c:purge_inode_data).  This is to
-+ensure that Unionfs will re-get the newer data from the lower branches.  We
-+perform this purging only if the Unionfs operation in question is a reading
-+operation; if Unionfs is performing a data writing operation (e.g., ->write,
-+->commit_write, etc.) then we do NOT flush the lower mappings/pages: this is
-+because (1) a self-deadlock could occur and (2) the upper Unionfs pages are
-+considered more authoritative anyway, as they are newer and will overwrite
-+any lower pages.
-+
-+Unionfs maintains the following important invariant regarding mtime's,
-+ctime's, and atime's: the upper inode object's times are the max() of all of
-+the lower ones.  For non-directory objects, there's only one object below,
-+so the mapping is simple; for directory objects, there could me multiple
-+lower objects and we have to sync up with the newest one of all the lower
-+ones.  This invariant is important to maintain, especially for directories
-+(besides, we need this to be POSIX compliant).  A union could comprise
-+multiple writable branches, each of which could change.  If we don't reflect
-+the newest possible mtime/ctime, some applications could fail.  For example,
-+NFSv2/v3 exports check for newer directory mtimes on the server to determine
-+if the client-side attribute cache should be purged.
-+
-+To maintain these important invariants, of course, Unionfs carefully
-+synchronizes upper and lower times in various places.  For example, if we
-+copy-up a file to a top-level branch, the parent directory where the file
-+was copied up to will now have a new mtime: so after a successful copy-up,
-+we sync up with the new top-level branch's parent directory mtime.
-+
-+Implementation:
-+
-+This cache-coherency implementation is efficient because it defers any
-+synchronizing between the upper and lower layers until absolutely needed.
-+Consider the example a common situation where users perform a lot of lower
-+changes, such as untarring a whole package.  While these take place,
-+typically the user doesn't access the files via Unionfs; only after the
-+lower changes are done, does the user try to access the lower files.  With
-+our cache-coherency implementation, the entirety of the changes to the lower
-+branches will not result in a single CPU cycle spent at the Unionfs level
-+until the user invokes a system call that goes through Unionfs.
-+
-+We have considered two alternate cache-coherency designs.  (1) Using the
-+dentry/inode notify functionality to register interest in finding out about
-+any lower changes.  This is a somewhat limited and also a heavy-handed
-+approach which could result in many notifications to the Unionfs layer upon
-+each small change at the lower layer (imagine a file being modified multiple
-+times in rapid succession).  (2) Rewriting the VFS to support explicit
-+callbacks from lower objects to upper objects.  We began exploring such an
-+implementation, but found it to be very complicated--it would have resulted
-+in massive VFS/MM changes which are unlikely to be accepted by the LKML
-+community.  We therefore believe that our current cache-coherency design and
-+implementation represent the best approach at this time.
-+
-+Limitations:
-+
-+Our implementation works in that as long as a user process will have caused
-+Unionfs to be called, directly or indirectly, even to just do
-+->d_revalidate; then we will have purged the current Unionfs data and the
-+process will see the new data.  For example, a process that continually
-+re-reads the same file's data will see the NEW data as soon as the lower
-+file had changed, upon the next read(2) syscall (even if the file is still
-+open!)  However, this doesn't work when the process re-reads the open file's
-+data via mmap(2) (unless the user unmaps/closes the file and remaps/reopens
-+it).  Once we respond to ->readpage(s), then the kernel maps the page into
-+the process's address space and there doesn't appear to be a way to force
-+the kernel to invalidate those pages/mappings, and force the process to
-+re-issue ->readpage.  If there's a way to invalidate active mappings and
-+force a ->readpage, let us know please (invalidate_inode_pages2 doesn't do
-+the trick).
-+
-+Our current Unionfs code has to perform many file-revalidation calls.  It
-+would be really nice if the VFS would export an optional file system hook
-+->file_revalidate (similarly to dentry->d_revalidate) that will be called
-+before each VFS op that has a "struct file" in it.
-+
-+Certain file systems have micro-second granularity (or better) for inode
-+times, and asynchronous actions could cause those times to change with some
-+small delay.  In such cases, Unionfs may see a changed inode time that only
-+differs by a tiny fraction of a second: such a change may be a false
-+positive indication that the lower object has changed, whereas if unionfs
-+waits a little longer, that false indication will not be seen.  (These false
-+positives are harmless, because they would at most cause unionfs to
-+re-validate an object that may need no revalidation, and print a debugging
-+message that clutters the console/logs.)  Therefore, to minimize the chances
-+of these situations, we delay the detection of changed times by a small
-+factor of a few seconds, called UNIONFS_MIN_CC_TIME (which defaults to 3
-+seconds, as does NFS).  This means that we will detect the change, only a
-+couple of seconds later, if indeed the time change persists in the lower
-+file object.  This delayed detection has an added performance benefit: we
-+reduce the number of times that unionfs has to revalidate objects, in case
-+there's a lot of concurrent activity on both the upper and lower objects,
-+for the same file(s).  Lastly, this delayed time attribute detection is
-+similar to how NFS clients operate (e.g., acregmin).
-+
-+Finally, there is no way currently in Linux to prevent lower directories
-+from being moved around (i.e., topology changes); there's no way to prevent
-+modifications to directory sub-trees of whole file systems which are mounted
-+read-write.  It is therefore possible for in-flight operations in unionfs to
-+take place, while a lower directory is being moved around.  Therefore, if
-+you try to, say, create a new file in a directory through unionfs, while the
-+directory is being moved around directly, then the new file may get created
-+in the new location where that directory was moved to.  This is a somewhat
-+similar behaviour in NFS: an NFS client could be creating a new file while
-+th NFS server is moving th directory around; the file will get successfully
-+created in the new location.  (The one exception in unionfs is that if the
-+branch is marked read-only by unionfs, then a copyup will take place.)
-+
-+For more information, see <http://unionfs.filesystems.org/>.
-diff --git a/Documentation/filesystems/unionfs/issues.txt b/Documentation/filesystems/unionfs/issues.txt
-new file mode 100644
-index 0000000..f4b7e7e
---- /dev/null
-+++ b/Documentation/filesystems/unionfs/issues.txt
-@@ -0,0 +1,28 @@
-+KNOWN Unionfs 2.x ISSUES:
-+=========================
-+
-+1. Unionfs should not use lookup_one_len() on the underlying f/s as it
-+   confuses NFSv4.  Currently, unionfs_lookup() passes lookup intents to the
-+   lower file-system, this eliminates part of the problem.  The remaining
-+   calls to lookup_one_len may need to be changed to pass an intent.  We are
-+   currently introducing VFS changes to fs/namei.c's do_path_lookup() to
-+   allow proper file lookup and opening in stackable file systems.
-+
-+2. Lockdep (a debugging feature) isn't aware of stacking, and so it
-+   incorrectly complains about locking problems.  The problem boils down to
-+   this: Lockdep considers all objects of a certain type to be in the same
-+   class, for example, all inodes.  Lockdep doesn't like to see a lock held
-+   on two inodes within the same task, and warns that it could lead to a
-+   deadlock.  However, stackable file systems do precisely that: they lock
-+   an upper object, and then a lower object, in a strict order to avoid
-+   locking problems; in addition, Unionfs, as a fan-out file system, may
-+   have to lock several lower inodes.  We are currently looking into Lockdep
-+   to see how to make it aware of stackable file systems.  For now, we
-+   temporarily disable lockdep when calling vfs methods on lower objects,
-+   but only for those places where lockdep complained.  While this solution
-+   may seem unclean, it is not without precedent: other places in the kernel
-+   also do similar temporary disabling, of course after carefully having
-+   checked that it is the right thing to do.  Anyway, you get any warnings
-+   from Lockdep, please report them to the Unionfs maintainers.
-+
-+For more information, see <http://unionfs.filesystems.org/>.
-diff --git a/Documentation/filesystems/unionfs/rename.txt b/Documentation/filesystems/unionfs/rename.txt
-new file mode 100644
-index 0000000..e20bb82
---- /dev/null
-+++ b/Documentation/filesystems/unionfs/rename.txt
-@@ -0,0 +1,31 @@
-+Rename is a complex beast. The following table shows which rename(2) operations
-+should succeed and which should fail.
-+
-+o: success
-+E: error (either unionfs or vfs)
-+X: EXDEV
-+
-+none = file does not exist
-+file = file is a file
-+dir  = file is a empty directory
-+child= file is a non-empty directory
-+wh   = file is a directory containing only whiteouts; this makes it logically
-+              empty
-+
-+                      none    file    dir     child   wh
-+file                  o       o       E       E       E
-+dir                   o       E       o       E       o
-+child                 X       E       X       E       X
-+wh                    o       E       o       E       o
-+
-+
-+Renaming directories:
-+=====================
-+
-+Whenever a empty (either physically or logically) directory is being renamed,
-+the following sequence of events should take place:
-+
-+1) Remove whiteouts from both source and destination directory
-+2) Rename source to destination
-+3) Make destination opaque to prevent anything under it from showing up
-+
-diff --git a/Documentation/filesystems/unionfs/usage.txt b/Documentation/filesystems/unionfs/usage.txt
-new file mode 100644
-index 0000000..1adde69
---- /dev/null
-+++ b/Documentation/filesystems/unionfs/usage.txt
-@@ -0,0 +1,134 @@
-+Unionfs is a stackable unification file system, which can appear to merge
-+the contents of several directories (branches), while keeping their physical
-+content separate.  Unionfs is useful for unified source tree management,
-+merged contents of split CD-ROM, merged separate software package
-+directories, data grids, and more.  Unionfs allows any mix of read-only and
-+read-write branches, as well as insertion and deletion of branches anywhere
-+in the fan-out.  To maintain Unix semantics, Unionfs handles elimination of
-+duplicates, partial-error conditions, and more.
-+
-+GENERAL SYNTAX
-+==============
-+
-+# mount -t unionfs -o <OPTIONS>,<BRANCH-OPTIONS> none MOUNTPOINT
-+
-+OPTIONS can be any legal combination of:
-+
-+- ro          # mount file system read-only
-+- rw          # mount file system read-write
-+- remount     # remount the file system (see Branch Management below)
-+- incgen      # increment generation no. (see Cache Consistency below)
-+
-+BRANCH-OPTIONS can be either (1) a list of branches given to the "dirs="
-+option, or (2) a list of individual branch manipulation commands, combined
-+with the "remount" option, and is further described in the "Branch
-+Management" section below.
-+
-+The syntax for the "dirs=" mount option is:
-+
-+      dirs=branch[=ro|=rw][:...]
-+
-+The "dirs=" option takes a colon-delimited list of directories to compose
-+the union, with an optional branch mode for each of those directories.
-+Directories that come earlier (specified first, on the left) in the list
-+have a higher precedence than those which come later.  Additionally,
-+read-only or read-write permissions of the branch can be specified by
-+appending =ro or =rw (default) to each directory.  See the Copyup section in
-+concepts.txt, for a description of Unionfs's behavior when mixing read-only
-+and read-write branches and mounts.
-+
-+Syntax:
-+
-+      dirs=/branch1[=ro|=rw]:/branch2[=ro|=rw]:...:/branchN[=ro|=rw]
-+
-+Example:
-+
-+      dirs=/writable_branch=rw:/read-only_branch=ro
-+
-+
-+BRANCH MANAGEMENT
-+=================
-+
-+Once you mount your union for the first time, using the "dirs=" option, you
-+can then change the union's overall mode or reconfigure the branches, using
-+the remount option, as follows.
-+
-+To downgrade a union from read-write to read-only:
-+
-+# mount -t unionfs -o remount,ro none MOUNTPOINT
-+
-+To upgrade a union from read-only to read-write:
-+
-+# mount -t unionfs -o remount,rw none MOUNTPOINT
-+
-+To delete a branch /foo, regardless where it is in the current union:
-+
-+# mount -t unionfs -o remount,del=/foo none MOUNTPOINT
-+
-+To insert (add) a branch /foo before /bar:
-+
-+# mount -t unionfs -o remount,add=/bar:/foo none MOUNTPOINT
-+
-+To insert (add) a branch /foo (with the "rw" mode flag) before /bar:
-+
-+# mount -t unionfs -o remount,add=/bar:/foo=rw none MOUNTPOINT
-+
-+To insert (add) a branch /foo (in "rw" mode) at the very beginning (i.e., a
-+new highest-priority branch), you can use the above syntax, or use a short
-+hand version as follows:
-+
-+# mount -t unionfs -o remount,add=/foo none MOUNTPOINT
-+
-+To append a branch to the very end (new lowest-priority branch):
-+
-+# mount -t unionfs -o remount,add=:/foo none MOUNTPOINT
-+
-+To append a branch to the very end (new lowest-priority branch), in
-+read-only mode:
-+
-+# mount -t unionfs -o remount,add=:/foo=ro none MOUNTPOINT
-+
-+Finally, to change the mode of one existing branch, say /foo, from read-only
-+to read-write, and change /bar from read-write to read-only:
-+
-+# mount -t unionfs -o remount,mode=/foo=rw,mode=/bar=ro none MOUNTPOINT
-+
-+Note: in Unionfs 2.x, you cannot set the leftmost branch to readonly because
-+then Unionfs won't have any writable place for copyups to take place.
-+Moreover, the VFS can get confused when it tries to modify something in a
-+file system mounted read-write, but isn't permitted to write to it.
-+Instead, you should set the whole union as readonly, as described above.
-+If, however, you must set the leftmost branch as readonly, perhaps so you
-+can get a snapshot of it at a point in time, then you should insert a new
-+writable top-level branch, and mark the one you want as readonly.  This can
-+be accomplished as follows, assuming that /foo is your current leftmost
-+branch:
-+
-+# mount -t tmpfs -o size=NNN /new
-+# mount -t unionfs -o remount,add=/new,mode=/foo=ro none MOUNTPOINT
-+<do what you want safely in /foo>
-+# mount -t unionfs -o remount,del=/new,mode=/foo=rw none MOUNTPOINT
-+<check if there's anything in /new you want to preserve>
-+# umount /new
-+
-+CACHE CONSISTENCY
-+=================
-+
-+If you modify any file on any of the lower branches directly, while there is
-+a Unionfs 2.x mounted above any of those branches, you should tell Unionfs
-+to purge its caches and re-get the objects.  To do that, you have to
-+increment the generation number of the superblock using the following
-+command:
-+
-+# mount -t unionfs -o remount,incgen none MOUNTPOINT
-+
-+Note that the older way of incrementing the generation number using an
-+ioctl, is no longer supported in Unionfs 2.0 and newer.  Ioctls in general
-+are not encouraged.  Plus, an ioctl is per-file concept, whereas the
-+generation number is a per-file-system concept.  Worse, such an ioctl
-+requires an open file, which then has to be invalidated by the very nature
-+of the generation number increase (read: the old generation increase ioctl
-+was pretty racy).
-+
-+
-+For more information, see <http://unionfs.filesystems.org/>.
-diff --git a/MAINTAINERS b/MAINTAINERS
-index deedc0d..c722f8e 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -4173,6 +4173,14 @@ L:      linux-kernel@vger.kernel.org
- W:    http://www.kernel.dk
- S:    Maintained
-+UNIONFS
-+P:    Erez Zadok
-+M:    ezk@cs.sunysb.edu
-+L:    unionfs@filesystems.org
-+W:    http://unionfs.filesystems.org
-+T:    git git.kernel.org/pub/scm/linux/kernel/git/ezk/unionfs.git
-+S:    Maintained
-+
- USB ACM DRIVER
- P:    Oliver Neukum
- M:    oliver@neukum.name
-diff --git a/fs/Kconfig b/fs/Kconfig
-index d387358..31610a2 100644
---- a/fs/Kconfig
-+++ b/fs/Kconfig
-@@ -981,6 +981,47 @@ config CONFIGFS_FS
- endmenu
-+menu "Layered filesystems"
-+
-+config ECRYPT_FS
-+      tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
-+      depends on EXPERIMENTAL && KEYS && CRYPTO && NET
-+      help
-+        Encrypted filesystem that operates on the VFS layer.  See
-+        <file:Documentation/filesystems/ecryptfs.txt> to learn more about
-+        eCryptfs.  Userspace components are required and can be
-+        obtained from <http://ecryptfs.sf.net>.
-+
-+        To compile this file system support as a module, choose M here: the
-+        module will be called ecryptfs.
-+
-+config UNION_FS
-+      tristate "Union file system (EXPERIMENTAL)"
-+      depends on EXPERIMENTAL
-+      help
-+        Unionfs is a stackable unification file system, which appears to
-+        merge the contents of several directories (branches), while keeping
-+        their physical content separate.
-+
-+        See <http://unionfs.filesystems.org> for details
-+
-+config UNION_FS_XATTR
-+      bool "Unionfs extended attributes"
-+      depends on UNION_FS
-+      help
-+        Extended attributes are name:value pairs associated with inodes by
-+        the kernel or by users (see the attr(5) manual page).
-+
-+        If unsure, say N.
-+
-+config UNION_FS_DEBUG
-+      bool "Debug Unionfs"
-+      depends on UNION_FS
-+      help
-+        If you say Y here, you can turn on debugging output from Unionfs.
-+
-+endmenu
-+
- menu "Miscellaneous filesystems"
- config ADFS_FS
-@@ -1033,18 +1074,6 @@ config AFFS_FS
-         To compile this file system support as a module, choose M here: the
-         module will be called affs.  If unsure, say N.
--config ECRYPT_FS
--      tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
--      depends on EXPERIMENTAL && KEYS && CRYPTO && NET
--      help
--        Encrypted filesystem that operates on the VFS layer.  See
--        <file:Documentation/filesystems/ecryptfs.txt> to learn more about
--        eCryptfs.  Userspace components are required and can be
--        obtained from <http://ecryptfs.sf.net>.
--
--        To compile this file system support as a module, choose M here: the
--        module will be called ecryptfs.
--
- config HFS_FS
-       tristate "Apple Macintosh file system support (EXPERIMENTAL)"
-       depends on BLOCK && EXPERIMENTAL
-diff --git a/fs/Makefile b/fs/Makefile
-index a1482a5..9bf3915 100644
---- a/fs/Makefile
-+++ b/fs/Makefile
-@@ -86,6 +86,7 @@ obj-$(CONFIG_ISO9660_FS)     += isofs/
- obj-$(CONFIG_HFSPLUS_FS)      += hfsplus/ # Before hfs to find wrapped HFS+
- obj-$(CONFIG_HFS_FS)          += hfs/
- obj-$(CONFIG_ECRYPT_FS)               += ecryptfs/
-+obj-$(CONFIG_UNION_FS)                += unionfs/
- obj-$(CONFIG_VXFS_FS)         += freevxfs/
- obj-$(CONFIG_NFS_FS)          += nfs/
- obj-$(CONFIG_EXPORTFS)                += exportfs/
-diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
-index 5e59658..4621f89 100644
---- a/fs/ecryptfs/dentry.c
-+++ b/fs/ecryptfs/dentry.c
-@@ -62,7 +62,7 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
-               struct inode *lower_inode =
-                       ecryptfs_inode_to_lower(dentry->d_inode);
--              fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL);
-+              fsstack_copy_attr_all(dentry->d_inode, lower_inode);
-       }
- out:
-       return rc;
-diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
-index 89209f0..d99a83e 100644
---- a/fs/ecryptfs/inode.c
-+++ b/fs/ecryptfs/inode.c
-@@ -589,9 +589,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-                       lower_new_dir_dentry->d_inode, lower_new_dentry);
-       if (rc)
-               goto out_lock;
--      fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
-+      fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
-       if (new_dir != old_dir)
--              fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL);
-+              fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
- out_lock:
-       unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
-       dput(lower_new_dentry->d_parent);
-@@ -913,7 +913,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
-       rc = notify_change(lower_dentry, ia);
-       mutex_unlock(&lower_dentry->d_inode->i_mutex);
- out:
--      fsstack_copy_attr_all(inode, lower_inode, NULL);
-+      fsstack_copy_attr_all(inode, lower_inode);
-       return rc;
- }
-diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
-index 448dfd5..db2db5d 100644
---- a/fs/ecryptfs/main.c
-+++ b/fs/ecryptfs/main.c
-@@ -197,7 +197,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
-               d_add(dentry, inode);
-       else
-               d_instantiate(dentry, inode);
--      fsstack_copy_attr_all(inode, lower_inode, NULL);
-+      fsstack_copy_attr_all(inode, lower_inode);
-       /* This size will be overwritten for real files w/ headers and
-        * other metadata */
-       fsstack_copy_inode_size(inode, lower_inode);
-diff --git a/fs/namei.c b/fs/namei.c
-index a7b0a0b..d05ee31 100644
---- a/fs/namei.c
-+++ b/fs/namei.c
-@@ -392,6 +392,7 @@ void release_open_intent(struct nameidata *nd)
-       else
-               fput(nd->intent.open.file);
- }
-+EXPORT_SYMBOL_GPL(release_open_intent);
- static inline struct dentry *
- do_revalidate(struct dentry *dentry, struct nameidata *nd)
-diff --git a/fs/splice.c b/fs/splice.c
-index b30311b..204bb3c 100644
---- a/fs/splice.c
-+++ b/fs/splice.c
-@@ -887,8 +887,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
- /*
-  * Attempt to initiate a splice from pipe to file.
-  */
--static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
--                         loff_t *ppos, size_t len, unsigned int flags)
-+long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out,
-+                   loff_t *ppos, size_t len, unsigned int flags)
- {
-       int ret;
-@@ -904,13 +904,14 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-       return out->f_op->splice_write(pipe, out, ppos, len, flags);
- }
-+EXPORT_SYMBOL_GPL(vfs_splice_from);
- /*
-  * Attempt to initiate a splice from a file to a pipe.
-  */
--static long do_splice_to(struct file *in, loff_t *ppos,
--                       struct pipe_inode_info *pipe, size_t len,
--                       unsigned int flags)
-+long vfs_splice_to(struct file *in, loff_t *ppos,
-+                 struct pipe_inode_info *pipe, size_t len,
-+                 unsigned int flags)
- {
-       int ret;
-@@ -926,6 +927,7 @@ static long do_splice_to(struct file *in, loff_t *ppos,
-       return in->f_op->splice_read(in, ppos, pipe, len, flags);
- }
-+EXPORT_SYMBOL_GPL(vfs_splice_to);
- /**
-  * splice_direct_to_actor - splices data directly between two non-pipes
-@@ -995,7 +997,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
-               size_t read_len;
-               loff_t pos = sd->pos, prev_pos = pos;
--              ret = do_splice_to(in, &pos, pipe, len, flags);
-+              ret = vfs_splice_to(in, &pos, pipe, len, flags);
-               if (unlikely(ret <= 0))
-                       goto out_release;
-@@ -1054,7 +1056,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
- {
-       struct file *file = sd->u.file;
--      return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
-+      return vfs_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
- }
- /**
-@@ -1128,7 +1130,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
-               } else
-                       off = &out->f_pos;
--              ret = do_splice_from(pipe, out, off, len, flags);
-+              ret = vfs_splice_from(pipe, out, off, len, flags);
-               if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
-                       ret = -EFAULT;
-@@ -1149,7 +1151,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
-               } else
-                       off = &in->f_pos;
--              ret = do_splice_to(in, off, pipe, len, flags);
-+              ret = vfs_splice_to(in, off, pipe, len, flags);
-               if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
-                       ret = -EFAULT;
-diff --git a/fs/stack.c b/fs/stack.c
-index 67716f6..a66ff6c 100644
---- a/fs/stack.c
-+++ b/fs/stack.c
-@@ -1,24 +1,82 @@
-+/*
-+ * Copyright (c) 2006-2007 Erez Zadok
-+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2006-2007 Stony Brook University
-+ * Copyright (c) 2006-2007 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/fs_stack.h>
--/* does _NOT_ require i_mutex to be held.
-+/*
-+ * does _NOT_ require i_mutex to be held.
-  *
-  * This function cannot be inlined since i_size_{read,write} is rather
-  * heavy-weight on 32-bit systems
-  */
--void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
-+void fsstack_copy_inode_size(struct inode *dst, struct inode *src)
- {
--      i_size_write(dst, i_size_read((struct inode *)src));
--      dst->i_blocks = src->i_blocks;
-+      loff_t i_size;
-+      blkcnt_t i_blocks;
-+
-+      /*
-+       * i_size_read() includes its own seqlocking and protection from
-+       * preemption (see include/linux/fs.h): we need nothing extra for
-+       * that here, and prefer to avoid nesting locks than attempt to
-+       * keep i_size and i_blocks in synch together.
-+       */
-+      i_size = i_size_read(src);
-+
-+      /*
-+       * But if CONFIG_LSF (on 32-bit), we ought to make an effort to keep
-+       * the two halves of i_blocks in synch despite SMP or PREEMPT - though
-+       * stat's generic_fillattr() doesn't bother, and we won't be applying
-+       * quotas (where i_blocks does become important) at the upper level.
-+       *
-+       * We don't actually know what locking is used at the lower level; but
-+       * if it's a filesystem that supports quotas, it will be using i_lock
-+       * as in inode_add_bytes().  tmpfs uses other locking, and its 32-bit
-+       * is (just) able to exceed 2TB i_size with the aid of holes; but its
-+       * i_blocks cannot carry into the upper long without almost 2TB swap -
-+       * let's ignore that case.
-+       */
-+      if (sizeof(i_blocks) > sizeof(long))
-+              spin_lock(&src->i_lock);
-+      i_blocks = src->i_blocks;
-+      if (sizeof(i_blocks) > sizeof(long))
-+              spin_unlock(&src->i_lock);
-+
-+      /*
-+       * If CONFIG_SMP on 32-bit, it's vital for fsstack_copy_inode_size()
-+       * to hold some lock around i_size_write(), otherwise i_size_read()
-+       * may spin forever (see include/linux/fs.h).  We don't necessarily
-+       * hold i_mutex when this is called, so take i_lock for that case.
-+       *
-+       * And if CONFIG_LSF (on 32-bit), continue our effort to keep the
-+       * two halves of i_blocks in synch despite SMP or PREEMPT: use i_lock
-+       * for that case too, and do both at once by combining the tests.
-+       *
-+       * There is none of this locking overhead in the 64-bit case.
-+       */
-+      if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
-+              spin_lock(&dst->i_lock);
-+      i_size_write(dst, i_size);
-+      dst->i_blocks = i_blocks;
-+      if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
-+              spin_unlock(&dst->i_lock);
- }
- EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
--/* copy all attributes; get_nlinks is optional way to override the i_nlink
-+/*
-+ * copy all attributes; get_nlinks is optional way to override the i_nlink
-  * copying
-  */
--void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
--                              int (*get_nlinks)(struct inode *))
-+void fsstack_copy_attr_all(struct inode *dest, const struct inode *src)
- {
-       dest->i_mode = src->i_mode;
-       dest->i_uid = src->i_uid;
-@@ -29,14 +87,6 @@ void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
-       dest->i_ctime = src->i_ctime;
-       dest->i_blkbits = src->i_blkbits;
-       dest->i_flags = src->i_flags;
--
--      /*
--       * Update the nlinks AFTER updating the above fields, because the
--       * get_links callback may depend on them.
--       */
--      if (!get_nlinks)
--              dest->i_nlink = src->i_nlink;
--      else
--              dest->i_nlink = (*get_nlinks)(dest);
-+      dest->i_nlink = src->i_nlink;
- }
- EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
-diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
-new file mode 100644
-index 0000000..fa04e30
---- /dev/null
-+++ b/fs/unionfs/Makefile
-@@ -0,0 +1,17 @@
-+UNIONFS_VERSION="2.4 (for 2.6.27-rc1)"
-+
-+EXTRA_CFLAGS += -DUNIONFS_VERSION=\"$(UNIONFS_VERSION)\"
-+
-+obj-$(CONFIG_UNION_FS) += unionfs.o
-+
-+unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
-+      rdstate.o copyup.o dirhelper.o rename.o unlink.o \
-+      lookup.o commonfops.o dirfops.o sioq.o mmap.o whiteout.o
-+
-+unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
-+
-+unionfs-$(CONFIG_UNION_FS_DEBUG) += debug.o
-+
-+ifeq ($(CONFIG_UNION_FS_DEBUG),y)
-+EXTRA_CFLAGS += -DDEBUG
-+endif
-diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
-new file mode 100644
-index 0000000..5861970
---- /dev/null
-+++ b/fs/unionfs/commonfops.c
-@@ -0,0 +1,905 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * 1) Copyup the file
-+ * 2) Rename the file to '.unionfs<original inode#><counter>' - obviously
-+ * stolen from NFS's silly rename
-+ */
-+static int copyup_deleted_file(struct file *file, struct dentry *dentry,
-+                             int bstart, int bindex)
-+{
-+      static unsigned int counter;
-+      const int i_inosize = sizeof(dentry->d_inode->i_ino) * 2;
-+      const int countersize = sizeof(counter) * 2;
-+      const int nlen = sizeof(".unionfs") + i_inosize + countersize - 1;
-+      char name[nlen + 1];
-+      int err;
-+      struct dentry *tmp_dentry = NULL;
-+      struct dentry *lower_dentry;
-+      struct dentry *lower_dir_dentry = NULL;
-+
-+      lower_dentry = unionfs_lower_dentry_idx(dentry, bstart);
-+
-+      sprintf(name, ".unionfs%*.*lx",
-+              i_inosize, i_inosize, lower_dentry->d_inode->i_ino);
-+
-+      /*
-+       * Loop, looking for an unused temp name to copyup to.
-+       *
-+       * It's somewhat silly that we look for a free temp tmp name in the
-+       * source branch (bstart) instead of the dest branch (bindex), where
-+       * the final name will be created.  We _will_ catch it if somehow
-+       * the name exists in the dest branch, but it'd be nice to catch it
-+       * sooner than later.
-+       */
-+retry:
-+      tmp_dentry = NULL;
-+      do {
-+              char *suffix = name + nlen - countersize;
-+
-+              dput(tmp_dentry);
-+              counter++;
-+              sprintf(suffix, "%*.*x", countersize, countersize, counter);
-+
-+              pr_debug("unionfs: trying to rename %s to %s\n",
-+                       dentry->d_name.name, name);
-+
-+              tmp_dentry = lookup_one_len(name, lower_dentry->d_parent,
-+                                          nlen);
-+              if (IS_ERR(tmp_dentry)) {
-+                      err = PTR_ERR(tmp_dentry);
-+                      goto out;
-+              }
-+      } while (tmp_dentry->d_inode != NULL);  /* need negative dentry */
-+      dput(tmp_dentry);
-+
-+      err = copyup_named_file(dentry->d_parent->d_inode, file, name, bstart,
-+                              bindex,
-+                              i_size_read(file->f_path.dentry->d_inode));
-+      if (err) {
-+              if (unlikely(err == -EEXIST))
-+                      goto retry;
-+              goto out;
-+      }
-+
-+      /* bring it to the same state as an unlinked file */
-+      lower_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
-+      if (!unionfs_lower_inode_idx(dentry->d_inode, bindex)) {
-+              atomic_inc(&lower_dentry->d_inode->i_count);
-+              unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
-+                                          lower_dentry->d_inode);
-+      }
-+      lower_dir_dentry = lock_parent(lower_dentry);
-+      err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
-+      unlock_dir(lower_dir_dentry);
-+
-+out:
-+      if (!err)
-+              unionfs_check_dentry(dentry);
-+      return err;
-+}
-+
-+/*
-+ * put all references held by upper struct file and free lower file pointer
-+ * array
-+ */
-+static void cleanup_file(struct file *file)
-+{
-+      int bindex, bstart, bend;
-+      struct file **lower_files;
-+      struct file *lower_file;
-+      struct super_block *sb = file->f_path.dentry->d_sb;
-+
-+      lower_files = UNIONFS_F(file)->lower_files;
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              int i;  /* holds (possibly) updated branch index */
-+              int old_bid;
-+
-+              lower_file = unionfs_lower_file_idx(file, bindex);
-+              if (!lower_file)
-+                      continue;
-+
-+              /*
-+               * Find new index of matching branch with an open
-+               * file, since branches could have been added or
-+               * deleted causing the one with open files to shift.
-+               */
-+              old_bid = UNIONFS_F(file)->saved_branch_ids[bindex];
-+              i = branch_id_to_idx(sb, old_bid);
-+              if (unlikely(i < 0)) {
-+                      printk(KERN_ERR "unionfs: no superblock for "
-+                             "file %p\n", file);
-+                      continue;
-+              }
-+
-+              /* decrement count of open files */
-+              branchput(sb, i);
-+              /*
-+               * fput will perform an mntput for us on the correct branch.
-+               * Although we're using the file's old branch configuration,
-+               * bindex, which is the old index, correctly points to the
-+               * right branch in the file's branch list.  In other words,
-+               * we're going to mntput the correct branch even if branches
-+               * have been added/removed.
-+               */
-+              fput(lower_file);
-+              UNIONFS_F(file)->lower_files[bindex] = NULL;
-+              UNIONFS_F(file)->saved_branch_ids[bindex] = -1;
-+      }
-+
-+      UNIONFS_F(file)->lower_files = NULL;
-+      kfree(lower_files);
-+      kfree(UNIONFS_F(file)->saved_branch_ids);
-+      /* set to NULL because caller needs to know if to kfree on error */
-+      UNIONFS_F(file)->saved_branch_ids = NULL;
-+}
-+
-+/* open all lower files for a given file */
-+static int open_all_files(struct file *file)
-+{
-+      int bindex, bstart, bend, err = 0;
-+      struct file *lower_file;
-+      struct dentry *lower_dentry;
-+      struct dentry *dentry = file->f_path.dentry;
-+      struct super_block *sb = dentry->d_sb;
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry)
-+                      continue;
-+
-+              dget(lower_dentry);
-+              unionfs_mntget(dentry, bindex);
-+              branchget(sb, bindex);
-+
-+              lower_file =
-+                      dentry_open(lower_dentry,
-+                                  unionfs_lower_mnt_idx(dentry, bindex),
-+                                  file->f_flags);
-+              if (IS_ERR(lower_file)) {
-+                      err = PTR_ERR(lower_file);
-+                      goto out;
-+              } else {
-+                      unionfs_set_lower_file_idx(file, bindex, lower_file);
-+              }
-+      }
-+out:
-+      return err;
-+}
-+
-+/* open the highest priority file for a given upper file */
-+static int open_highest_file(struct file *file, bool willwrite)
-+{
-+      int bindex, bstart, bend, err = 0;
-+      struct file *lower_file;
-+      struct dentry *lower_dentry;
-+      struct dentry *dentry = file->f_path.dentry;
-+      struct inode *parent_inode = dentry->d_parent->d_inode;
-+      struct super_block *sb = dentry->d_sb;
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      lower_dentry = unionfs_lower_dentry(dentry);
-+      if (willwrite && IS_WRITE_FLAG(file->f_flags) && is_robranch(dentry)) {
-+              for (bindex = bstart - 1; bindex >= 0; bindex--) {
-+                      err = copyup_file(parent_inode, file, bstart, bindex,
-+                                        i_size_read(dentry->d_inode));
-+                      if (!err)
-+                              break;
-+              }
-+              atomic_set(&UNIONFS_F(file)->generation,
-+                         atomic_read(&UNIONFS_I(dentry->d_inode)->
-+                                     generation));
-+              goto out;
-+      }
-+
-+      dget(lower_dentry);
-+      unionfs_mntget(dentry, bstart);
-+      lower_file = dentry_open(lower_dentry,
-+                               unionfs_lower_mnt_idx(dentry, bstart),
-+                               file->f_flags);
-+      if (IS_ERR(lower_file)) {
-+              err = PTR_ERR(lower_file);
-+              goto out;
-+      }
-+      branchget(sb, bstart);
-+      unionfs_set_lower_file(file, lower_file);
-+      /* Fix up the position. */
-+      lower_file->f_pos = file->f_pos;
-+
-+      memcpy(&lower_file->f_ra, &file->f_ra, sizeof(struct file_ra_state));
-+out:
-+      return err;
-+}
-+
-+/* perform a delayed copyup of a read-write file on a read-only branch */
-+static int do_delayed_copyup(struct file *file)
-+{
-+      int bindex, bstart, bend, err = 0;
-+      struct dentry *dentry = file->f_path.dentry;
-+      struct inode *parent_inode = dentry->d_parent->d_inode;
-+
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+
-+      BUG_ON(!S_ISREG(dentry->d_inode->i_mode));
-+
-+      unionfs_check_file(file);
-+      for (bindex = bstart - 1; bindex >= 0; bindex--) {
-+              if (!d_deleted(dentry))
-+                      err = copyup_file(parent_inode, file, bstart,
-+                                        bindex,
-+                                        i_size_read(dentry->d_inode));
-+              else
-+                      err = copyup_deleted_file(file, dentry, bstart,
-+                                                bindex);
-+              /* if succeeded, set lower open-file flags and break */
-+              if (!err) {
-+                      struct file *lower_file;
-+                      lower_file = unionfs_lower_file_idx(file, bindex);
-+                      lower_file->f_flags = file->f_flags;
-+                      break;
-+              }
-+      }
-+      if (err || (bstart <= fbstart(file)))
-+              goto out;
-+      bend = fbend(file);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              if (unionfs_lower_file_idx(file, bindex)) {
-+                      branchput(dentry->d_sb, bindex);
-+                      fput(unionfs_lower_file_idx(file, bindex));
-+                      unionfs_set_lower_file_idx(file, bindex, NULL);
-+              }
-+      }
-+      path_put_lowers(dentry, bstart, bend, false);
-+      iput_lowers(dentry->d_inode, bstart, bend, false);
-+      /* for reg file, we only open it "once" */
-+      fbend(file) = fbstart(file);
-+      dbend(dentry) = dbstart(dentry);
-+      ibend(dentry->d_inode) = ibstart(dentry->d_inode);
-+
-+out:
-+      unionfs_check_file(file);
-+      return err;
-+}
-+
-+/*
-+ * Helper function for unionfs_file_revalidate/locked.
-+ * Expects dentry/parent to be locked already, and revalidated.
-+ */
-+static int __unionfs_file_revalidate(struct file *file, struct dentry *dentry,
-+                                   struct super_block *sb, int sbgen,
-+                                   int dgen, bool willwrite)
-+{
-+      int fgen;
-+      int bstart, bend, orig_brid;
-+      int size;
-+      int err = 0;
-+
-+      fgen = atomic_read(&UNIONFS_F(file)->generation);
-+
-+      /*
-+       * There are two cases we are interested in.  The first is if the
-+       * generation is lower than the super-block.  The second is if
-+       * someone has copied up this file from underneath us, we also need
-+       * to refresh things.
-+       */
-+      if (d_deleted(dentry) ||
-+          (sbgen <= fgen &&
-+           dbstart(dentry) == fbstart(file) &&
-+           unionfs_lower_file(file)))
-+              goto out_may_copyup;
-+
-+      /* save orig branch ID */
-+      orig_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
-+
-+      /* First we throw out the existing files. */
-+      cleanup_file(file);
-+
-+      /* Now we reopen the file(s) as in unionfs_open. */
-+      bstart = fbstart(file) = dbstart(dentry);
-+      bend = fbend(file) = dbend(dentry);
-+
-+      size = sizeof(struct file *) * sbmax(sb);
-+      UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
-+      if (unlikely(!UNIONFS_F(file)->lower_files)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+      size = sizeof(int) * sbmax(sb);
-+      UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
-+      if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      if (S_ISDIR(dentry->d_inode->i_mode)) {
-+              /* We need to open all the files. */
-+              err = open_all_files(file);
-+              if (err)
-+                      goto out;
-+      } else {
-+              int new_brid;
-+              /* We only open the highest priority branch. */
-+              err = open_highest_file(file, willwrite);
-+              if (err)
-+                      goto out;
-+              new_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
-+              if (unlikely(new_brid != orig_brid && sbgen > fgen)) {
-+                      /*
-+                       * If we re-opened the file on a different branch
-+                       * than the original one, and this was due to a new
-+                       * branch inserted, then update the mnt counts of
-+                       * the old and new branches accordingly.
-+                       */
-+                      unionfs_mntget(dentry, bstart);
-+                      unionfs_mntput(sb->s_root,
-+                                     branch_id_to_idx(sb, orig_brid));
-+              }
-+              /* regular files have only one open lower file */
-+              fbend(file) = fbstart(file);
-+      }
-+      atomic_set(&UNIONFS_F(file)->generation,
-+                 atomic_read(&UNIONFS_I(dentry->d_inode)->generation));
-+
-+out_may_copyup:
-+      /* Copyup on the first write to a file on a readonly branch. */
-+      if (willwrite && IS_WRITE_FLAG(file->f_flags) &&
-+          !IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) &&
-+          is_robranch(dentry)) {
-+              pr_debug("unionfs: do delay copyup of \"%s\"\n",
-+                       dentry->d_name.name);
-+              err = do_delayed_copyup(file);
-+              /* regular files have only one open lower file */
-+              if (!err && !S_ISDIR(dentry->d_inode->i_mode))
-+                      fbend(file) = fbstart(file);
-+      }
-+
-+out:
-+      if (err) {
-+              kfree(UNIONFS_F(file)->lower_files);
-+              kfree(UNIONFS_F(file)->saved_branch_ids);
-+      } else {
-+              unionfs_check_file(file);
-+      }
-+      return err;
-+}
-+
-+/*
-+ * Revalidate the struct file
-+ * @file: file to revalidate
-+ * @willwrite: true if caller may cause changes to the file; false otherwise.
-+ * Caller must lock/unlock dentry's branch configuration.
-+ */
-+int unionfs_file_revalidate(struct file *file, bool willwrite)
-+{
-+      struct super_block *sb;
-+      struct dentry *dentry;
-+      int sbgen, dgen;
-+      int err = 0;
-+
-+      dentry = file->f_path.dentry;
-+      sb = dentry->d_sb;
-+      verify_locked(dentry);
-+
-+      /*
-+       * First revalidate the dentry inside struct file,
-+       * but not unhashed dentries.
-+       */
-+reval_dentry:
-+      if (!d_deleted(dentry) &&
-+          !__unionfs_d_revalidate_chain(dentry, NULL, willwrite)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      sbgen = atomic_read(&UNIONFS_SB(sb)->generation);
-+      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
-+
-+      if (unlikely(sbgen > dgen)) {
-+              pr_debug("unionfs: retry dentry %s revalidation\n",
-+                       dentry->d_name.name);
-+              schedule();
-+              goto reval_dentry;
-+      }
-+      BUG_ON(sbgen > dgen);
-+
-+      err = __unionfs_file_revalidate(file, dentry, sb,
-+                                      sbgen, dgen, willwrite);
-+out:
-+      return err;
-+}
-+
-+/* same as unionfs_file_revalidate, but parent dentry must be locked too */
-+int unionfs_file_revalidate_locked(struct file *file, bool willwrite)
-+{
-+      struct super_block *sb;
-+      struct dentry *dentry;
-+      int sbgen, dgen;
-+      int err = 0, valid;
-+
-+      dentry = file->f_path.dentry;
-+      sb = dentry->d_sb;
-+      verify_locked(dentry);
-+      verify_locked(dentry->d_parent);
-+
-+      /* first revalidate (locked) parent, then child */
-+      valid = __unionfs_d_revalidate_chain(dentry->d_parent, NULL, false);
-+      if (unlikely(!valid)) {
-+              err = -ESTALE;  /* same as what real_lookup does */
-+              goto out;
-+      }
-+
-+reval_dentry:
-+      if (!d_deleted(dentry) &&
-+          !__unionfs_d_revalidate_one_locked(dentry, NULL, willwrite)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      sbgen = atomic_read(&UNIONFS_SB(sb)->generation);
-+      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
-+
-+      if (unlikely(sbgen > dgen)) {
-+              pr_debug("unionfs: retry (locked) dentry %s revalidation\n",
-+                       dentry->d_name.name);
-+              schedule();
-+              goto reval_dentry;
-+      }
-+      BUG_ON(sbgen > dgen);
-+
-+      err = __unionfs_file_revalidate(file, dentry, sb,
-+                                      sbgen, dgen, willwrite);
-+out:
-+      return err;
-+}
-+
-+/* unionfs_open helper function: open a directory */
-+static int __open_dir(struct inode *inode, struct file *file)
-+{
-+      struct dentry *lower_dentry;
-+      struct file *lower_file;
-+      int bindex, bstart, bend;
-+      struct vfsmount *mnt;
-+
-+      bstart = fbstart(file) = dbstart(file->f_path.dentry);
-+      bend = fbend(file) = dbend(file->f_path.dentry);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry =
-+                      unionfs_lower_dentry_idx(file->f_path.dentry, bindex);
-+              if (!lower_dentry)
-+                      continue;
-+
-+              dget(lower_dentry);
-+              unionfs_mntget(file->f_path.dentry, bindex);
-+              mnt = unionfs_lower_mnt_idx(file->f_path.dentry, bindex);
-+              lower_file = dentry_open(lower_dentry, mnt, file->f_flags);
-+              if (IS_ERR(lower_file))
-+                      return PTR_ERR(lower_file);
-+
-+              unionfs_set_lower_file_idx(file, bindex, lower_file);
-+
-+              /*
-+               * The branchget goes after the open, because otherwise
-+               * we would miss the reference on release.
-+               */
-+              branchget(inode->i_sb, bindex);
-+      }
-+
-+      return 0;
-+}
-+
-+/* unionfs_open helper function: open a file */
-+static int __open_file(struct inode *inode, struct file *file)
-+{
-+      struct dentry *lower_dentry;
-+      struct file *lower_file;
-+      int lower_flags;
-+      int bindex, bstart, bend;
-+
-+      lower_dentry = unionfs_lower_dentry(file->f_path.dentry);
-+      lower_flags = file->f_flags;
-+
-+      bstart = fbstart(file) = dbstart(file->f_path.dentry);
-+      bend = fbend(file) = dbend(file->f_path.dentry);
-+
-+      /*
-+       * check for the permission for lower file.  If the error is
-+       * COPYUP_ERR, copyup the file.
-+       */
-+      if (lower_dentry->d_inode && is_robranch(file->f_path.dentry)) {
-+              /*
-+               * if the open will change the file, copy it up otherwise
-+               * defer it.
-+               */
-+              if (lower_flags & O_TRUNC) {
-+                      int size = 0;
-+                      int err = -EROFS;
-+
-+                      /* copyup the file */
-+                      for (bindex = bstart - 1; bindex >= 0; bindex--) {
-+                              err = copyup_file(
-+                                      file->f_path.dentry->d_parent->d_inode,
-+                                      file, bstart, bindex, size);
-+                              if (!err)
-+                                      break;
-+                      }
-+                      return err;
-+              } else {
-+                      /*
-+                       * turn off writeable flags, to force delayed copyup
-+                       * by caller.
-+                       */
-+                      lower_flags &= ~(OPEN_WRITE_FLAGS);
-+              }
-+      }
-+
-+      dget(lower_dentry);
-+
-+      /*
-+       * dentry_open will decrement mnt refcnt if err.
-+       * otherwise fput() will do an mntput() for us upon file close.
-+       */
-+      unionfs_mntget(file->f_path.dentry, bstart);
-+      lower_file =
-+              dentry_open(lower_dentry,
-+                          unionfs_lower_mnt_idx(file->f_path.dentry, bstart),
-+                          lower_flags);
-+      if (IS_ERR(lower_file))
-+              return PTR_ERR(lower_file);
-+
-+      unionfs_set_lower_file(file, lower_file);
-+      branchget(inode->i_sb, bstart);
-+
-+      return 0;
-+}
-+
-+int unionfs_open(struct inode *inode, struct file *file)
-+{
-+      int err = 0;
-+      struct file *lower_file = NULL;
-+      struct dentry *dentry = file->f_path.dentry;
-+      int bindex = 0, bstart = 0, bend = 0;
-+      int size;
-+      int valid = 0;
-+
-+      unionfs_read_lock(inode->i_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      if (dentry != dentry->d_parent)
-+              unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_PARENT);
-+
-+      valid = __unionfs_d_revalidate_chain(dentry->d_parent, NULL, false);
-+      if (unlikely(!valid)) {
-+              err = -ESTALE;
-+              goto out_nofree;
-+      }
-+
-+      file->private_data =
-+              kzalloc(sizeof(struct unionfs_file_info), GFP_KERNEL);
-+      if (unlikely(!UNIONFS_F(file))) {
-+              err = -ENOMEM;
-+              goto out_nofree;
-+      }
-+      fbstart(file) = -1;
-+      fbend(file) = -1;
-+      atomic_set(&UNIONFS_F(file)->generation,
-+                 atomic_read(&UNIONFS_I(inode)->generation));
-+
-+      size = sizeof(struct file *) * sbmax(inode->i_sb);
-+      UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
-+      if (unlikely(!UNIONFS_F(file)->lower_files)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+      size = sizeof(int) * sbmax(inode->i_sb);
-+      UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
-+      if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      bstart = fbstart(file) = dbstart(dentry);
-+      bend = fbend(file) = dbend(dentry);
-+
-+      /*
-+       * open all directories and make the unionfs file struct point to
-+       * these lower file structs
-+       */
-+      if (S_ISDIR(inode->i_mode))
-+              err = __open_dir(inode, file);  /* open a dir */
-+      else
-+              err = __open_file(inode, file); /* open a file */
-+
-+      /* freeing the allocated resources, and fput the opened files */
-+      if (err) {
-+              for (bindex = bstart; bindex <= bend; bindex++) {
-+                      lower_file = unionfs_lower_file_idx(file, bindex);
-+                      if (!lower_file)
-+                              continue;
-+
-+                      branchput(dentry->d_sb, bindex);
-+                      /* fput calls dput for lower_dentry */
-+                      fput(lower_file);
-+              }
-+      }
-+
-+out:
-+      if (err) {
-+              kfree(UNIONFS_F(file)->lower_files);
-+              kfree(UNIONFS_F(file)->saved_branch_ids);
-+              kfree(UNIONFS_F(file));
-+      }
-+out_nofree:
-+      if (!err) {
-+              unionfs_postcopyup_setmnt(dentry);
-+              unionfs_copy_attr_times(inode);
-+              unionfs_check_file(file);
-+              unionfs_check_inode(inode);
-+      }
-+      if (dentry != dentry->d_parent)
-+              unionfs_unlock_dentry(dentry->d_parent);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(inode->i_sb);
-+      return err;
-+}
-+
-+/*
-+ * release all lower object references & free the file info structure
-+ *
-+ * No need to grab sb info's rwsem.
-+ */
-+int unionfs_file_release(struct inode *inode, struct file *file)
-+{
-+      struct file *lower_file = NULL;
-+      struct unionfs_file_info *fileinfo;
-+      struct unionfs_inode_info *inodeinfo;
-+      struct super_block *sb = inode->i_sb;
-+      struct dentry *dentry = file->f_path.dentry;
-+      int bindex, bstart, bend;
-+      int fgen, err = 0;
-+
-+      unionfs_read_lock(sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      /*
-+       * Yes, we have to revalidate this file even if it's being released.
-+       * This is important for open-but-unlinked files, as well as mmap
-+       * support.
-+       */
-+      err = unionfs_file_revalidate(file, UNIONFS_F(file)->wrote_to_file);
-+      if (unlikely(err))
-+              goto out;
-+      unionfs_check_file(file);
-+      fileinfo = UNIONFS_F(file);
-+      BUG_ON(file->f_path.dentry->d_inode != inode);
-+      inodeinfo = UNIONFS_I(inode);
-+
-+      /* fput all the lower files */
-+      fgen = atomic_read(&fileinfo->generation);
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_file = unionfs_lower_file_idx(file, bindex);
-+
-+              if (lower_file) {
-+                      unionfs_set_lower_file_idx(file, bindex, NULL);
-+                      fput(lower_file);
-+                      branchput(sb, bindex);
-+              }
-+
-+              /* if there are no more refs to the dentry, dput it */
-+              if (d_deleted(dentry)) {
-+                      dput(unionfs_lower_dentry_idx(dentry, bindex));
-+                      unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
-+              }
-+      }
-+
-+      kfree(fileinfo->lower_files);
-+      kfree(fileinfo->saved_branch_ids);
-+
-+      if (fileinfo->rdstate) {
-+              fileinfo->rdstate->access = jiffies;
-+              spin_lock(&inodeinfo->rdlock);
-+              inodeinfo->rdcount++;
-+              list_add_tail(&fileinfo->rdstate->cache,
-+                            &inodeinfo->readdircache);
-+              mark_inode_dirty(inode);
-+              spin_unlock(&inodeinfo->rdlock);
-+              fileinfo->rdstate = NULL;
-+      }
-+      kfree(fileinfo);
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(sb);
-+      return err;
-+}
-+
-+/* pass the ioctl to the lower fs */
-+static long do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+      struct file *lower_file;
-+      int err;
-+
-+      lower_file = unionfs_lower_file(file);
-+
-+      err = -ENOTTY;
-+      if (!lower_file || !lower_file->f_op)
-+              goto out;
-+      if (lower_file->f_op->unlocked_ioctl) {
-+              err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
-+      } else if (lower_file->f_op->ioctl) {
-+              lock_kernel();
-+              err = lower_file->f_op->ioctl(
-+                      lower_file->f_path.dentry->d_inode,
-+                      lower_file, cmd, arg);
-+              unlock_kernel();
-+      }
-+
-+out:
-+      return err;
-+}
-+
-+/*
-+ * return to user-space the branch indices containing the file in question
-+ *
-+ * We use fd_set and therefore we are limited to the number of the branches
-+ * to FD_SETSIZE, which is currently 1024 - plenty for most people
-+ */
-+static int unionfs_ioctl_queryfile(struct file *file, unsigned int cmd,
-+                                 unsigned long arg)
-+{
-+      int err = 0;
-+      fd_set branchlist;
-+      int bstart = 0, bend = 0, bindex = 0;
-+      int orig_bstart, orig_bend;
-+      struct dentry *dentry, *lower_dentry;
-+      struct vfsmount *mnt;
-+
-+      dentry = file->f_path.dentry;
-+      orig_bstart = dbstart(dentry);
-+      orig_bend = dbend(dentry);
-+      err = unionfs_partial_lookup(dentry);
-+      if (err)
-+              goto out;
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      FD_ZERO(&branchlist);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry)
-+                      continue;
-+              if (likely(lower_dentry->d_inode))
-+                      FD_SET(bindex, &branchlist);
-+              /* purge any lower objects after partial_lookup */
-+              if (bindex < orig_bstart || bindex > orig_bend) {
-+                      dput(lower_dentry);
-+                      unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
-+                      iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
-+                      unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
-+                                                  NULL);
-+                      mnt = unionfs_lower_mnt_idx(dentry, bindex);
-+                      if (!mnt)
-+                              continue;
-+                      unionfs_mntput(dentry, bindex);
-+                      unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
-+              }
-+      }
-+      /* restore original dentry's offsets */
-+      dbstart(dentry) = orig_bstart;
-+      dbend(dentry) = orig_bend;
-+      ibstart(dentry->d_inode) = orig_bstart;
-+      ibend(dentry->d_inode) = orig_bend;
-+
-+      err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set));
-+      if (unlikely(err))
-+              err = -EFAULT;
-+
-+out:
-+      return err < 0 ? err : bend;
-+}
-+
-+long unionfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+      long err;
-+      struct dentry *dentry = file->f_path.dentry;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      err = unionfs_file_revalidate(file, true);
-+      if (unlikely(err))
-+              goto out;
-+
-+      /* check if asked for local commands */
-+      switch (cmd) {
-+      case UNIONFS_IOCTL_INCGEN:
-+              /* Increment the superblock generation count */
-+              pr_info("unionfs: incgen ioctl deprecated; "
-+                      "use \"-o remount,incgen\"\n");
-+              err = -ENOSYS;
-+              break;
-+
-+      case UNIONFS_IOCTL_QUERYFILE:
-+              /* Return list of branches containing the given file */
-+              err = unionfs_ioctl_queryfile(file, cmd, arg);
-+              break;
-+
-+      default:
-+              /* pass the ioctl down */
-+              err = do_ioctl(file, cmd, arg);
-+              break;
-+      }
-+
-+out:
-+      unionfs_check_file(file);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+int unionfs_flush(struct file *file, fl_owner_t id)
-+{
-+      int err = 0;
-+      struct file *lower_file = NULL;
-+      struct dentry *dentry = file->f_path.dentry;
-+      int bindex, bstart, bend;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      err = unionfs_file_revalidate(file, UNIONFS_F(file)->wrote_to_file);
-+      if (unlikely(err))
-+              goto out;
-+      unionfs_check_file(file);
-+
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_file = unionfs_lower_file_idx(file, bindex);
-+
-+              if (lower_file && lower_file->f_op &&
-+                  lower_file->f_op->flush) {
-+                      err = lower_file->f_op->flush(lower_file, id);
-+                      if (err)
-+                              goto out;
-+              }
-+
-+      }
-+
-+out:
-+      if (!err)
-+              unionfs_check_file(file);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
-new file mode 100644
-index 0000000..ae6ea2b
---- /dev/null
-+++ b/fs/unionfs/copyup.c
-@@ -0,0 +1,879 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * For detailed explanation of copyup see:
-+ * Documentation/filesystems/unionfs/concepts.txt
-+ */
-+
-+#ifdef CONFIG_UNION_FS_XATTR
-+/* copyup all extended attrs for a given dentry */
-+static int copyup_xattrs(struct dentry *old_lower_dentry,
-+                       struct dentry *new_lower_dentry)
-+{
-+      int err = 0;
-+      ssize_t list_size = -1;
-+      char *name_list = NULL;
-+      char *attr_value = NULL;
-+      char *name_list_buf = NULL;
-+
-+      /* query the actual size of the xattr list */
-+      list_size = vfs_listxattr(old_lower_dentry, NULL, 0);
-+      if (list_size <= 0) {
-+              err = list_size;
-+              goto out;
-+      }
-+
-+      /* allocate space for the actual list */
-+      name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
-+      if (unlikely(!name_list || IS_ERR(name_list))) {
-+              err = PTR_ERR(name_list);
-+              goto out;
-+      }
-+
-+      name_list_buf = name_list; /* save for kfree at end */
-+
-+      /* now get the actual xattr list of the source file */
-+      list_size = vfs_listxattr(old_lower_dentry, name_list, list_size);
-+      if (list_size <= 0) {
-+              err = list_size;
-+              goto out;
-+      }
-+
-+      /* allocate space to hold each xattr's value */
-+      attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
-+      if (unlikely(!attr_value || IS_ERR(attr_value))) {
-+              err = PTR_ERR(name_list);
-+              goto out;
-+      }
-+
-+      /* in a loop, get and set each xattr from src to dst file */
-+      while (*name_list) {
-+              ssize_t size;
-+
-+              /* Lock here since vfs_getxattr doesn't lock for us */
-+              mutex_lock(&old_lower_dentry->d_inode->i_mutex);
-+              size = vfs_getxattr(old_lower_dentry, name_list,
-+                                  attr_value, XATTR_SIZE_MAX);
-+              mutex_unlock(&old_lower_dentry->d_inode->i_mutex);
-+              if (size < 0) {
-+                      err = size;
-+                      goto out;
-+              }
-+              if (size > XATTR_SIZE_MAX) {
-+                      err = -E2BIG;
-+                      goto out;
-+              }
-+              /* Don't lock here since vfs_setxattr does it for us. */
-+              err = vfs_setxattr(new_lower_dentry, name_list, attr_value,
-+                                 size, 0);
-+              /*
-+               * Selinux depends on "security.*" xattrs, so to maintain
-+               * the security of copied-up files, if Selinux is active,
-+               * then we must copy these xattrs as well.  So we need to
-+               * temporarily get FOWNER privileges.
-+               * XXX: move entire copyup code to SIOQ.
-+               */
-+              if (err == -EPERM && !capable(CAP_FOWNER)) {
-+                      cap_raise(current->cap_effective, CAP_FOWNER);
-+                      err = vfs_setxattr(new_lower_dentry, name_list,
-+                                         attr_value, size, 0);
-+                      cap_lower(current->cap_effective, CAP_FOWNER);
-+              }
-+              if (err < 0)
-+                      goto out;
-+              name_list += strlen(name_list) + 1;
-+      }
-+out:
-+      unionfs_xattr_kfree(name_list_buf);
-+      unionfs_xattr_kfree(attr_value);
-+      /* Ignore if xattr isn't supported */
-+      if (err == -ENOTSUPP || err == -EOPNOTSUPP)
-+              err = 0;
-+      return err;
-+}
-+#endif /* CONFIG_UNION_FS_XATTR */
-+
-+/*
-+ * Determine the mode based on the copyup flags, and the existing dentry.
-+ *
-+ * Handle file systems which may not support certain options.  For example
-+ * jffs2 doesn't allow one to chmod a symlink.  So we ignore such harmless
-+ * errors, rather than propagating them up, which results in copyup errors
-+ * and errors returned back to users.
-+ */
-+static int copyup_permissions(struct super_block *sb,
-+                            struct dentry *old_lower_dentry,
-+                            struct dentry *new_lower_dentry)
-+{
-+      struct inode *i = old_lower_dentry->d_inode;
-+      struct iattr newattrs;
-+      int err;
-+
-+      newattrs.ia_atime = i->i_atime;
-+      newattrs.ia_mtime = i->i_mtime;
-+      newattrs.ia_ctime = i->i_ctime;
-+      newattrs.ia_gid = i->i_gid;
-+      newattrs.ia_uid = i->i_uid;
-+      newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME |
-+              ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
-+              ATTR_GID | ATTR_UID;
-+      mutex_lock(&new_lower_dentry->d_inode->i_mutex);
-+      err = notify_change(new_lower_dentry, &newattrs);
-+      if (err)
-+              goto out;
-+
-+      /* now try to change the mode and ignore EOPNOTSUPP on symlinks */
-+      newattrs.ia_mode = i->i_mode;
-+      newattrs.ia_valid = ATTR_MODE | ATTR_FORCE;
-+      err = notify_change(new_lower_dentry, &newattrs);
-+      if (err == -EOPNOTSUPP &&
-+          S_ISLNK(new_lower_dentry->d_inode->i_mode)) {
-+              printk(KERN_WARNING
-+                     "unionfs: changing \"%s\" symlink mode unsupported\n",
-+                     new_lower_dentry->d_name.name);
-+              err = 0;
-+      }
-+
-+out:
-+      mutex_unlock(&new_lower_dentry->d_inode->i_mutex);
-+      return err;
-+}
-+
-+/*
-+ * create the new device/file/directory - use copyup_permission to copyup
-+ * times, and mode
-+ *
-+ * if the object being copied up is a regular file, the file is only created,
-+ * the contents have to be copied up separately
-+ */
-+static int __copyup_ndentry(struct dentry *old_lower_dentry,
-+                          struct dentry *new_lower_dentry,
-+                          struct dentry *new_lower_parent_dentry,
-+                          char *symbuf)
-+{
-+      int err = 0;
-+      umode_t old_mode = old_lower_dentry->d_inode->i_mode;
-+      struct sioq_args args;
-+
-+      if (S_ISDIR(old_mode)) {
-+              args.mkdir.parent = new_lower_parent_dentry->d_inode;
-+              args.mkdir.dentry = new_lower_dentry;
-+              args.mkdir.mode = old_mode;
-+
-+              run_sioq(__unionfs_mkdir, &args);
-+              err = args.err;
-+      } else if (S_ISLNK(old_mode)) {
-+              args.symlink.parent = new_lower_parent_dentry->d_inode;
-+              args.symlink.dentry = new_lower_dentry;
-+              args.symlink.symbuf = symbuf;
-+
-+              run_sioq(__unionfs_symlink, &args);
-+              err = args.err;
-+      } else if (S_ISBLK(old_mode) || S_ISCHR(old_mode) ||
-+                 S_ISFIFO(old_mode) || S_ISSOCK(old_mode)) {
-+              args.mknod.parent = new_lower_parent_dentry->d_inode;
-+              args.mknod.dentry = new_lower_dentry;
-+              args.mknod.mode = old_mode;
-+              args.mknod.dev = old_lower_dentry->d_inode->i_rdev;
-+
-+              run_sioq(__unionfs_mknod, &args);
-+              err = args.err;
-+      } else if (S_ISREG(old_mode)) {
-+              struct nameidata nd;
-+              err = init_lower_nd(&nd, LOOKUP_CREATE);
-+              if (unlikely(err < 0))
-+                      goto out;
-+              args.create.nd = &nd;
-+              args.create.parent = new_lower_parent_dentry->d_inode;
-+              args.create.dentry = new_lower_dentry;
-+              args.create.mode = old_mode;
-+
-+              run_sioq(__unionfs_create, &args);
-+              err = args.err;
-+              release_lower_nd(&nd, err);
-+      } else {
-+              printk(KERN_CRIT "unionfs: unknown inode type %d\n",
-+                     old_mode);
-+              BUG();
-+      }
-+
-+out:
-+      return err;
-+}
-+
-+static int __copyup_reg_data(struct dentry *dentry,
-+                           struct dentry *new_lower_dentry, int new_bindex,
-+                           struct dentry *old_lower_dentry, int old_bindex,
-+                           struct file **copyup_file, loff_t len)
-+{
-+      struct super_block *sb = dentry->d_sb;
-+      struct file *input_file;
-+      struct file *output_file;
-+      struct vfsmount *output_mnt;
-+      mm_segment_t old_fs;
-+      char *buf = NULL;
-+      ssize_t read_bytes, write_bytes;
-+      loff_t size;
-+      int err = 0;
-+
-+      /* open old file */
-+      unionfs_mntget(dentry, old_bindex);
-+      branchget(sb, old_bindex);
-+      /* dentry_open calls dput and mntput if it returns an error */
-+      input_file = dentry_open(old_lower_dentry,
-+                               unionfs_lower_mnt_idx(dentry, old_bindex),
-+                               O_RDONLY | O_LARGEFILE);
-+      if (IS_ERR(input_file)) {
-+              dput(old_lower_dentry);
-+              err = PTR_ERR(input_file);
-+              goto out;
-+      }
-+      if (unlikely(!input_file->f_op || !input_file->f_op->read)) {
-+              err = -EINVAL;
-+              goto out_close_in;
-+      }
-+
-+      /* open new file */
-+      dget(new_lower_dentry);
-+      output_mnt = unionfs_mntget(sb->s_root, new_bindex);
-+      branchget(sb, new_bindex);
-+      output_file = dentry_open(new_lower_dentry, output_mnt,
-+                                O_RDWR | O_LARGEFILE);
-+      if (IS_ERR(output_file)) {
-+              err = PTR_ERR(output_file);
-+              goto out_close_in2;
-+      }
-+      if (unlikely(!output_file->f_op || !output_file->f_op->write)) {
-+              err = -EINVAL;
-+              goto out_close_out;
-+      }
-+
-+      /* allocating a buffer */
-+      buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+      if (unlikely(!buf)) {
-+              err = -ENOMEM;
-+              goto out_close_out;
-+      }
-+
-+      input_file->f_pos = 0;
-+      output_file->f_pos = 0;
-+
-+      old_fs = get_fs();
-+      set_fs(KERNEL_DS);
-+
-+      size = len;
-+      err = 0;
-+      do {
-+              if (len >= PAGE_SIZE)
-+                      size = PAGE_SIZE;
-+              else if ((len < PAGE_SIZE) && (len > 0))
-+                      size = len;
-+
-+              len -= PAGE_SIZE;
-+
-+              read_bytes =
-+                      input_file->f_op->read(input_file,
-+                                             (char __user *)buf, size,
-+                                             &input_file->f_pos);
-+              if (read_bytes <= 0) {
-+                      err = read_bytes;
-+                      break;
-+              }
-+
-+              /* see Documentation/filesystems/unionfs/issues.txt */
-+              lockdep_off();
-+              write_bytes =
-+                      output_file->f_op->write(output_file,
-+                                               (char __user *)buf,
-+                                               read_bytes,
-+                                               &output_file->f_pos);
-+              lockdep_on();
-+              if ((write_bytes < 0) || (write_bytes < read_bytes)) {
-+                      err = write_bytes;
-+                      break;
-+              }
-+      } while ((read_bytes > 0) && (len > 0));
-+
-+      set_fs(old_fs);
-+
-+      kfree(buf);
-+
-+      if (!err)
-+              err = output_file->f_op->fsync(output_file,
-+                                             new_lower_dentry, 0);
-+
-+      if (err)
-+              goto out_close_out;
-+
-+      if (copyup_file) {
-+              *copyup_file = output_file;
-+              goto out_close_in;
-+      }
-+
-+out_close_out:
-+      fput(output_file);
-+
-+out_close_in2:
-+      branchput(sb, new_bindex);
-+
-+out_close_in:
-+      fput(input_file);
-+
-+out:
-+      branchput(sb, old_bindex);
-+
-+      return err;
-+}
-+
-+/*
-+ * dput the lower references for old and new dentry & clear a lower dentry
-+ * pointer
-+ */
-+static void __clear(struct dentry *dentry, struct dentry *old_lower_dentry,
-+                  int old_bstart, int old_bend,
-+                  struct dentry *new_lower_dentry, int new_bindex)
-+{
-+      /* get rid of the lower dentry and all its traces */
-+      unionfs_set_lower_dentry_idx(dentry, new_bindex, NULL);
-+      dbstart(dentry) = old_bstart;
-+      dbend(dentry) = old_bend;
-+
-+      dput(new_lower_dentry);
-+      dput(old_lower_dentry);
-+}
-+
-+/*
-+ * Copy up a dentry to a file of specified name.
-+ *
-+ * @dir: used to pull the ->i_sb to access other branches
-+ * @dentry: the non-negative dentry whose lower_inode we should copy
-+ * @bstart: the branch of the lower_inode to copy from
-+ * @new_bindex: the branch to create the new file in
-+ * @name: the name of the file to create
-+ * @namelen: length of @name
-+ * @copyup_file: the "struct file" to return (optional)
-+ * @len: how many bytes to copy-up?
-+ */
-+int copyup_dentry(struct inode *dir, struct dentry *dentry, int bstart,
-+                int new_bindex, const char *name, int namelen,
-+                struct file **copyup_file, loff_t len)
-+{
-+      struct dentry *new_lower_dentry;
-+      struct dentry *old_lower_dentry = NULL;
-+      struct super_block *sb;
-+      int err = 0;
-+      int old_bindex;
-+      int old_bstart;
-+      int old_bend;
-+      struct dentry *new_lower_parent_dentry = NULL;
-+      mm_segment_t oldfs;
-+      char *symbuf = NULL;
-+
-+      verify_locked(dentry);
-+
-+      old_bindex = bstart;
-+      old_bstart = dbstart(dentry);
-+      old_bend = dbend(dentry);
-+
-+      BUG_ON(new_bindex < 0);
-+      BUG_ON(new_bindex >= old_bindex);
-+
-+      sb = dir->i_sb;
-+
-+      err = is_robranch_super(sb, new_bindex);
-+      if (err)
-+              goto out;
-+
-+      /* Create the directory structure above this dentry. */
-+      new_lower_dentry = create_parents(dir, dentry, name, new_bindex);
-+      if (IS_ERR(new_lower_dentry)) {
-+              err = PTR_ERR(new_lower_dentry);
-+              goto out;
-+      }
-+
-+      old_lower_dentry = unionfs_lower_dentry_idx(dentry, old_bindex);
-+      /* we conditionally dput this old_lower_dentry at end of function */
-+      dget(old_lower_dentry);
-+
-+      /* For symlinks, we must read the link before we lock the directory. */
-+      if (S_ISLNK(old_lower_dentry->d_inode->i_mode)) {
-+
-+              symbuf = kmalloc(PATH_MAX, GFP_KERNEL);
-+              if (unlikely(!symbuf)) {
-+                      __clear(dentry, old_lower_dentry,
-+                              old_bstart, old_bend,
-+                              new_lower_dentry, new_bindex);
-+                      err = -ENOMEM;
-+                      goto out_free;
-+              }
-+
-+              oldfs = get_fs();
-+              set_fs(KERNEL_DS);
-+              err = old_lower_dentry->d_inode->i_op->readlink(
-+                      old_lower_dentry,
-+                      (char __user *)symbuf,
-+                      PATH_MAX);
-+              set_fs(oldfs);
-+              if (err < 0) {
-+                      __clear(dentry, old_lower_dentry,
-+                              old_bstart, old_bend,
-+                              new_lower_dentry, new_bindex);
-+                      goto out_free;
-+              }
-+              symbuf[err] = '\0';
-+      }
-+
-+      /* Now we lock the parent, and create the object in the new branch. */
-+      new_lower_parent_dentry = lock_parent(new_lower_dentry);
-+
-+      /* create the new inode */
-+      err = __copyup_ndentry(old_lower_dentry, new_lower_dentry,
-+                             new_lower_parent_dentry, symbuf);
-+
-+      if (err) {
-+              __clear(dentry, old_lower_dentry,
-+                      old_bstart, old_bend,
-+                      new_lower_dentry, new_bindex);
-+              goto out_unlock;
-+      }
-+
-+      /* We actually copyup the file here. */
-+      if (S_ISREG(old_lower_dentry->d_inode->i_mode))
-+              err = __copyup_reg_data(dentry, new_lower_dentry, new_bindex,
-+                                      old_lower_dentry, old_bindex,
-+                                      copyup_file, len);
-+      if (err)
-+              goto out_unlink;
-+
-+      /* Set permissions. */
-+      err = copyup_permissions(sb, old_lower_dentry, new_lower_dentry);
-+      if (err)
-+              goto out_unlink;
-+
-+#ifdef CONFIG_UNION_FS_XATTR
-+      /* Selinux uses extended attributes for permissions. */
-+      err = copyup_xattrs(old_lower_dentry, new_lower_dentry);
-+      if (err)
-+              goto out_unlink;
-+#endif /* CONFIG_UNION_FS_XATTR */
-+
-+      /* do not allow files getting deleted to be re-interposed */
-+      if (!d_deleted(dentry))
-+              unionfs_reinterpose(dentry);
-+
-+      goto out_unlock;
-+
-+out_unlink:
-+      /*
-+       * copyup failed, because we possibly ran out of space or
-+       * quota, or something else happened so let's unlink; we don't
-+       * really care about the return value of vfs_unlink
-+       */
-+      vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry);
-+
-+      if (copyup_file) {
-+              /* need to close the file */
-+
-+              fput(*copyup_file);
-+              branchput(sb, new_bindex);
-+      }
-+
-+      /*
-+       * TODO: should we reset the error to something like -EIO?
-+       *
-+       * If we don't reset, the user may get some nonsensical errors, but
-+       * on the other hand, if we reset to EIO, we guarantee that the user
-+       * will get a "confusing" error message.
-+       */
-+
-+out_unlock:
-+      unlock_dir(new_lower_parent_dentry);
-+
-+out_free:
-+      /*
-+       * If old_lower_dentry was not a file, then we need to dput it.  If
-+       * it was a file, then it was already dput indirectly by other
-+       * functions we call above which operate on regular files.
-+       */
-+      if (old_lower_dentry && old_lower_dentry->d_inode &&
-+          !S_ISREG(old_lower_dentry->d_inode->i_mode))
-+              dput(old_lower_dentry);
-+      kfree(symbuf);
-+
-+      if (err)
-+              goto out;
-+      if (!S_ISDIR(dentry->d_inode->i_mode)) {
-+              unionfs_postcopyup_release(dentry);
-+              if (!unionfs_lower_inode(dentry->d_inode)) {
-+                      /*
-+                       * If we got here, then we copied up to an
-+                       * unlinked-open file, whose name is .unionfsXXXXX.
-+                       */
-+                      struct inode *inode = new_lower_dentry->d_inode;
-+                      atomic_inc(&inode->i_count);
-+                      unionfs_set_lower_inode_idx(dentry->d_inode,
-+                                                  ibstart(dentry->d_inode),
-+                                                  inode);
-+              }
-+      }
-+      unionfs_postcopyup_setmnt(dentry);
-+      /* sync inode times from copied-up inode to our inode */
-+      unionfs_copy_attr_times(dentry->d_inode);
-+      unionfs_check_inode(dir);
-+      unionfs_check_dentry(dentry);
-+out:
-+      return err;
-+}
-+
-+/*
-+ * This function creates a copy of a file represented by 'file' which
-+ * currently resides in branch 'bstart' to branch 'new_bindex.'  The copy
-+ * will be named "name".
-+ */
-+int copyup_named_file(struct inode *dir, struct file *file, char *name,
-+                    int bstart, int new_bindex, loff_t len)
-+{
-+      int err = 0;
-+      struct file *output_file = NULL;
-+
-+      err = copyup_dentry(dir, file->f_path.dentry, bstart, new_bindex,
-+                          name, strlen(name), &output_file, len);
-+      if (!err) {
-+              fbstart(file) = new_bindex;
-+              unionfs_set_lower_file_idx(file, new_bindex, output_file);
-+      }
-+
-+      return err;
-+}
-+
-+/*
-+ * This function creates a copy of a file represented by 'file' which
-+ * currently resides in branch 'bstart' to branch 'new_bindex'.
-+ */
-+int copyup_file(struct inode *dir, struct file *file, int bstart,
-+              int new_bindex, loff_t len)
-+{
-+      int err = 0;
-+      struct file *output_file = NULL;
-+      struct dentry *dentry = file->f_path.dentry;
-+
-+      err = copyup_dentry(dir, dentry, bstart, new_bindex,
-+                          dentry->d_name.name, dentry->d_name.len,
-+                          &output_file, len);
-+      if (!err) {
-+              fbstart(file) = new_bindex;
-+              unionfs_set_lower_file_idx(file, new_bindex, output_file);
-+      }
-+
-+      return err;
-+}
-+
-+/* purge a dentry's lower-branch states (dput/mntput, etc.) */
-+static void __cleanup_dentry(struct dentry *dentry, int bindex,
-+                           int old_bstart, int old_bend)
-+{
-+      int loop_start;
-+      int loop_end;
-+      int new_bstart = -1;
-+      int new_bend = -1;
-+      int i;
-+
-+      loop_start = min(old_bstart, bindex);
-+      loop_end = max(old_bend, bindex);
-+
-+      /*
-+       * This loop sets the bstart and bend for the new dentry by
-+       * traversing from left to right.  It also dputs all negative
-+       * dentries except bindex
-+       */
-+      for (i = loop_start; i <= loop_end; i++) {
-+              if (!unionfs_lower_dentry_idx(dentry, i))
-+                      continue;
-+
-+              if (i == bindex) {
-+                      new_bend = i;
-+                      if (new_bstart < 0)
-+                              new_bstart = i;
-+                      continue;
-+              }
-+
-+              if (!unionfs_lower_dentry_idx(dentry, i)->d_inode) {
-+                      dput(unionfs_lower_dentry_idx(dentry, i));
-+                      unionfs_set_lower_dentry_idx(dentry, i, NULL);
-+
-+                      unionfs_mntput(dentry, i);
-+                      unionfs_set_lower_mnt_idx(dentry, i, NULL);
-+              } else {
-+                      if (new_bstart < 0)
-+                              new_bstart = i;
-+                      new_bend = i;
-+              }
-+      }
-+
-+      if (new_bstart < 0)
-+              new_bstart = bindex;
-+      if (new_bend < 0)
-+              new_bend = bindex;
-+      dbstart(dentry) = new_bstart;
-+      dbend(dentry) = new_bend;
-+
-+}
-+
-+/* set lower inode ptr and update bstart & bend if necessary */
-+static void __set_inode(struct dentry *upper, struct dentry *lower,
-+                      int bindex)
-+{
-+      unionfs_set_lower_inode_idx(upper->d_inode, bindex,
-+                                  igrab(lower->d_inode));
-+      if (likely(ibstart(upper->d_inode) > bindex))
-+              ibstart(upper->d_inode) = bindex;
-+      if (likely(ibend(upper->d_inode) < bindex))
-+              ibend(upper->d_inode) = bindex;
-+
-+}
-+
-+/* set lower dentry ptr and update bstart & bend if necessary */
-+static void __set_dentry(struct dentry *upper, struct dentry *lower,
-+                       int bindex)
-+{
-+      unionfs_set_lower_dentry_idx(upper, bindex, lower);
-+      if (likely(dbstart(upper) > bindex))
-+              dbstart(upper) = bindex;
-+      if (likely(dbend(upper) < bindex))
-+              dbend(upper) = bindex;
-+}
-+
-+/*
-+ * This function replicates the directory structure up-to given dentry
-+ * in the bindex branch.
-+ */
-+struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
-+                            const char *name, int bindex)
-+{
-+      int err;
-+      struct dentry *child_dentry;
-+      struct dentry *parent_dentry;
-+      struct dentry *lower_parent_dentry = NULL;
-+      struct dentry *lower_dentry = NULL;
-+      const char *childname;
-+      unsigned int childnamelen;
-+      int nr_dentry;
-+      int count = 0;
-+      int old_bstart;
-+      int old_bend;
-+      struct dentry **path = NULL;
-+      struct super_block *sb;
-+
-+      verify_locked(dentry);
-+
-+      err = is_robranch_super(dir->i_sb, bindex);
-+      if (err) {
-+              lower_dentry = ERR_PTR(err);
-+              goto out;
-+      }
-+
-+      old_bstart = dbstart(dentry);
-+      old_bend = dbend(dentry);
-+
-+      lower_dentry = ERR_PTR(-ENOMEM);
-+
-+      /* There is no sense allocating any less than the minimum. */
-+      nr_dentry = 1;
-+      path = kmalloc(nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
-+      if (unlikely(!path))
-+              goto out;
-+
-+      /* assume the negative dentry of unionfs as the parent dentry */
-+      parent_dentry = dentry;
-+
-+      /*
-+       * This loop finds the first parent that exists in the given branch.
-+       * We start building the directory structure from there.  At the end
-+       * of the loop, the following should hold:
-+       *  - child_dentry is the first nonexistent child
-+       *  - parent_dentry is the first existent parent
-+       *  - path[0] is the = deepest child
-+       *  - path[count] is the first child to create
-+       */
-+      do {
-+              child_dentry = parent_dentry;
-+
-+              /* find the parent directory dentry in unionfs */
-+              parent_dentry = dget_parent(child_dentry);
-+
-+              /* find out the lower_parent_dentry in the given branch */
-+              lower_parent_dentry =
-+                      unionfs_lower_dentry_idx(parent_dentry, bindex);
-+
-+              /* grow path table */
-+              if (count == nr_dentry) {
-+                      void *p;
-+
-+                      nr_dentry *= 2;
-+                      p = krealloc(path, nr_dentry * sizeof(struct dentry *),
-+                                   GFP_KERNEL);
-+                      if (unlikely(!p)) {
-+                              lower_dentry = ERR_PTR(-ENOMEM);
-+                              goto out;
-+                      }
-+                      path = p;
-+              }
-+
-+              /* store the child dentry */
-+              path[count++] = child_dentry;
-+      } while (!lower_parent_dentry);
-+      count--;
-+
-+      sb = dentry->d_sb;
-+
-+      /*
-+       * This code goes between the begin/end labels and basically
-+       * emulates a while(child_dentry != dentry), only cleaner and
-+       * shorter than what would be a much longer while loop.
-+       */
-+begin:
-+      /* get lower parent dir in the current branch */
-+      lower_parent_dentry = unionfs_lower_dentry_idx(parent_dentry, bindex);
-+      dput(parent_dentry);
-+
-+      /* init the values to lookup */
-+      childname = child_dentry->d_name.name;
-+      childnamelen = child_dentry->d_name.len;
-+
-+      if (child_dentry != dentry) {
-+              /* lookup child in the underlying file system */
-+              lower_dentry = lookup_one_len(childname, lower_parent_dentry,
-+                                            childnamelen);
-+              if (IS_ERR(lower_dentry))
-+                      goto out;
-+      } else {
-+              /*
-+               * Is the name a whiteout of the child name ?  lookup the
-+               * whiteout child in the underlying file system
-+               */
-+              lower_dentry = lookup_one_len(name, lower_parent_dentry,
-+                                            strlen(name));
-+              if (IS_ERR(lower_dentry))
-+                      goto out;
-+
-+              /* Replace the current dentry (if any) with the new one */
-+              dput(unionfs_lower_dentry_idx(dentry, bindex));
-+              unionfs_set_lower_dentry_idx(dentry, bindex,
-+                                           lower_dentry);
-+
-+              __cleanup_dentry(dentry, bindex, old_bstart, old_bend);
-+              goto out;
-+      }
-+
-+      if (lower_dentry->d_inode) {
-+              /*
-+               * since this already exists we dput to avoid
-+               * multiple references on the same dentry
-+               */
-+              dput(lower_dentry);
-+      } else {
-+              struct sioq_args args;
-+
-+              /* it's a negative dentry, create a new dir */
-+              lower_parent_dentry = lock_parent(lower_dentry);
-+
-+              args.mkdir.parent = lower_parent_dentry->d_inode;
-+              args.mkdir.dentry = lower_dentry;
-+              args.mkdir.mode = child_dentry->d_inode->i_mode;
-+
-+              run_sioq(__unionfs_mkdir, &args);
-+              err = args.err;
-+
-+              if (!err)
-+                      err = copyup_permissions(dir->i_sb, child_dentry,
-+                                               lower_dentry);
-+              unlock_dir(lower_parent_dentry);
-+              if (err) {
-+                      dput(lower_dentry);
-+                      lower_dentry = ERR_PTR(err);
-+                      goto out;
-+              }
-+
-+      }
-+
-+      __set_inode(child_dentry, lower_dentry, bindex);
-+      __set_dentry(child_dentry, lower_dentry, bindex);
-+      /*
-+       * update times of this dentry, but also the parent, because if
-+       * we changed, the parent may have changed too.
-+       */
-+      fsstack_copy_attr_times(parent_dentry->d_inode,
-+                              lower_parent_dentry->d_inode);
-+      unionfs_copy_attr_times(child_dentry->d_inode);
-+
-+      parent_dentry = child_dentry;
-+      child_dentry = path[--count];
-+      goto begin;
-+out:
-+      /* cleanup any leftover locks from the do/while loop above */
-+      if (IS_ERR(lower_dentry))
-+              while (count)
-+                      dput(path[count--]);
-+      kfree(path);
-+      return lower_dentry;
-+}
-+
-+/*
-+ * Post-copyup helper to ensure we have valid mnts: set lower mnt of
-+ * dentry+parents to the first parent node that has an mnt.
-+ */
-+void unionfs_postcopyup_setmnt(struct dentry *dentry)
-+{
-+      struct dentry *parent, *hasone;
-+      int bindex = dbstart(dentry);
-+
-+      if (unionfs_lower_mnt_idx(dentry, bindex))
-+              return;
-+      hasone = dentry->d_parent;
-+      /* this loop should stop at root dentry */
-+      while (!unionfs_lower_mnt_idx(hasone, bindex))
-+              hasone = hasone->d_parent;
-+      parent = dentry;
-+      while (!unionfs_lower_mnt_idx(parent, bindex)) {
-+              unionfs_set_lower_mnt_idx(parent, bindex,
-+                                        unionfs_mntget(hasone, bindex));
-+              parent = parent->d_parent;
-+      }
-+}
-+
-+/*
-+ * Post-copyup helper to release all non-directory source objects of a
-+ * copied-up file.  Regular files should have only one lower object.
-+ */
-+void unionfs_postcopyup_release(struct dentry *dentry)
-+{
-+      int bstart, bend;
-+
-+      BUG_ON(S_ISDIR(dentry->d_inode->i_mode));
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      path_put_lowers(dentry, bstart + 1, bend, false);
-+      iput_lowers(dentry->d_inode, bstart + 1, bend, false);
-+
-+      dbend(dentry) = bstart;
-+      ibend(dentry->d_inode) = ibstart(dentry->d_inode) = bstart;
-+}
-diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c
-new file mode 100644
-index 0000000..db62d22
---- /dev/null
-+++ b/fs/unionfs/debug.c
-@@ -0,0 +1,533 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * Helper debugging functions for maintainers (and for users to report back
-+ * useful information back to maintainers)
-+ */
-+
-+/* it's always useful to know what part of the code called us */
-+#define PRINT_CALLER(fname, fxn, line)                                        \
-+      do {                                                            \
-+              if (!printed_caller) {                                  \
-+                      pr_debug("PC:%s:%s:%d\n", (fname), (fxn), (line)); \
-+                      printed_caller = 1;                             \
-+              }                                                       \
-+      } while (0)
-+
-+/*
-+ * __unionfs_check_{inode,dentry,file} perform exhaustive sanity checking on
-+ * the fan-out of various Unionfs objects.  We check that no lower objects
-+ * exist  outside the start/end branch range; that all objects within are
-+ * non-NULL (with some allowed exceptions); that for every lower file
-+ * there's a lower dentry+inode; that the start/end ranges match for all
-+ * corresponding lower objects; that open files/symlinks have only one lower
-+ * objects, but directories can have several; and more.
-+ */
-+void __unionfs_check_inode(const struct inode *inode,
-+                         const char *fname, const char *fxn, int line)
-+{
-+      int bindex;
-+      int istart, iend;
-+      struct inode *lower_inode;
-+      struct super_block *sb;
-+      int printed_caller = 0;
-+      void *poison_ptr;
-+
-+      /* for inodes now */
-+      BUG_ON(!inode);
-+      sb = inode->i_sb;
-+      istart = ibstart(inode);
-+      iend = ibend(inode);
-+      /* don't check inode if no lower branches */
-+      if (istart < 0 && iend < 0)
-+              return;
-+      if (unlikely(istart > iend)) {
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" Ci0: inode=%p istart/end=%d:%d\n",
-+                       inode, istart, iend);
-+      }
-+      if (unlikely((istart == -1 && iend != -1) ||
-+                   (istart != -1 && iend == -1))) {
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" Ci1: inode=%p istart/end=%d:%d\n",
-+                       inode, istart, iend);
-+      }
-+      if (!S_ISDIR(inode->i_mode)) {
-+              if (unlikely(iend != istart)) {
-+                      PRINT_CALLER(fname, fxn, line);
-+                      pr_debug(" Ci2: inode=%p istart=%d iend=%d\n",
-+                               inode, istart, iend);
-+              }
-+      }
-+
-+      for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
-+              if (unlikely(!UNIONFS_I(inode))) {
-+                      PRINT_CALLER(fname, fxn, line);
-+                      pr_debug(" Ci3: no inode_info %p\n", inode);
-+                      return;
-+              }
-+              if (unlikely(!UNIONFS_I(inode)->lower_inodes)) {
-+                      PRINT_CALLER(fname, fxn, line);
-+                      pr_debug(" Ci4: no lower_inodes %p\n", inode);
-+                      return;
-+              }
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (lower_inode) {
-+                      memset(&poison_ptr, POISON_INUSE, sizeof(void *));
-+                      if (unlikely(bindex < istart || bindex > iend)) {
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" Ci5: inode/linode=%p:%p bindex=%d "
-+                                       "istart/end=%d:%d\n", inode,
-+                                       lower_inode, bindex, istart, iend);
-+                      } else if (unlikely(lower_inode == poison_ptr)) {
-+                              /* freed inode! */
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" Ci6: inode/linode=%p:%p bindex=%d "
-+                                       "istart/end=%d:%d\n", inode,
-+                                       lower_inode, bindex, istart, iend);
-+                      }
-+                      continue;
-+              }
-+              /* if we get here, then lower_inode == NULL */
-+              if (bindex < istart || bindex > iend)
-+                      continue;
-+              /*
-+               * directories can have NULL lower inodes in b/t start/end,
-+               * but NOT if at the start/end range.
-+               */
-+              if (unlikely(S_ISDIR(inode->i_mode) &&
-+                           bindex > istart && bindex < iend))
-+                      continue;
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" Ci7: inode/linode=%p:%p "
-+                       "bindex=%d istart/end=%d:%d\n",
-+                       inode, lower_inode, bindex, istart, iend);
-+      }
-+}
-+
-+void __unionfs_check_dentry(const struct dentry *dentry,
-+                          const char *fname, const char *fxn, int line)
-+{
-+      int bindex;
-+      int dstart, dend, istart, iend;
-+      struct dentry *lower_dentry;
-+      struct inode *inode, *lower_inode;
-+      struct super_block *sb;
-+      struct vfsmount *lower_mnt;
-+      int printed_caller = 0;
-+      void *poison_ptr;
-+
-+      BUG_ON(!dentry);
-+      sb = dentry->d_sb;
-+      inode = dentry->d_inode;
-+      dstart = dbstart(dentry);
-+      dend = dbend(dentry);
-+      /* don't check dentry/mnt if no lower branches */
-+      if (dstart < 0 && dend < 0)
-+              goto check_inode;
-+      BUG_ON(dstart > dend);
-+
-+      if (unlikely((dstart == -1 && dend != -1) ||
-+                   (dstart != -1 && dend == -1))) {
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" CD0: dentry=%p dstart/end=%d:%d\n",
-+                       dentry, dstart, dend);
-+      }
-+      /*
-+       * check for NULL dentries inside the start/end range, or
-+       * non-NULL dentries outside the start/end range.
-+       */
-+      for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (lower_dentry) {
-+                      if (unlikely(bindex < dstart || bindex > dend)) {
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" CD1: dentry/lower=%p:%p(%p) "
-+                                       "bindex=%d dstart/end=%d:%d\n",
-+                                       dentry, lower_dentry,
-+                                       (lower_dentry ? lower_dentry->d_inode :
-+                                        (void *) -1L),
-+                                       bindex, dstart, dend);
-+                      }
-+              } else {        /* lower_dentry == NULL */
-+                      if (bindex < dstart || bindex > dend)
-+                              continue;
-+                      /*
-+                       * Directories can have NULL lower inodes in b/t
-+                       * start/end, but NOT if at the start/end range.
-+                       * Ignore this rule, however, if this is a NULL
-+                       * dentry or a deleted dentry.
-+                       */
-+                      if (unlikely(!d_deleted((struct dentry *) dentry) &&
-+                                   inode &&
-+                                   !(inode && S_ISDIR(inode->i_mode) &&
-+                                     bindex > dstart && bindex < dend))) {
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" CD2: dentry/lower=%p:%p(%p) "
-+                                       "bindex=%d dstart/end=%d:%d\n",
-+                                       dentry, lower_dentry,
-+                                       (lower_dentry ?
-+                                        lower_dentry->d_inode :
-+                                        (void *) -1L),
-+                                       bindex, dstart, dend);
-+                      }
-+              }
-+      }
-+
-+      /* check for vfsmounts same as for dentries */
-+      for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
-+              lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
-+              if (lower_mnt) {
-+                      if (unlikely(bindex < dstart || bindex > dend)) {
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" CM0: dentry/lmnt=%p:%p bindex=%d "
-+                                       "dstart/end=%d:%d\n", dentry,
-+                                       lower_mnt, bindex, dstart, dend);
-+                      }
-+              } else {        /* lower_mnt == NULL */
-+                      if (bindex < dstart || bindex > dend)
-+                              continue;
-+                      /*
-+                       * Directories can have NULL lower inodes in b/t
-+                       * start/end, but NOT if at the start/end range.
-+                       * Ignore this rule, however, if this is a NULL
-+                       * dentry.
-+                       */
-+                      if (unlikely(inode &&
-+                                   !(inode && S_ISDIR(inode->i_mode) &&
-+                                     bindex > dstart && bindex < dend))) {
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" CM1: dentry/lmnt=%p:%p "
-+                                       "bindex=%d dstart/end=%d:%d\n",
-+                                       dentry, lower_mnt, bindex,
-+                                       dstart, dend);
-+                      }
-+              }
-+      }
-+
-+check_inode:
-+      /* for inodes now */
-+      if (!inode)
-+              return;
-+      istart = ibstart(inode);
-+      iend = ibend(inode);
-+      /* don't check inode if no lower branches */
-+      if (istart < 0 && iend < 0)
-+              return;
-+      BUG_ON(istart > iend);
-+      if (unlikely((istart == -1 && iend != -1) ||
-+                   (istart != -1 && iend == -1))) {
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" CI0: dentry/inode=%p:%p istart/end=%d:%d\n",
-+                       dentry, inode, istart, iend);
-+      }
-+      if (unlikely(istart != dstart)) {
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" CI1: dentry/inode=%p:%p istart=%d dstart=%d\n",
-+                       dentry, inode, istart, dstart);
-+      }
-+      if (unlikely(iend != dend)) {
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" CI2: dentry/inode=%p:%p iend=%d dend=%d\n",
-+                       dentry, inode, iend, dend);
-+      }
-+
-+      if (!S_ISDIR(inode->i_mode)) {
-+              if (unlikely(dend != dstart)) {
-+                      PRINT_CALLER(fname, fxn, line);
-+                      pr_debug(" CI3: dentry/inode=%p:%p dstart=%d dend=%d\n",
-+                               dentry, inode, dstart, dend);
-+              }
-+              if (unlikely(iend != istart)) {
-+                      PRINT_CALLER(fname, fxn, line);
-+                      pr_debug(" CI4: dentry/inode=%p:%p istart=%d iend=%d\n",
-+                               dentry, inode, istart, iend);
-+              }
-+      }
-+
-+      for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (lower_inode) {
-+                      memset(&poison_ptr, POISON_INUSE, sizeof(void *));
-+                      if (unlikely(bindex < istart || bindex > iend)) {
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" CI5: dentry/linode=%p:%p bindex=%d "
-+                                       "istart/end=%d:%d\n", dentry,
-+                                       lower_inode, bindex, istart, iend);
-+                      } else if (unlikely(lower_inode == poison_ptr)) {
-+                              /* freed inode! */
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" CI6: dentry/linode=%p:%p bindex=%d "
-+                                       "istart/end=%d:%d\n", dentry,
-+                                       lower_inode, bindex, istart, iend);
-+                      }
-+                      continue;
-+              }
-+              /* if we get here, then lower_inode == NULL */
-+              if (bindex < istart || bindex > iend)
-+                      continue;
-+              /*
-+               * directories can have NULL lower inodes in b/t start/end,
-+               * but NOT if at the start/end range.
-+               */
-+              if (unlikely(S_ISDIR(inode->i_mode) &&
-+                           bindex > istart && bindex < iend))
-+                      continue;
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" CI7: dentry/linode=%p:%p "
-+                       "bindex=%d istart/end=%d:%d\n",
-+                       dentry, lower_inode, bindex, istart, iend);
-+      }
-+
-+      /*
-+       * If it's a directory, then intermediate objects b/t start/end can
-+       * be NULL.  But, check that all three are NULL: lower dentry, mnt,
-+       * and inode.
-+       */
-+      if (dstart >= 0 && dend >= 0 && S_ISDIR(inode->i_mode))
-+              for (bindex = dstart+1; bindex < dend; bindex++) {
-+                      lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+                      lower_dentry = unionfs_lower_dentry_idx(dentry,
-+                                                              bindex);
-+                      lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
-+                      if (unlikely(!((lower_inode && lower_dentry &&
-+                                      lower_mnt) ||
-+                                     (!lower_inode &&
-+                                      !lower_dentry && !lower_mnt)))) {
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" Cx: lmnt/ldentry/linode=%p:%p:%p "
-+                                       "bindex=%d dstart/end=%d:%d\n",
-+                                       lower_mnt, lower_dentry, lower_inode,
-+                                       bindex, dstart, dend);
-+                      }
-+              }
-+      /* check if lower inode is newer than upper one (it shouldn't) */
-+      if (unlikely(is_newer_lower(dentry) && !is_negative_lower(dentry))) {
-+              PRINT_CALLER(fname, fxn, line);
-+              for (bindex = ibstart(inode); bindex <= ibend(inode);
-+                   bindex++) {
-+                      lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+                      if (unlikely(!lower_inode))
-+                              continue;
-+                      pr_debug(" CI8: bindex=%d mtime/lmtime=%lu.%lu/%lu.%lu "
-+                               "ctime/lctime=%lu.%lu/%lu.%lu\n",
-+                               bindex,
-+                               inode->i_mtime.tv_sec,
-+                               inode->i_mtime.tv_nsec,
-+                               lower_inode->i_mtime.tv_sec,
-+                               lower_inode->i_mtime.tv_nsec,
-+                               inode->i_ctime.tv_sec,
-+                               inode->i_ctime.tv_nsec,
-+                               lower_inode->i_ctime.tv_sec,
-+                               lower_inode->i_ctime.tv_nsec);
-+              }
-+      }
-+}
-+
-+void __unionfs_check_file(const struct file *file,
-+                        const char *fname, const char *fxn, int line)
-+{
-+      int bindex;
-+      int dstart, dend, fstart, fend;
-+      struct dentry *dentry;
-+      struct file *lower_file;
-+      struct inode *inode;
-+      struct super_block *sb;
-+      int printed_caller = 0;
-+
-+      BUG_ON(!file);
-+      dentry = file->f_path.dentry;
-+      sb = dentry->d_sb;
-+      dstart = dbstart(dentry);
-+      dend = dbend(dentry);
-+      BUG_ON(dstart > dend);
-+      fstart = fbstart(file);
-+      fend = fbend(file);
-+      BUG_ON(fstart > fend);
-+
-+      if (unlikely((fstart == -1 && fend != -1) ||
-+                   (fstart != -1 && fend == -1))) {
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" CF0: file/dentry=%p:%p fstart/end=%d:%d\n",
-+                       file, dentry, fstart, fend);
-+      }
-+      if (unlikely(fstart != dstart)) {
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" CF1: file/dentry=%p:%p fstart=%d dstart=%d\n",
-+                       file, dentry, fstart, dstart);
-+      }
-+      if (unlikely(fend != dend)) {
-+              PRINT_CALLER(fname, fxn, line);
-+              pr_debug(" CF2: file/dentry=%p:%p fend=%d dend=%d\n",
-+                       file, dentry, fend, dend);
-+      }
-+      inode = dentry->d_inode;
-+      if (!S_ISDIR(inode->i_mode)) {
-+              if (unlikely(fend != fstart)) {
-+                      PRINT_CALLER(fname, fxn, line);
-+                      pr_debug(" CF3: file/inode=%p:%p fstart=%d fend=%d\n",
-+                               file, inode, fstart, fend);
-+              }
-+              if (unlikely(dend != dstart)) {
-+                      PRINT_CALLER(fname, fxn, line);
-+                      pr_debug(" CF4: file/dentry=%p:%p dstart=%d dend=%d\n",
-+                               file, dentry, dstart, dend);
-+              }
-+      }
-+
-+      /*
-+       * check for NULL dentries inside the start/end range, or
-+       * non-NULL dentries outside the start/end range.
-+       */
-+      for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
-+              lower_file = unionfs_lower_file_idx(file, bindex);
-+              if (lower_file) {
-+                      if (unlikely(bindex < fstart || bindex > fend)) {
-+                              PRINT_CALLER(fname, fxn, line);
-+                              pr_debug(" CF5: file/lower=%p:%p bindex=%d "
-+                                       "fstart/end=%d:%d\n", file,
-+                                       lower_file, bindex, fstart, fend);
-+                      }
-+              } else {        /* lower_file == NULL */
-+                      if (bindex >= fstart && bindex <= fend) {
-+                              /*
-+                               * directories can have NULL lower inodes in
-+                               * b/t start/end, but NOT if at the
-+                               * start/end range.
-+                               */
-+                              if (unlikely(!(S_ISDIR(inode->i_mode) &&
-+                                             bindex > fstart &&
-+                                             bindex < fend))) {
-+                                      PRINT_CALLER(fname, fxn, line);
-+                                      pr_debug(" CF6: file/lower=%p:%p "
-+                                               "bindex=%d fstart/end=%d:%d\n",
-+                                               file, lower_file, bindex,
-+                                               fstart, fend);
-+                              }
-+                      }
-+              }
-+      }
-+
-+      __unionfs_check_dentry(dentry, fname, fxn, line);
-+}
-+
-+void __unionfs_check_nd(const struct nameidata *nd,
-+                      const char *fname, const char *fxn, int line)
-+{
-+      struct file *file;
-+      int printed_caller = 0;
-+
-+      if (unlikely(!nd))
-+              return;
-+      if (nd->flags & LOOKUP_OPEN) {
-+              file = nd->intent.open.file;
-+              if (unlikely(file->f_path.dentry &&
-+                           strcmp(file->f_path.dentry->d_sb->s_type->name,
-+                                  UNIONFS_NAME))) {
-+                      PRINT_CALLER(fname, fxn, line);
-+                      pr_debug(" CND1: lower_file of type %s\n",
-+                               file->f_path.dentry->d_sb->s_type->name);
-+                      BUG();
-+              }
-+      }
-+}
-+
-+/* useful to track vfsmount leaks that could cause EBUSY on unmount */
-+void __show_branch_counts(const struct super_block *sb,
-+                        const char *file, const char *fxn, int line)
-+{
-+      int i;
-+      struct vfsmount *mnt;
-+
-+      pr_debug("BC:");
-+      for (i = 0; i < sbmax(sb); i++) {
-+              if (likely(sb->s_root))
-+                      mnt = UNIONFS_D(sb->s_root)->lower_paths[i].mnt;
-+              else
-+                      mnt = NULL;
-+              printk(KERN_CONT "%d:",
-+                     (mnt ? atomic_read(&mnt->mnt_count) : -99));
-+      }
-+      printk(KERN_CONT "%s:%s:%d\n", file, fxn, line);
-+}
-+
-+void __show_inode_times(const struct inode *inode,
-+                      const char *file, const char *fxn, int line)
-+{
-+      struct inode *lower_inode;
-+      int bindex;
-+
-+      for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (unlikely(!lower_inode))
-+                      continue;
-+              pr_debug("IT(%lu:%d): %s:%s:%d "
-+                       "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n",
-+                       inode->i_ino, bindex,
-+                       file, fxn, line,
-+                       inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
-+                       lower_inode->i_mtime.tv_sec,
-+                       lower_inode->i_mtime.tv_nsec,
-+                       inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
-+                       lower_inode->i_ctime.tv_sec,
-+                       lower_inode->i_ctime.tv_nsec);
-+      }
-+}
-+
-+void __show_dinode_times(const struct dentry *dentry,
-+                      const char *file, const char *fxn, int line)
-+{
-+      struct inode *inode = dentry->d_inode;
-+      struct inode *lower_inode;
-+      int bindex;
-+
-+      for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (!lower_inode)
-+                      continue;
-+              pr_debug("DT(%s:%lu:%d): %s:%s:%d "
-+                       "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n",
-+                       dentry->d_name.name, inode->i_ino, bindex,
-+                       file, fxn, line,
-+                       inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
-+                       lower_inode->i_mtime.tv_sec,
-+                       lower_inode->i_mtime.tv_nsec,
-+                       inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
-+                       lower_inode->i_ctime.tv_sec,
-+                       lower_inode->i_ctime.tv_nsec);
-+      }
-+}
-+
-+void __show_inode_counts(const struct inode *inode,
-+                      const char *file, const char *fxn, int line)
-+{
-+      struct inode *lower_inode;
-+      int bindex;
-+
-+      if (unlikely(!inode)) {
-+              pr_debug("SiC: Null inode\n");
-+              return;
-+      }
-+      for (bindex = sbstart(inode->i_sb); bindex <= sbend(inode->i_sb);
-+           bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (unlikely(!lower_inode))
-+                      continue;
-+              pr_debug("SIC(%lu:%d:%d): lc=%d %s:%s:%d\n",
-+                       inode->i_ino, bindex,
-+                       atomic_read(&(inode)->i_count),
-+                       atomic_read(&(lower_inode)->i_count),
-+                       file, fxn, line);
-+      }
-+}
-diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
-new file mode 100644
-index 0000000..7f0c7f7
---- /dev/null
-+++ b/fs/unionfs/dentry.c
-@@ -0,0 +1,570 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+bool is_negative_lower(const struct dentry *dentry)
-+{
-+      int bindex;
-+      struct dentry *lower_dentry;
-+
-+      BUG_ON(!dentry);
-+      /* cache coherency: check if file was deleted on lower branch */
-+      if (dbstart(dentry) < 0)
-+              return true;
-+      for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              /* unhashed (i.e., unlinked) lower dentries don't count */
-+              if (lower_dentry && lower_dentry->d_inode &&
-+                  !d_deleted(lower_dentry) &&
-+                  !(lower_dentry->d_flags & DCACHE_NFSFS_RENAMED))
-+                      return false;
-+      }
-+      return true;
-+}
-+
-+static inline void __dput_lowers(struct dentry *dentry, int start, int end)
-+{
-+      struct dentry *lower_dentry;
-+      int bindex;
-+
-+      if (start < 0)
-+              return;
-+      for (bindex = start; bindex <= end; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry)
-+                      continue;
-+              unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
-+              dput(lower_dentry);
-+      }
-+}
-+
-+/*
-+ * Revalidate a single dentry.
-+ * Assume that dentry's info node is locked.
-+ * Assume that parent(s) are all valid already, but
-+ * the child may not yet be valid.
-+ * Returns true if valid, false otherwise.
-+ */
-+static bool __unionfs_d_revalidate_one(struct dentry *dentry,
-+                                     struct nameidata *nd)
-+{
-+      bool valid = true;      /* default is valid */
-+      struct dentry *lower_dentry;
-+      int bindex, bstart, bend;
-+      int sbgen, dgen;
-+      int positive = 0;
-+      int interpose_flag;
-+      struct nameidata lowernd; /* TODO: be gentler to the stack */
-+
-+      if (nd)
-+              memcpy(&lowernd, nd, sizeof(struct nameidata));
-+      else
-+              memset(&lowernd, 0, sizeof(struct nameidata));
-+
-+      verify_locked(dentry);
-+      verify_locked(dentry->d_parent);
-+
-+      sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
-+      /* if the dentry is unhashed, do NOT revalidate */
-+      if (d_deleted(dentry))
-+              goto out;
-+
-+      BUG_ON(dbstart(dentry) == -1);
-+      if (dentry->d_inode)
-+              positive = 1;
-+      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
-+      /*
-+       * If we are working on an unconnected dentry, then there is no
-+       * revalidation to be done, because this file does not exist within
-+       * the namespace, and Unionfs operates on the namespace, not data.
-+       */
-+      if (unlikely(sbgen != dgen)) {
-+              struct dentry *result;
-+              int pdgen;
-+
-+              /* The root entry should always be valid */
-+              BUG_ON(IS_ROOT(dentry));
-+
-+              /* We can't work correctly if our parent isn't valid. */
-+              pdgen = atomic_read(&UNIONFS_D(dentry->d_parent)->generation);
-+              BUG_ON(pdgen != sbgen); /* should never happen here */
-+
-+              /* Free the pointers for our inodes and this dentry. */
-+              bstart = dbstart(dentry);
-+              bend = dbend(dentry);
-+
-+              /*
-+               * mntput unhashed lower dentries, because those files got
-+               * deleted or rmdir'ed.
-+               */
-+              for (bindex = bstart; bindex <= bend; bindex++) {
-+                      lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+                      if (!lower_dentry)
-+                              continue;
-+                      if (!d_deleted(lower_dentry) &&
-+                          !(lower_dentry->d_flags & DCACHE_NFSFS_RENAMED))
-+                          continue;
-+                      unionfs_mntput(dentry, bindex);
-+              }
-+
-+              __dput_lowers(dentry, bstart, bend);
-+              dbstart(dentry) = dbend(dentry) = -1;
-+
-+              interpose_flag = INTERPOSE_REVAL_NEG;
-+              if (positive) {
-+                      interpose_flag = INTERPOSE_REVAL;
-+                      iput_lowers_all(dentry->d_inode, true);
-+              }
-+
-+              if (realloc_dentry_private_data(dentry) != 0) {
-+                      valid = false;
-+                      goto out;
-+              }
-+
-+              result = unionfs_lookup_full(dentry, &lowernd, interpose_flag);
-+              if (result) {
-+                      if (IS_ERR(result)) {
-+                              valid = false;
-+                              goto out;
-+                      }
-+                      /*
-+                       * current unionfs_lookup_backend() doesn't return
-+                       * a valid dentry
-+                       */
-+                      dput(dentry);
-+                      dentry = result;
-+              }
-+
-+              if (unlikely(positive && is_negative_lower(dentry))) {
-+                      make_bad_inode(dentry->d_inode);
-+                      d_drop(dentry);
-+                      valid = false;
-+                      goto out;
-+              }
-+              goto out;
-+      }
-+
-+      /* The revalidation must occur across all branches */
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      BUG_ON(bstart == -1);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry || !lower_dentry->d_op
-+                  || !lower_dentry->d_op->d_revalidate)
-+                      continue;
-+              /*
-+               * Don't pass nameidata to lower file system, because we
-+               * don't want an arbitrary lower file being opened or
-+               * returned to us: it may be useless to us because of the
-+               * fanout nature of unionfs (cf. file/directory open-file
-+               * invariants).  We will open lower files as and when needed
-+               * later on.
-+               */
-+              if (!lower_dentry->d_op->d_revalidate(lower_dentry, NULL))
-+                      valid = false;
-+      }
-+
-+      if (!dentry->d_inode ||
-+          ibstart(dentry->d_inode) < 0 ||
-+          ibend(dentry->d_inode) < 0) {
-+              valid = false;
-+              goto out;
-+      }
-+
-+      if (valid) {
-+              /*
-+               * If we get here, and we copy the meta-data from the lower
-+               * inode to our inode, then it is vital that we have already
-+               * purged all unionfs-level file data.  We do that in the
-+               * caller (__unionfs_d_revalidate_chain) by calling
-+               * purge_inode_data.
-+               */
-+              unionfs_copy_attr_all(dentry->d_inode,
-+                                    unionfs_lower_inode(dentry->d_inode));
-+              fsstack_copy_inode_size(dentry->d_inode,
-+                                      unionfs_lower_inode(dentry->d_inode));
-+      }
-+
-+out:
-+      if (valid)
-+              atomic_set(&UNIONFS_D(dentry)->generation, sbgen);
-+
-+      return valid;
-+}
-+
-+/*
-+ * Determine if the lower inode objects have changed from below the unionfs
-+ * inode.  Return true if changed, false otherwise.
-+ *
-+ * We check if the mtime or ctime have changed.  However, the inode times
-+ * can be changed by anyone without much protection, including
-+ * asynchronously.  This can sometimes cause unionfs to find that the lower
-+ * file system doesn't change its inode times quick enough, resulting in a
-+ * false positive indication (which is harmless, it just makes unionfs do
-+ * extra work in re-validating the objects).  To minimize the chances of
-+ * these situations, we still consider such small time changes valid, but we
-+ * don't print debugging messages unless the time changes are greater than
-+ * UNIONFS_MIN_CC_TIME (which defaults to 3 seconds, as with NFS's acregmin)
-+ * because significant changes are more likely due to users manually
-+ * touching lower files.
-+ */
-+bool is_newer_lower(const struct dentry *dentry)
-+{
-+      int bindex;
-+      struct inode *inode;
-+      struct inode *lower_inode;
-+
-+      /* ignore if we're called on semi-initialized dentries/inodes */
-+      if (!dentry || !UNIONFS_D(dentry))
-+              return false;
-+      inode = dentry->d_inode;
-+      if (!inode || !UNIONFS_I(inode)->lower_inodes ||
-+          ibstart(inode) < 0 || ibend(inode) < 0)
-+              return false;
-+
-+      for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (!lower_inode)
-+                      continue;
-+
-+              /* check if mtime/ctime have changed */
-+              if (unlikely(timespec_compare(&inode->i_mtime,
-+                                            &lower_inode->i_mtime) < 0)) {
-+                      if ((lower_inode->i_mtime.tv_sec -
-+                           inode->i_mtime.tv_sec) > UNIONFS_MIN_CC_TIME) {
-+                              pr_info("unionfs: new lower inode mtime "
-+                                      "(bindex=%d, name=%s)\n", bindex,
-+                                      dentry->d_name.name);
-+                              show_dinode_times(dentry);
-+                      }
-+                      return true;
-+              }
-+              if (unlikely(timespec_compare(&inode->i_ctime,
-+                                            &lower_inode->i_ctime) < 0)) {
-+                      if ((lower_inode->i_ctime.tv_sec -
-+                           inode->i_ctime.tv_sec) > UNIONFS_MIN_CC_TIME) {
-+                              pr_info("unionfs: new lower inode ctime "
-+                                      "(bindex=%d, name=%s)\n", bindex,
-+                                      dentry->d_name.name);
-+                              show_dinode_times(dentry);
-+                      }
-+                      return true;
-+              }
-+      }
-+
-+      /*
-+       * Last check: if this is a positive dentry, but somehow all lower
-+       * dentries are negative or unhashed, then this dentry needs to be
-+       * revalidated, because someone probably deleted the objects from
-+       * the lower branches directly.
-+       */
-+      if (is_negative_lower(dentry))
-+              return true;
-+
-+      return false;           /* default: lower is not newer */
-+}
-+
-+/*
-+ * Purge and invalidate as many data pages of a unionfs inode.  This is
-+ * called when the lower inode has changed, and we want to force processes
-+ * to re-get the new data.
-+ */
-+static inline void purge_inode_data(struct inode *inode)
-+{
-+      /* remove all non-private mappings */
-+      unmap_mapping_range(inode->i_mapping, 0, 0, 0);
-+      /* invalidate as many pages as possible */
-+      invalidate_mapping_pages(inode->i_mapping, 0, -1);
-+      /*
-+       * Don't try to truncate_inode_pages here, because this could lead
-+       * to a deadlock between some of address_space ops and dentry
-+       * revalidation: the address space op is invoked with a lock on our
-+       * own page, and truncate_inode_pages will block on locked pages.
-+       */
-+}
-+
-+/*
-+ * Revalidate a single file/symlink/special dentry.  Assume that info nodes
-+ * of the dentry and its parent are locked.  Assume that parent(s) are all
-+ * valid already, but the child may not yet be valid.  Returns true if
-+ * valid, false otherwise.
-+ */
-+bool __unionfs_d_revalidate_one_locked(struct dentry *dentry,
-+                                     struct nameidata *nd,
-+                                     bool willwrite)
-+{
-+      bool valid = false;     /* default is invalid */
-+      int sbgen, dgen, bindex;
-+
-+      verify_locked(dentry);
-+      verify_locked(dentry->d_parent);
-+
-+      sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
-+      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
-+
-+      if (unlikely(is_newer_lower(dentry))) {
-+              /* root dentry special case as aforementioned */
-+              if (IS_ROOT(dentry)) {
-+                      unionfs_copy_attr_times(dentry->d_inode);
-+              } else {
-+                      /*
-+                       * reset generation number to zero, guaranteed to be
-+                       * "old"
-+                       */
-+                      dgen = 0;
-+                      atomic_set(&UNIONFS_D(dentry)->generation, dgen);
-+              }
-+              if (!willwrite)
-+                      purge_inode_data(dentry->d_inode);
-+      }
-+      valid = __unionfs_d_revalidate_one(dentry, nd);
-+
-+      /*
-+       * If __unionfs_d_revalidate_one() succeeded above, then it will
-+       * have incremented the refcnt of the mnt's, but also the branch
-+       * indices of the dentry will have been updated (to take into
-+       * account any branch insertions/deletion.  So the current
-+       * dbstart/dbend match the current, and new, indices of the mnts
-+       * which __unionfs_d_revalidate_one has incremented.  Note: the "if"
-+       * test below does not depend on whether chain_len was 0 or greater.
-+       */
-+      if (!valid || sbgen == dgen)
-+              goto out;
-+      for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++)
-+              unionfs_mntput(dentry, bindex);
-+out:
-+      return valid;
-+}
-+
-+/*
-+ * Revalidate a parent chain of dentries, then the actual node.
-+ * Assumes that dentry is locked, but will lock all parents if/when needed.
-+ *
-+ * If 'willwrite' is true, and the lower inode times are not in sync, then
-+ * *don't* purge_inode_data, as it could deadlock if ->write calls us and we
-+ * try to truncate a locked page.  Besides, if unionfs is about to write
-+ * data to a file, then there's the data unionfs is about to write is more
-+ * authoritative than what's below, therefore we can safely overwrite the
-+ * lower inode times and data.
-+ */
-+bool __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata *nd,
-+                                bool willwrite)
-+{
-+      bool valid = false;     /* default is invalid */
-+      struct dentry **chain = NULL; /* chain of dentries to reval */
-+      int chain_len = 0;
-+      struct dentry *dtmp;
-+      int sbgen, dgen, i;
-+      int saved_bstart, saved_bend, bindex;
-+
-+      /* find length of chain needed to revalidate */
-+      /* XXX: should I grab some global (dcache?) lock? */
-+      chain_len = 0;
-+      sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
-+      dtmp = dentry->d_parent;
-+      verify_locked(dentry);
-+      if (dentry != dtmp)
-+              unionfs_lock_dentry(dtmp, UNIONFS_DMUTEX_REVAL_PARENT);
-+      dgen = atomic_read(&UNIONFS_D(dtmp)->generation);
-+      /* XXX: should we check if is_newer_lower all the way up? */
-+      if (unlikely(is_newer_lower(dtmp))) {
-+              /*
-+               * Special case: the root dentry's generation number must
-+               * always be valid, but its lower inode times don't have to
-+               * be, so sync up the times only.
-+               */
-+              if (IS_ROOT(dtmp)) {
-+                      unionfs_copy_attr_times(dtmp->d_inode);
-+              } else {
-+                      /*
-+                       * reset generation number to zero, guaranteed to be
-+                       * "old"
-+                       */
-+                      dgen = 0;
-+                      atomic_set(&UNIONFS_D(dtmp)->generation, dgen);
-+              }
-+              purge_inode_data(dtmp->d_inode);
-+      }
-+      if (dentry != dtmp)
-+              unionfs_unlock_dentry(dtmp);
-+      while (sbgen != dgen) {
-+              /* The root entry should always be valid */
-+              BUG_ON(IS_ROOT(dtmp));
-+              chain_len++;
-+              dtmp = dtmp->d_parent;
-+              dgen = atomic_read(&UNIONFS_D(dtmp)->generation);
-+      }
-+      if (chain_len == 0)
-+              goto out_this;  /* shortcut if parents are OK */
-+
-+      /*
-+       * Allocate array of dentries to reval.  We could use linked lists,
-+       * but the number of entries we need to alloc here is often small,
-+       * and short lived, so locality will be better.
-+       */
-+      chain = kzalloc(chain_len * sizeof(struct dentry *), GFP_KERNEL);
-+      if (unlikely(!chain)) {
-+              printk(KERN_CRIT "unionfs: no more memory in %s\n",
-+                     __func__);
-+              goto out;
-+      }
-+
-+      /* grab all dentries in chain, in child to parent order */
-+      dtmp = dentry;
-+      for (i = chain_len-1; i >= 0; i--)
-+              dtmp = chain[i] = dget_parent(dtmp);
-+
-+      /*
-+       * call __unionfs_d_revalidate_one() on each dentry, but in parent
-+       * to child order.
-+       */
-+      for (i = 0; i < chain_len; i++) {
-+              unionfs_lock_dentry(chain[i], UNIONFS_DMUTEX_REVAL_CHILD);
-+              if (chain[i] != chain[i]->d_parent)
-+                      unionfs_lock_dentry(chain[i]->d_parent,
-+                                          UNIONFS_DMUTEX_REVAL_PARENT);
-+              saved_bstart = dbstart(chain[i]);
-+              saved_bend = dbend(chain[i]);
-+              sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
-+              dgen = atomic_read(&UNIONFS_D(chain[i])->generation);
-+
-+              valid = __unionfs_d_revalidate_one(chain[i], nd);
-+              /* XXX: is this the correct mntput condition?! */
-+              if (valid && chain_len > 0 &&
-+                  sbgen != dgen && chain[i]->d_inode &&
-+                  S_ISDIR(chain[i]->d_inode->i_mode)) {
-+                      for (bindex = saved_bstart; bindex <= saved_bend;
-+                           bindex++)
-+                              unionfs_mntput(chain[i], bindex);
-+              }
-+              if (chain[i] != chain[i]->d_parent)
-+                      unionfs_unlock_dentry(chain[i]->d_parent);
-+              unionfs_unlock_dentry(chain[i]);
-+
-+              if (unlikely(!valid))
-+                      goto out_free;
-+      }
-+
-+
-+out_this:
-+      /* finally, lock this dentry and revalidate it */
-+      verify_locked(dentry);  /* verify child is locked */
-+      if (dentry != dentry->d_parent)
-+              unionfs_lock_dentry(dentry->d_parent,
-+                                  UNIONFS_DMUTEX_REVAL_PARENT);
-+      valid = __unionfs_d_revalidate_one_locked(dentry, nd, willwrite);
-+      if (dentry != dentry->d_parent)
-+              unionfs_unlock_dentry(dentry->d_parent);
-+
-+out_free:
-+      /* unlock/dput all dentries in chain and return status */
-+      if (chain_len > 0) {
-+              for (i = 0; i < chain_len; i++)
-+                      dput(chain[i]);
-+              kfree(chain);
-+      }
-+out:
-+      return valid;
-+}
-+
-+static int unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
-+{
-+      int err;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      err = __unionfs_d_revalidate_chain(dentry, nd, false);
-+      if (likely(err > 0)) { /* true==1: dentry is valid */
-+              unionfs_postcopyup_setmnt(dentry);
-+              unionfs_check_dentry(dentry);
-+              unionfs_check_nd(nd);
-+      }
-+      unionfs_unlock_dentry(dentry);
-+
-+      unionfs_read_unlock(dentry->d_sb);
-+
-+      return err;
-+}
-+
-+static void unionfs_d_release(struct dentry *dentry)
-+{
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      if (unlikely(!UNIONFS_D(dentry)))
-+              goto out;       /* skip if no lower branches */
-+      /* must lock our branch configuration here */
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      unionfs_check_dentry(dentry);
-+      /* this could be a negative dentry, so check first */
-+      if (dbstart(dentry) < 0) {
-+              unionfs_unlock_dentry(dentry);
-+              goto out;       /* due to a (normal) failed lookup */
-+      }
-+
-+      /* Release all the lower dentries */
-+      path_put_lowers_all(dentry, true);
-+
-+      unionfs_unlock_dentry(dentry);
-+
-+out:
-+      free_dentry_private_data(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return;
-+}
-+
-+/*
-+ * Called when we're removing the last reference to our dentry.  So we
-+ * should drop all lower references too.
-+ */
-+static void unionfs_d_iput(struct dentry *dentry, struct inode *inode)
-+{
-+      int rc;
-+
-+      BUG_ON(!dentry);
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      if (!UNIONFS_D(dentry) || dbstart(dentry) < 0)
-+              goto drop_lower_inodes;
-+      path_put_lowers_all(dentry, false);
-+
-+drop_lower_inodes:
-+      rc = atomic_read(&inode->i_count);
-+      if (rc == 1 && inode->i_nlink == 1 && ibstart(inode) >= 0) {
-+              /* see Documentation/filesystems/unionfs/issues.txt */
-+              lockdep_off();
-+              iput(unionfs_lower_inode(inode));
-+              lockdep_on();
-+              unionfs_set_lower_inode(inode, NULL);
-+              /* XXX: may need to set start/end to -1? */
-+      }
-+
-+      iput(inode);
-+
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+}
-+
-+struct dentry_operations unionfs_dops = {
-+      .d_revalidate   = unionfs_d_revalidate,
-+      .d_release      = unionfs_d_release,
-+      .d_iput         = unionfs_d_iput,
-+};
-diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
-new file mode 100644
-index 0000000..14ca7d3
---- /dev/null
-+++ b/fs/unionfs/dirfops.c
-@@ -0,0 +1,292 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/* Make sure our rdstate is playing by the rules. */
-+static void verify_rdstate_offset(struct unionfs_dir_state *rdstate)
-+{
-+      BUG_ON(rdstate->offset >= DIREOF);
-+      BUG_ON(rdstate->cookie >= MAXRDCOOKIE);
-+}
-+
-+struct unionfs_getdents_callback {
-+      struct unionfs_dir_state *rdstate;
-+      void *dirent;
-+      int entries_written;
-+      int filldir_called;
-+      int filldir_error;
-+      filldir_t filldir;
-+      struct super_block *sb;
-+};
-+
-+/* based on generic filldir in fs/readir.c */
-+static int unionfs_filldir(void *dirent, const char *oname, int namelen,
-+                         loff_t offset, u64 ino, unsigned int d_type)
-+{
-+      struct unionfs_getdents_callback *buf = dirent;
-+      struct filldir_node *found = NULL;
-+      int err = 0;
-+      int is_whiteout;
-+      char *name = (char *) oname;
-+
-+      buf->filldir_called++;
-+
-+      is_whiteout = is_whiteout_name(&name, &namelen);
-+
-+      found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout);
-+
-+      if (found) {
-+              /*
-+               * If we had non-whiteout entry in dir cache, then mark it
-+               * as a whiteout and but leave it in the dir cache.
-+               */
-+              if (is_whiteout && !found->whiteout)
-+                      found->whiteout = is_whiteout;
-+              goto out;
-+      }
-+
-+      /* if 'name' isn't a whiteout, filldir it. */
-+      if (!is_whiteout) {
-+              off_t pos = rdstate2offset(buf->rdstate);
-+              u64 unionfs_ino = ino;
-+
-+              err = buf->filldir(buf->dirent, name, namelen, pos,
-+                                 unionfs_ino, d_type);
-+              buf->rdstate->offset++;
-+              verify_rdstate_offset(buf->rdstate);
-+      }
-+      /*
-+       * If we did fill it, stuff it in our hash, otherwise return an
-+       * error.
-+       */
-+      if (err) {
-+              buf->filldir_error = err;
-+              goto out;
-+      }
-+      buf->entries_written++;
-+      err = add_filldir_node(buf->rdstate, name, namelen,
-+                             buf->rdstate->bindex, is_whiteout);
-+      if (err)
-+              buf->filldir_error = err;
-+
-+out:
-+      return err;
-+}
-+
-+static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
-+{
-+      int err = 0;
-+      struct file *lower_file = NULL;
-+      struct dentry *dentry = file->f_path.dentry;
-+      struct inode *inode = NULL;
-+      struct unionfs_getdents_callback buf;
-+      struct unionfs_dir_state *uds;
-+      int bend;
-+      loff_t offset;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      err = unionfs_file_revalidate(file, false);
-+      if (unlikely(err))
-+              goto out;
-+
-+      inode = dentry->d_inode;
-+
-+      uds = UNIONFS_F(file)->rdstate;
-+      if (!uds) {
-+              if (file->f_pos == DIREOF) {
-+                      goto out;
-+              } else if (file->f_pos > 0) {
-+                      uds = find_rdstate(inode, file->f_pos);
-+                      if (unlikely(!uds)) {
-+                              err = -ESTALE;
-+                              goto out;
-+                      }
-+                      UNIONFS_F(file)->rdstate = uds;
-+              } else {
-+                      init_rdstate(file);
-+                      uds = UNIONFS_F(file)->rdstate;
-+              }
-+      }
-+      bend = fbend(file);
-+
-+      while (uds->bindex <= bend) {
-+              lower_file = unionfs_lower_file_idx(file, uds->bindex);
-+              if (!lower_file) {
-+                      uds->bindex++;
-+                      uds->dirpos = 0;
-+                      continue;
-+              }
-+
-+              /* prepare callback buffer */
-+              buf.filldir_called = 0;
-+              buf.filldir_error = 0;
-+              buf.entries_written = 0;
-+              buf.dirent = dirent;
-+              buf.filldir = filldir;
-+              buf.rdstate = uds;
-+              buf.sb = inode->i_sb;
-+
-+              /* Read starting from where we last left off. */
-+              offset = vfs_llseek(lower_file, uds->dirpos, SEEK_SET);
-+              if (offset < 0) {
-+                      err = offset;
-+                      goto out;
-+              }
-+              err = vfs_readdir(lower_file, unionfs_filldir, &buf);
-+
-+              /* Save the position for when we continue. */
-+              offset = vfs_llseek(lower_file, 0, SEEK_CUR);
-+              if (offset < 0) {
-+                      err = offset;
-+                      goto out;
-+              }
-+              uds->dirpos = offset;
-+
-+              /* Copy the atime. */
-+              fsstack_copy_attr_atime(inode,
-+                                      lower_file->f_path.dentry->d_inode);
-+
-+              if (err < 0)
-+                      goto out;
-+
-+              if (buf.filldir_error)
-+                      break;
-+
-+              if (!buf.entries_written) {
-+                      uds->bindex++;
-+                      uds->dirpos = 0;
-+              }
-+      }
-+
-+      if (!buf.filldir_error && uds->bindex >= bend) {
-+              /* Save the number of hash entries for next time. */
-+              UNIONFS_I(inode)->hashsize = uds->hashentries;
-+              free_rdstate(uds);
-+              UNIONFS_F(file)->rdstate = NULL;
-+              file->f_pos = DIREOF;
-+      } else {
-+              file->f_pos = rdstate2offset(uds);
-+      }
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+/*
-+ * This is not meant to be a generic repositioning function.  If you do
-+ * things that aren't supported, then we return EINVAL.
-+ *
-+ * What is allowed:
-+ *  (1) seeking to the same position that you are currently at
-+ *    This really has no effect, but returns where you are.
-+ *  (2) seeking to the beginning of the file
-+ *    This throws out all state, and lets you begin again.
-+ */
-+static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin)
-+{
-+      struct unionfs_dir_state *rdstate;
-+      struct dentry *dentry = file->f_path.dentry;
-+      loff_t err;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      err = unionfs_file_revalidate(file, false);
-+      if (unlikely(err))
-+              goto out;
-+
-+      rdstate = UNIONFS_F(file)->rdstate;
-+
-+      /*
-+       * we let users seek to their current position, but not anywhere
-+       * else.
-+       */
-+      if (!offset) {
-+              switch (origin) {
-+              case SEEK_SET:
-+                      if (rdstate) {
-+                              free_rdstate(rdstate);
-+                              UNIONFS_F(file)->rdstate = NULL;
-+                      }
-+                      init_rdstate(file);
-+                      err = 0;
-+                      break;
-+              case SEEK_CUR:
-+                      err = file->f_pos;
-+                      break;
-+              case SEEK_END:
-+                      /* Unsupported, because we would break everything.  */
-+                      err = -EINVAL;
-+                      break;
-+              }
-+      } else {
-+              switch (origin) {
-+              case SEEK_SET:
-+                      if (rdstate) {
-+                              if (offset == rdstate2offset(rdstate))
-+                                      err = offset;
-+                              else if (file->f_pos == DIREOF)
-+                                      err = DIREOF;
-+                              else
-+                                      err = -EINVAL;
-+                      } else {
-+                              struct inode *inode;
-+                              inode = dentry->d_inode;
-+                              rdstate = find_rdstate(inode, offset);
-+                              if (rdstate) {
-+                                      UNIONFS_F(file)->rdstate = rdstate;
-+                                      err = rdstate->offset;
-+                              } else {
-+                                      err = -EINVAL;
-+                              }
-+                      }
-+                      break;
-+              case SEEK_CUR:
-+              case SEEK_END:
-+                      /* Unsupported, because we would break everything.  */
-+                      err = -EINVAL;
-+                      break;
-+              }
-+      }
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+/*
-+ * Trimmed directory options, we shouldn't pass everything down since
-+ * we don't want to operate on partial directories.
-+ */
-+struct file_operations unionfs_dir_fops = {
-+      .llseek         = unionfs_dir_llseek,
-+      .read           = generic_read_dir,
-+      .readdir        = unionfs_readdir,
-+      .unlocked_ioctl = unionfs_ioctl,
-+      .open           = unionfs_open,
-+      .release        = unionfs_file_release,
-+      .flush          = unionfs_flush,
-+      .fsync          = unionfs_fsync,
-+      .fasync         = unionfs_fasync,
-+};
-diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
-new file mode 100644
-index 0000000..d936f03
---- /dev/null
-+++ b/fs/unionfs/dirhelper.c
-@@ -0,0 +1,157 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+#define RD_NONE 0
-+#define RD_CHECK_EMPTY 1
-+/* The callback structure for check_empty. */
-+struct unionfs_rdutil_callback {
-+      int err;
-+      int filldir_called;
-+      struct unionfs_dir_state *rdstate;
-+      int mode;
-+};
-+
-+/* This filldir function makes sure only whiteouts exist within a directory. */
-+static int readdir_util_callback(void *dirent, const char *oname, int namelen,
-+                               loff_t offset, u64 ino, unsigned int d_type)
-+{
-+      int err = 0;
-+      struct unionfs_rdutil_callback *buf = dirent;
-+      int is_whiteout;
-+      struct filldir_node *found;
-+      char *name = (char *) oname;
-+
-+      buf->filldir_called = 1;
-+
-+      if (name[0] == '.' && (namelen == 1 ||
-+                             (name[1] == '.' && namelen == 2)))
-+              goto out;
-+
-+      is_whiteout = is_whiteout_name(&name, &namelen);
-+
-+      found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout);
-+      /* If it was found in the table there was a previous whiteout. */
-+      if (found)
-+              goto out;
-+
-+      /*
-+       * if it wasn't found and isn't a whiteout, the directory isn't
-+       * empty.
-+       */
-+      err = -ENOTEMPTY;
-+      if ((buf->mode == RD_CHECK_EMPTY) && !is_whiteout)
-+              goto out;
-+
-+      err = add_filldir_node(buf->rdstate, name, namelen,
-+                             buf->rdstate->bindex, is_whiteout);
-+
-+out:
-+      buf->err = err;
-+      return err;
-+}
-+
-+/* Is a directory logically empty? */
-+int check_empty(struct dentry *dentry, struct unionfs_dir_state **namelist)
-+{
-+      int err = 0;
-+      struct dentry *lower_dentry = NULL;
-+      struct vfsmount *mnt;
-+      struct super_block *sb;
-+      struct file *lower_file;
-+      struct unionfs_rdutil_callback *buf = NULL;
-+      int bindex, bstart, bend, bopaque;
-+
-+      sb = dentry->d_sb;
-+
-+
-+      BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
-+
-+      err = unionfs_partial_lookup(dentry);
-+      if (err)
-+              goto out;
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      bopaque = dbopaque(dentry);
-+      if (0 <= bopaque && bopaque < bend)
-+              bend = bopaque;
-+
-+      buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
-+      if (unlikely(!buf)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+      buf->err = 0;
-+      buf->mode = RD_CHECK_EMPTY;
-+      buf->rdstate = alloc_rdstate(dentry->d_inode, bstart);
-+      if (unlikely(!buf->rdstate)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      /* Process the lower directories with rdutil_callback as a filldir. */
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry)
-+                      continue;
-+              if (!lower_dentry->d_inode)
-+                      continue;
-+              if (!S_ISDIR(lower_dentry->d_inode->i_mode))
-+                      continue;
-+
-+              dget(lower_dentry);
-+              mnt = unionfs_mntget(dentry, bindex);
-+              branchget(sb, bindex);
-+              lower_file = dentry_open(lower_dentry, mnt, O_RDONLY);
-+              if (IS_ERR(lower_file)) {
-+                      err = PTR_ERR(lower_file);
-+                      branchput(sb, bindex);
-+                      goto out;
-+              }
-+
-+              do {
-+                      buf->filldir_called = 0;
-+                      buf->rdstate->bindex = bindex;
-+                      err = vfs_readdir(lower_file,
-+                                        readdir_util_callback, buf);
-+                      if (buf->err)
-+                              err = buf->err;
-+              } while ((err >= 0) && buf->filldir_called);
-+
-+              /* fput calls dput for lower_dentry */
-+              fput(lower_file);
-+              branchput(sb, bindex);
-+
-+              if (err < 0)
-+                      goto out;
-+      }
-+
-+out:
-+      if (buf) {
-+              if (namelist && !err)
-+                      *namelist = buf->rdstate;
-+              else if (buf->rdstate)
-+                      free_rdstate(buf->rdstate);
-+              kfree(buf);
-+      }
-+
-+
-+      return err;
-+}
-diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
-new file mode 100644
-index 0000000..4f264de
---- /dev/null
-+++ b/fs/unionfs/fanout.h
-@@ -0,0 +1,384 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef _FANOUT_H_
-+#define _FANOUT_H_
-+
-+/*
-+ * Inode to private data
-+ *
-+ * Since we use containers and the struct inode is _inside_ the
-+ * unionfs_inode_info structure, UNIONFS_I will always (given a non-NULL
-+ * inode pointer), return a valid non-NULL pointer.
-+ */
-+static inline struct unionfs_inode_info *UNIONFS_I(const struct inode *inode)
-+{
-+      return container_of(inode, struct unionfs_inode_info, vfs_inode);
-+}
-+
-+#define ibstart(ino) (UNIONFS_I(ino)->bstart)
-+#define ibend(ino) (UNIONFS_I(ino)->bend)
-+
-+/* Dentry to private data */
-+#define UNIONFS_D(dent) ((struct unionfs_dentry_info *)(dent)->d_fsdata)
-+#define dbstart(dent) (UNIONFS_D(dent)->bstart)
-+#define dbend(dent) (UNIONFS_D(dent)->bend)
-+#define dbopaque(dent) (UNIONFS_D(dent)->bopaque)
-+
-+/* Superblock to private data */
-+#define UNIONFS_SB(super) ((struct unionfs_sb_info *)(super)->s_fs_info)
-+#define sbstart(sb) 0
-+#define sbend(sb) (UNIONFS_SB(sb)->bend)
-+#define sbmax(sb) (UNIONFS_SB(sb)->bend + 1)
-+#define sbhbid(sb) (UNIONFS_SB(sb)->high_branch_id)
-+
-+/* File to private Data */
-+#define UNIONFS_F(file) ((struct unionfs_file_info *)((file)->private_data))
-+#define fbstart(file) (UNIONFS_F(file)->bstart)
-+#define fbend(file) (UNIONFS_F(file)->bend)
-+
-+/* macros to manipulate branch IDs in stored in our superblock */
-+static inline int branch_id(struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      return UNIONFS_SB(sb)->data[index].branch_id;
-+}
-+
-+static inline void set_branch_id(struct super_block *sb, int index, int val)
-+{
-+      BUG_ON(!sb || index < 0);
-+      UNIONFS_SB(sb)->data[index].branch_id = val;
-+}
-+
-+static inline void new_branch_id(struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      set_branch_id(sb, index, ++UNIONFS_SB(sb)->high_branch_id);
-+}
-+
-+/*
-+ * Find new index of matching branch with an existing superblock of a known
-+ * (possibly old) id.  This is needed because branches could have been
-+ * added/deleted causing the branches of any open files to shift.
-+ *
-+ * @sb: the new superblock which may have new/different branch IDs
-+ * @id: the old/existing id we're looking for
-+ * Returns index of newly found branch (0 or greater), -1 otherwise.
-+ */
-+static inline int branch_id_to_idx(struct super_block *sb, int id)
-+{
-+      int i;
-+      for (i = 0; i < sbmax(sb); i++) {
-+              if (branch_id(sb, i) == id)
-+                      return i;
-+      }
-+      /* in the non-ODF code, this should really never happen */
-+      printk(KERN_WARNING "unionfs: cannot find branch with id %d\n", id);
-+      return -1;
-+}
-+
-+/* File to lower file. */
-+static inline struct file *unionfs_lower_file(const struct file *f)
-+{
-+      BUG_ON(!f);
-+      return UNIONFS_F(f)->lower_files[fbstart(f)];
-+}
-+
-+static inline struct file *unionfs_lower_file_idx(const struct file *f,
-+                                                int index)
-+{
-+      BUG_ON(!f || index < 0);
-+      return UNIONFS_F(f)->lower_files[index];
-+}
-+
-+static inline void unionfs_set_lower_file_idx(struct file *f, int index,
-+                                            struct file *val)
-+{
-+      BUG_ON(!f || index < 0);
-+      UNIONFS_F(f)->lower_files[index] = val;
-+      /* save branch ID (may be redundant?) */
-+      UNIONFS_F(f)->saved_branch_ids[index] =
-+              branch_id((f)->f_path.dentry->d_sb, index);
-+}
-+
-+static inline void unionfs_set_lower_file(struct file *f, struct file *val)
-+{
-+      BUG_ON(!f);
-+      unionfs_set_lower_file_idx((f), fbstart(f), (val));
-+}
-+
-+/* Inode to lower inode. */
-+static inline struct inode *unionfs_lower_inode(const struct inode *i)
-+{
-+      BUG_ON(!i);
-+      return UNIONFS_I(i)->lower_inodes[ibstart(i)];
-+}
-+
-+static inline struct inode *unionfs_lower_inode_idx(const struct inode *i,
-+                                                  int index)
-+{
-+      BUG_ON(!i || index < 0);
-+      return UNIONFS_I(i)->lower_inodes[index];
-+}
-+
-+static inline void unionfs_set_lower_inode_idx(struct inode *i, int index,
-+                                             struct inode *val)
-+{
-+      BUG_ON(!i || index < 0);
-+      UNIONFS_I(i)->lower_inodes[index] = val;
-+}
-+
-+static inline void unionfs_set_lower_inode(struct inode *i, struct inode *val)
-+{
-+      BUG_ON(!i);
-+      UNIONFS_I(i)->lower_inodes[ibstart(i)] = val;
-+}
-+
-+/* Superblock to lower superblock. */
-+static inline struct super_block *unionfs_lower_super(
-+                                      const struct super_block *sb)
-+{
-+      BUG_ON(!sb);
-+      return UNIONFS_SB(sb)->data[sbstart(sb)].sb;
-+}
-+
-+static inline struct super_block *unionfs_lower_super_idx(
-+                                      const struct super_block *sb,
-+                                      int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      return UNIONFS_SB(sb)->data[index].sb;
-+}
-+
-+static inline void unionfs_set_lower_super_idx(struct super_block *sb,
-+                                             int index,
-+                                             struct super_block *val)
-+{
-+      BUG_ON(!sb || index < 0);
-+      UNIONFS_SB(sb)->data[index].sb = val;
-+}
-+
-+static inline void unionfs_set_lower_super(struct super_block *sb,
-+                                         struct super_block *val)
-+{
-+      BUG_ON(!sb);
-+      UNIONFS_SB(sb)->data[sbstart(sb)].sb = val;
-+}
-+
-+/* Branch count macros. */
-+static inline int branch_count(const struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      return atomic_read(&UNIONFS_SB(sb)->data[index].open_files);
-+}
-+
-+static inline void set_branch_count(struct super_block *sb, int index, int val)
-+{
-+      BUG_ON(!sb || index < 0);
-+      atomic_set(&UNIONFS_SB(sb)->data[index].open_files, val);
-+}
-+
-+static inline void branchget(struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      atomic_inc(&UNIONFS_SB(sb)->data[index].open_files);
-+}
-+
-+static inline void branchput(struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      atomic_dec(&UNIONFS_SB(sb)->data[index].open_files);
-+}
-+
-+/* Dentry macros */
-+static inline void unionfs_set_lower_dentry_idx(struct dentry *dent, int index,
-+                                              struct dentry *val)
-+{
-+      BUG_ON(!dent || index < 0);
-+      UNIONFS_D(dent)->lower_paths[index].dentry = val;
-+}
-+
-+static inline struct dentry *unionfs_lower_dentry_idx(
-+                              const struct dentry *dent,
-+                              int index)
-+{
-+      BUG_ON(!dent || index < 0);
-+      return UNIONFS_D(dent)->lower_paths[index].dentry;
-+}
-+
-+static inline struct dentry *unionfs_lower_dentry(const struct dentry *dent)
-+{
-+      BUG_ON(!dent);
-+      return unionfs_lower_dentry_idx(dent, dbstart(dent));
-+}
-+
-+static inline void unionfs_set_lower_mnt_idx(struct dentry *dent, int index,
-+                                           struct vfsmount *mnt)
-+{
-+      BUG_ON(!dent || index < 0);
-+      UNIONFS_D(dent)->lower_paths[index].mnt = mnt;
-+}
-+
-+static inline struct vfsmount *unionfs_lower_mnt_idx(
-+                                      const struct dentry *dent,
-+                                      int index)
-+{
-+      BUG_ON(!dent || index < 0);
-+      return UNIONFS_D(dent)->lower_paths[index].mnt;
-+}
-+
-+static inline struct vfsmount *unionfs_lower_mnt(const struct dentry *dent)
-+{
-+      BUG_ON(!dent);
-+      return unionfs_lower_mnt_idx(dent, dbstart(dent));
-+}
-+
-+/* Macros for locking a dentry. */
-+enum unionfs_dentry_lock_class {
-+      UNIONFS_DMUTEX_NORMAL,
-+      UNIONFS_DMUTEX_ROOT,
-+      UNIONFS_DMUTEX_PARENT,
-+      UNIONFS_DMUTEX_CHILD,
-+      UNIONFS_DMUTEX_WHITEOUT,
-+      UNIONFS_DMUTEX_REVAL_PARENT, /* for file/dentry revalidate */
-+      UNIONFS_DMUTEX_REVAL_CHILD,   /* for file/dentry revalidate */
-+};
-+
-+static inline void unionfs_lock_dentry(struct dentry *d,
-+                                     unsigned int subclass)
-+{
-+      BUG_ON(!d);
-+      mutex_lock_nested(&UNIONFS_D(d)->lock, subclass);
-+}
-+
-+static inline void unionfs_unlock_dentry(struct dentry *d)
-+{
-+      BUG_ON(!d);
-+      mutex_unlock(&UNIONFS_D(d)->lock);
-+}
-+
-+static inline void verify_locked(struct dentry *d)
-+{
-+      BUG_ON(!d);
-+      BUG_ON(!mutex_is_locked(&UNIONFS_D(d)->lock));
-+}
-+
-+/* macros to put lower objects */
-+
-+/*
-+ * iput lower inodes of an unionfs dentry, from bstart to bend.  If
-+ * @free_lower is true, then also kfree the memory used to hold the lower
-+ * object pointers.
-+ */
-+static inline void iput_lowers(struct inode *inode,
-+                             int bstart, int bend, bool free_lower)
-+{
-+      struct inode *lower_inode;
-+      int bindex;
-+
-+      BUG_ON(!inode);
-+      BUG_ON(!UNIONFS_I(inode));
-+      BUG_ON(bstart < 0);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (lower_inode) {
-+                      unionfs_set_lower_inode_idx(inode, bindex, NULL);
-+                      /* see Documentation/filesystems/unionfs/issues.txt */
-+                      lockdep_off();
-+                      iput(lower_inode);
-+                      lockdep_on();
-+              }
-+      }
-+
-+      if (free_lower) {
-+              kfree(UNIONFS_I(inode)->lower_inodes);
-+              UNIONFS_I(inode)->lower_inodes = NULL;
-+      }
-+}
-+
-+/* iput all lower inodes, and reset start/end branch indices to -1 */
-+static inline void iput_lowers_all(struct inode *inode, bool free_lower)
-+{
-+      int bstart, bend;
-+
-+      BUG_ON(!inode);
-+      BUG_ON(!UNIONFS_I(inode));
-+      bstart = ibstart(inode);
-+      bend = ibend(inode);
-+      BUG_ON(bstart < 0);
-+
-+      iput_lowers(inode, bstart, bend, free_lower);
-+      ibstart(inode) = ibend(inode) = -1;
-+}
-+
-+/*
-+ * dput/mntput all lower dentries and vfsmounts of an unionfs dentry, from
-+ * bstart to bend.  If @free_lower is true, then also kfree the memory used
-+ * to hold the lower object pointers.
-+ *
-+ * XXX: implement using path_put VFS macros
-+ */
-+static inline void path_put_lowers(struct dentry *dentry,
-+                                 int bstart, int bend, bool free_lower)
-+{
-+      struct dentry *lower_dentry;
-+      struct vfsmount *lower_mnt;
-+      int bindex;
-+
-+      BUG_ON(!dentry);
-+      BUG_ON(!UNIONFS_D(dentry));
-+      BUG_ON(bstart < 0);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (lower_dentry) {
-+                      unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
-+                      dput(lower_dentry);
-+              }
-+              lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
-+              if (lower_mnt) {
-+                      unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
-+                      mntput(lower_mnt);
-+              }
-+      }
-+
-+      if (free_lower) {
-+              kfree(UNIONFS_D(dentry)->lower_paths);
-+              UNIONFS_D(dentry)->lower_paths = NULL;
-+      }
-+}
-+
-+/*
-+ * dput/mntput all lower dentries and vfsmounts, and reset start/end branch
-+ * indices to -1.
-+ */
-+static inline void path_put_lowers_all(struct dentry *dentry, bool free_lower)
-+{
-+      int bstart, bend;
-+
-+      BUG_ON(!dentry);
-+      BUG_ON(!UNIONFS_D(dentry));
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      BUG_ON(bstart < 0);
-+
-+      path_put_lowers(dentry, bstart, bend, free_lower);
-+      dbstart(dentry) = dbend(dentry) = -1;
-+}
-+
-+#endif        /* not _FANOUT_H */
-diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
-new file mode 100644
-index 0000000..965d071
---- /dev/null
-+++ b/fs/unionfs/file.c
-@@ -0,0 +1,341 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+static ssize_t unionfs_read(struct file *file, char __user *buf,
-+                          size_t count, loff_t *ppos)
-+{
-+      int err;
-+      struct file *lower_file;
-+      struct dentry *dentry = file->f_path.dentry;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      err = unionfs_file_revalidate(file, false);
-+      if (unlikely(err))
-+              goto out;
-+
-+      lower_file = unionfs_lower_file(file);
-+      err = vfs_read(lower_file, buf, count, ppos);
-+      /* update our inode atime upon a successful lower read */
-+      if (err >= 0) {
-+              fsstack_copy_attr_atime(dentry->d_inode,
-+                                      lower_file->f_path.dentry->d_inode);
-+              unionfs_check_file(file);
-+      }
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static ssize_t unionfs_write(struct file *file, const char __user *buf,
-+                           size_t count, loff_t *ppos)
-+{
-+      int err = 0;
-+      struct file *lower_file;
-+      struct dentry *dentry = file->f_path.dentry;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      if (dentry != dentry->d_parent)
-+              unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_PARENT);
-+      err = unionfs_file_revalidate_locked(file, true);
-+      if (unlikely(err))
-+              goto out;
-+
-+      lower_file = unionfs_lower_file(file);
-+      err = vfs_write(lower_file, buf, count, ppos);
-+      /* update our inode times+sizes upon a successful lower write */
-+      if (err >= 0) {
-+              fsstack_copy_inode_size(dentry->d_inode,
-+                                      lower_file->f_path.dentry->d_inode);
-+              fsstack_copy_attr_times(dentry->d_inode,
-+                                      lower_file->f_path.dentry->d_inode);
-+              UNIONFS_F(file)->wrote_to_file = true; /* for delayed copyup */
-+              unionfs_check_file(file);
-+      }
-+
-+out:
-+      if (dentry != dentry->d_parent)
-+              unionfs_unlock_dentry(dentry->d_parent);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static int unionfs_file_readdir(struct file *file, void *dirent,
-+                              filldir_t filldir)
-+{
-+      return -ENOTDIR;
-+}
-+
-+static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+      int err = 0;
-+      bool willwrite;
-+      struct file *lower_file;
-+      struct dentry *dentry = file->f_path.dentry;
-+      struct vm_operations_struct *saved_vm_ops = NULL;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      /* This might be deferred to mmap's writepage */
-+      willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
-+      err = unionfs_file_revalidate(file, willwrite);
-+      if (unlikely(err))
-+              goto out;
-+      unionfs_check_file(file);
-+
-+      /*
-+       * File systems which do not implement ->writepage may use
-+       * generic_file_readonly_mmap as their ->mmap op.  If you call
-+       * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
-+       * But we cannot call the lower ->mmap op, so we can't tell that
-+       * writeable mappings won't work.  Therefore, our only choice is to
-+       * check if the lower file system supports the ->writepage, and if
-+       * not, return EINVAL (the same error that
-+       * generic_file_readonly_mmap returns in that case).
-+       */
-+      lower_file = unionfs_lower_file(file);
-+      if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
-+              err = -EINVAL;
-+              printk(KERN_ERR "unionfs: branch %d file system does not "
-+                     "support writeable mmap\n", fbstart(file));
-+              goto out;
-+      }
-+
-+      /*
-+       * find and save lower vm_ops.
-+       *
-+       * XXX: the VFS should have a cleaner way of finding the lower vm_ops
-+       */
-+      if (!UNIONFS_F(file)->lower_vm_ops) {
-+              err = lower_file->f_op->mmap(lower_file, vma);
-+              if (err) {
-+                      printk(KERN_ERR "unionfs: lower mmap failed %d\n", err);
-+                      goto out;
-+              }
-+              saved_vm_ops = vma->vm_ops;
-+              err = do_munmap(current->mm, vma->vm_start,
-+                              vma->vm_end - vma->vm_start);
-+              if (err) {
-+                      printk(KERN_ERR "unionfs: do_munmap failed %d\n", err);
-+                      goto out;
-+              }
-+      }
-+
-+      file->f_mapping->a_ops = &unionfs_dummy_aops;
-+      err = generic_file_mmap(file, vma);
-+      file->f_mapping->a_ops = &unionfs_aops;
-+      if (err) {
-+              printk(KERN_ERR "unionfs: generic_file_mmap failed %d\n", err);
-+              goto out;
-+      }
-+      vma->vm_ops = &unionfs_vm_ops;
-+      if (!UNIONFS_F(file)->lower_vm_ops)
-+              UNIONFS_F(file)->lower_vm_ops = saved_vm_ops;
-+
-+out:
-+      if (!err) {
-+              /* copyup could cause parent dir times to change */
-+              unionfs_copy_attr_times(dentry->d_parent->d_inode);
-+              unionfs_check_file(file);
-+      }
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+int unionfs_fsync(struct file *file, struct dentry *dentry, int datasync)
-+{
-+      int bindex, bstart, bend;
-+      struct file *lower_file;
-+      struct dentry *lower_dentry;
-+      struct inode *lower_inode, *inode;
-+      int err = -EINVAL;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      err = unionfs_file_revalidate(file, true);
-+      if (unlikely(err))
-+              goto out;
-+      unionfs_check_file(file);
-+
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+      if (bstart < 0 || bend < 0)
-+              goto out;
-+
-+      inode = dentry->d_inode;
-+      if (unlikely(!inode)) {
-+              printk(KERN_ERR
-+                     "unionfs: null lower inode in unionfs_fsync\n");
-+              goto out;
-+      }
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (!lower_inode || !lower_inode->i_fop->fsync)
-+                      continue;
-+              lower_file = unionfs_lower_file_idx(file, bindex);
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              mutex_lock(&lower_inode->i_mutex);
-+              err = lower_inode->i_fop->fsync(lower_file,
-+                                              lower_dentry,
-+                                              datasync);
-+              if (!err && bindex == bstart)
-+                      fsstack_copy_attr_times(inode, lower_inode);
-+              mutex_unlock(&lower_inode->i_mutex);
-+              if (err)
-+                      goto out;
-+      }
-+
-+out:
-+      if (!err)
-+              unionfs_check_file(file);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+int unionfs_fasync(int fd, struct file *file, int flag)
-+{
-+      int bindex, bstart, bend;
-+      struct file *lower_file;
-+      struct dentry *dentry = file->f_path.dentry;
-+      struct inode *lower_inode, *inode;
-+      int err = 0;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      err = unionfs_file_revalidate(file, true);
-+      if (unlikely(err))
-+              goto out;
-+      unionfs_check_file(file);
-+
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+      if (bstart < 0 || bend < 0)
-+              goto out;
-+
-+      inode = dentry->d_inode;
-+      if (unlikely(!inode)) {
-+              printk(KERN_ERR
-+                     "unionfs: null lower inode in unionfs_fasync\n");
-+              goto out;
-+      }
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (!lower_inode || !lower_inode->i_fop->fasync)
-+                      continue;
-+              lower_file = unionfs_lower_file_idx(file, bindex);
-+              mutex_lock(&lower_inode->i_mutex);
-+              err = lower_inode->i_fop->fasync(fd, lower_file, flag);
-+              if (!err && bindex == bstart)
-+                      fsstack_copy_attr_times(inode, lower_inode);
-+              mutex_unlock(&lower_inode->i_mutex);
-+              if (err)
-+                      goto out;
-+      }
-+
-+out:
-+      if (!err)
-+              unionfs_check_file(file);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static ssize_t unionfs_splice_read(struct file *file, loff_t *ppos,
-+                                 struct pipe_inode_info *pipe, size_t len,
-+                                 unsigned int flags)
-+{
-+      ssize_t err;
-+      struct file *lower_file;
-+      struct dentry *dentry = file->f_path.dentry;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      err = unionfs_file_revalidate(file, false);
-+      if (unlikely(err))
-+              goto out;
-+
-+      lower_file = unionfs_lower_file(file);
-+      err = vfs_splice_to(lower_file, ppos, pipe, len, flags);
-+      /* update our inode atime upon a successful lower splice-read */
-+      if (err >= 0) {
-+              fsstack_copy_attr_atime(dentry->d_inode,
-+                                      lower_file->f_path.dentry->d_inode);
-+              unionfs_check_file(file);
-+      }
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static ssize_t unionfs_splice_write(struct pipe_inode_info *pipe,
-+                                  struct file *file, loff_t *ppos,
-+                                  size_t len, unsigned int flags)
-+{
-+      ssize_t err = 0;
-+      struct file *lower_file;
-+      struct dentry *dentry = file->f_path.dentry;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      err = unionfs_file_revalidate(file, true);
-+      if (unlikely(err))
-+              goto out;
-+
-+      lower_file = unionfs_lower_file(file);
-+      err = vfs_splice_from(pipe, lower_file, ppos, len, flags);
-+      /* update our inode times+sizes upon a successful lower write */
-+      if (err >= 0) {
-+              fsstack_copy_inode_size(dentry->d_inode,
-+                                      lower_file->f_path.dentry->d_inode);
-+              fsstack_copy_attr_times(dentry->d_inode,
-+                                      lower_file->f_path.dentry->d_inode);
-+              unionfs_check_file(file);
-+      }
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+struct file_operations unionfs_main_fops = {
-+      .llseek         = generic_file_llseek,
-+      .read           = unionfs_read,
-+      .write          = unionfs_write,
-+      .readdir        = unionfs_file_readdir,
-+      .unlocked_ioctl = unionfs_ioctl,
-+      .mmap           = unionfs_mmap,
-+      .open           = unionfs_open,
-+      .flush          = unionfs_flush,
-+      .release        = unionfs_file_release,
-+      .fsync          = unionfs_fsync,
-+      .fasync         = unionfs_fasync,
-+      .splice_read    = unionfs_splice_read,
-+      .splice_write   = unionfs_splice_write,
-+};
-diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
-new file mode 100644
-index 0000000..0bd9fab
---- /dev/null
-+++ b/fs/unionfs/inode.c
-@@ -0,0 +1,984 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * Find a writeable branch to create new object in.  Checks all writeble
-+ * branches of the parent inode, from istart to iend order; if none are
-+ * suitable, also tries branch 0 (which may require a copyup).
-+ *
-+ * Return a lower_dentry we can use to create object in, or ERR_PTR.
-+ */
-+static struct dentry *find_writeable_branch(struct inode *parent,
-+                                          struct dentry *dentry)
-+{
-+      int err = -EINVAL;
-+      int bindex, istart, iend;
-+      struct dentry *lower_dentry = NULL;
-+
-+      istart = ibstart(parent);
-+      iend = ibend(parent);
-+      if (istart < 0)
-+              goto out;
-+
-+begin:
-+      for (bindex = istart; bindex <= iend; bindex++) {
-+              /* skip non-writeable branches */
-+              err = is_robranch_super(dentry->d_sb, bindex);
-+              if (err) {
-+                      err = -EROFS;
-+                      continue;
-+              }
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry)
-+                      continue;
-+              /*
-+               * check for whiteouts in writeable branch, and remove them
-+               * if necessary.
-+               */
-+              err = check_unlink_whiteout(dentry, lower_dentry, bindex);
-+              if (err > 0)    /* ignore if whiteout found and removed */
-+                      err = 0;
-+              if (err)
-+                      continue;
-+              /* if get here, we can write to the branch */
-+              break;
-+      }
-+      /*
-+       * If istart wasn't already branch 0, and we got any error, then try
-+       * branch 0 (which may require copyup)
-+       */
-+      if (err && istart > 0) {
-+              istart = iend = 0;
-+              goto begin;
-+      }
-+
-+      /*
-+       * If we tried even branch 0, and still got an error, abort.  But if
-+       * the error was an EROFS, then we should try to copyup.
-+       */
-+      if (err && err != -EROFS)
-+              goto out;
-+
-+      /*
-+       * If we get here, then check if copyup needed.  If lower_dentry is
-+       * NULL, create the entire dentry directory structure in branch 0.
-+       */
-+      if (!lower_dentry) {
-+              bindex = 0;
-+              lower_dentry = create_parents(parent, dentry,
-+                                            dentry->d_name.name, bindex);
-+              if (IS_ERR(lower_dentry)) {
-+                      err = PTR_ERR(lower_dentry);
-+                      goto out;
-+              }
-+      }
-+      err = 0;                /* all's well */
-+out:
-+      if (err)
-+              return ERR_PTR(err);
-+      return lower_dentry;
-+}
-+
-+static int unionfs_create(struct inode *parent, struct dentry *dentry,
-+                        int mode, struct nameidata *nd)
-+{
-+      int err = 0;
-+      struct dentry *lower_dentry = NULL;
-+      struct dentry *lower_parent_dentry = NULL;
-+      int valid = 0;
-+      struct nameidata lower_nd;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_PARENT);
-+
-+      valid = __unionfs_d_revalidate_chain(dentry->d_parent, nd, false);
-+      if (unlikely(!valid)) {
-+              err = -ESTALE;  /* same as what real_lookup does */
-+              goto out;
-+      }
-+
-+      valid = __unionfs_d_revalidate_one_locked(dentry, nd, false);
-+      /*
-+       * It's only a bug if this dentry was not negative and couldn't be
-+       * revalidated (shouldn't happen).
-+       */
-+      BUG_ON(!valid && dentry->d_inode);
-+
-+      lower_dentry = find_writeable_branch(parent, dentry);
-+      if (IS_ERR(lower_dentry)) {
-+              err = PTR_ERR(lower_dentry);
-+              goto out;
-+      }
-+
-+      lower_parent_dentry = lock_parent(lower_dentry);
-+      if (IS_ERR(lower_parent_dentry)) {
-+              err = PTR_ERR(lower_parent_dentry);
-+              goto out;
-+      }
-+
-+      err = init_lower_nd(&lower_nd, LOOKUP_CREATE);
-+      if (unlikely(err < 0))
-+              goto out;
-+      err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode,
-+                       &lower_nd);
-+      release_lower_nd(&lower_nd, err);
-+
-+      if (!err) {
-+              err = PTR_ERR(unionfs_interpose(dentry, parent->i_sb, 0));
-+              if (!err) {
-+                      unionfs_copy_attr_times(parent);
-+                      fsstack_copy_inode_size(parent,
-+                                              lower_parent_dentry->d_inode);
-+                      /* update no. of links on parent directory */
-+                      parent->i_nlink = unionfs_get_nlinks(parent);
-+              }
-+      }
-+
-+      unlock_dir(lower_parent_dentry);
-+
-+out:
-+      if (!err) {
-+              unionfs_postcopyup_setmnt(dentry);
-+              unionfs_check_inode(parent);
-+              unionfs_check_dentry(dentry);
-+              unionfs_check_nd(nd);
-+      }
-+      unionfs_unlock_dentry(dentry->d_parent);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+/*
-+ * unionfs_lookup is the only special function which takes a dentry, yet we
-+ * do NOT want to call __unionfs_d_revalidate_chain because by definition,
-+ * we don't have a valid dentry here yet.
-+ */
-+static struct dentry *unionfs_lookup(struct inode *parent,
-+                                   struct dentry *dentry,
-+                                   struct nameidata *nd)
-+{
-+      struct path path_save = {NULL, NULL};
-+      struct dentry *ret;
-+      int err = 0;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      if (dentry != dentry->d_parent)
-+              unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_ROOT);
-+
-+      /* save the dentry & vfsmnt from namei */
-+      if (nd) {
-+              path_save.dentry = nd->path.dentry;
-+              path_save.mnt = nd->path.mnt;
-+      }
-+
-+      /*
-+       * unionfs_lookup_backend returns a locked dentry upon success,
-+       * so we'll have to unlock it below.
-+       */
-+
-+      /* allocate dentry private data.  We free it in ->d_release */
-+      err = new_dentry_private_data(dentry, UNIONFS_DMUTEX_CHILD);
-+      if (unlikely(err)) {
-+              ret = ERR_PTR(err);
-+              goto out;
-+      }
-+      ret = unionfs_lookup_full(dentry, nd, INTERPOSE_LOOKUP);
-+
-+      /* restore the dentry & vfsmnt in namei */
-+      if (nd) {
-+              nd->path.dentry = path_save.dentry;
-+              nd->path.mnt = path_save.mnt;
-+      }
-+      if (!IS_ERR(ret)) {
-+              if (ret)
-+                      dentry = ret;
-+              /* lookup_full can return multiple positive dentries */
-+              if (dentry->d_inode && !S_ISDIR(dentry->d_inode->i_mode)) {
-+                      BUG_ON(dbstart(dentry) < 0);
-+                      unionfs_postcopyup_release(dentry);
-+              }
-+              unionfs_copy_attr_times(dentry->d_inode);
-+              /* parent times may have changed */
-+              unionfs_copy_attr_times(dentry->d_parent->d_inode);
-+      }
-+
-+      unionfs_check_inode(parent);
-+      if (!IS_ERR(ret)) {
-+              unionfs_check_dentry(dentry);
-+              unionfs_check_nd(nd);
-+      }
-+      unionfs_unlock_dentry(dentry);
-+
-+out:
-+      if (dentry != dentry->d_parent) {
-+              unionfs_check_dentry(dentry->d_parent);
-+              unionfs_unlock_dentry(dentry->d_parent);
-+      }
-+      unionfs_read_unlock(dentry->d_sb);
-+
-+      return ret;
-+}
-+
-+static int unionfs_link(struct dentry *old_dentry, struct inode *dir,
-+                      struct dentry *new_dentry)
-+{
-+      int err = 0;
-+      struct dentry *lower_old_dentry = NULL;
-+      struct dentry *lower_new_dentry = NULL;
-+      struct dentry *lower_dir_dentry = NULL;
-+      char *name = NULL;
-+
-+      unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_double_lock_dentry(new_dentry, old_dentry);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(old_dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      if (unlikely(new_dentry->d_inode &&
-+                   !__unionfs_d_revalidate_chain(new_dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      lower_new_dentry = unionfs_lower_dentry(new_dentry);
-+
-+      /* check for a whiteout in new dentry branch, and delete it */
-+      err = check_unlink_whiteout(new_dentry, lower_new_dentry,
-+                                  dbstart(new_dentry));
-+      if (err > 0) {         /* whiteout found and removed successfully */
-+              lower_dir_dentry = dget_parent(lower_new_dentry);
-+              fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-+              dput(lower_dir_dentry);
-+              dir->i_nlink = unionfs_get_nlinks(dir);
-+              err = 0;
-+      }
-+      if (err)
-+              goto out;
-+
-+      /* check if parent hierachy is needed, then link in same branch */
-+      if (dbstart(old_dentry) != dbstart(new_dentry)) {
-+              lower_new_dentry = create_parents(dir, new_dentry,
-+                                                new_dentry->d_name.name,
-+                                                dbstart(old_dentry));
-+              err = PTR_ERR(lower_new_dentry);
-+              if (IS_COPYUP_ERR(err))
-+                      goto docopyup;
-+              if (!lower_new_dentry || IS_ERR(lower_new_dentry))
-+                      goto out;
-+      }
-+      lower_new_dentry = unionfs_lower_dentry(new_dentry);
-+      lower_old_dentry = unionfs_lower_dentry(old_dentry);
-+
-+      BUG_ON(dbstart(old_dentry) != dbstart(new_dentry));
-+      lower_dir_dentry = lock_parent(lower_new_dentry);
-+      err = is_robranch(old_dentry);
-+      if (!err) {
-+              /* see Documentation/filesystems/unionfs/issues.txt */
-+              lockdep_off();
-+              err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
-+                             lower_new_dentry);
-+              lockdep_on();
-+      }
-+      unlock_dir(lower_dir_dentry);
-+
-+docopyup:
-+      if (IS_COPYUP_ERR(err)) {
-+              int old_bstart = dbstart(old_dentry);
-+              int bindex;
-+
-+              for (bindex = old_bstart - 1; bindex >= 0; bindex--) {
-+                      err = copyup_dentry(old_dentry->d_parent->d_inode,
-+                                          old_dentry, old_bstart,
-+                                          bindex, old_dentry->d_name.name,
-+                                          old_dentry->d_name.len, NULL,
-+                                          i_size_read(old_dentry->d_inode));
-+                      if (err)
-+                              continue;
-+                      lower_new_dentry =
-+                              create_parents(dir, new_dentry,
-+                                             new_dentry->d_name.name,
-+                                             bindex);
-+                      lower_old_dentry = unionfs_lower_dentry(old_dentry);
-+                      lower_dir_dentry = lock_parent(lower_new_dentry);
-+                      /* see Documentation/filesystems/unionfs/issues.txt */
-+                      lockdep_off();
-+                      /* do vfs_link */
-+                      err = vfs_link(lower_old_dentry,
-+                                     lower_dir_dentry->d_inode,
-+                                     lower_new_dentry);
-+                      lockdep_on();
-+                      unlock_dir(lower_dir_dentry);
-+                      goto check_link;
-+              }
-+              goto out;
-+      }
-+
-+check_link:
-+      if (err || !lower_new_dentry->d_inode)
-+              goto out;
-+
-+      /* Its a hard link, so use the same inode */
-+      new_dentry->d_inode = igrab(old_dentry->d_inode);
-+      d_add(new_dentry, new_dentry->d_inode);
-+      unionfs_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode);
-+      fsstack_copy_inode_size(dir, lower_new_dentry->d_parent->d_inode);
-+
-+      /* propagate number of hard-links */
-+      old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode);
-+      /* new dentry's ctime may have changed due to hard-link counts */
-+      unionfs_copy_attr_times(new_dentry->d_inode);
-+
-+out:
-+      if (!new_dentry->d_inode)
-+              d_drop(new_dentry);
-+
-+      kfree(name);
-+      if (!err)
-+              unionfs_postcopyup_setmnt(new_dentry);
-+
-+      unionfs_check_inode(dir);
-+      unionfs_check_dentry(new_dentry);
-+      unionfs_check_dentry(old_dentry);
-+
-+      unionfs_unlock_dentry(new_dentry);
-+      unionfs_unlock_dentry(old_dentry);
-+      unionfs_read_unlock(old_dentry->d_sb);
-+
-+      return err;
-+}
-+
-+static int unionfs_symlink(struct inode *parent, struct dentry *dentry,
-+                         const char *symname)
-+{
-+      int err = 0;
-+      struct dentry *lower_dentry = NULL;
-+      struct dentry *wh_dentry = NULL;
-+      struct dentry *lower_parent_dentry = NULL;
-+      char *name = NULL;
-+      int valid = 0;
-+      umode_t mode;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_PARENT);
-+
-+      valid = __unionfs_d_revalidate_chain(dentry->d_parent, NULL, false);
-+      if (unlikely(!valid)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      if (unlikely(dentry->d_inode &&
-+                   !__unionfs_d_revalidate_one_locked(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      /*
-+       * It's only a bug if this dentry was not negative and couldn't be
-+       * revalidated (shouldn't happen).
-+       */
-+      BUG_ON(!valid && dentry->d_inode);
-+
-+      lower_dentry = find_writeable_branch(parent, dentry);
-+      if (IS_ERR(lower_dentry)) {
-+              err = PTR_ERR(lower_dentry);
-+              goto out;
-+      }
-+
-+      lower_parent_dentry = lock_parent(lower_dentry);
-+      if (IS_ERR(lower_parent_dentry)) {
-+              err = PTR_ERR(lower_parent_dentry);
-+              goto out;
-+      }
-+
-+      mode = S_IALLUGO;
-+      err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname);
-+      if (!err) {
-+              err = PTR_ERR(unionfs_interpose(dentry, parent->i_sb, 0));
-+              if (!err) {
-+                      unionfs_copy_attr_times(parent);
-+                      fsstack_copy_inode_size(parent,
-+                                              lower_parent_dentry->d_inode);
-+                      /* update no. of links on parent directory */
-+                      parent->i_nlink = unionfs_get_nlinks(parent);
-+              }
-+      }
-+
-+      unlock_dir(lower_parent_dentry);
-+
-+out:
-+      dput(wh_dentry);
-+      kfree(name);
-+
-+      if (!err) {
-+              unionfs_postcopyup_setmnt(dentry);
-+              unionfs_check_inode(parent);
-+              unionfs_check_dentry(dentry);
-+      }
-+      unionfs_unlock_dentry(dentry->d_parent);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static int unionfs_mkdir(struct inode *parent, struct dentry *dentry, int mode)
-+{
-+      int err = 0;
-+      struct dentry *lower_dentry = NULL;
-+      struct dentry *lower_parent_dentry = NULL;
-+      int bindex = 0, bstart;
-+      char *name = NULL;
-+      int valid;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_PARENT);
-+
-+      valid = __unionfs_d_revalidate_chain(dentry->d_parent, NULL, false);
-+      if (unlikely(!valid)) {
-+              err = -ESTALE;  /* same as what real_lookup does */
-+              goto out;
-+      }
-+      if (unlikely(dentry->d_inode &&
-+                   !__unionfs_d_revalidate_one_locked(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      bstart = dbstart(dentry);
-+
-+      lower_dentry = unionfs_lower_dentry(dentry);
-+
-+      /* check for a whiteout in new dentry branch, and delete it */
-+      err = check_unlink_whiteout(dentry, lower_dentry, bstart);
-+      if (err > 0)           /* whiteout found and removed successfully */
-+              err = 0;
-+      if (err) {
-+              /* exit if the error returned was NOT -EROFS */
-+              if (!IS_COPYUP_ERR(err))
-+                      goto out;
-+              bstart--;
-+      }
-+
-+      /* check if copyup's needed, and mkdir */
-+      for (bindex = bstart; bindex >= 0; bindex--) {
-+              int i;
-+              int bend = dbend(dentry);
-+
-+              if (is_robranch_super(dentry->d_sb, bindex))
-+                      continue;
-+
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry) {
-+                      lower_dentry = create_parents(parent, dentry,
-+                                                    dentry->d_name.name,
-+                                                    bindex);
-+                      if (!lower_dentry || IS_ERR(lower_dentry)) {
-+                              printk(KERN_ERR "unionfs: lower dentry "
-+                                     " NULL for bindex = %d\n", bindex);
-+                              continue;
-+                      }
-+              }
-+
-+              lower_parent_dentry = lock_parent(lower_dentry);
-+
-+              if (IS_ERR(lower_parent_dentry)) {
-+                      err = PTR_ERR(lower_parent_dentry);
-+                      goto out;
-+              }
-+
-+              err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry,
-+                              mode);
-+
-+              unlock_dir(lower_parent_dentry);
-+
-+              /* did the mkdir succeed? */
-+              if (err)
-+                      break;
-+
-+              for (i = bindex + 1; i < bend; i++) {
-+                      if (unionfs_lower_dentry_idx(dentry, i)) {
-+                              dput(unionfs_lower_dentry_idx(dentry, i));
-+                              unionfs_set_lower_dentry_idx(dentry, i, NULL);
-+                      }
-+              }
-+              dbend(dentry) = bindex;
-+
-+              /*
-+               * Only INTERPOSE_LOOKUP can return a value other than 0 on
-+               * err.
-+               */
-+              err = PTR_ERR(unionfs_interpose(dentry, parent->i_sb, 0));
-+              if (!err) {
-+                      unionfs_copy_attr_times(parent);
-+                      fsstack_copy_inode_size(parent,
-+                                              lower_parent_dentry->d_inode);
-+
-+                      /* update number of links on parent directory */
-+                      parent->i_nlink = unionfs_get_nlinks(parent);
-+              }
-+
-+              err = make_dir_opaque(dentry, dbstart(dentry));
-+              if (err) {
-+                      printk(KERN_ERR "unionfs: mkdir: error creating "
-+                             ".wh.__dir_opaque: %d\n", err);
-+                      goto out;
-+              }
-+
-+              /* we are done! */
-+              break;
-+      }
-+
-+out:
-+      if (!dentry->d_inode)
-+              d_drop(dentry);
-+
-+      kfree(name);
-+
-+      if (!err) {
-+              unionfs_copy_attr_times(dentry->d_inode);
-+              unionfs_postcopyup_setmnt(dentry);
-+      }
-+      unionfs_check_inode(parent);
-+      unionfs_check_dentry(dentry);
-+      unionfs_unlock_dentry(dentry->d_parent);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+
-+      return err;
-+}
-+
-+static int unionfs_mknod(struct inode *parent, struct dentry *dentry, int mode,
-+                       dev_t dev)
-+{
-+      int err = 0;
-+      struct dentry *lower_dentry = NULL;
-+      struct dentry *wh_dentry = NULL;
-+      struct dentry *lower_parent_dentry = NULL;
-+      char *name = NULL;
-+      int valid = 0;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_PARENT);
-+
-+      valid = __unionfs_d_revalidate_chain(dentry->d_parent, NULL, false);
-+      if (unlikely(!valid)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      if (unlikely(dentry->d_inode &&
-+                   !__unionfs_d_revalidate_one_locked(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      /*
-+       * It's only a bug if this dentry was not negative and couldn't be
-+       * revalidated (shouldn't happen).
-+       */
-+      BUG_ON(!valid && dentry->d_inode);
-+
-+      lower_dentry = find_writeable_branch(parent, dentry);
-+      if (IS_ERR(lower_dentry)) {
-+              err = PTR_ERR(lower_dentry);
-+              goto out;
-+      }
-+
-+      lower_parent_dentry = lock_parent(lower_dentry);
-+      if (IS_ERR(lower_parent_dentry)) {
-+              err = PTR_ERR(lower_parent_dentry);
-+              goto out;
-+      }
-+
-+      err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
-+      if (!err) {
-+              err = PTR_ERR(unionfs_interpose(dentry, parent->i_sb, 0));
-+              if (!err) {
-+                      unionfs_copy_attr_times(parent);
-+                      fsstack_copy_inode_size(parent,
-+                                              lower_parent_dentry->d_inode);
-+                      /* update no. of links on parent directory */
-+                      parent->i_nlink = unionfs_get_nlinks(parent);
-+              }
-+      }
-+
-+      unlock_dir(lower_parent_dentry);
-+
-+out:
-+      dput(wh_dentry);
-+      kfree(name);
-+
-+      if (!err) {
-+              unionfs_postcopyup_setmnt(dentry);
-+              unionfs_check_inode(parent);
-+              unionfs_check_dentry(dentry);
-+      }
-+      unionfs_unlock_dentry(dentry->d_parent);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static int unionfs_readlink(struct dentry *dentry, char __user *buf,
-+                          int bufsiz)
-+{
-+      int err;
-+      struct dentry *lower_dentry;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      lower_dentry = unionfs_lower_dentry(dentry);
-+
-+      if (!lower_dentry->d_inode->i_op ||
-+          !lower_dentry->d_inode->i_op->readlink) {
-+              err = -EINVAL;
-+              goto out;
-+      }
-+
-+      err = lower_dentry->d_inode->i_op->readlink(lower_dentry,
-+                                                  buf, bufsiz);
-+      if (err > 0)
-+              fsstack_copy_attr_atime(dentry->d_inode,
-+                                      lower_dentry->d_inode);
-+
-+out:
-+      unionfs_check_dentry(dentry);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+
-+      return err;
-+}
-+
-+/*
-+ * unionfs_follow_link takes a dentry, but it is simple.  It only needs to
-+ * allocate some memory and then call our ->readlink method.  Our
-+ * unionfs_readlink *does* lock our dentry and revalidate the dentry.
-+ * Therefore, we do not have to lock our dentry here, to prevent a deadlock;
-+ * nor do we need to revalidate it either.  It is safe to not lock our
-+ * dentry here, nor revalidate it, because unionfs_follow_link does not do
-+ * anything (prior to calling ->readlink) which could become inconsistent
-+ * due to branch management.  We also don't need to lock our super because
-+ * this function isn't affected by branch-management.
-+ */
-+static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-+{
-+      char *buf;
-+      int len = PAGE_SIZE, err;
-+      mm_segment_t old_fs;
-+
-+      /* This is freed by the put_link method assuming a successful call. */
-+      buf = kmalloc(len, GFP_KERNEL);
-+      if (unlikely(!buf)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      /* read the symlink, and then we will follow it */
-+      old_fs = get_fs();
-+      set_fs(KERNEL_DS);
-+      err = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
-+      set_fs(old_fs);
-+      if (err < 0) {
-+              kfree(buf);
-+              buf = NULL;
-+              goto out;
-+      }
-+      buf[err] = 0;
-+      nd_set_link(nd, buf);
-+      err = 0;
-+
-+out:
-+      if (!err) {
-+              unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+              unionfs_check_dentry(dentry);
-+              unionfs_unlock_dentry(dentry);
-+      }
-+      unionfs_check_nd(nd);
-+      return ERR_PTR(err);
-+}
-+
-+/* FIXME: We may not have to lock here */
-+static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd,
-+                           void *cookie)
-+{
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      if (unlikely(!__unionfs_d_revalidate_chain(dentry, nd, false)))
-+              printk(KERN_ERR
-+                     "unionfs: put_link failed to revalidate dentry\n");
-+
-+      unionfs_check_dentry(dentry);
-+      unionfs_check_nd(nd);
-+      kfree(nd_get_link(nd));
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+}
-+
-+/*
-+ * Don't grab the superblock read-lock in unionfs_permission, which prevents
-+ * a deadlock with the branch-management "add branch" code (which grabbed
-+ * the write lock).  It is safe to not grab the read lock here, because even
-+ * with branch management taking place, there is no chance that
-+ * unionfs_permission, or anything it calls, will use stale branch
-+ * information.
-+ */
-+static int unionfs_permission(struct inode *inode, int mask)
-+{
-+      struct inode *lower_inode = NULL;
-+      int err = 0;
-+      int bindex, bstart, bend;
-+      const int is_file = !S_ISDIR(inode->i_mode);
-+      const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ);
-+
-+      if (!UNIONFS_I(inode)->lower_inodes) {
-+              if (is_file)    /* dirs can be unlinked but chdir'ed to */
-+                      err = -ESTALE;  /* force revalidate */
-+              goto out;
-+      }
-+      bstart = ibstart(inode);
-+      bend = ibend(inode);
-+      if (unlikely(bstart < 0 || bend < 0)) {
-+              /*
-+               * With branch-management, we can get a stale inode here.
-+               * If so, we return ESTALE back to link_path_walk, which
-+               * would discard the dcache entry and re-lookup the
-+               * dentry+inode.  This should be equivalent to issuing
-+               * __unionfs_d_revalidate_chain on nd.dentry here.
-+               */
-+              if (is_file)    /* dirs can be unlinked but chdir'ed to */
-+                      err = -ESTALE;  /* force revalidate */
-+              goto out;
-+      }
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (!lower_inode)
-+                      continue;
-+
-+              /*
-+               * check the condition for D-F-D underlying files/directories,
-+               * we don't have to check for files, if we are checking for
-+               * directories.
-+               */
-+              if (!is_file && !S_ISDIR(lower_inode->i_mode))
-+                      continue;
-+
-+              /*
-+               * We check basic permissions, but we ignore any conditions
-+               * such as readonly file systems or branches marked as
-+               * readonly, because those conditions should lead to a
-+               * copyup taking place later on.
-+               */
-+              err = inode_permission(lower_inode, mask);
-+              if (err && bindex > 0) {
-+                      umode_t mode = lower_inode->i_mode;
-+                      if (is_robranch_super(inode->i_sb, bindex) &&
-+                          (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-+                              err = 0;
-+                      if (IS_COPYUP_ERR(err))
-+                              err = 0;
-+              }
-+
-+              /*
-+               * The permissions are an intersection of the overall directory
-+               * permissions, so we fail if one fails.
-+               */
-+              if (err)
-+                      goto out;
-+
-+              /* only the leftmost file matters. */
-+              if (is_file || write_mask) {
-+                      if (is_file && write_mask) {
-+                              err = get_write_access(lower_inode);
-+                              if (!err)
-+                                      put_write_access(lower_inode);
-+                      }
-+                      break;
-+              }
-+      }
-+      /* sync times which may have changed (asynchronously) below */
-+      unionfs_copy_attr_times(inode);
-+
-+out:
-+      unionfs_check_inode(inode);
-+      return err;
-+}
-+
-+static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
-+{
-+      int err = 0;
-+      struct dentry *lower_dentry;
-+      struct inode *inode;
-+      struct inode *lower_inode;
-+      int bstart, bend, bindex;
-+      loff_t size;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      inode = dentry->d_inode;
-+
-+      /*
-+       * mode change is for clearing setuid/setgid. Allow lower filesystem
-+       * to reinterpret it in its own way.
-+       */
-+      if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
-+              ia->ia_valid &= ~ATTR_MODE;
-+
-+      lower_dentry = unionfs_lower_dentry(dentry);
-+      BUG_ON(!lower_dentry);  /* should never happen after above revalidate */
-+
-+      /* copyup if the file is on a read only branch */
-+      if (is_robranch_super(dentry->d_sb, bstart)
-+          || IS_RDONLY(lower_dentry->d_inode)) {
-+              /* check if we have a branch to copy up to */
-+              if (bstart <= 0) {
-+                      err = -EACCES;
-+                      goto out;
-+              }
-+
-+              if (ia->ia_valid & ATTR_SIZE)
-+                      size = ia->ia_size;
-+              else
-+                      size = i_size_read(inode);
-+              /* copyup to next available branch */
-+              for (bindex = bstart - 1; bindex >= 0; bindex--) {
-+                      err = copyup_dentry(dentry->d_parent->d_inode,
-+                                          dentry, bstart, bindex,
-+                                          dentry->d_name.name,
-+                                          dentry->d_name.len,
-+                                          NULL, size);
-+                      if (!err)
-+                              break;
-+              }
-+              if (err)
-+                      goto out;
-+              /* get updated lower_dentry after copyup */
-+              lower_dentry = unionfs_lower_dentry(dentry);
-+      }
-+
-+      lower_inode = unionfs_lower_inode(inode);
-+
-+      /*
-+       * If shrinking, first truncate upper level to cancel writing dirty
-+       * pages beyond the new eof; and also if its' maxbytes is more
-+       * limiting (fail with -EFBIG before making any change to the lower
-+       * level).  There is no need to vmtruncate the upper level
-+       * afterwards in the other cases: we fsstack_copy_inode_size from
-+       * the lower level.
-+       */
-+      if (ia->ia_valid & ATTR_SIZE) {
-+              size = i_size_read(inode);
-+              if (ia->ia_size < size || (ia->ia_size > size &&
-+                  inode->i_sb->s_maxbytes < lower_inode->i_sb->s_maxbytes)) {
-+                      err = vmtruncate(inode, ia->ia_size);
-+                      if (err)
-+                              goto out;
-+              }
-+      }
-+
-+      /* notify the (possibly copied-up) lower inode */
-+      mutex_lock(&lower_dentry->d_inode->i_mutex);
-+      err = notify_change(lower_dentry, ia);
-+      mutex_unlock(&lower_dentry->d_inode->i_mutex);
-+      if (err)
-+              goto out;
-+
-+      /* get attributes from the first lower inode */
-+      unionfs_copy_attr_all(inode, lower_inode);
-+      /*
-+       * unionfs_copy_attr_all will copy the lower times to our inode if
-+       * the lower ones are newer (useful for cache coherency).  However,
-+       * ->setattr is the only place in which we may have to copy the
-+       * lower inode times absolutely, to support utimes(2).
-+       */
-+      if (ia->ia_valid & ATTR_MTIME_SET)
-+              inode->i_mtime = lower_inode->i_mtime;
-+      if (ia->ia_valid & ATTR_CTIME)
-+              inode->i_ctime = lower_inode->i_ctime;
-+      if (ia->ia_valid & ATTR_ATIME_SET)
-+              inode->i_atime = lower_inode->i_atime;
-+      fsstack_copy_inode_size(inode, lower_inode);
-+
-+out:
-+      if (!err)
-+              unionfs_check_dentry(dentry);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+
-+      return err;
-+}
-+
-+struct inode_operations unionfs_symlink_iops = {
-+      .readlink       = unionfs_readlink,
-+      .permission     = unionfs_permission,
-+      .follow_link    = unionfs_follow_link,
-+      .setattr        = unionfs_setattr,
-+      .put_link       = unionfs_put_link,
-+};
-+
-+struct inode_operations unionfs_dir_iops = {
-+      .create         = unionfs_create,
-+      .lookup         = unionfs_lookup,
-+      .link           = unionfs_link,
-+      .unlink         = unionfs_unlink,
-+      .symlink        = unionfs_symlink,
-+      .mkdir          = unionfs_mkdir,
-+      .rmdir          = unionfs_rmdir,
-+      .mknod          = unionfs_mknod,
-+      .rename         = unionfs_rename,
-+      .permission     = unionfs_permission,
-+      .setattr        = unionfs_setattr,
-+#ifdef CONFIG_UNION_FS_XATTR
-+      .setxattr       = unionfs_setxattr,
-+      .getxattr       = unionfs_getxattr,
-+      .removexattr    = unionfs_removexattr,
-+      .listxattr      = unionfs_listxattr,
-+#endif /* CONFIG_UNION_FS_XATTR */
-+};
-+
-+struct inode_operations unionfs_main_iops = {
-+      .permission     = unionfs_permission,
-+      .setattr        = unionfs_setattr,
-+#ifdef CONFIG_UNION_FS_XATTR
-+      .setxattr       = unionfs_setxattr,
-+      .getxattr       = unionfs_getxattr,
-+      .removexattr    = unionfs_removexattr,
-+      .listxattr      = unionfs_listxattr,
-+#endif /* CONFIG_UNION_FS_XATTR */
-+};
-diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
-new file mode 100644
-index 0000000..0a9602a
---- /dev/null
-+++ b/fs/unionfs/lookup.c
-@@ -0,0 +1,570 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * Lookup one path component @name relative to a <base,mnt> path pair.
-+ * Behaves nearly the same as lookup_one_len (i.e., return negative dentry
-+ * on ENOENT), but uses the @mnt passed, so it can cross bind mounts and
-+ * other lower mounts properly.  If @new_mnt is non-null, will fill in the
-+ * new mnt there.  Caller is responsible to dput/mntput/path_put returned
-+ * @dentry and @new_mnt.
-+ */
-+struct dentry *__lookup_one(struct dentry *base, struct vfsmount *mnt,
-+                          const char *name, struct vfsmount **new_mnt)
-+{
-+      struct dentry *dentry = NULL;
-+      struct nameidata lower_nd;
-+      int err;
-+
-+      /* we use flags=0 to get basic lookup */
-+      err = vfs_path_lookup(base, mnt, name, 0, &lower_nd);
-+
-+      switch (err) {
-+      case 0: /* no error */
-+              dentry = lower_nd.path.dentry;
-+              if (new_mnt)
-+                      *new_mnt = lower_nd.path.mnt; /* rc already inc'ed */
-+              break;
-+      case -ENOENT:
-+               /*
-+                * We don't consider ENOENT an error, and we want to return
-+                * a negative dentry (ala lookup_one_len).  As we know
-+                * there was no inode for this name before (-ENOENT), then
-+                * it's safe to call lookup_one_len (which doesn't take a
-+                * vfsmount).
-+                */
-+              dentry = lookup_one_len(name, base, strlen(name));
-+              if (new_mnt)
-+                      *new_mnt = mntget(lower_nd.path.mnt);
-+              break;
-+      default: /* all other real errors */
-+              dentry = ERR_PTR(err);
-+              break;
-+      }
-+
-+      return dentry;
-+}
-+
-+/*
-+ * This is a utility function that fills in a unionfs dentry.
-+ * Caller must lock this dentry with unionfs_lock_dentry.
-+ *
-+ * Returns: 0 (ok), or -ERRNO if an error occurred.
-+ * XXX: get rid of _partial_lookup and make callers call _lookup_full directly
-+ */
-+int unionfs_partial_lookup(struct dentry *dentry)
-+{
-+      struct dentry *tmp;
-+      struct nameidata nd = { .flags = 0 };
-+      int err = -ENOSYS;
-+
-+      tmp = unionfs_lookup_full(dentry, &nd, INTERPOSE_PARTIAL);
-+
-+      if (!tmp) {
-+              err = 0;
-+              goto out;
-+      }
-+      if (IS_ERR(tmp)) {
-+              err = PTR_ERR(tmp);
-+              goto out;
-+      }
-+      /* XXX: need to change the interface */
-+      BUG_ON(tmp != dentry);
-+out:
-+      return err;
-+}
-+
-+/* The dentry cache is just so we have properly sized dentries. */
-+static struct kmem_cache *unionfs_dentry_cachep;
-+int unionfs_init_dentry_cache(void)
-+{
-+      unionfs_dentry_cachep =
-+              kmem_cache_create("unionfs_dentry",
-+                                sizeof(struct unionfs_dentry_info),
-+                                0, SLAB_RECLAIM_ACCOUNT, NULL);
-+
-+      return (unionfs_dentry_cachep ? 0 : -ENOMEM);
-+}
-+
-+void unionfs_destroy_dentry_cache(void)
-+{
-+      if (unionfs_dentry_cachep)
-+              kmem_cache_destroy(unionfs_dentry_cachep);
-+}
-+
-+void free_dentry_private_data(struct dentry *dentry)
-+{
-+      if (!dentry || !dentry->d_fsdata)
-+              return;
-+      kfree(UNIONFS_D(dentry)->lower_paths);
-+      UNIONFS_D(dentry)->lower_paths = NULL;
-+      kmem_cache_free(unionfs_dentry_cachep, dentry->d_fsdata);
-+      dentry->d_fsdata = NULL;
-+}
-+
-+static inline int __realloc_dentry_private_data(struct dentry *dentry)
-+{
-+      struct unionfs_dentry_info *info = UNIONFS_D(dentry);
-+      void *p;
-+      int size;
-+
-+      BUG_ON(!info);
-+
-+      size = sizeof(struct path) * sbmax(dentry->d_sb);
-+      p = krealloc(info->lower_paths, size, GFP_ATOMIC);
-+      if (unlikely(!p))
-+              return -ENOMEM;
-+
-+      info->lower_paths = p;
-+
-+      info->bstart = -1;
-+      info->bend = -1;
-+      info->bopaque = -1;
-+      info->bcount = sbmax(dentry->d_sb);
-+      atomic_set(&info->generation,
-+                      atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
-+
-+      memset(info->lower_paths, 0, size);
-+
-+      return 0;
-+}
-+
-+/* UNIONFS_D(dentry)->lock must be locked */
-+int realloc_dentry_private_data(struct dentry *dentry)
-+{
-+      if (!__realloc_dentry_private_data(dentry))
-+              return 0;
-+
-+      kfree(UNIONFS_D(dentry)->lower_paths);
-+      free_dentry_private_data(dentry);
-+      return -ENOMEM;
-+}
-+
-+/* allocate new dentry private data */
-+int new_dentry_private_data(struct dentry *dentry, int subclass)
-+{
-+      struct unionfs_dentry_info *info = UNIONFS_D(dentry);
-+
-+      BUG_ON(info);
-+
-+      info = kmem_cache_alloc(unionfs_dentry_cachep, GFP_ATOMIC);
-+      if (unlikely(!info))
-+              return -ENOMEM;
-+
-+      mutex_init(&info->lock);
-+      mutex_lock_nested(&info->lock, subclass);
-+
-+      info->lower_paths = NULL;
-+
-+      dentry->d_fsdata = info;
-+
-+      if (!__realloc_dentry_private_data(dentry))
-+              return 0;
-+
-+      mutex_unlock(&info->lock);
-+      free_dentry_private_data(dentry);
-+      return -ENOMEM;
-+}
-+
-+/*
-+ * scan through the lower dentry objects, and set bstart to reflect the
-+ * starting branch
-+ */
-+void update_bstart(struct dentry *dentry)
-+{
-+      int bindex;
-+      int bstart = dbstart(dentry);
-+      int bend = dbend(dentry);
-+      struct dentry *lower_dentry;
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry)
-+                      continue;
-+              if (lower_dentry->d_inode) {
-+                      dbstart(dentry) = bindex;
-+                      break;
-+              }
-+              dput(lower_dentry);
-+              unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
-+      }
-+}
-+
-+
-+/*
-+ * Initialize a nameidata structure (the intent part) we can pass to a lower
-+ * file system.  Returns 0 on success or -error (only -ENOMEM possible).
-+ * Inside that nd structure, this function may also return an allocated
-+ * struct file (for open intents).  The caller, when done with this nd, must
-+ * kfree the intent file (using release_lower_nd).
-+ *
-+ * XXX: this code, and the callers of this code, should be redone using
-+ * vfs_path_lookup() when (1) the nameidata structure is refactored into a
-+ * separate intent-structure, and (2) open_namei() is broken into a VFS-only
-+ * function and a method that other file systems can call.
-+ */
-+int init_lower_nd(struct nameidata *nd, unsigned int flags)
-+{
-+      int err = 0;
-+#ifdef ALLOC_LOWER_ND_FILE
-+      /*
-+       * XXX: one day we may need to have the lower return an open file
-+       * for us.  It is not needed in 2.6.23-rc1 for nfs2/nfs3, but may
-+       * very well be needed for nfs4.
-+       */
-+      struct file *file;
-+#endif /* ALLOC_LOWER_ND_FILE */
-+
-+      memset(nd, 0, sizeof(struct nameidata));
-+      if (!flags)
-+              return err;
-+
-+      switch (flags) {
-+      case LOOKUP_CREATE:
-+              nd->intent.open.flags |= O_CREAT;
-+              /* fall through: shared code for create/open cases */
-+      case LOOKUP_OPEN:
-+              nd->flags = flags;
-+              nd->intent.open.flags |= (FMODE_READ | FMODE_WRITE);
-+#ifdef ALLOC_LOWER_ND_FILE
-+              file = kzalloc(sizeof(struct file), GFP_KERNEL);
-+              if (unlikely(!file)) {
-+                      err = -ENOMEM;
-+                      break; /* exit switch statement and thus return */
-+              }
-+              nd->intent.open.file = file;
-+#endif /* ALLOC_LOWER_ND_FILE */
-+              break;
-+      default:
-+              /*
-+               * We should never get here, for now.
-+               * We can add new cases here later on.
-+               */
-+              pr_debug("unionfs: unknown nameidata flag 0x%x\n", flags);
-+              BUG();
-+              break;
-+      }
-+
-+      return err;
-+}
-+
-+void release_lower_nd(struct nameidata *nd, int err)
-+{
-+      if (!nd->intent.open.file)
-+              return;
-+      else if (!err)
-+              release_open_intent(nd);
-+#ifdef ALLOC_LOWER_ND_FILE
-+      kfree(nd->intent.open.file);
-+#endif /* ALLOC_LOWER_ND_FILE */
-+}
-+
-+/*
-+ * Main (and complex) driver function for Unionfs's lookup
-+ *
-+ * Returns: NULL (ok), ERR_PTR if an error occurred, or a non-null non-error
-+ * PTR if d_splice returned a different dentry.
-+ *
-+ * If lookupmode is INTERPOSE_PARTIAL/REVAL/REVAL_NEG, the passed dentry's
-+ * inode info must be locked.  If lookupmode is INTERPOSE_LOOKUP (i.e., a
-+ * newly looked-up dentry), then unionfs_lookup_backend will return a locked
-+ * dentry's info, which the caller must unlock.
-+ */
-+struct dentry *unionfs_lookup_full(struct dentry *dentry,
-+                                 struct nameidata *nd_unused, int lookupmode)
-+{
-+      int err = 0;
-+      struct dentry *lower_dentry = NULL;
-+      struct vfsmount *lower_mnt;
-+      struct vfsmount *lower_dir_mnt;
-+      struct dentry *wh_lower_dentry = NULL;
-+      struct dentry *lower_dir_dentry = NULL;
-+      struct dentry *parent_dentry = NULL;
-+      struct dentry *d_interposed = NULL;
-+      int bindex, bstart, bend, bopaque;
-+      int opaque, num_positive = 0;
-+      const char *name;
-+      int namelen;
-+      int pos_start, pos_end;
-+
-+      /*
-+       * We should already have a lock on this dentry in the case of a
-+       * partial lookup, or a revalidation.  Otherwise it is returned from
-+       * new_dentry_private_data already locked.
-+       */
-+      verify_locked(dentry);
-+
-+      /* must initialize dentry operations */
-+      dentry->d_op = &unionfs_dops;
-+
-+      /* We never partial lookup the root directory. */
-+      if (IS_ROOT(dentry))
-+              goto out;
-+      parent_dentry = dget_parent(dentry);
-+
-+      name = dentry->d_name.name;
-+      namelen = dentry->d_name.len;
-+
-+      /* No dentries should get created for possible whiteout names. */
-+      if (!is_validname(name)) {
-+              err = -EPERM;
-+              goto out_free;
-+      }
-+
-+      /* Now start the actual lookup procedure. */
-+      bstart = dbstart(parent_dentry);
-+      bend = dbend(parent_dentry);
-+      bopaque = dbopaque(parent_dentry);
-+      BUG_ON(bstart < 0);
-+
-+      /* adjust bend to bopaque if needed */
-+      if ((bopaque >= 0) && (bopaque < bend))
-+              bend = bopaque;
-+
-+      /* lookup all possible dentries */
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
-+
-+              /* skip if we already have a positive lower dentry */
-+              if (lower_dentry) {
-+                      if (dbstart(dentry) < 0)
-+                              dbstart(dentry) = bindex;
-+                      if (bindex > dbend(dentry))
-+                              dbend(dentry) = bindex;
-+                      if (lower_dentry->d_inode)
-+                              num_positive++;
-+                      continue;
-+              }
-+
-+              lower_dir_dentry =
-+                      unionfs_lower_dentry_idx(parent_dentry, bindex);
-+              /* if the lower dentry's parent does not exist, skip this */
-+              if (!lower_dir_dentry || !lower_dir_dentry->d_inode)
-+                      continue;
-+
-+              /* also skip it if the parent isn't a directory. */
-+              if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode))
-+                      continue; /* XXX: should be BUG_ON */
-+
-+              /* check for whiteouts: stop lookup if found */
-+              wh_lower_dentry = lookup_whiteout(name, lower_dir_dentry);
-+              if (IS_ERR(wh_lower_dentry)) {
-+                      err = PTR_ERR(wh_lower_dentry);
-+                      goto out_free;
-+              }
-+              if (wh_lower_dentry->d_inode) {
-+                      dbend(dentry) = dbopaque(dentry) = bindex;
-+                      if (dbstart(dentry) < 0)
-+                              dbstart(dentry) = bindex;
-+                      dput(wh_lower_dentry);
-+                      break;
-+              }
-+              dput(wh_lower_dentry);
-+
-+              /* Now do regular lookup; lookup @name */
-+              lower_dir_mnt = unionfs_lower_mnt_idx(parent_dentry, bindex);
-+              lower_mnt = NULL; /* XXX: needed? */
-+
-+              lower_dentry = __lookup_one(lower_dir_dentry, lower_dir_mnt,
-+                                          name, &lower_mnt);
-+
-+              if (IS_ERR(lower_dentry)) {
-+                      err = PTR_ERR(lower_dentry);
-+                      goto out_free;
-+              }
-+              unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
-+              BUG_ON(!lower_mnt);
-+              unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt);
-+
-+              /* adjust dbstart/end */
-+              if (dbstart(dentry) < 0)
-+                      dbstart(dentry) = bindex;
-+              if (bindex > dbend(dentry))
-+                      dbend(dentry) = bindex;
-+              /*
-+               * We always store the lower dentries above, and update
-+               * dbstart/dbend, even if the whole unionfs dentry is
-+               * negative (i.e., no lower inodes).
-+               */
-+              if (!lower_dentry->d_inode)
-+                      continue;
-+              num_positive++;
-+
-+              /*
-+               * check if we just found an opaque directory, if so, stop
-+               * lookups here.
-+               */
-+              if (!S_ISDIR(lower_dentry->d_inode->i_mode))
-+                      continue;
-+              opaque = is_opaque_dir(dentry, bindex);
-+              if (opaque < 0) {
-+                      err = opaque;
-+                      goto out_free;
-+              } else if (opaque) {
-+                      dbend(dentry) = dbopaque(dentry) = bindex;
-+                      break;
-+              }
-+              dbend(dentry) = bindex;
-+
-+              /* update parent directory's atime with the bindex */
-+              fsstack_copy_attr_atime(parent_dentry->d_inode,
-+                                      lower_dir_dentry->d_inode);
-+      }
-+
-+      /* sanity checks, then decide if to process a negative dentry */
-+      BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0);
-+      BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0);
-+
-+      if (num_positive > 0)
-+              goto out_positive;
-+
-+      /*** handle NEGATIVE dentries ***/
-+
-+      /*
-+       * If negative, keep only first lower negative dentry, to save on
-+       * memory.
-+       */
-+      if (dbstart(dentry) < dbend(dentry)) {
-+              path_put_lowers(dentry, dbstart(dentry) + 1,
-+                              dbend(dentry), false);
-+              dbend(dentry) = dbstart(dentry);
-+      }
-+      if (lookupmode == INTERPOSE_PARTIAL)
-+              goto out;
-+      if (lookupmode == INTERPOSE_LOOKUP) {
-+              /*
-+               * If all we found was a whiteout in the first available
-+               * branch, then create a negative dentry for a possibly new
-+               * file to be created.
-+               */
-+              if (dbopaque(dentry) < 0)
-+                      goto out;
-+              /* XXX: need to get mnt here */
-+              bindex = dbstart(dentry);
-+              if (unionfs_lower_dentry_idx(dentry, bindex))
-+                      goto out;
-+              lower_dir_dentry =
-+                      unionfs_lower_dentry_idx(parent_dentry, bindex);
-+              if (!lower_dir_dentry || !lower_dir_dentry->d_inode)
-+                      goto out;
-+              if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode))
-+                      goto out; /* XXX: should be BUG_ON */
-+              /* XXX: do we need to cross bind mounts here? */
-+              lower_dentry = lookup_one_len(name, lower_dir_dentry, namelen);
-+              if (IS_ERR(lower_dentry)) {
-+                      err = PTR_ERR(lower_dentry);
-+                      goto out;
-+              }
-+              /* XXX: need to mntget/mntput as needed too! */
-+              unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
-+              /* XXX: wrong mnt for crossing bind mounts! */
-+              lower_mnt = unionfs_mntget(dentry->d_sb->s_root, bindex);
-+              unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt);
-+
-+              goto out;
-+      }
-+
-+      /* if we're revalidating a positive dentry, don't make it negative */
-+      if (lookupmode != INTERPOSE_REVAL)
-+              d_add(dentry, NULL);
-+
-+      goto out;
-+
-+out_positive:
-+      /*** handle POSITIVE dentries ***/
-+
-+      /*
-+       * This unionfs dentry is positive (at least one lower inode
-+       * exists), so scan entire dentry from beginning to end, and remove
-+       * any negative lower dentries, if any.  Then, update dbstart/dbend
-+       * to reflect the start/end of positive dentries.
-+       */
-+      pos_start = pos_end = -1;
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry,
-+                                                      bindex);
-+              if (lower_dentry && lower_dentry->d_inode) {
-+                      if (pos_start < 0)
-+                              pos_start = bindex;
-+                      if (bindex > pos_end)
-+                              pos_end = bindex;
-+                      continue;
-+              }
-+              path_put_lowers(dentry, bindex, bindex, false);
-+      }
-+      if (pos_start >= 0)
-+              dbstart(dentry) = pos_start;
-+      if (pos_end >= 0)
-+              dbend(dentry) = pos_end;
-+
-+      /* Partial lookups need to re-interpose, or throw away older negs. */
-+      if (lookupmode == INTERPOSE_PARTIAL) {
-+              if (dentry->d_inode) {
-+                      unionfs_reinterpose(dentry);
-+                      goto out;
-+              }
-+
-+              /*
-+               * This dentry was positive, so it is as if we had a
-+               * negative revalidation.
-+               */
-+              lookupmode = INTERPOSE_REVAL_NEG;
-+              update_bstart(dentry);
-+      }
-+
-+      /*
-+       * Interpose can return a dentry if d_splice returned a different
-+       * dentry.
-+       */
-+      d_interposed = unionfs_interpose(dentry, dentry->d_sb, lookupmode);
-+      if (IS_ERR(d_interposed))
-+              err = PTR_ERR(d_interposed);
-+      else if (d_interposed)
-+              dentry = d_interposed;
-+
-+      if (!err)
-+              goto out;
-+      d_drop(dentry);
-+
-+out_free:
-+      /* should dput/mntput all the underlying dentries on error condition */
-+      if (dbstart(dentry) >= 0)
-+              path_put_lowers_all(dentry, false);
-+      /* free lower_paths unconditionally */
-+      kfree(UNIONFS_D(dentry)->lower_paths);
-+      UNIONFS_D(dentry)->lower_paths = NULL;
-+
-+out:
-+      if (dentry && UNIONFS_D(dentry)) {
-+              BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0);
-+              BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0);
-+      }
-+      if (d_interposed && UNIONFS_D(d_interposed)) {
-+              BUG_ON(dbstart(d_interposed) < 0 && dbend(d_interposed) >= 0);
-+              BUG_ON(dbstart(d_interposed) >= 0 && dbend(d_interposed) < 0);
-+      }
-+
-+      dput(parent_dentry);
-+      if (!err && d_interposed)
-+              return d_interposed;
-+      return ERR_PTR(err);
-+}
-diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
-new file mode 100644
-index 0000000..fea670b
---- /dev/null
-+++ b/fs/unionfs/main.c
-@@ -0,0 +1,777 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+
-+static void unionfs_fill_inode(struct dentry *dentry,
-+                             struct inode *inode)
-+{
-+      struct inode *lower_inode;
-+      struct dentry *lower_dentry;
-+      int bindex, bstart, bend;
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry) {
-+                      unionfs_set_lower_inode_idx(inode, bindex, NULL);
-+                      continue;
-+              }
-+
-+              /* Initialize the lower inode to the new lower inode. */
-+              if (!lower_dentry->d_inode)
-+                      continue;
-+
-+              unionfs_set_lower_inode_idx(inode, bindex,
-+                                          igrab(lower_dentry->d_inode));
-+      }
-+
-+      ibstart(inode) = dbstart(dentry);
-+      ibend(inode) = dbend(dentry);
-+
-+      /* Use attributes from the first branch. */
-+      lower_inode = unionfs_lower_inode(inode);
-+
-+      /* Use different set of inode ops for symlinks & directories */
-+      if (S_ISLNK(lower_inode->i_mode))
-+              inode->i_op = &unionfs_symlink_iops;
-+      else if (S_ISDIR(lower_inode->i_mode))
-+              inode->i_op = &unionfs_dir_iops;
-+
-+      /* Use different set of file ops for directories */
-+      if (S_ISDIR(lower_inode->i_mode))
-+              inode->i_fop = &unionfs_dir_fops;
-+
-+      /* properly initialize special inodes */
-+      if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
-+          S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
-+              init_special_inode(inode, lower_inode->i_mode,
-+                                 lower_inode->i_rdev);
-+
-+      /* all well, copy inode attributes */
-+      unionfs_copy_attr_all(inode, lower_inode);
-+      fsstack_copy_inode_size(inode, lower_inode);
-+}
-+
-+/*
-+ * Connect a unionfs inode dentry/inode with several lower ones.  This is
-+ * the classic stackable file system "vnode interposition" action.
-+ *
-+ * @sb: unionfs's super_block
-+ */
-+struct dentry *unionfs_interpose(struct dentry *dentry, struct super_block *sb,
-+                               int flag)
-+{
-+      int err = 0;
-+      struct inode *inode;
-+      int need_fill_inode = 1;
-+      struct dentry *spliced = NULL;
-+
-+      verify_locked(dentry);
-+
-+      /*
-+       * We allocate our new inode below by calling unionfs_iget,
-+       * which will initialize some of the new inode's fields
-+       */
-+
-+      /*
-+       * On revalidate we've already got our own inode and just need
-+       * to fix it up.
-+       */
-+      if (flag == INTERPOSE_REVAL) {
-+              inode = dentry->d_inode;
-+              UNIONFS_I(inode)->bstart = -1;
-+              UNIONFS_I(inode)->bend = -1;
-+              atomic_set(&UNIONFS_I(inode)->generation,
-+                         atomic_read(&UNIONFS_SB(sb)->generation));
-+
-+              UNIONFS_I(inode)->lower_inodes =
-+                      kcalloc(sbmax(sb), sizeof(struct inode *), GFP_KERNEL);
-+              if (unlikely(!UNIONFS_I(inode)->lower_inodes)) {
-+                      err = -ENOMEM;
-+                      goto out;
-+              }
-+      } else {
-+              /* get unique inode number for unionfs */
-+              inode = unionfs_iget(sb, iunique(sb, UNIONFS_ROOT_INO));
-+              if (IS_ERR(inode)) {
-+                      err = PTR_ERR(inode);
-+                      goto out;
-+              }
-+              if (atomic_read(&inode->i_count) > 1)
-+                      goto skip;
-+      }
-+
-+      need_fill_inode = 0;
-+      unionfs_fill_inode(dentry, inode);
-+
-+skip:
-+      /* only (our) lookup wants to do a d_add */
-+      switch (flag) {
-+      case INTERPOSE_DEFAULT:
-+              /* for operations which create new inodes */
-+              d_add(dentry, inode);
-+              break;
-+      case INTERPOSE_REVAL_NEG:
-+              d_instantiate(dentry, inode);
-+              break;
-+      case INTERPOSE_LOOKUP:
-+              spliced = d_splice_alias(inode, dentry);
-+              if (spliced && spliced != dentry) {
-+                      /*
-+                       * d_splice can return a dentry if it was
-+                       * disconnected and had to be moved.  We must ensure
-+                       * that the private data of the new dentry is
-+                       * correct and that the inode info was filled
-+                       * properly.  Finally we must return this new
-+                       * dentry.
-+                       */
-+                      spliced->d_op = &unionfs_dops;
-+                      spliced->d_fsdata = dentry->d_fsdata;
-+                      dentry->d_fsdata = NULL;
-+                      dentry = spliced;
-+                      if (need_fill_inode) {
-+                              need_fill_inode = 0;
-+                              unionfs_fill_inode(dentry, inode);
-+                      }
-+                      goto out_spliced;
-+              } else if (!spliced) {
-+                      if (need_fill_inode) {
-+                              need_fill_inode = 0;
-+                              unionfs_fill_inode(dentry, inode);
-+                              goto out_spliced;
-+                      }
-+              }
-+              break;
-+      case INTERPOSE_REVAL:
-+              /* Do nothing. */
-+              break;
-+      default:
-+              printk(KERN_CRIT "unionfs: invalid interpose flag passed!\n");
-+              BUG();
-+      }
-+      goto out;
-+
-+out_spliced:
-+      if (!err)
-+              return spliced;
-+out:
-+      return ERR_PTR(err);
-+}
-+
-+/* like interpose above, but for an already existing dentry */
-+void unionfs_reinterpose(struct dentry *dentry)
-+{
-+      struct dentry *lower_dentry;
-+      struct inode *inode;
-+      int bindex, bstart, bend;
-+
-+      verify_locked(dentry);
-+
-+      /* This is pre-allocated inode */
-+      inode = dentry->d_inode;
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry)
-+                      continue;
-+
-+              if (!lower_dentry->d_inode)
-+                      continue;
-+              if (unionfs_lower_inode_idx(inode, bindex))
-+                      continue;
-+              unionfs_set_lower_inode_idx(inode, bindex,
-+                                          igrab(lower_dentry->d_inode));
-+      }
-+      ibstart(inode) = dbstart(dentry);
-+      ibend(inode) = dbend(dentry);
-+}
-+
-+/*
-+ * make sure the branch we just looked up (nd) makes sense:
-+ *
-+ * 1) we're not trying to stack unionfs on top of unionfs
-+ * 2) it exists
-+ * 3) is a directory
-+ */
-+int check_branch(struct nameidata *nd)
-+{
-+      /* XXX: remove in ODF code -- stacking unions allowed there */
-+      if (!strcmp(nd->path.dentry->d_sb->s_type->name, UNIONFS_NAME))
-+              return -EINVAL;
-+      if (!nd->path.dentry->d_inode)
-+              return -ENOENT;
-+      if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
-+              return -ENOTDIR;
-+      return 0;
-+}
-+
-+/* checks if two lower_dentries have overlapping branches */
-+static int is_branch_overlap(struct dentry *dent1, struct dentry *dent2)
-+{
-+      struct dentry *dent = NULL;
-+
-+      dent = dent1;
-+      while ((dent != dent2) && (dent->d_parent != dent))
-+              dent = dent->d_parent;
-+
-+      if (dent == dent2)
-+              return 1;
-+
-+      dent = dent2;
-+      while ((dent != dent1) && (dent->d_parent != dent))
-+              dent = dent->d_parent;
-+
-+      return (dent == dent1);
-+}
-+
-+/*
-+ * Parse "ro" or "rw" options, but default to "rw" if no mode options was
-+ * specified.  Fill the mode bits in @perms.  If encounter an unknown
-+ * string, return -EINVAL.  Otherwise return 0.
-+ */
-+int parse_branch_mode(const char *name, int *perms)
-+{
-+      if (!name || !strcmp(name, "rw")) {
-+              *perms = MAY_READ | MAY_WRITE;
-+              return 0;
-+      }
-+      if (!strcmp(name, "ro")) {
-+              *perms = MAY_READ;
-+              return 0;
-+      }
-+      return -EINVAL;
-+}
-+
-+/*
-+ * parse the dirs= mount argument
-+ *
-+ * We don't need to lock the superblock private data's rwsem, as we get
-+ * called only by unionfs_read_super - it is still a long time before anyone
-+ * can even get a reference to us.
-+ */
-+static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info
-+                           *lower_root_info, char *options)
-+{
-+      struct nameidata nd;
-+      char *name;
-+      int err = 0;
-+      int branches = 1;
-+      int bindex = 0;
-+      int i = 0;
-+      int j = 0;
-+      struct dentry *dent1;
-+      struct dentry *dent2;
-+
-+      if (options[0] == '\0') {
-+              printk(KERN_ERR "unionfs: no branches specified\n");
-+              err = -EINVAL;
-+              goto out;
-+      }
-+
-+      /*
-+       * Each colon means we have a separator, this is really just a rough
-+       * guess, since strsep will handle empty fields for us.
-+       */
-+      for (i = 0; options[i]; i++)
-+              if (options[i] == ':')
-+                      branches++;
-+
-+      /* allocate space for underlying pointers to lower dentry */
-+      UNIONFS_SB(sb)->data =
-+              kcalloc(branches, sizeof(struct unionfs_data), GFP_KERNEL);
-+      if (unlikely(!UNIONFS_SB(sb)->data)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      lower_root_info->lower_paths =
-+              kcalloc(branches, sizeof(struct path), GFP_KERNEL);
-+      if (unlikely(!lower_root_info->lower_paths)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */
-+      branches = 0;
-+      while ((name = strsep(&options, ":")) != NULL) {
-+              int perms;
-+              char *mode = strchr(name, '=');
-+
-+              if (!name)
-+                      continue;
-+              if (!*name) {   /* bad use of ':' (extra colons) */
-+                      err = -EINVAL;
-+                      goto out;
-+              }
-+
-+              branches++;
-+
-+              /* strip off '=' if any */
-+              if (mode)
-+                      *mode++ = '\0';
-+
-+              err = parse_branch_mode(mode, &perms);
-+              if (err) {
-+                      printk(KERN_ERR "unionfs: invalid mode \"%s\" for "
-+                             "branch %d\n", mode, bindex);
-+                      goto out;
-+              }
-+              /* ensure that leftmost branch is writeable */
-+              if (!bindex && !(perms & MAY_WRITE)) {
-+                      printk(KERN_ERR "unionfs: leftmost branch cannot be "
-+                             "read-only (use \"-o ro\" to create a "
-+                             "read-only union)\n");
-+                      err = -EINVAL;
-+                      goto out;
-+              }
-+
-+              err = path_lookup(name, LOOKUP_FOLLOW, &nd);
-+              if (err) {
-+                      printk(KERN_ERR "unionfs: error accessing "
-+                             "lower directory '%s' (error %d)\n",
-+                             name, err);
-+                      goto out;
-+              }
-+
-+              err = check_branch(&nd);
-+              if (err) {
-+                      printk(KERN_ERR "unionfs: lower directory "
-+                             "'%s' is not a valid branch\n", name);
-+                      path_put(&nd.path);
-+                      goto out;
-+              }
-+
-+              lower_root_info->lower_paths[bindex].dentry = nd.path.dentry;
-+              lower_root_info->lower_paths[bindex].mnt = nd.path.mnt;
-+
-+              set_branchperms(sb, bindex, perms);
-+              set_branch_count(sb, bindex, 0);
-+              new_branch_id(sb, bindex);
-+
-+              if (lower_root_info->bstart < 0)
-+                      lower_root_info->bstart = bindex;
-+              lower_root_info->bend = bindex;
-+              bindex++;
-+      }
-+
-+      if (branches == 0) {
-+              printk(KERN_ERR "unionfs: no branches specified\n");
-+              err = -EINVAL;
-+              goto out;
-+      }
-+
-+      BUG_ON(branches != (lower_root_info->bend + 1));
-+
-+      /*
-+       * Ensure that no overlaps exist in the branches.
-+       *
-+       * This test is required because the Linux kernel has no support
-+       * currently for ensuring coherency between stackable layers and
-+       * branches.  If we were to allow overlapping branches, it would be
-+       * possible, for example, to delete a file via one branch, which
-+       * would not be reflected in another branch.  Such incoherency could
-+       * lead to inconsistencies and even kernel oopses.  Rather than
-+       * implement hacks to work around some of these cache-coherency
-+       * problems, we prevent branch overlapping, for now.  A complete
-+       * solution will involve proper kernel/VFS support for cache
-+       * coherency, at which time we could safely remove this
-+       * branch-overlapping test.
-+       */
-+      for (i = 0; i < branches; i++) {
-+              dent1 = lower_root_info->lower_paths[i].dentry;
-+              for (j = i + 1; j < branches; j++) {
-+                      dent2 = lower_root_info->lower_paths[j].dentry;
-+                      if (is_branch_overlap(dent1, dent2)) {
-+                              printk(KERN_ERR "unionfs: branches %d and "
-+                                     "%d overlap\n", i, j);
-+                              err = -EINVAL;
-+                              goto out;
-+                      }
-+              }
-+      }
-+
-+out:
-+      if (err) {
-+              for (i = 0; i < branches; i++)
-+                      if (lower_root_info->lower_paths[i].dentry) {
-+                              dput(lower_root_info->lower_paths[i].dentry);
-+                              /* initialize: can't use unionfs_mntput here */
-+                              mntput(lower_root_info->lower_paths[i].mnt);
-+                      }
-+
-+              kfree(lower_root_info->lower_paths);
-+              kfree(UNIONFS_SB(sb)->data);
-+
-+              /*
-+               * MUST clear the pointers to prevent potential double free if
-+               * the caller dies later on
-+               */
-+              lower_root_info->lower_paths = NULL;
-+              UNIONFS_SB(sb)->data = NULL;
-+      }
-+      return err;
-+}
-+
-+/*
-+ * Parse mount options.  See the manual page for usage instructions.
-+ *
-+ * Returns the dentry object of the lower-level (lower) directory;
-+ * We want to mount our stackable file system on top of that lower directory.
-+ */
-+static struct unionfs_dentry_info *unionfs_parse_options(
-+                                       struct super_block *sb,
-+                                       char *options)
-+{
-+      struct unionfs_dentry_info *lower_root_info;
-+      char *optname;
-+      int err = 0;
-+      int bindex;
-+      int dirsfound = 0;
-+
-+      /* allocate private data area */
-+      err = -ENOMEM;
-+      lower_root_info =
-+              kzalloc(sizeof(struct unionfs_dentry_info), GFP_KERNEL);
-+      if (unlikely(!lower_root_info))
-+              goto out_error;
-+      lower_root_info->bstart = -1;
-+      lower_root_info->bend = -1;
-+      lower_root_info->bopaque = -1;
-+
-+      while ((optname = strsep(&options, ",")) != NULL) {
-+              char *optarg;
-+
-+              if (!optname || !*optname)
-+                      continue;
-+
-+              optarg = strchr(optname, '=');
-+              if (optarg)
-+                      *optarg++ = '\0';
-+
-+              /*
-+               * All of our options take an argument now. Insert ones that
-+               * don't, above this check.
-+               */
-+              if (!optarg) {
-+                      printk(KERN_ERR "unionfs: %s requires an argument\n",
-+                             optname);
-+                      err = -EINVAL;
-+                      goto out_error;
-+              }
-+
-+              if (!strcmp("dirs", optname)) {
-+                      if (++dirsfound > 1) {
-+                              printk(KERN_ERR
-+                                     "unionfs: multiple dirs specified\n");
-+                              err = -EINVAL;
-+                              goto out_error;
-+                      }
-+                      err = parse_dirs_option(sb, lower_root_info, optarg);
-+                      if (err)
-+                              goto out_error;
-+                      continue;
-+              }
-+
-+              err = -EINVAL;
-+              printk(KERN_ERR
-+                     "unionfs: unrecognized option '%s'\n", optname);
-+              goto out_error;
-+      }
-+      if (dirsfound != 1) {
-+              printk(KERN_ERR "unionfs: dirs option required\n");
-+              err = -EINVAL;
-+              goto out_error;
-+      }
-+      goto out;
-+
-+out_error:
-+      if (lower_root_info && lower_root_info->lower_paths) {
-+              for (bindex = lower_root_info->bstart;
-+                   bindex >= 0 && bindex <= lower_root_info->bend;
-+                   bindex++) {
-+                      struct dentry *d;
-+                      struct vfsmount *m;
-+
-+                      d = lower_root_info->lower_paths[bindex].dentry;
-+                      m = lower_root_info->lower_paths[bindex].mnt;
-+
-+                      dput(d);
-+                      /* initializing: can't use unionfs_mntput here */
-+                      mntput(m);
-+              }
-+      }
-+
-+      kfree(lower_root_info->lower_paths);
-+      kfree(lower_root_info);
-+
-+      kfree(UNIONFS_SB(sb)->data);
-+      UNIONFS_SB(sb)->data = NULL;
-+
-+      lower_root_info = ERR_PTR(err);
-+out:
-+      return lower_root_info;
-+}
-+
-+/*
-+ * our custom d_alloc_root work-alike
-+ *
-+ * we can't use d_alloc_root if we want to use our own interpose function
-+ * unchanged, so we simply call our own "fake" d_alloc_root
-+ */
-+static struct dentry *unionfs_d_alloc_root(struct super_block *sb)
-+{
-+      struct dentry *ret = NULL;
-+
-+      if (sb) {
-+              static const struct qstr name = {
-+                      .name = "/",
-+                      .len = 1
-+              };
-+
-+              ret = d_alloc(NULL, &name);
-+              if (likely(ret)) {
-+                      ret->d_op = &unionfs_dops;
-+                      ret->d_sb = sb;
-+                      ret->d_parent = ret;
-+              }
-+      }
-+      return ret;
-+}
-+
-+/*
-+ * There is no need to lock the unionfs_super_info's rwsem as there is no
-+ * way anyone can have a reference to the superblock at this point in time.
-+ */
-+static int unionfs_read_super(struct super_block *sb, void *raw_data,
-+                            int silent)
-+{
-+      int err = 0;
-+      struct unionfs_dentry_info *lower_root_info = NULL;
-+      int bindex, bstart, bend;
-+
-+      if (!raw_data) {
-+              printk(KERN_ERR
-+                     "unionfs: read_super: missing data argument\n");
-+              err = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* Allocate superblock private data */
-+      sb->s_fs_info = kzalloc(sizeof(struct unionfs_sb_info), GFP_KERNEL);
-+      if (unlikely(!UNIONFS_SB(sb))) {
-+              printk(KERN_CRIT "unionfs: read_super: out of memory\n");
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      UNIONFS_SB(sb)->bend = -1;
-+      atomic_set(&UNIONFS_SB(sb)->generation, 1);
-+      init_rwsem(&UNIONFS_SB(sb)->rwsem);
-+      UNIONFS_SB(sb)->high_branch_id = -1; /* -1 == invalid branch ID */
-+
-+      lower_root_info = unionfs_parse_options(sb, raw_data);
-+      if (IS_ERR(lower_root_info)) {
-+              printk(KERN_ERR
-+                     "unionfs: read_super: error while parsing options "
-+                     "(err = %ld)\n", PTR_ERR(lower_root_info));
-+              err = PTR_ERR(lower_root_info);
-+              lower_root_info = NULL;
-+              goto out_free;
-+      }
-+      if (lower_root_info->bstart == -1) {
-+              err = -ENOENT;
-+              goto out_free;
-+      }
-+
-+      /* set the lower superblock field of upper superblock */
-+      bstart = lower_root_info->bstart;
-+      BUG_ON(bstart != 0);
-+      sbend(sb) = bend = lower_root_info->bend;
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              struct dentry *d = lower_root_info->lower_paths[bindex].dentry;
-+              atomic_inc(&d->d_sb->s_active);
-+              unionfs_set_lower_super_idx(sb, bindex, d->d_sb);
-+      }
-+
-+      /* max Bytes is the maximum bytes from highest priority branch */
-+      sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
-+
-+      /*
-+       * Our c/m/atime granularity is 1 ns because we may stack on file
-+       * systems whose granularity is as good.  This is important for our
-+       * time-based cache coherency.
-+       */
-+      sb->s_time_gran = 1;
-+
-+      sb->s_op = &unionfs_sops;
-+
-+      /* See comment next to the definition of unionfs_d_alloc_root */
-+      sb->s_root = unionfs_d_alloc_root(sb);
-+      if (unlikely(!sb->s_root)) {
-+              err = -ENOMEM;
-+              goto out_dput;
-+      }
-+
-+      /* link the upper and lower dentries */
-+      sb->s_root->d_fsdata = NULL;
-+      err = new_dentry_private_data(sb->s_root, UNIONFS_DMUTEX_ROOT);
-+      if (unlikely(err))
-+              goto out_freedpd;
-+
-+      /* Set the lower dentries for s_root */
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              struct dentry *d;
-+              struct vfsmount *m;
-+
-+              d = lower_root_info->lower_paths[bindex].dentry;
-+              m = lower_root_info->lower_paths[bindex].mnt;
-+
-+              unionfs_set_lower_dentry_idx(sb->s_root, bindex, d);
-+              unionfs_set_lower_mnt_idx(sb->s_root, bindex, m);
-+      }
-+      dbstart(sb->s_root) = bstart;
-+      dbend(sb->s_root) = bend;
-+
-+      /* Set the generation number to one, since this is for the mount. */
-+      atomic_set(&UNIONFS_D(sb->s_root)->generation, 1);
-+
-+      /*
-+       * Call interpose to create the upper level inode.  Only
-+       * INTERPOSE_LOOKUP can return a value other than 0 on err.
-+       */
-+      err = PTR_ERR(unionfs_interpose(sb->s_root, sb, 0));
-+      unionfs_unlock_dentry(sb->s_root);
-+      if (!err)
-+              goto out;
-+      /* else fall through */
-+
-+out_freedpd:
-+      if (UNIONFS_D(sb->s_root)) {
-+              kfree(UNIONFS_D(sb->s_root)->lower_paths);
-+              free_dentry_private_data(sb->s_root);
-+      }
-+      dput(sb->s_root);
-+
-+out_dput:
-+      if (lower_root_info && !IS_ERR(lower_root_info)) {
-+              for (bindex = lower_root_info->bstart;
-+                   bindex <= lower_root_info->bend; bindex++) {
-+                      struct dentry *d;
-+                      struct vfsmount *m;
-+
-+                      d = lower_root_info->lower_paths[bindex].dentry;
-+                      m = lower_root_info->lower_paths[bindex].mnt;
-+
-+                      dput(d);
-+                      /* initializing: can't use unionfs_mntput here */
-+                      mntput(m);
-+                      /* drop refs we took earlier */
-+                      atomic_dec(&d->d_sb->s_active);
-+              }
-+              kfree(lower_root_info->lower_paths);
-+              kfree(lower_root_info);
-+              lower_root_info = NULL;
-+      }
-+
-+out_free:
-+      kfree(UNIONFS_SB(sb)->data);
-+      kfree(UNIONFS_SB(sb));
-+      sb->s_fs_info = NULL;
-+
-+out:
-+      if (lower_root_info && !IS_ERR(lower_root_info)) {
-+              kfree(lower_root_info->lower_paths);
-+              kfree(lower_root_info);
-+      }
-+      return err;
-+}
-+
-+static int unionfs_get_sb(struct file_system_type *fs_type,
-+                        int flags, const char *dev_name,
-+                        void *raw_data, struct vfsmount *mnt)
-+{
-+      int err;
-+      err = get_sb_nodev(fs_type, flags, raw_data, unionfs_read_super, mnt);
-+      if (!err)
-+              UNIONFS_SB(mnt->mnt_sb)->dev_name =
-+                      kstrdup(dev_name, GFP_KERNEL);
-+      return err;
-+}
-+
-+static struct file_system_type unionfs_fs_type = {
-+      .owner          = THIS_MODULE,
-+      .name           = UNIONFS_NAME,
-+      .get_sb         = unionfs_get_sb,
-+      .kill_sb        = generic_shutdown_super,
-+      .fs_flags       = FS_REVAL_DOT,
-+};
-+
-+static int __init init_unionfs_fs(void)
-+{
-+      int err;
-+
-+      pr_info("Registering unionfs " UNIONFS_VERSION "\n");
-+
-+      err = unionfs_init_filldir_cache();
-+      if (unlikely(err))
-+              goto out;
-+      err = unionfs_init_inode_cache();
-+      if (unlikely(err))
-+              goto out;
-+      err = unionfs_init_dentry_cache();
-+      if (unlikely(err))
-+              goto out;
-+      err = init_sioq();
-+      if (unlikely(err))
-+              goto out;
-+      err = register_filesystem(&unionfs_fs_type);
-+out:
-+      if (unlikely(err)) {
-+              stop_sioq();
-+              unionfs_destroy_filldir_cache();
-+              unionfs_destroy_inode_cache();
-+              unionfs_destroy_dentry_cache();
-+      }
-+      return err;
-+}
-+
-+static void __exit exit_unionfs_fs(void)
-+{
-+      stop_sioq();
-+      unionfs_destroy_filldir_cache();
-+      unionfs_destroy_inode_cache();
-+      unionfs_destroy_dentry_cache();
-+      unregister_filesystem(&unionfs_fs_type);
-+      pr_info("Completed unionfs module unload\n");
-+}
-+
-+MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
-+            " (http://www.fsl.cs.sunysb.edu)");
-+MODULE_DESCRIPTION("Unionfs " UNIONFS_VERSION
-+                 " (http://unionfs.filesystems.org)");
-+MODULE_LICENSE("GPL");
-+
-+module_init(init_unionfs_fs);
-+module_exit(exit_unionfs_fs);
-diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
-new file mode 100644
-index 0000000..b7d4713
---- /dev/null
-+++ b/fs/unionfs/mmap.c
-@@ -0,0 +1,89 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2006      Shaya Potter
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+
-+/*
-+ * XXX: we need a dummy readpage handler because generic_file_mmap (which we
-+ * use in unionfs_mmap) checks for the existence of
-+ * mapping->a_ops->readpage, else it returns -ENOEXEC.  The VFS will need to
-+ * be fixed to allow a file system to define vm_ops->fault without any
-+ * address_space_ops whatsoever.
-+ *
-+ * Otherwise, we don't want to use our readpage method at all.
-+ */
-+static int unionfs_readpage(struct file *file, struct page *page)
-+{
-+      BUG();
-+      return -EINVAL;
-+}
-+
-+static int unionfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-+{
-+      int err;
-+      struct file *file, *lower_file;
-+      struct vm_operations_struct *lower_vm_ops;
-+      struct vm_area_struct lower_vma;
-+
-+      BUG_ON(!vma);
-+      memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
-+      file = lower_vma.vm_file;
-+      lower_vm_ops = UNIONFS_F(file)->lower_vm_ops;
-+      BUG_ON(!lower_vm_ops);
-+
-+      lower_file = unionfs_lower_file(file);
-+      BUG_ON(!lower_file);
-+      /*
-+       * XXX: vm_ops->fault may be called in parallel.  Because we have to
-+       * resort to temporarily changing the vma->vm_file to point to the
-+       * lower file, a concurrent invocation of unionfs_fault could see a
-+       * different value.  In this workaround, we keep a different copy of
-+       * the vma structure in our stack, so we never expose a different
-+       * value of the vma->vm_file called to us, even temporarily.  A
-+       * better fix would be to change the calling semantics of ->fault to
-+       * take an explicit file pointer.
-+       */
-+      lower_vma.vm_file = lower_file;
-+      err = lower_vm_ops->fault(&lower_vma, vmf);
-+      return err;
-+}
-+
-+/*
-+ * XXX: the default address_space_ops for unionfs is empty.  We cannot set
-+ * our inode->i_mapping->a_ops to NULL because too many code paths expect
-+ * the a_ops vector to be non-NULL.
-+ */
-+struct address_space_operations unionfs_aops = {
-+      /* empty on purpose */
-+};
-+
-+/*
-+ * XXX: we need a second, dummy address_space_ops vector, to be used
-+ * temporarily during unionfs_mmap, because the latter calls
-+ * generic_file_mmap, which checks if ->readpage exists, else returns
-+ * -ENOEXEC.
-+ */
-+struct address_space_operations unionfs_dummy_aops = {
-+      .readpage       = unionfs_readpage,
-+};
-+
-+struct vm_operations_struct unionfs_vm_ops = {
-+      .fault          = unionfs_fault,
-+};
-diff --git a/fs/unionfs/rdstate.c b/fs/unionfs/rdstate.c
-new file mode 100644
-index 0000000..06d5374
---- /dev/null
-+++ b/fs/unionfs/rdstate.c
-@@ -0,0 +1,285 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/* This file contains the routines for maintaining readdir state. */
-+
-+/*
-+ * There are two structures here, rdstate which is a hash table
-+ * of the second structure which is a filldir_node.
-+ */
-+
-+/*
-+ * This is a struct kmem_cache for filldir nodes, because we allocate a lot
-+ * of them and they shouldn't waste memory.  If the node has a small name
-+ * (as defined by the dentry structure), then we use an inline name to
-+ * preserve kmalloc space.
-+ */
-+static struct kmem_cache *unionfs_filldir_cachep;
-+
-+int unionfs_init_filldir_cache(void)
-+{
-+      unionfs_filldir_cachep =
-+              kmem_cache_create("unionfs_filldir",
-+                                sizeof(struct filldir_node), 0,
-+                                SLAB_RECLAIM_ACCOUNT, NULL);
-+
-+      return (unionfs_filldir_cachep ? 0 : -ENOMEM);
-+}
-+
-+void unionfs_destroy_filldir_cache(void)
-+{
-+      if (unionfs_filldir_cachep)
-+              kmem_cache_destroy(unionfs_filldir_cachep);
-+}
-+
-+/*
-+ * This is a tuning parameter that tells us roughly how big to make the
-+ * hash table in directory entries per page.  This isn't perfect, but
-+ * at least we get a hash table size that shouldn't be too overloaded.
-+ * The following averages are based on my home directory.
-+ * 14.44693   Overall
-+ * 12.29      Single Page Directories
-+ * 117.93     Multi-page directories
-+ */
-+#define DENTPAGE 4096
-+#define DENTPERONEPAGE 12
-+#define DENTPERPAGE 118
-+#define MINHASHSIZE 1
-+static int guesstimate_hash_size(struct inode *inode)
-+{
-+      struct inode *lower_inode;
-+      int bindex;
-+      int hashsize = MINHASHSIZE;
-+
-+      if (UNIONFS_I(inode)->hashsize > 0)
-+              return UNIONFS_I(inode)->hashsize;
-+
-+      for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
-+              lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (!lower_inode)
-+                      continue;
-+
-+              if (i_size_read(lower_inode) == DENTPAGE)
-+                      hashsize += DENTPERONEPAGE;
-+              else
-+                      hashsize += (i_size_read(lower_inode) / DENTPAGE) *
-+                              DENTPERPAGE;
-+      }
-+
-+      return hashsize;
-+}
-+
-+int init_rdstate(struct file *file)
-+{
-+      BUG_ON(sizeof(loff_t) !=
-+             (sizeof(unsigned int) + sizeof(unsigned int)));
-+      BUG_ON(UNIONFS_F(file)->rdstate != NULL);
-+
-+      UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_path.dentry->d_inode,
-+                                               fbstart(file));
-+
-+      return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM);
-+}
-+
-+struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos)
-+{
-+      struct unionfs_dir_state *rdstate = NULL;
-+      struct list_head *pos;
-+
-+      spin_lock(&UNIONFS_I(inode)->rdlock);
-+      list_for_each(pos, &UNIONFS_I(inode)->readdircache) {
-+              struct unionfs_dir_state *r =
-+                      list_entry(pos, struct unionfs_dir_state, cache);
-+              if (fpos == rdstate2offset(r)) {
-+                      UNIONFS_I(inode)->rdcount--;
-+                      list_del(&r->cache);
-+                      rdstate = r;
-+                      break;
-+              }
-+      }
-+      spin_unlock(&UNIONFS_I(inode)->rdlock);
-+      return rdstate;
-+}
-+
-+struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex)
-+{
-+      int i = 0;
-+      int hashsize;
-+      unsigned long mallocsize = sizeof(struct unionfs_dir_state);
-+      struct unionfs_dir_state *rdstate;
-+
-+      hashsize = guesstimate_hash_size(inode);
-+      mallocsize += hashsize * sizeof(struct list_head);
-+      mallocsize = __roundup_pow_of_two(mallocsize);
-+
-+      /* This should give us about 500 entries anyway. */
-+      if (mallocsize > PAGE_SIZE)
-+              mallocsize = PAGE_SIZE;
-+
-+      hashsize = (mallocsize - sizeof(struct unionfs_dir_state)) /
-+              sizeof(struct list_head);
-+
-+      rdstate = kmalloc(mallocsize, GFP_KERNEL);
-+      if (unlikely(!rdstate))
-+              return NULL;
-+
-+      spin_lock(&UNIONFS_I(inode)->rdlock);
-+      if (UNIONFS_I(inode)->cookie >= (MAXRDCOOKIE - 1))
-+              UNIONFS_I(inode)->cookie = 1;
-+      else
-+              UNIONFS_I(inode)->cookie++;
-+
-+      rdstate->cookie = UNIONFS_I(inode)->cookie;
-+      spin_unlock(&UNIONFS_I(inode)->rdlock);
-+      rdstate->offset = 1;
-+      rdstate->access = jiffies;
-+      rdstate->bindex = bindex;
-+      rdstate->dirpos = 0;
-+      rdstate->hashentries = 0;
-+      rdstate->size = hashsize;
-+      for (i = 0; i < rdstate->size; i++)
-+              INIT_LIST_HEAD(&rdstate->list[i]);
-+
-+      return rdstate;
-+}
-+
-+static void free_filldir_node(struct filldir_node *node)
-+{
-+      if (node->namelen >= DNAME_INLINE_LEN_MIN)
-+              kfree(node->name);
-+      kmem_cache_free(unionfs_filldir_cachep, node);
-+}
-+
-+void free_rdstate(struct unionfs_dir_state *state)
-+{
-+      struct filldir_node *tmp;
-+      int i;
-+
-+      for (i = 0; i < state->size; i++) {
-+              struct list_head *head = &(state->list[i]);
-+              struct list_head *pos, *n;
-+
-+              /* traverse the list and deallocate space */
-+              list_for_each_safe(pos, n, head) {
-+                      tmp = list_entry(pos, struct filldir_node, file_list);
-+                      list_del(&tmp->file_list);
-+                      free_filldir_node(tmp);
-+              }
-+      }
-+
-+      kfree(state);
-+}
-+
-+struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
-+                                     const char *name, int namelen,
-+                                     int is_whiteout)
-+{
-+      int index;
-+      unsigned int hash;
-+      struct list_head *head;
-+      struct list_head *pos;
-+      struct filldir_node *cursor = NULL;
-+      int found = 0;
-+
-+      BUG_ON(namelen <= 0);
-+
-+      hash = full_name_hash(name, namelen);
-+      index = hash % rdstate->size;
-+
-+      head = &(rdstate->list[index]);
-+      list_for_each(pos, head) {
-+              cursor = list_entry(pos, struct filldir_node, file_list);
-+
-+              if (cursor->namelen == namelen && cursor->hash == hash &&
-+                  !strncmp(cursor->name, name, namelen)) {
-+                      /*
-+                       * a duplicate exists, and hence no need to create
-+                       * entry to the list
-+                       */
-+                      found = 1;
-+
-+                      /*
-+                       * if a duplicate is found in this branch, and is
-+                       * not due to the caller looking for an entry to
-+                       * whiteout, then the file system may be corrupted.
-+                       */
-+                      if (unlikely(!is_whiteout &&
-+                                   cursor->bindex == rdstate->bindex))
-+                              printk(KERN_ERR "unionfs: filldir: possible "
-+                                     "I/O error: a file is duplicated "
-+                                     "in the same branch %d: %s\n",
-+                                     rdstate->bindex, cursor->name);
-+                      break;
-+              }
-+      }
-+
-+      if (!found)
-+              cursor = NULL;
-+
-+      return cursor;
-+}
-+
-+int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
-+                   int namelen, int bindex, int whiteout)
-+{
-+      struct filldir_node *new;
-+      unsigned int hash;
-+      int index;
-+      int err = 0;
-+      struct list_head *head;
-+
-+      BUG_ON(namelen <= 0);
-+
-+      hash = full_name_hash(name, namelen);
-+      index = hash % rdstate->size;
-+      head = &(rdstate->list[index]);
-+
-+      new = kmem_cache_alloc(unionfs_filldir_cachep, GFP_KERNEL);
-+      if (unlikely(!new)) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      INIT_LIST_HEAD(&new->file_list);
-+      new->namelen = namelen;
-+      new->hash = hash;
-+      new->bindex = bindex;
-+      new->whiteout = whiteout;
-+
-+      if (namelen < DNAME_INLINE_LEN_MIN) {
-+              new->name = new->iname;
-+      } else {
-+              new->name = kmalloc(namelen + 1, GFP_KERNEL);
-+              if (unlikely(!new->name)) {
-+                      kmem_cache_free(unionfs_filldir_cachep, new);
-+                      new = NULL;
-+                      goto out;
-+              }
-+      }
-+
-+      memcpy(new->name, name, namelen);
-+      new->name[namelen] = '\0';
-+
-+      rdstate->hashentries++;
-+
-+      list_add(&(new->file_list), head);
-+out:
-+      return err;
-+}
-diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
-new file mode 100644
-index 0000000..da7d589
---- /dev/null
-+++ b/fs/unionfs/rename.c
-@@ -0,0 +1,478 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * This is a helper function for rename, used when rename ends up with hosed
-+ * over dentries and we need to revert.
-+ */
-+static int unionfs_refresh_lower_dentry(struct dentry *dentry, int bindex)
-+{
-+      struct dentry *lower_dentry;
-+      struct dentry *lower_parent;
-+      int err = 0;
-+
-+      verify_locked(dentry);
-+
-+      unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_CHILD);
-+      lower_parent = unionfs_lower_dentry_idx(dentry->d_parent, bindex);
-+      unionfs_unlock_dentry(dentry->d_parent);
-+
-+      BUG_ON(!S_ISDIR(lower_parent->d_inode->i_mode));
-+
-+      lower_dentry = lookup_one_len(dentry->d_name.name, lower_parent,
-+                                    dentry->d_name.len);
-+      if (IS_ERR(lower_dentry)) {
-+              err = PTR_ERR(lower_dentry);
-+              goto out;
-+      }
-+
-+      dput(unionfs_lower_dentry_idx(dentry, bindex));
-+      iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
-+      unionfs_set_lower_inode_idx(dentry->d_inode, bindex, NULL);
-+
-+      if (!lower_dentry->d_inode) {
-+              dput(lower_dentry);
-+              unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
-+      } else {
-+              unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
-+              unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
-+                                          igrab(lower_dentry->d_inode));
-+      }
-+
-+out:
-+      return err;
-+}
-+
-+static int __unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+                          struct inode *new_dir, struct dentry *new_dentry,
-+                          int bindex)
-+{
-+      int err = 0;
-+      struct dentry *lower_old_dentry;
-+      struct dentry *lower_new_dentry;
-+      struct dentry *lower_old_dir_dentry;
-+      struct dentry *lower_new_dir_dentry;
-+      struct dentry *trap;
-+
-+      lower_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
-+      lower_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex);
-+
-+      if (!lower_new_dentry) {
-+              lower_new_dentry =
-+                      create_parents(new_dentry->d_parent->d_inode,
-+                                     new_dentry, new_dentry->d_name.name,
-+                                     bindex);
-+              if (IS_ERR(lower_new_dentry)) {
-+                      err = PTR_ERR(lower_new_dentry);
-+                      if (IS_COPYUP_ERR(err))
-+                              goto out;
-+                      printk(KERN_ERR "unionfs: error creating directory "
-+                             "tree for rename, bindex=%d err=%d\n",
-+                             bindex, err);
-+                      goto out;
-+              }
-+      }
-+
-+      /* check for and remove whiteout, if any */
-+      err = check_unlink_whiteout(new_dentry, lower_new_dentry, bindex);
-+      if (err > 0) /* ignore if whiteout found and successfully removed */
-+              err = 0;
-+      if (err)
-+              goto out;
-+
-+      /* check of old_dentry branch is writable */
-+      err = is_robranch_super(old_dentry->d_sb, bindex);
-+      if (err)
-+              goto out;
-+
-+      dget(lower_old_dentry);
-+      dget(lower_new_dentry);
-+      lower_old_dir_dentry = dget_parent(lower_old_dentry);
-+      lower_new_dir_dentry = dget_parent(lower_new_dentry);
-+
-+      /* see Documentation/filesystems/unionfs/issues.txt */
-+      lockdep_off();
-+      trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
-+      /* source should not be ancenstor of target */
-+      if (trap == lower_old_dentry) {
-+              err = -EINVAL;
-+              goto out_err_unlock;
-+      }
-+      /* target should not be ancenstor of source */
-+      if (trap == lower_new_dentry) {
-+              err = -ENOTEMPTY;
-+              goto out_err_unlock;
-+      }
-+      err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
-+                       lower_new_dir_dentry->d_inode, lower_new_dentry);
-+out_err_unlock:
-+      if (!err) {
-+              /* update parent dir times */
-+              fsstack_copy_attr_times(old_dir, lower_old_dir_dentry->d_inode);
-+              fsstack_copy_attr_times(new_dir, lower_new_dir_dentry->d_inode);
-+      }
-+      unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
-+      lockdep_on();
-+
-+      dput(lower_old_dir_dentry);
-+      dput(lower_new_dir_dentry);
-+      dput(lower_old_dentry);
-+      dput(lower_new_dentry);
-+
-+out:
-+      if (!err) {
-+              /* Fixup the new_dentry. */
-+              if (bindex < dbstart(new_dentry))
-+                      dbstart(new_dentry) = bindex;
-+              else if (bindex > dbend(new_dentry))
-+                      dbend(new_dentry) = bindex;
-+      }
-+
-+      return err;
-+}
-+
-+/*
-+ * Main rename code.  This is sufficiently complex, that it's documented in
-+ * Documentation/filesystems/unionfs/rename.txt.  This routine calls
-+ * __unionfs_rename() above to perform some of the work.
-+ */
-+static int do_unionfs_rename(struct inode *old_dir,
-+                           struct dentry *old_dentry,
-+                           struct inode *new_dir,
-+                           struct dentry *new_dentry)
-+{
-+      int err = 0;
-+      int bindex, bwh_old;
-+      int old_bstart, old_bend;
-+      int new_bstart, new_bend;
-+      int do_copyup = -1;
-+      struct dentry *parent_dentry;
-+      int local_err = 0;
-+      int eio = 0;
-+      int revert = 0;
-+
-+      old_bstart = dbstart(old_dentry);
-+      bwh_old = old_bstart;
-+      old_bend = dbend(old_dentry);
-+      parent_dentry = old_dentry->d_parent;
-+
-+      new_bstart = dbstart(new_dentry);
-+      new_bend = dbend(new_dentry);
-+
-+      /* Rename source to destination. */
-+      err = __unionfs_rename(old_dir, old_dentry, new_dir, new_dentry,
-+                             old_bstart);
-+      if (err) {
-+              if (!IS_COPYUP_ERR(err))
-+                      goto out;
-+              do_copyup = old_bstart - 1;
-+      } else {
-+              revert = 1;
-+      }
-+
-+      /*
-+       * Unlink all instances of destination that exist to the left of
-+       * bstart of source. On error, revert back, goto out.
-+       */
-+      for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) {
-+              struct dentry *unlink_dentry;
-+              struct dentry *unlink_dir_dentry;
-+
-+              BUG_ON(bindex < 0);
-+              unlink_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
-+              if (!unlink_dentry)
-+                      continue;
-+
-+              unlink_dir_dentry = lock_parent(unlink_dentry);
-+              err = is_robranch_super(old_dir->i_sb, bindex);
-+              if (!err)
-+                      err = vfs_unlink(unlink_dir_dentry->d_inode,
-+                                       unlink_dentry);
-+
-+              fsstack_copy_attr_times(new_dentry->d_parent->d_inode,
-+                                      unlink_dir_dentry->d_inode);
-+              /* propagate number of hard-links */
-+              new_dentry->d_parent->d_inode->i_nlink =
-+                      unionfs_get_nlinks(new_dentry->d_parent->d_inode);
-+
-+              unlock_dir(unlink_dir_dentry);
-+              if (!err) {
-+                      if (bindex != new_bstart) {
-+                              dput(unlink_dentry);
-+                              unionfs_set_lower_dentry_idx(new_dentry,
-+                                                           bindex, NULL);
-+                      }
-+              } else if (IS_COPYUP_ERR(err)) {
-+                      do_copyup = bindex - 1;
-+              } else if (revert) {
-+                      goto revert;
-+              }
-+      }
-+
-+      if (do_copyup != -1) {
-+              for (bindex = do_copyup; bindex >= 0; bindex--) {
-+                      /*
-+                       * copyup the file into some left directory, so that
-+                       * you can rename it
-+                       */
-+                      err = copyup_dentry(old_dentry->d_parent->d_inode,
-+                                          old_dentry, old_bstart, bindex,
-+                                          old_dentry->d_name.name,
-+                                          old_dentry->d_name.len, NULL,
-+                                          i_size_read(old_dentry->d_inode));
-+                      /* if copyup failed, try next branch to the left */
-+                      if (err)
-+                              continue;
-+                      bwh_old = bindex;
-+                      err = __unionfs_rename(old_dir, old_dentry,
-+                                             new_dir, new_dentry,
-+                                             bindex);
-+                      break;
-+              }
-+      }
-+
-+      /* make it opaque */
-+      if (S_ISDIR(old_dentry->d_inode->i_mode)) {
-+              err = make_dir_opaque(old_dentry, dbstart(old_dentry));
-+              if (err)
-+                      goto revert;
-+      }
-+
-+      /*
-+       * Create whiteout for source, only if:
-+       * (1) There is more than one underlying instance of source.
-+       * (2) We did a copy_up
-+       */
-+      if ((old_bstart != old_bend) || (do_copyup != -1)) {
-+              if (bwh_old < 0) {
-+                      printk(KERN_ERR "unionfs: rename error (bwh_old=%d)\n",
-+                             bwh_old);
-+                      err = -EIO;
-+                      goto out;
-+              }
-+              err = create_whiteout(old_dentry, bwh_old);
-+              if (err) {
-+                      /* can't fix anything now, so we exit with -EIO */
-+                      printk(KERN_ERR "unionfs: can't create a whiteout for "
-+                             "%s in rename!\n", old_dentry->d_name.name);
-+                      err = -EIO;
-+              }
-+      }
-+
-+out:
-+      return err;
-+
-+revert:
-+      /* Do revert here. */
-+      local_err = unionfs_refresh_lower_dentry(new_dentry, old_bstart);
-+      if (local_err) {
-+              printk(KERN_ERR "unionfs: revert failed in rename: "
-+                     "the new refresh failed\n");
-+              eio = -EIO;
-+      }
-+
-+      local_err = unionfs_refresh_lower_dentry(old_dentry, old_bstart);
-+      if (local_err) {
-+              printk(KERN_ERR "unionfs: revert failed in rename: "
-+                     "the old refresh failed\n");
-+              eio = -EIO;
-+              goto revert_out;
-+      }
-+
-+      if (!unionfs_lower_dentry_idx(new_dentry, bindex) ||
-+          !unionfs_lower_dentry_idx(new_dentry, bindex)->d_inode) {
-+              printk(KERN_ERR "unionfs: revert failed in rename: "
-+                     "the object disappeared from under us!\n");
-+              eio = -EIO;
-+              goto revert_out;
-+      }
-+
-+      if (unionfs_lower_dentry_idx(old_dentry, bindex) &&
-+          unionfs_lower_dentry_idx(old_dentry, bindex)->d_inode) {
-+              printk(KERN_ERR "unionfs: revert failed in rename: "
-+                     "the object was created underneath us!\n");
-+              eio = -EIO;
-+              goto revert_out;
-+      }
-+
-+      local_err = __unionfs_rename(new_dir, new_dentry,
-+                                   old_dir, old_dentry, old_bstart);
-+
-+      /* If we can't fix it, then we cop-out with -EIO. */
-+      if (local_err) {
-+              printk(KERN_ERR "unionfs: revert failed in rename!\n");
-+              eio = -EIO;
-+      }
-+
-+      local_err = unionfs_refresh_lower_dentry(new_dentry, bindex);
-+      if (local_err)
-+              eio = -EIO;
-+      local_err = unionfs_refresh_lower_dentry(old_dentry, bindex);
-+      if (local_err)
-+              eio = -EIO;
-+
-+revert_out:
-+      if (eio)
-+              err = eio;
-+      return err;
-+}
-+
-+/*
-+ * We can't copyup a directory, because it may involve huge numbers of
-+ * children, etc.  Doing that in the kernel would be bad, so instead we
-+ * return EXDEV to the user-space utility that caused this, and let the
-+ * user-space recurse and ask us to copy up each file separately.
-+ */
-+static int may_rename_dir(struct dentry *dentry)
-+{
-+      int err, bstart;
-+
-+      err = check_empty(dentry, NULL);
-+      if (err == -ENOTEMPTY) {
-+              if (is_robranch(dentry))
-+                      return -EXDEV;
-+      } else if (err) {
-+              return err;
-+      }
-+
-+      bstart = dbstart(dentry);
-+      if (dbend(dentry) == bstart || dbopaque(dentry) == bstart)
-+              return 0;
-+
-+      dbstart(dentry) = bstart + 1;
-+      err = check_empty(dentry, NULL);
-+      dbstart(dentry) = bstart;
-+      if (err == -ENOTEMPTY)
-+              err = -EXDEV;
-+      return err;
-+}
-+
-+int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+                 struct inode *new_dir, struct dentry *new_dentry)
-+{
-+      int err = 0;
-+      struct dentry *wh_dentry;
-+
-+      unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_double_lock_dentry(old_dentry, new_dentry);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(old_dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      if (unlikely(!d_deleted(new_dentry) && new_dentry->d_inode &&
-+                   !__unionfs_d_revalidate_chain(new_dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      if (!S_ISDIR(old_dentry->d_inode->i_mode))
-+              err = unionfs_partial_lookup(old_dentry);
-+      else
-+              err = may_rename_dir(old_dentry);
-+
-+      if (err)
-+              goto out;
-+
-+      err = unionfs_partial_lookup(new_dentry);
-+      if (err)
-+              goto out;
-+
-+      /*
-+       * if new_dentry is already lower because of whiteout,
-+       * simply override it even if the whited-out dir is not empty.
-+       */
-+      wh_dentry = find_first_whiteout(new_dentry);
-+      if (!IS_ERR(wh_dentry)) {
-+              dput(wh_dentry);
-+      } else if (new_dentry->d_inode) {
-+              if (S_ISDIR(old_dentry->d_inode->i_mode) !=
-+                  S_ISDIR(new_dentry->d_inode->i_mode)) {
-+                      err = S_ISDIR(old_dentry->d_inode->i_mode) ?
-+                              -ENOTDIR : -EISDIR;
-+                      goto out;
-+              }
-+
-+              if (S_ISDIR(new_dentry->d_inode->i_mode)) {
-+                      struct unionfs_dir_state *namelist = NULL;
-+                      /* check if this unionfs directory is empty or not */
-+                      err = check_empty(new_dentry, &namelist);
-+                      if (err)
-+                              goto out;
-+
-+                      if (!is_robranch(new_dentry))
-+                              err = delete_whiteouts(new_dentry,
-+                                                     dbstart(new_dentry),
-+                                                     namelist);
-+
-+                      free_rdstate(namelist);
-+
-+                      if (err)
-+                              goto out;
-+              }
-+      }
-+
-+      err = do_unionfs_rename(old_dir, old_dentry, new_dir, new_dentry);
-+      if (err)
-+              goto out;
-+
-+      /*
-+       * force re-lookup since the dir on ro branch is not renamed, and
-+       * lower dentries still indicate the un-renamed ones.
-+       */
-+      if (S_ISDIR(old_dentry->d_inode->i_mode))
-+              atomic_dec(&UNIONFS_D(old_dentry)->generation);
-+      else
-+              unionfs_postcopyup_release(old_dentry);
-+      if (new_dentry->d_inode && !S_ISDIR(new_dentry->d_inode->i_mode)) {
-+              unionfs_postcopyup_release(new_dentry);
-+              unionfs_postcopyup_setmnt(new_dentry);
-+              if (!unionfs_lower_inode(new_dentry->d_inode)) {
-+                      /*
-+                       * If we get here, it means that no copyup was
-+                       * needed, and that a file by the old name already
-+                       * existing on the destination branch; that file got
-+                       * renamed earlier in this function, so all we need
-+                       * to do here is set the lower inode.
-+                       */
-+                      struct inode *inode;
-+                      inode = unionfs_lower_inode(old_dentry->d_inode);
-+                      igrab(inode);
-+                      unionfs_set_lower_inode_idx(new_dentry->d_inode,
-+                                                  dbstart(new_dentry),
-+                                                  inode);
-+              }
-+      }
-+      /* if all of this renaming succeeded, update our times */
-+      unionfs_copy_attr_times(old_dentry->d_inode);
-+      unionfs_copy_attr_times(new_dentry->d_inode);
-+      unionfs_check_inode(old_dir);
-+      unionfs_check_inode(new_dir);
-+      unionfs_check_dentry(old_dentry);
-+      unionfs_check_dentry(new_dentry);
-+
-+out:
-+      if (err)                /* clear the new_dentry stuff created */
-+              d_drop(new_dentry);
-+      unionfs_unlock_dentry(new_dentry);
-+      unionfs_unlock_dentry(old_dentry);
-+      unionfs_read_unlock(old_dentry->d_sb);
-+      return err;
-+}
-diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
-new file mode 100644
-index 0000000..dd45e39
---- /dev/null
-+++ b/fs/unionfs/sioq.c
-@@ -0,0 +1,101 @@
-+/*
-+ * Copyright (c) 2006-2008 Erez Zadok
-+ * Copyright (c) 2006      Charles P. Wright
-+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2006      Junjiro Okajima
-+ * Copyright (c) 2006      David P. Quigley
-+ * Copyright (c) 2006-2008 Stony Brook University
-+ * Copyright (c) 2006-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * Super-user IO work Queue - sometimes we need to perform actions which
-+ * would fail due to the unix permissions on the parent directory (e.g.,
-+ * rmdir a directory which appears empty, but in reality contains
-+ * whiteouts).
-+ */
-+
-+static struct workqueue_struct *superio_workqueue;
-+
-+int __init init_sioq(void)
-+{
-+      int err;
-+
-+      superio_workqueue = create_workqueue("unionfs_siod");
-+      if (!IS_ERR(superio_workqueue))
-+              return 0;
-+
-+      err = PTR_ERR(superio_workqueue);
-+      printk(KERN_ERR "unionfs: create_workqueue failed %d\n", err);
-+      superio_workqueue = NULL;
-+      return err;
-+}
-+
-+void stop_sioq(void)
-+{
-+      if (superio_workqueue)
-+              destroy_workqueue(superio_workqueue);
-+}
-+
-+void run_sioq(work_func_t func, struct sioq_args *args)
-+{
-+      INIT_WORK(&args->work, func);
-+
-+      init_completion(&args->comp);
-+      while (!queue_work(superio_workqueue, &args->work)) {
-+              /* TODO: do accounting if needed */
-+              schedule();
-+      }
-+      wait_for_completion(&args->comp);
-+}
-+
-+void __unionfs_create(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct create_args *c = &args->create;
-+
-+      args->err = vfs_create(c->parent, c->dentry, c->mode, c->nd);
-+      complete(&args->comp);
-+}
-+
-+void __unionfs_mkdir(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct mkdir_args *m = &args->mkdir;
-+
-+      args->err = vfs_mkdir(m->parent, m->dentry, m->mode);
-+      complete(&args->comp);
-+}
-+
-+void __unionfs_mknod(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct mknod_args *m = &args->mknod;
-+
-+      args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev);
-+      complete(&args->comp);
-+}
-+
-+void __unionfs_symlink(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct symlink_args *s = &args->symlink;
-+
-+      args->err = vfs_symlink(s->parent, s->dentry, s->symbuf);
-+      complete(&args->comp);
-+}
-+
-+void __unionfs_unlink(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct unlink_args *u = &args->unlink;
-+
-+      args->err = vfs_unlink(u->parent, u->dentry);
-+      complete(&args->comp);
-+}
-diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
-new file mode 100644
-index 0000000..679a0df
---- /dev/null
-+++ b/fs/unionfs/sioq.h
-@@ -0,0 +1,91 @@
-+/*
-+ * Copyright (c) 2006-2008 Erez Zadok
-+ * Copyright (c) 2006      Charles P. Wright
-+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2006      Junjiro Okajima
-+ * Copyright (c) 2006      David P. Quigley
-+ * Copyright (c) 2006-2008 Stony Brook University
-+ * Copyright (c) 2006-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef _SIOQ_H
-+#define _SIOQ_H
-+
-+struct deletewh_args {
-+      struct unionfs_dir_state *namelist;
-+      struct dentry *dentry;
-+      int bindex;
-+};
-+
-+struct is_opaque_args {
-+      struct dentry *dentry;
-+};
-+
-+struct create_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+      umode_t mode;
-+      struct nameidata *nd;
-+};
-+
-+struct mkdir_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+      umode_t mode;
-+};
-+
-+struct mknod_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+      umode_t mode;
-+      dev_t dev;
-+};
-+
-+struct symlink_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+      char *symbuf;
-+};
-+
-+struct unlink_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+};
-+
-+
-+struct sioq_args {
-+      struct completion comp;
-+      struct work_struct work;
-+      int err;
-+      void *ret;
-+
-+      union {
-+              struct deletewh_args deletewh;
-+              struct is_opaque_args is_opaque;
-+              struct create_args create;
-+              struct mkdir_args mkdir;
-+              struct mknod_args mknod;
-+              struct symlink_args symlink;
-+              struct unlink_args unlink;
-+      };
-+};
-+
-+/* Extern definitions for SIOQ functions */
-+extern int __init init_sioq(void);
-+extern void stop_sioq(void);
-+extern void run_sioq(work_func_t func, struct sioq_args *args);
-+
-+/* Extern definitions for our privilege escalation helpers */
-+extern void __unionfs_create(struct work_struct *work);
-+extern void __unionfs_mkdir(struct work_struct *work);
-+extern void __unionfs_mknod(struct work_struct *work);
-+extern void __unionfs_symlink(struct work_struct *work);
-+extern void __unionfs_unlink(struct work_struct *work);
-+extern void __delete_whiteouts(struct work_struct *work);
-+extern void __is_opaque_dir(struct work_struct *work);
-+
-+#endif /* not _SIOQ_H */
-diff --git a/fs/unionfs/subr.c b/fs/unionfs/subr.c
-new file mode 100644
-index 0000000..8747d20
---- /dev/null
-+++ b/fs/unionfs/subr.c
-@@ -0,0 +1,95 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * returns the right n_link value based on the inode type
-+ */
-+int unionfs_get_nlinks(const struct inode *inode)
-+{
-+      /* don't bother to do all the work since we're unlinked */
-+      if (inode->i_nlink == 0)
-+              return 0;
-+
-+      if (!S_ISDIR(inode->i_mode))
-+              return unionfs_lower_inode(inode)->i_nlink;
-+
-+      /*
-+       * For directories, we return 1. The only place that could cares
-+       * about links is readdir, and there's d_type there so even that
-+       * doesn't matter.
-+       */
-+      return 1;
-+}
-+
-+/* copy a/m/ctime from the lower branch with the newest times */
-+void unionfs_copy_attr_times(struct inode *upper)
-+{
-+      int bindex;
-+      struct inode *lower;
-+
-+      if (!upper)
-+              return;
-+      if (ibstart(upper) < 0) {
-+#ifdef CONFIG_UNION_FS_DEBUG
-+              WARN_ON(ibstart(upper) < 0);
-+#endif /* CONFIG_UNION_FS_DEBUG */
-+              return;
-+      }
-+      for (bindex = ibstart(upper); bindex <= ibend(upper); bindex++) {
-+              lower = unionfs_lower_inode_idx(upper, bindex);
-+              if (!lower)
-+                      continue; /* not all lower dir objects may exist */
-+              if (unlikely(timespec_compare(&upper->i_mtime,
-+                                            &lower->i_mtime) < 0))
-+                      upper->i_mtime = lower->i_mtime;
-+              if (unlikely(timespec_compare(&upper->i_ctime,
-+                                            &lower->i_ctime) < 0))
-+                      upper->i_ctime = lower->i_ctime;
-+              if (unlikely(timespec_compare(&upper->i_atime,
-+                                            &lower->i_atime) < 0))
-+                      upper->i_atime = lower->i_atime;
-+      }
-+}
-+
-+/*
-+ * A unionfs/fanout version of fsstack_copy_attr_all.  Uses a
-+ * unionfs_get_nlinks to properly calcluate the number of links to a file.
-+ * Also, copies the max() of all a/m/ctimes for all lower inodes (which is
-+ * important if the lower inode is a directory type)
-+ */
-+void unionfs_copy_attr_all(struct inode *dest,
-+                         const struct inode *src)
-+{
-+      dest->i_mode = src->i_mode;
-+      dest->i_uid = src->i_uid;
-+      dest->i_gid = src->i_gid;
-+      dest->i_rdev = src->i_rdev;
-+
-+      unionfs_copy_attr_times(dest);
-+
-+      dest->i_blkbits = src->i_blkbits;
-+      dest->i_flags = src->i_flags;
-+
-+      /*
-+       * Update the nlinks AFTER updating the above fields, because the
-+       * get_links callback may depend on them.
-+       */
-+      dest->i_nlink = unionfs_get_nlinks(dest);
-+}
-diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
-new file mode 100644
-index 0000000..e774ef3
---- /dev/null
-+++ b/fs/unionfs/super.c
-@@ -0,0 +1,1042 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * The inode cache is used with alloc_inode for both our inode info and the
-+ * vfs inode.
-+ */
-+static struct kmem_cache *unionfs_inode_cachep;
-+
-+struct inode *unionfs_iget(struct super_block *sb, unsigned long ino)
-+{
-+      int size;
-+      struct unionfs_inode_info *info;
-+      struct inode *inode;
-+
-+      inode = iget_locked(sb, ino);
-+      if (!inode)
-+              return ERR_PTR(-ENOMEM);
-+      if (!(inode->i_state & I_NEW))
-+              return inode;
-+
-+      info = UNIONFS_I(inode);
-+      memset(info, 0, offsetof(struct unionfs_inode_info, vfs_inode));
-+      info->bstart = -1;
-+      info->bend = -1;
-+      atomic_set(&info->generation,
-+                 atomic_read(&UNIONFS_SB(inode->i_sb)->generation));
-+      spin_lock_init(&info->rdlock);
-+      info->rdcount = 1;
-+      info->hashsize = -1;
-+      INIT_LIST_HEAD(&info->readdircache);
-+
-+      size = sbmax(inode->i_sb) * sizeof(struct inode *);
-+      info->lower_inodes = kzalloc(size, GFP_KERNEL);
-+      if (unlikely(!info->lower_inodes)) {
-+              printk(KERN_CRIT "unionfs: no kernel memory when allocating "
-+                     "lower-pointer array!\n");
-+              iget_failed(inode);
-+              return ERR_PTR(-ENOMEM);
-+      }
-+
-+      inode->i_version++;
-+      inode->i_op = &unionfs_main_iops;
-+      inode->i_fop = &unionfs_main_fops;
-+
-+      inode->i_mapping->a_ops = &unionfs_aops;
-+
-+      /*
-+       * reset times so unionfs_copy_attr_all can keep out time invariants
-+       * right (upper inode time being the max of all lower ones).
-+       */
-+      inode->i_atime.tv_sec = inode->i_atime.tv_nsec = 0;
-+      inode->i_mtime.tv_sec = inode->i_mtime.tv_nsec = 0;
-+      inode->i_ctime.tv_sec = inode->i_ctime.tv_nsec = 0;
-+      unlock_new_inode(inode);
-+      return inode;
-+}
-+
-+/*
-+ * we now define delete_inode, because there are two VFS paths that may
-+ * destroy an inode: one of them calls clear inode before doing everything
-+ * else that's needed, and the other is fine.  This way we truncate the inode
-+ * size (and its pages) and then clear our own inode, which will do an iput
-+ * on our and the lower inode.
-+ *
-+ * No need to lock sb info's rwsem.
-+ */
-+static void unionfs_delete_inode(struct inode *inode)
-+{
-+#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
-+      spin_lock(&inode->i_lock);
-+#endif
-+      i_size_write(inode, 0); /* every f/s seems to do that */
-+#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
-+      spin_unlock(&inode->i_lock);
-+#endif
-+
-+      if (inode->i_data.nrpages)
-+              truncate_inode_pages(&inode->i_data, 0);
-+
-+      clear_inode(inode);
-+}
-+
-+/*
-+ * final actions when unmounting a file system
-+ *
-+ * No need to lock rwsem.
-+ */
-+static void unionfs_put_super(struct super_block *sb)
-+{
-+      int bindex, bstart, bend;
-+      struct unionfs_sb_info *spd;
-+      int leaks = 0;
-+
-+      spd = UNIONFS_SB(sb);
-+      if (!spd)
-+              return;
-+
-+      bstart = sbstart(sb);
-+      bend = sbend(sb);
-+
-+      /* Make sure we have no leaks of branchget/branchput. */
-+      for (bindex = bstart; bindex <= bend; bindex++)
-+              if (unlikely(branch_count(sb, bindex) != 0)) {
-+                      printk(KERN_CRIT
-+                             "unionfs: branch %d has %d references left!\n",
-+                             bindex, branch_count(sb, bindex));
-+                      leaks = 1;
-+              }
-+      BUG_ON(leaks != 0);
-+
-+      /* decrement lower super references */
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              struct super_block *s;
-+              s = unionfs_lower_super_idx(sb, bindex);
-+              unionfs_set_lower_super_idx(sb, bindex, NULL);
-+              atomic_dec(&s->s_active);
-+      }
-+
-+      kfree(spd->dev_name);
-+      kfree(spd->data);
-+      kfree(spd);
-+      sb->s_fs_info = NULL;
-+}
-+
-+/*
-+ * Since people use this to answer the "How big of a file can I write?"
-+ * question, we report the size of the highest priority branch as the size of
-+ * the union.
-+ */
-+static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-+{
-+      int err = 0;
-+      struct super_block *sb;
-+      struct dentry *lower_dentry;
-+
-+      sb = dentry->d_sb;
-+
-+      unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      unionfs_check_dentry(dentry);
-+
-+      lower_dentry = unionfs_lower_dentry(sb->s_root);
-+      err = vfs_statfs(lower_dentry, buf);
-+
-+      /* set return buf to our f/s to avoid confusing user-level utils */
-+      buf->f_type = UNIONFS_SUPER_MAGIC;
-+      /*
-+       * Our maximum file name can is shorter by a few bytes because every
-+       * file name could potentially be whited-out.
-+       *
-+       * XXX: this restriction goes away with ODF.
-+       */
-+      unionfs_set_max_namelen(&buf->f_namelen);
-+
-+      /*
-+       * reset two fields to avoid confusing user-land.
-+       * XXX: is this still necessary?
-+       */
-+      memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t));
-+      memset(&buf->f_spare, 0, sizeof(buf->f_spare));
-+
-+out:
-+      unionfs_check_dentry(dentry);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(sb);
-+      return err;
-+}
-+
-+/* handle mode changing during remount */
-+static noinline_for_stack int do_remount_mode_option(
-+                                      char *optarg,
-+                                      int cur_branches,
-+                                      struct unionfs_data *new_data,
-+                                      struct path *new_lower_paths)
-+{
-+      int err = -EINVAL;
-+      int perms, idx;
-+      char *modename = strchr(optarg, '=');
-+      struct nameidata nd;
-+
-+      /* by now, optarg contains the branch name */
-+      if (!*optarg) {
-+              printk(KERN_ERR
-+                     "unionfs: no branch specified for mode change\n");
-+              goto out;
-+      }
-+      if (!modename) {
-+              printk(KERN_ERR "unionfs: branch \"%s\" requires a mode\n",
-+                     optarg);
-+              goto out;
-+      }
-+      *modename++ = '\0';
-+      err = parse_branch_mode(modename, &perms);
-+      if (err) {
-+              printk(KERN_ERR "unionfs: invalid mode \"%s\" for \"%s\"\n",
-+                     modename, optarg);
-+              goto out;
-+      }
-+
-+      /*
-+       * Find matching branch index.  For now, this assumes that nothing
-+       * has been mounted on top of this Unionfs stack.  Once we have /odf
-+       * and cache-coherency resolved, we'll address the branch-path
-+       * uniqueness.
-+       */
-+      err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
-+      if (err) {
-+              printk(KERN_ERR "unionfs: error accessing "
-+                     "lower directory \"%s\" (error %d)\n",
-+                     optarg, err);
-+              goto out;
-+      }
-+      for (idx = 0; idx < cur_branches; idx++)
-+              if (nd.path.mnt == new_lower_paths[idx].mnt &&
-+                  nd.path.dentry == new_lower_paths[idx].dentry)
-+                      break;
-+      path_put(&nd.path);     /* no longer needed */
-+      if (idx == cur_branches) {
-+              err = -ENOENT;  /* err may have been reset above */
-+              printk(KERN_ERR "unionfs: branch \"%s\" "
-+                     "not found\n", optarg);
-+              goto out;
-+      }
-+      /* check/change mode for existing branch */
-+      /* we don't warn if perms==branchperms */
-+      new_data[idx].branchperms = perms;
-+      err = 0;
-+out:
-+      return err;
-+}
-+
-+/* handle branch deletion during remount */
-+static noinline_for_stack int do_remount_del_option(
-+                                      char *optarg, int cur_branches,
-+                                      struct unionfs_data *new_data,
-+                                      struct path *new_lower_paths)
-+{
-+      int err = -EINVAL;
-+      int idx;
-+      struct nameidata nd;
-+
-+      /* optarg contains the branch name to delete */
-+
-+      /*
-+       * Find matching branch index.  For now, this assumes that nothing
-+       * has been mounted on top of this Unionfs stack.  Once we have /odf
-+       * and cache-coherency resolved, we'll address the branch-path
-+       * uniqueness.
-+       */
-+      err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
-+      if (err) {
-+              printk(KERN_ERR "unionfs: error accessing "
-+                     "lower directory \"%s\" (error %d)\n",
-+                     optarg, err);
-+              goto out;
-+      }
-+      for (idx = 0; idx < cur_branches; idx++)
-+              if (nd.path.mnt == new_lower_paths[idx].mnt &&
-+                  nd.path.dentry == new_lower_paths[idx].dentry)
-+                      break;
-+      path_put(&nd.path);     /* no longer needed */
-+      if (idx == cur_branches) {
-+              printk(KERN_ERR "unionfs: branch \"%s\" "
-+                     "not found\n", optarg);
-+              err = -ENOENT;
-+              goto out;
-+      }
-+      /* check if there are any open files on the branch to be deleted */
-+      if (atomic_read(&new_data[idx].open_files) > 0) {
-+              err = -EBUSY;
-+              goto out;
-+      }
-+
-+      /*
-+       * Now we have to delete the branch.  First, release any handles it
-+       * has.  Then, move the remaining array indexes past "idx" in
-+       * new_data and new_lower_paths one to the left.  Finally, adjust
-+       * cur_branches.
-+       */
-+      path_put(&new_lower_paths[idx]);
-+
-+      if (idx < cur_branches - 1) {
-+              /* if idx==cur_branches-1, we delete last branch: easy */
-+              memmove(&new_data[idx], &new_data[idx+1],
-+                      (cur_branches - 1 - idx) *
-+                      sizeof(struct unionfs_data));
-+              memmove(&new_lower_paths[idx], &new_lower_paths[idx+1],
-+                      (cur_branches - 1 - idx) * sizeof(struct path));
-+      }
-+
-+      err = 0;
-+out:
-+      return err;
-+}
-+
-+/* handle branch insertion during remount */
-+static noinline_for_stack int do_remount_add_option(
-+                                      char *optarg, int cur_branches,
-+                                      struct unionfs_data *new_data,
-+                                      struct path *new_lower_paths,
-+                                      int *high_branch_id)
-+{
-+      int err = -EINVAL;
-+      int perms;
-+      int idx = 0;            /* default: insert at beginning */
-+      char *new_branch , *modename = NULL;
-+      struct nameidata nd;
-+
-+      /*
-+       * optarg can be of several forms:
-+       *
-+       * /bar:/foo            insert /foo before /bar
-+       * /bar:/foo=ro         insert /foo in ro mode before /bar
-+       * /foo                 insert /foo in the beginning (prepend)
-+       * :/foo                insert /foo at the end (append)
-+       */
-+      if (*optarg == ':') {   /* append? */
-+              new_branch = optarg + 1; /* skip ':' */
-+              idx = cur_branches;
-+              goto found_insertion_point;
-+      }
-+      new_branch = strchr(optarg, ':');
-+      if (!new_branch) {      /* prepend? */
-+              new_branch = optarg;
-+              goto found_insertion_point;
-+      }
-+      *new_branch++ = '\0';   /* holds path+mode of new branch */
-+
-+      /*
-+       * Find matching branch index.  For now, this assumes that nothing
-+       * has been mounted on top of this Unionfs stack.  Once we have /odf
-+       * and cache-coherency resolved, we'll address the branch-path
-+       * uniqueness.
-+       */
-+      err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
-+      if (err) {
-+              printk(KERN_ERR "unionfs: error accessing "
-+                     "lower directory \"%s\" (error %d)\n",
-+                     optarg, err);
-+              goto out;
-+      }
-+      for (idx = 0; idx < cur_branches; idx++)
-+              if (nd.path.mnt == new_lower_paths[idx].mnt &&
-+                  nd.path.dentry == new_lower_paths[idx].dentry)
-+                      break;
-+      path_put(&nd.path);     /* no longer needed */
-+      if (idx == cur_branches) {
-+              printk(KERN_ERR "unionfs: branch \"%s\" "
-+                     "not found\n", optarg);
-+              err = -ENOENT;
-+              goto out;
-+      }
-+
-+      /*
-+       * At this point idx will hold the index where the new branch should
-+       * be inserted before.
-+       */
-+found_insertion_point:
-+      /* find the mode for the new branch */
-+      if (new_branch)
-+              modename = strchr(new_branch, '=');
-+      if (modename)
-+              *modename++ = '\0';
-+      if (!new_branch || !*new_branch) {
-+              printk(KERN_ERR "unionfs: null new branch\n");
-+              err = -EINVAL;
-+              goto out;
-+      }
-+      err = parse_branch_mode(modename, &perms);
-+      if (err) {
-+              printk(KERN_ERR "unionfs: invalid mode \"%s\" for "
-+                     "branch \"%s\"\n", modename, new_branch);
-+              goto out;
-+      }
-+      err = path_lookup(new_branch, LOOKUP_FOLLOW, &nd);
-+      if (err) {
-+              printk(KERN_ERR "unionfs: error accessing "
-+                     "lower directory \"%s\" (error %d)\n",
-+                     new_branch, err);
-+              goto out;
-+      }
-+      /*
-+       * It's probably safe to check_mode the new branch to insert.  Note:
-+       * we don't allow inserting branches which are unionfs's by
-+       * themselves (check_branch returns EINVAL in that case).  This is
-+       * because this code base doesn't support stacking unionfs: the ODF
-+       * code base supports that correctly.
-+       */
-+      err = check_branch(&nd);
-+      if (err) {
-+              printk(KERN_ERR "unionfs: lower directory "
-+                     "\"%s\" is not a valid branch\n", optarg);
-+              path_put(&nd.path);
-+              goto out;
-+      }
-+
-+      /*
-+       * Now we have to insert the new branch.  But first, move the bits
-+       * to make space for the new branch, if needed.  Finally, adjust
-+       * cur_branches.
-+       * We don't release nd here; it's kept until umount/remount.
-+       */
-+      if (idx < cur_branches) {
-+              /* if idx==cur_branches, we append: easy */
-+              memmove(&new_data[idx+1], &new_data[idx],
-+                      (cur_branches - idx) * sizeof(struct unionfs_data));
-+              memmove(&new_lower_paths[idx+1], &new_lower_paths[idx],
-+                      (cur_branches - idx) * sizeof(struct path));
-+      }
-+      new_lower_paths[idx].dentry = nd.path.dentry;
-+      new_lower_paths[idx].mnt = nd.path.mnt;
-+
-+      new_data[idx].sb = nd.path.dentry->d_sb;
-+      atomic_set(&new_data[idx].open_files, 0);
-+      new_data[idx].branchperms = perms;
-+      new_data[idx].branch_id = ++*high_branch_id; /* assign new branch ID */
-+
-+      err = 0;
-+out:
-+      return err;
-+}
-+
-+
-+/*
-+ * Support branch management options on remount.
-+ *
-+ * See Documentation/filesystems/unionfs/ for details.
-+ *
-+ * @flags: numeric mount options
-+ * @options: mount options string
-+ *
-+ * This function can rearrange a mounted union dynamically, adding and
-+ * removing branches, including changing branch modes.  Clearly this has to
-+ * be done safely and atomically.  Luckily, the VFS already calls this
-+ * function with lock_super(sb) and lock_kernel() held, preventing
-+ * concurrent mixing of new mounts, remounts, and unmounts.  Moreover,
-+ * do_remount_sb(), our caller function, already called shrink_dcache_sb(sb)
-+ * to purge dentries/inodes from our superblock, and also called
-+ * fsync_super(sb) to purge any dirty pages.  So we're good.
-+ *
-+ * XXX: however, our remount code may also need to invalidate mapped pages
-+ * so as to force them to be re-gotten from the (newly reconfigured) lower
-+ * branches.  This has to wait for proper mmap and cache coherency support
-+ * in the VFS.
-+ *
-+ */
-+static int unionfs_remount_fs(struct super_block *sb, int *flags,
-+                            char *options)
-+{
-+      int err = 0;
-+      int i;
-+      char *optionstmp, *tmp_to_free; /* kstrdup'ed of "options" */
-+      char *optname;
-+      int cur_branches = 0;   /* no. of current branches */
-+      int new_branches = 0;   /* no. of branches actually left in the end */
-+      int add_branches;       /* est. no. of branches to add */
-+      int del_branches;       /* est. no. of branches to del */
-+      int max_branches;       /* max possible no. of branches */
-+      struct unionfs_data *new_data = NULL, *tmp_data = NULL;
-+      struct path *new_lower_paths = NULL, *tmp_lower_paths = NULL;
-+      struct inode **new_lower_inodes = NULL;
-+      int new_high_branch_id; /* new high branch ID */
-+      int size;               /* memory allocation size, temp var */
-+      int old_ibstart, old_ibend;
-+
-+      unionfs_write_lock(sb);
-+
-+      /*
-+       * The VFS will take care of "ro" and "rw" flags, and we can safely
-+       * ignore MS_SILENT, but anything else left over is an error.  So we
-+       * need to check if any other flags may have been passed (none are
-+       * allowed/supported as of now).
-+       */
-+      if ((*flags & ~(MS_RDONLY | MS_SILENT)) != 0) {
-+              printk(KERN_ERR
-+                     "unionfs: remount flags 0x%x unsupported\n", *flags);
-+              err = -EINVAL;
-+              goto out_error;
-+      }
-+
-+      /*
-+       * If 'options' is NULL, it's probably because the user just changed
-+       * the union to a "ro" or "rw" and the VFS took care of it.  So
-+       * nothing to do and we're done.
-+       */
-+      if (!options || options[0] == '\0')
-+              goto out_error;
-+
-+      /*
-+       * Find out how many branches we will have in the end, counting
-+       * "add" and "del" commands.  Copy the "options" string because
-+       * strsep modifies the string and we need it later.
-+       */
-+      tmp_to_free = kstrdup(options, GFP_KERNEL);
-+      optionstmp = tmp_to_free;
-+      if (unlikely(!optionstmp)) {
-+              err = -ENOMEM;
-+              goto out_free;
-+      }
-+      cur_branches = sbmax(sb); /* current no. branches */
-+      new_branches = sbmax(sb);
-+      del_branches = 0;
-+      add_branches = 0;
-+      new_high_branch_id = sbhbid(sb); /* save current high_branch_id */
-+      while ((optname = strsep(&optionstmp, ",")) != NULL) {
-+              char *optarg;
-+
-+              if (!optname || !*optname)
-+                      continue;
-+
-+              optarg = strchr(optname, '=');
-+              if (optarg)
-+                      *optarg++ = '\0';
-+
-+              if (!strcmp("add", optname))
-+                      add_branches++;
-+              else if (!strcmp("del", optname))
-+                      del_branches++;
-+      }
-+      kfree(tmp_to_free);
-+      /* after all changes, will we have at least one branch left? */
-+      if ((new_branches + add_branches - del_branches) < 1) {
-+              printk(KERN_ERR
-+                     "unionfs: no branches left after remount\n");
-+              err = -EINVAL;
-+              goto out_free;
-+      }
-+
-+      /*
-+       * Since we haven't actually parsed all the add/del options, nor
-+       * have we checked them for errors, we don't know for sure how many
-+       * branches we will have after all changes have taken place.  In
-+       * fact, the total number of branches left could be less than what
-+       * we have now.  So we need to allocate space for a temporary
-+       * placeholder that is at least as large as the maximum number of
-+       * branches we *could* have, which is the current number plus all
-+       * the additions.  Once we're done with these temp placeholders, we
-+       * may have to re-allocate the final size, copy over from the temp,
-+       * and then free the temps (done near the end of this function).
-+       */
-+      max_branches = cur_branches + add_branches;
-+      /* allocate space for new pointers to lower dentry */
-+      tmp_data = kcalloc(max_branches,
-+                         sizeof(struct unionfs_data), GFP_KERNEL);
-+      if (unlikely(!tmp_data)) {
-+              err = -ENOMEM;
-+              goto out_free;
-+      }
-+      /* allocate space for new pointers to lower paths */
-+      tmp_lower_paths = kcalloc(max_branches,
-+                                sizeof(struct path), GFP_KERNEL);
-+      if (unlikely(!tmp_lower_paths)) {
-+              err = -ENOMEM;
-+              goto out_free;
-+      }
-+      /* copy current info into new placeholders, incrementing refcnts */
-+      memcpy(tmp_data, UNIONFS_SB(sb)->data,
-+             cur_branches * sizeof(struct unionfs_data));
-+      memcpy(tmp_lower_paths, UNIONFS_D(sb->s_root)->lower_paths,
-+             cur_branches * sizeof(struct path));
-+      for (i = 0; i < cur_branches; i++)
-+              path_get(&tmp_lower_paths[i]); /* drop refs at end of fxn */
-+
-+      /*******************************************************************
-+       * For each branch command, do path_lookup on the requested branch,
-+       * and apply the change to a temp branch list.  To handle errors, we
-+       * already dup'ed the old arrays (above), and increased the refcnts
-+       * on various f/s objects.  So now we can do all the path_lookups
-+       * and branch-management commands on the new arrays.  If it fail mid
-+       * way, we free the tmp arrays and *put all objects.  If we succeed,
-+       * then we free old arrays and *put its objects, and then replace
-+       * the arrays with the new tmp list (we may have to re-allocate the
-+       * memory because the temp lists could have been larger than what we
-+       * actually needed).
-+       *******************************************************************/
-+
-+      while ((optname = strsep(&options, ",")) != NULL) {
-+              char *optarg;
-+
-+              if (!optname || !*optname)
-+                      continue;
-+              /*
-+               * At this stage optname holds a comma-delimited option, but
-+               * without the commas.  Next, we need to break the string on
-+               * the '=' symbol to separate CMD=ARG, where ARG itself can
-+               * be KEY=VAL.  For example, in mode=/foo=rw, CMD is "mode",
-+               * KEY is "/foo", and VAL is "rw".
-+               */
-+              optarg = strchr(optname, '=');
-+              if (optarg)
-+                      *optarg++ = '\0';
-+              /* incgen remount option (instead of old ioctl) */
-+              if (!strcmp("incgen", optname)) {
-+                      err = 0;
-+                      goto out_no_change;
-+              }
-+
-+              /*
-+               * All of our options take an argument now.  (Insert ones
-+               * that don't above this check.)  So at this stage optname
-+               * contains the CMD part and optarg contains the ARG part.
-+               */
-+              if (!optarg || !*optarg) {
-+                      printk(KERN_ERR "unionfs: all remount options require "
-+                             "an argument (%s)\n", optname);
-+                      err = -EINVAL;
-+                      goto out_release;
-+              }
-+
-+              if (!strcmp("add", optname)) {
-+                      err = do_remount_add_option(optarg, new_branches,
-+                                                  tmp_data,
-+                                                  tmp_lower_paths,
-+                                                  &new_high_branch_id);
-+                      if (err)
-+                              goto out_release;
-+                      new_branches++;
-+                      if (new_branches > UNIONFS_MAX_BRANCHES) {
-+                              printk(KERN_ERR "unionfs: command exceeds "
-+                                     "%d branches\n", UNIONFS_MAX_BRANCHES);
-+                              err = -E2BIG;
-+                              goto out_release;
-+                      }
-+                      continue;
-+              }
-+              if (!strcmp("del", optname)) {
-+                      err = do_remount_del_option(optarg, new_branches,
-+                                                  tmp_data,
-+                                                  tmp_lower_paths);
-+                      if (err)
-+                              goto out_release;
-+                      new_branches--;
-+                      continue;
-+              }
-+              if (!strcmp("mode", optname)) {
-+                      err = do_remount_mode_option(optarg, new_branches,
-+                                                   tmp_data,
-+                                                   tmp_lower_paths);
-+                      if (err)
-+                              goto out_release;
-+                      continue;
-+              }
-+
-+              /*
-+               * When you use "mount -o remount,ro", mount(8) will
-+               * reportedly pass the original dirs= string from
-+               * /proc/mounts.  So for now, we have to ignore dirs= and
-+               * not consider it an error, unless we want to allow users
-+               * to pass dirs= in remount.  Note that to allow the VFS to
-+               * actually process the ro/rw remount options, we have to
-+               * return 0 from this function.
-+               */
-+              if (!strcmp("dirs", optname)) {
-+                      printk(KERN_WARNING
-+                             "unionfs: remount ignoring option \"%s\"\n",
-+                             optname);
-+                      continue;
-+              }
-+
-+              err = -EINVAL;
-+              printk(KERN_ERR
-+                     "unionfs: unrecognized option \"%s\"\n", optname);
-+              goto out_release;
-+      }
-+
-+out_no_change:
-+
-+      /******************************************************************
-+       * WE'RE ALMOST DONE: check if leftmost branch might be read-only,
-+       * see if we need to allocate a small-sized new vector, copy the
-+       * vectors to their correct place, release the refcnt of the older
-+       * ones, and return.  Also handle invalidating any pages that will
-+       * have to be re-read.
-+       *******************************************************************/
-+
-+      if (!(tmp_data[0].branchperms & MAY_WRITE)) {
-+              printk(KERN_ERR "unionfs: leftmost branch cannot be read-only "
-+                     "(use \"remount,ro\" to create a read-only union)\n");
-+              err = -EINVAL;
-+              goto out_release;
-+      }
-+
-+      /* (re)allocate space for new pointers to lower dentry */
-+      size = new_branches * sizeof(struct unionfs_data);
-+      new_data = krealloc(tmp_data, size, GFP_KERNEL);
-+      if (unlikely(!new_data)) {
-+              err = -ENOMEM;
-+              goto out_release;
-+      }
-+
-+      /* allocate space for new pointers to lower paths */
-+      size = new_branches * sizeof(struct path);
-+      new_lower_paths = krealloc(tmp_lower_paths, size, GFP_KERNEL);
-+      if (unlikely(!new_lower_paths)) {
-+              err = -ENOMEM;
-+              goto out_release;
-+      }
-+
-+      /* allocate space for new pointers to lower inodes */
-+      new_lower_inodes = kcalloc(new_branches,
-+                                 sizeof(struct inode *), GFP_KERNEL);
-+      if (unlikely(!new_lower_inodes)) {
-+              err = -ENOMEM;
-+              goto out_release;
-+      }
-+
-+      /*
-+       * OK, just before we actually put the new set of branches in place,
-+       * we need to ensure that our own f/s has no dirty objects left.
-+       * Luckily, do_remount_sb() already calls shrink_dcache_sb(sb) and
-+       * fsync_super(sb), taking care of dentries, inodes, and dirty
-+       * pages.  So all that's left is for us to invalidate any leftover
-+       * (non-dirty) pages to ensure that they will be re-read from the
-+       * new lower branches (and to support mmap).
-+       */
-+
-+      /*
-+       * Once we finish the remounting successfully, our superblock
-+       * generation number will have increased.  This will be detected by
-+       * our dentry-revalidation code upon subsequent f/s operations
-+       * through unionfs.  The revalidation code will rebuild the union of
-+       * lower inodes for a given unionfs inode and invalidate any pages
-+       * of such "stale" inodes (by calling our purge_inode_data
-+       * function).  This revalidation will happen lazily and
-+       * incrementally, as users perform operations on cached inodes.  We
-+       * would like to encourage this revalidation to happen sooner if
-+       * possible, so we like to try to invalidate as many other pages in
-+       * our superblock as we can.  We used to call drop_pagecache_sb() or
-+       * a variant thereof, but either method was racy (drop_caches alone
-+       * is known to be racy).  So now we let the revalidation happen on a
-+       * per file basis in ->d_revalidate.
-+       */
-+
-+      /* grab new lower super references; release old ones */
-+      for (i = 0; i < new_branches; i++)
-+              atomic_inc(&new_data[i].sb->s_active);
-+      for (i = 0; i < sbmax(sb); i++)
-+              atomic_dec(&UNIONFS_SB(sb)->data[i].sb->s_active);
-+
-+      /* copy new vectors into their correct place */
-+      tmp_data = UNIONFS_SB(sb)->data;
-+      UNIONFS_SB(sb)->data = new_data;
-+      new_data = NULL;        /* so don't free good pointers below */
-+      tmp_lower_paths = UNIONFS_D(sb->s_root)->lower_paths;
-+      UNIONFS_D(sb->s_root)->lower_paths = new_lower_paths;
-+      new_lower_paths = NULL; /* so don't free good pointers below */
-+
-+      /* update our unionfs_sb_info and root dentry index of last branch */
-+      i = sbmax(sb);          /* save no. of branches to release at end */
-+      sbend(sb) = new_branches - 1;
-+      dbend(sb->s_root) = new_branches - 1;
-+      old_ibstart = ibstart(sb->s_root->d_inode);
-+      old_ibend = ibend(sb->s_root->d_inode);
-+      ibend(sb->s_root->d_inode) = new_branches - 1;
-+      UNIONFS_D(sb->s_root)->bcount = new_branches;
-+      new_branches = i; /* no. of branches to release below */
-+
-+      /*
-+       * Update lower inodes: 3 steps
-+       * 1. grab ref on all new lower inodes
-+       */
-+      for (i = dbstart(sb->s_root); i <= dbend(sb->s_root); i++) {
-+              struct dentry *lower_dentry =
-+                      unionfs_lower_dentry_idx(sb->s_root, i);
-+              igrab(lower_dentry->d_inode);
-+              new_lower_inodes[i] = lower_dentry->d_inode;
-+      }
-+      /* 2. release reference on all older lower inodes */
-+      iput_lowers(sb->s_root->d_inode, old_ibstart, old_ibend, true);
-+      /* 3. update root dentry's inode to new lower_inodes array */
-+      UNIONFS_I(sb->s_root->d_inode)->lower_inodes = new_lower_inodes;
-+      new_lower_inodes = NULL;
-+
-+      /* maxbytes may have changed */
-+      sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
-+      /* update high branch ID */
-+      sbhbid(sb) = new_high_branch_id;
-+
-+      /* update our sb->generation for revalidating objects */
-+      i = atomic_inc_return(&UNIONFS_SB(sb)->generation);
-+      atomic_set(&UNIONFS_D(sb->s_root)->generation, i);
-+      atomic_set(&UNIONFS_I(sb->s_root->d_inode)->generation, i);
-+      if (!(*flags & MS_SILENT))
-+              pr_info("unionfs: %s: new generation number %d\n",
-+                      UNIONFS_SB(sb)->dev_name, i);
-+      /* finally, update the root dentry's times */
-+      unionfs_copy_attr_times(sb->s_root->d_inode);
-+      err = 0;                /* reset to success */
-+
-+      /*
-+       * The code above falls through to the next label, and releases the
-+       * refcnts of the older ones (stored in tmp_*): if we fell through
-+       * here, it means success.  However, if we jump directly to this
-+       * label from any error above, then an error occurred after we
-+       * grabbed various refcnts, and so we have to release the
-+       * temporarily constructed structures.
-+       */
-+out_release:
-+      /* no need to cleanup/release anything in tmp_data */
-+      if (tmp_lower_paths)
-+              for (i = 0; i < new_branches; i++)
-+                      path_put(&tmp_lower_paths[i]);
-+out_free:
-+      kfree(tmp_lower_paths);
-+      kfree(tmp_data);
-+      kfree(new_lower_paths);
-+      kfree(new_data);
-+      kfree(new_lower_inodes);
-+out_error:
-+      unionfs_check_dentry(sb->s_root);
-+      unionfs_write_unlock(sb);
-+      return err;
-+}
-+
-+/*
-+ * Called by iput() when the inode reference count reached zero
-+ * and the inode is not hashed anywhere.  Used to clear anything
-+ * that needs to be, before the inode is completely destroyed and put
-+ * on the inode free list.
-+ *
-+ * No need to lock sb info's rwsem.
-+ */
-+static void unionfs_clear_inode(struct inode *inode)
-+{
-+      int bindex, bstart, bend;
-+      struct inode *lower_inode;
-+      struct list_head *pos, *n;
-+      struct unionfs_dir_state *rdstate;
-+
-+      list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
-+              rdstate = list_entry(pos, struct unionfs_dir_state, cache);
-+              list_del(&rdstate->cache);
-+              free_rdstate(rdstate);
-+      }
-+
-+      /*
-+       * Decrement a reference to a lower_inode, which was incremented
-+       * by our read_inode when it was created initially.
-+       */
-+      bstart = ibstart(inode);
-+      bend = ibend(inode);
-+      if (bstart >= 0) {
-+              for (bindex = bstart; bindex <= bend; bindex++) {
-+                      lower_inode = unionfs_lower_inode_idx(inode, bindex);
-+                      if (!lower_inode)
-+                              continue;
-+                      unionfs_set_lower_inode_idx(inode, bindex, NULL);
-+                      /* see Documentation/filesystems/unionfs/issues.txt */
-+                      lockdep_off();
-+                      iput(lower_inode);
-+                      lockdep_on();
-+              }
-+      }
-+
-+      kfree(UNIONFS_I(inode)->lower_inodes);
-+      UNIONFS_I(inode)->lower_inodes = NULL;
-+}
-+
-+static struct inode *unionfs_alloc_inode(struct super_block *sb)
-+{
-+      struct unionfs_inode_info *i;
-+
-+      i = kmem_cache_alloc(unionfs_inode_cachep, GFP_KERNEL);
-+      if (unlikely(!i))
-+              return NULL;
-+
-+      /* memset everything up to the inode to 0 */
-+      memset(i, 0, offsetof(struct unionfs_inode_info, vfs_inode));
-+
-+      i->vfs_inode.i_version = 1;
-+      return &i->vfs_inode;
-+}
-+
-+static void unionfs_destroy_inode(struct inode *inode)
-+{
-+      kmem_cache_free(unionfs_inode_cachep, UNIONFS_I(inode));
-+}
-+
-+/* unionfs inode cache constructor */
-+static void init_once(void *obj)
-+{
-+      struct unionfs_inode_info *i = obj;
-+
-+      inode_init_once(&i->vfs_inode);
-+}
-+
-+int unionfs_init_inode_cache(void)
-+{
-+      int err = 0;
-+
-+      unionfs_inode_cachep =
-+              kmem_cache_create("unionfs_inode_cache",
-+                                sizeof(struct unionfs_inode_info), 0,
-+                                SLAB_RECLAIM_ACCOUNT, init_once);
-+      if (unlikely(!unionfs_inode_cachep))
-+              err = -ENOMEM;
-+      return err;
-+}
-+
-+/* unionfs inode cache destructor */
-+void unionfs_destroy_inode_cache(void)
-+{
-+      if (unionfs_inode_cachep)
-+              kmem_cache_destroy(unionfs_inode_cachep);
-+}
-+
-+/*
-+ * Called when we have a dirty inode, right here we only throw out
-+ * parts of our readdir list that are too old.
-+ *
-+ * No need to grab sb info's rwsem.
-+ */
-+static int unionfs_write_inode(struct inode *inode, int sync)
-+{
-+      struct list_head *pos, *n;
-+      struct unionfs_dir_state *rdstate;
-+
-+      spin_lock(&UNIONFS_I(inode)->rdlock);
-+      list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
-+              rdstate = list_entry(pos, struct unionfs_dir_state, cache);
-+              /* We keep this list in LRU order. */
-+              if ((rdstate->access + RDCACHE_JIFFIES) > jiffies)
-+                      break;
-+              UNIONFS_I(inode)->rdcount--;
-+              list_del(&rdstate->cache);
-+              free_rdstate(rdstate);
-+      }
-+      spin_unlock(&UNIONFS_I(inode)->rdlock);
-+
-+      return 0;
-+}
-+
-+/*
-+ * Used only in nfs, to kill any pending RPC tasks, so that subsequent
-+ * code can actually succeed and won't leave tasks that need handling.
-+ */
-+static void unionfs_umount_begin(struct super_block *sb)
-+{
-+      struct super_block *lower_sb;
-+      int bindex, bstart, bend;
-+
-+      unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
-+
-+      bstart = sbstart(sb);
-+      bend = sbend(sb);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_sb = unionfs_lower_super_idx(sb, bindex);
-+
-+              if (lower_sb && lower_sb->s_op &&
-+                  lower_sb->s_op->umount_begin)
-+                      lower_sb->s_op->umount_begin(lower_sb);
-+      }
-+
-+      unionfs_read_unlock(sb);
-+}
-+
-+static int unionfs_show_options(struct seq_file *m, struct vfsmount *mnt)
-+{
-+      struct super_block *sb = mnt->mnt_sb;
-+      int ret = 0;
-+      char *tmp_page;
-+      char *path;
-+      int bindex, bstart, bend;
-+      int perms;
-+
-+      unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
-+
-+      unionfs_lock_dentry(sb->s_root, UNIONFS_DMUTEX_CHILD);
-+
-+      tmp_page = (char *) __get_free_page(GFP_KERNEL);
-+      if (unlikely(!tmp_page)) {
-+              ret = -ENOMEM;
-+              goto out;
-+      }
-+
-+      bstart = sbstart(sb);
-+      bend = sbend(sb);
-+
-+      seq_printf(m, ",dirs=");
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              struct path p;
-+              p.dentry = unionfs_lower_dentry_idx(sb->s_root, bindex);
-+              p.mnt = unionfs_lower_mnt_idx(sb->s_root, bindex);
-+              path = d_path(&p, tmp_page, PAGE_SIZE);
-+              if (IS_ERR(path)) {
-+                      ret = PTR_ERR(path);
-+                      goto out;
-+              }
-+
-+              perms = branchperms(sb, bindex);
-+
-+              seq_printf(m, "%s=%s", path,
-+                         perms & MAY_WRITE ? "rw" : "ro");
-+              if (bindex != bend)
-+                      seq_printf(m, ":");
-+      }
-+
-+out:
-+      free_page((unsigned long) tmp_page);
-+
-+      unionfs_unlock_dentry(sb->s_root);
-+
-+      unionfs_read_unlock(sb);
-+
-+      return ret;
-+}
-+
-+struct super_operations unionfs_sops = {
-+      .delete_inode   = unionfs_delete_inode,
-+      .put_super      = unionfs_put_super,
-+      .statfs         = unionfs_statfs,
-+      .remount_fs     = unionfs_remount_fs,
-+      .clear_inode    = unionfs_clear_inode,
-+      .umount_begin   = unionfs_umount_begin,
-+      .show_options   = unionfs_show_options,
-+      .write_inode    = unionfs_write_inode,
-+      .alloc_inode    = unionfs_alloc_inode,
-+      .destroy_inode  = unionfs_destroy_inode,
-+};
-diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
-new file mode 100644
-index 0000000..1b9c3f7
---- /dev/null
-+++ b/fs/unionfs/union.h
-@@ -0,0 +1,607 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef _UNION_H_
-+#define _UNION_H_
-+
-+#include <linux/dcache.h>
-+#include <linux/file.h>
-+#include <linux/list.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/mount.h>
-+#include <linux/namei.h>
-+#include <linux/page-flags.h>
-+#include <linux/pagemap.h>
-+#include <linux/poll.h>
-+#include <linux/security.h>
-+#include <linux/seq_file.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/statfs.h>
-+#include <linux/string.h>
-+#include <linux/vmalloc.h>
-+#include <linux/writeback.h>
-+#include <linux/buffer_head.h>
-+#include <linux/xattr.h>
-+#include <linux/fs_stack.h>
-+#include <linux/magic.h>
-+#include <linux/log2.h>
-+#include <linux/poison.h>
-+#include <linux/mman.h>
-+#include <linux/backing-dev.h>
-+#include <linux/splice.h>
-+
-+#include <asm/system.h>
-+
-+#include <linux/union_fs.h>
-+
-+/* the file system name */
-+#define UNIONFS_NAME "unionfs"
-+
-+/* unionfs root inode number */
-+#define UNIONFS_ROOT_INO     1
-+
-+/* number of times we try to get a unique temporary file name */
-+#define GET_TMPNAM_MAX_RETRY  5
-+
-+/* maximum number of branches we support, to avoid memory blowup */
-+#define UNIONFS_MAX_BRANCHES  128
-+
-+/* minimum time (seconds) required for time-based cache-coherency */
-+#define UNIONFS_MIN_CC_TIME   3
-+
-+/* Operations vectors defined in specific files. */
-+extern struct file_operations unionfs_main_fops;
-+extern struct file_operations unionfs_dir_fops;
-+extern struct inode_operations unionfs_main_iops;
-+extern struct inode_operations unionfs_dir_iops;
-+extern struct inode_operations unionfs_symlink_iops;
-+extern struct super_operations unionfs_sops;
-+extern struct dentry_operations unionfs_dops;
-+extern struct address_space_operations unionfs_aops, unionfs_dummy_aops;
-+extern struct vm_operations_struct unionfs_vm_ops;
-+
-+/* How long should an entry be allowed to persist */
-+#define RDCACHE_JIFFIES       (5*HZ)
-+
-+/* compatibility with Real-Time patches */
-+#ifdef CONFIG_PREEMPT_RT
-+# define unionfs_rw_semaphore compat_rw_semaphore
-+#else /* not CONFIG_PREEMPT_RT */
-+# define unionfs_rw_semaphore rw_semaphore
-+#endif /* not CONFIG_PREEMPT_RT */
-+
-+/* file private data. */
-+struct unionfs_file_info {
-+      int bstart;
-+      int bend;
-+      atomic_t generation;
-+
-+      struct unionfs_dir_state *rdstate;
-+      struct file **lower_files;
-+      int *saved_branch_ids; /* IDs of branches when file was opened */
-+      struct vm_operations_struct *lower_vm_ops;
-+      bool wrote_to_file;     /* for delayed copyup */
-+};
-+
-+/* unionfs inode data in memory */
-+struct unionfs_inode_info {
-+      int bstart;
-+      int bend;
-+      atomic_t generation;
-+      /* Stuff for readdir over NFS. */
-+      spinlock_t rdlock;
-+      struct list_head readdircache;
-+      int rdcount;
-+      int hashsize;
-+      int cookie;
-+
-+      /* The lower inodes */
-+      struct inode **lower_inodes;
-+
-+      struct inode vfs_inode;
-+};
-+
-+/* unionfs dentry data in memory */
-+struct unionfs_dentry_info {
-+      /*
-+       * The semaphore is used to lock the dentry as soon as we get into a
-+       * unionfs function from the VFS.  Our lock ordering is that children
-+       * go before their parents.
-+       */
-+      struct mutex lock;
-+      int bstart;
-+      int bend;
-+      int bopaque;
-+      int bcount;
-+      atomic_t generation;
-+      struct path *lower_paths;
-+};
-+
-+/* These are the pointers to our various objects. */
-+struct unionfs_data {
-+      struct super_block *sb; /* lower super_block */
-+      atomic_t open_files;    /* number of open files on branch */
-+      int branchperms;
-+      int branch_id;          /* unique branch ID at re/mount time */
-+};
-+
-+/* unionfs super-block data in memory */
-+struct unionfs_sb_info {
-+      int bend;
-+
-+      atomic_t generation;
-+
-+      /*
-+       * This rwsem is used to make sure that a branch management
-+       * operation...
-+       *   1) will not begin before all currently in-flight operations
-+       *      complete.
-+       *   2) any new operations do not execute until the currently
-+       *      running branch management operation completes.
-+       *
-+       * The write_lock_owner records the PID of the task which grabbed
-+       * the rw_sem for writing.  If the same task also tries to grab the
-+       * read lock, we allow it.  This prevents a self-deadlock when
-+       * branch-management is used on a pivot_root'ed union, because we
-+       * have to ->lookup paths which belong to the same union.
-+       */
-+      struct unionfs_rw_semaphore rwsem;
-+      pid_t write_lock_owner; /* PID of rw_sem owner (write lock) */
-+      int high_branch_id;     /* last unique branch ID given */
-+      char *dev_name;         /* to identify different unions in pr_debug */
-+      struct unionfs_data *data;
-+};
-+
-+/*
-+ * structure for making the linked list of entries by readdir on left branch
-+ * to compare with entries on right branch
-+ */
-+struct filldir_node {
-+      struct list_head file_list;     /* list for directory entries */
-+      char *name;             /* name entry */
-+      int hash;               /* name hash */
-+      int namelen;            /* name len since name is not 0 terminated */
-+
-+      /*
-+       * we can check for duplicate whiteouts and files in the same branch
-+       * in order to return -EIO.
-+       */
-+      int bindex;
-+
-+      /* is this a whiteout entry? */
-+      int whiteout;
-+
-+      /* Inline name, so we don't need to separately kmalloc small ones */
-+      char iname[DNAME_INLINE_LEN_MIN];
-+};
-+
-+/* Directory hash table. */
-+struct unionfs_dir_state {
-+      unsigned int cookie;    /* the cookie, based off of rdversion */
-+      unsigned int offset;    /* The entry we have returned. */
-+      int bindex;
-+      loff_t dirpos;          /* offset within the lower level directory */
-+      int size;               /* How big is the hash table? */
-+      int hashentries;        /* How many entries have been inserted? */
-+      unsigned long access;
-+
-+      /* This cache list is used when the inode keeps us around. */
-+      struct list_head cache;
-+      struct list_head list[0];
-+};
-+
-+/* externs needed for fanout.h or sioq.h */
-+extern int unionfs_get_nlinks(const struct inode *inode);
-+extern void unionfs_copy_attr_times(struct inode *upper);
-+extern void unionfs_copy_attr_all(struct inode *dest, const struct inode *src);
-+
-+/* include miscellaneous macros */
-+#include "fanout.h"
-+#include "sioq.h"
-+
-+/* externs for cache creation/deletion routines */
-+extern void unionfs_destroy_filldir_cache(void);
-+extern int unionfs_init_filldir_cache(void);
-+extern int unionfs_init_inode_cache(void);
-+extern void unionfs_destroy_inode_cache(void);
-+extern int unionfs_init_dentry_cache(void);
-+extern void unionfs_destroy_dentry_cache(void);
-+
-+/* Initialize and free readdir-specific  state. */
-+extern int init_rdstate(struct file *file);
-+extern struct unionfs_dir_state *alloc_rdstate(struct inode *inode,
-+                                             int bindex);
-+extern struct unionfs_dir_state *find_rdstate(struct inode *inode,
-+                                            loff_t fpos);
-+extern void free_rdstate(struct unionfs_dir_state *state);
-+extern int add_filldir_node(struct unionfs_dir_state *rdstate,
-+                          const char *name, int namelen, int bindex,
-+                          int whiteout);
-+extern struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
-+                                            const char *name, int namelen,
-+                                            int is_whiteout);
-+
-+extern struct dentry **alloc_new_dentries(int objs);
-+extern struct unionfs_data *alloc_new_data(int objs);
-+
-+/* We can only use 32-bits of offset for rdstate --- blech! */
-+#define DIREOF (0xfffff)
-+#define RDOFFBITS 20          /* This is the number of bits in DIREOF. */
-+#define MAXRDCOOKIE (0xfff)
-+/* Turn an rdstate into an offset. */
-+static inline off_t rdstate2offset(struct unionfs_dir_state *buf)
-+{
-+      off_t tmp;
-+
-+      tmp = ((buf->cookie & MAXRDCOOKIE) << RDOFFBITS)
-+              | (buf->offset & DIREOF);
-+      return tmp;
-+}
-+
-+/* Macros for locking a super_block. */
-+enum unionfs_super_lock_class {
-+      UNIONFS_SMUTEX_NORMAL,
-+      UNIONFS_SMUTEX_PARENT,  /* when locking on behalf of file */
-+      UNIONFS_SMUTEX_CHILD,   /* when locking on behalf of dentry */
-+};
-+static inline void unionfs_read_lock(struct super_block *sb, int subclass)
-+{
-+      if (UNIONFS_SB(sb)->write_lock_owner &&
-+          UNIONFS_SB(sb)->write_lock_owner == current->pid)
-+              return;
-+      down_read_nested(&UNIONFS_SB(sb)->rwsem, subclass);
-+}
-+static inline void unionfs_read_unlock(struct super_block *sb)
-+{
-+      if (UNIONFS_SB(sb)->write_lock_owner &&
-+          UNIONFS_SB(sb)->write_lock_owner == current->pid)
-+              return;
-+      up_read(&UNIONFS_SB(sb)->rwsem);
-+}
-+static inline void unionfs_write_lock(struct super_block *sb)
-+{
-+      down_write(&UNIONFS_SB(sb)->rwsem);
-+      UNIONFS_SB(sb)->write_lock_owner = current->pid;
-+}
-+static inline void unionfs_write_unlock(struct super_block *sb)
-+{
-+      up_write(&UNIONFS_SB(sb)->rwsem);
-+      UNIONFS_SB(sb)->write_lock_owner = 0;
-+}
-+
-+static inline void unionfs_double_lock_dentry(struct dentry *d1,
-+                                            struct dentry *d2)
-+{
-+      BUG_ON(d1 == d2);
-+      if (d1 < d2) {
-+              unionfs_lock_dentry(d2, UNIONFS_DMUTEX_CHILD);
-+              unionfs_lock_dentry(d1, UNIONFS_DMUTEX_PARENT);
-+      } else {
-+              unionfs_lock_dentry(d1, UNIONFS_DMUTEX_CHILD);
-+              unionfs_lock_dentry(d2, UNIONFS_DMUTEX_PARENT);
-+      }
-+}
-+
-+extern int new_dentry_private_data(struct dentry *dentry, int subclass);
-+extern int realloc_dentry_private_data(struct dentry *dentry);
-+extern void free_dentry_private_data(struct dentry *dentry);
-+extern void update_bstart(struct dentry *dentry);
-+extern int init_lower_nd(struct nameidata *nd, unsigned int flags);
-+extern void release_lower_nd(struct nameidata *nd, int err);
-+
-+/*
-+ * EXTERNALS:
-+ */
-+
-+/* replicates the directory structure up to given dentry in given branch */
-+extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
-+                                   const char *name, int bindex);
-+
-+/* partial lookup */
-+extern int unionfs_partial_lookup(struct dentry *dentry);
-+extern struct dentry *unionfs_lookup_full(struct dentry *dentry,
-+                                        struct nameidata *nd_unused,
-+                                        int lookupmode);
-+
-+/* copies a file from dbstart to newbindex branch */
-+extern int copyup_file(struct inode *dir, struct file *file, int bstart,
-+                     int newbindex, loff_t size);
-+extern int copyup_named_file(struct inode *dir, struct file *file,
-+                           char *name, int bstart, int new_bindex,
-+                           loff_t len);
-+/* copies a dentry from dbstart to newbindex branch */
-+extern int copyup_dentry(struct inode *dir, struct dentry *dentry,
-+                       int bstart, int new_bindex, const char *name,
-+                       int namelen, struct file **copyup_file, loff_t len);
-+/* helper functions for post-copyup actions */
-+extern void unionfs_postcopyup_setmnt(struct dentry *dentry);
-+extern void unionfs_postcopyup_release(struct dentry *dentry);
-+
-+/* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */
-+extern int check_empty(struct dentry *dentry,
-+                     struct unionfs_dir_state **namelist);
-+/* whiteout and opaque directory helpers */
-+extern char *alloc_whname(const char *name, int len);
-+extern bool is_whiteout_name(char **namep, int *namelenp);
-+extern bool is_validname(const char *name);
-+extern struct dentry *lookup_whiteout(const char *name,
-+                                    struct dentry *lower_parent);
-+extern struct dentry *find_first_whiteout(struct dentry *dentry);
-+extern int unlink_whiteout(struct dentry *wh_dentry);
-+extern int check_unlink_whiteout(struct dentry *dentry,
-+                               struct dentry *lower_dentry, int bindex);
-+extern int create_whiteout(struct dentry *dentry, int start);
-+extern int delete_whiteouts(struct dentry *dentry, int bindex,
-+                          struct unionfs_dir_state *namelist);
-+extern int is_opaque_dir(struct dentry *dentry, int bindex);
-+extern int make_dir_opaque(struct dentry *dir, int bindex);
-+extern void unionfs_set_max_namelen(long *namelen);
-+
-+extern void unionfs_reinterpose(struct dentry *this_dentry);
-+extern struct super_block *unionfs_duplicate_super(struct super_block *sb);
-+
-+/* Locking functions. */
-+extern int unionfs_setlk(struct file *file, int cmd, struct file_lock *fl);
-+extern int unionfs_getlk(struct file *file, struct file_lock *fl);
-+
-+/* Common file operations. */
-+extern int unionfs_file_revalidate(struct file *file, bool willwrite);
-+extern int unionfs_file_revalidate_locked(struct file *file, bool willwrite);
-+extern int unionfs_open(struct inode *inode, struct file *file);
-+extern int unionfs_file_release(struct inode *inode, struct file *file);
-+extern int unionfs_flush(struct file *file, fl_owner_t id);
-+extern long unionfs_ioctl(struct file *file, unsigned int cmd,
-+                        unsigned long arg);
-+extern int unionfs_fsync(struct file *file, struct dentry *dentry,
-+                       int datasync);
-+extern int unionfs_fasync(int fd, struct file *file, int flag);
-+
-+/* Inode operations */
-+extern struct inode *unionfs_iget(struct super_block *sb, unsigned long ino);
-+extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+                        struct inode *new_dir, struct dentry *new_dentry);
-+extern int unionfs_unlink(struct inode *dir, struct dentry *dentry);
-+extern int unionfs_rmdir(struct inode *dir, struct dentry *dentry);
-+
-+extern bool __unionfs_d_revalidate_one_locked(struct dentry *dentry,
-+                                            struct nameidata *nd,
-+                                            bool willwrite);
-+extern bool __unionfs_d_revalidate_chain(struct dentry *dentry,
-+                                       struct nameidata *nd, bool willwrite);
-+extern bool is_negative_lower(const struct dentry *dentry);
-+extern bool is_newer_lower(const struct dentry *dentry);
-+extern void purge_sb_data(struct super_block *sb);
-+
-+/* The values for unionfs_interpose's flag. */
-+#define INTERPOSE_DEFAULT     0
-+#define INTERPOSE_LOOKUP      1
-+#define INTERPOSE_REVAL               2
-+#define INTERPOSE_REVAL_NEG   3
-+#define INTERPOSE_PARTIAL     4
-+
-+extern struct dentry *unionfs_interpose(struct dentry *this_dentry,
-+                                      struct super_block *sb, int flag);
-+
-+#ifdef CONFIG_UNION_FS_XATTR
-+/* Extended attribute functions. */
-+extern void *unionfs_xattr_alloc(size_t size, size_t limit);
-+static inline void unionfs_xattr_kfree(const void *p)
-+{
-+      kfree(p);
-+}
-+extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
-+                              void *value, size_t size);
-+extern int unionfs_removexattr(struct dentry *dentry, const char *name);
-+extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list,
-+                               size_t size);
-+extern int unionfs_setxattr(struct dentry *dentry, const char *name,
-+                          const void *value, size_t size, int flags);
-+#endif /* CONFIG_UNION_FS_XATTR */
-+
-+/* The root directory is unhashed, but isn't deleted. */
-+static inline int d_deleted(struct dentry *d)
-+{
-+      return d_unhashed(d) && (d != d->d_sb->s_root);
-+}
-+
-+/* unionfs_permission, check if we should bypass error to facilitate copyup */
-+#define IS_COPYUP_ERR(err) ((err) == -EROFS)
-+
-+/* unionfs_open, check if we need to copyup the file */
-+#define OPEN_WRITE_FLAGS (O_WRONLY | O_RDWR | O_APPEND)
-+#define IS_WRITE_FLAG(flag) ((flag) & OPEN_WRITE_FLAGS)
-+
-+static inline int branchperms(const struct super_block *sb, int index)
-+{
-+      BUG_ON(index < 0);
-+      return UNIONFS_SB(sb)->data[index].branchperms;
-+}
-+
-+static inline int set_branchperms(struct super_block *sb, int index, int perms)
-+{
-+      BUG_ON(index < 0);
-+      UNIONFS_SB(sb)->data[index].branchperms = perms;
-+      return perms;
-+}
-+
-+/* Is this file on a read-only branch? */
-+static inline int is_robranch_super(const struct super_block *sb, int index)
-+{
-+      int ret;
-+
-+      ret = (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0;
-+      return ret;
-+}
-+
-+/* Is this file on a read-only branch? */
-+static inline int is_robranch_idx(const struct dentry *dentry, int index)
-+{
-+      struct super_block *lower_sb;
-+
-+      BUG_ON(index < 0);
-+
-+      if (!(branchperms(dentry->d_sb, index) & MAY_WRITE))
-+              return -EROFS;
-+
-+      lower_sb = unionfs_lower_super_idx(dentry->d_sb, index);
-+      BUG_ON(lower_sb == NULL);
-+      /*
-+       * test sb flags directly, not IS_RDONLY(lower_inode) because the
-+       * lower_dentry could be a negative.
-+       */
-+      if (lower_sb->s_flags & MS_RDONLY)
-+              return -EROFS;
-+
-+      return 0;
-+}
-+
-+static inline int is_robranch(const struct dentry *dentry)
-+{
-+      int index;
-+
-+      index = UNIONFS_D(dentry)->bstart;
-+      BUG_ON(index < 0);
-+
-+      return is_robranch_idx(dentry, index);
-+}
-+
-+/*
-+ * EXTERNALS:
-+ */
-+extern int check_branch(struct nameidata *nd);
-+extern int parse_branch_mode(const char *name, int *perms);
-+
-+/* locking helpers */
-+static inline struct dentry *lock_parent(struct dentry *dentry)
-+{
-+      struct dentry *dir = dget_parent(dentry);
-+      mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
-+      return dir;
-+}
-+static inline struct dentry *lock_parent_wh(struct dentry *dentry)
-+{
-+      struct dentry *dir = dget_parent(dentry);
-+
-+      mutex_lock_nested(&dir->d_inode->i_mutex, UNIONFS_DMUTEX_WHITEOUT);
-+      return dir;
-+}
-+
-+static inline void unlock_dir(struct dentry *dir)
-+{
-+      mutex_unlock(&dir->d_inode->i_mutex);
-+      dput(dir);
-+}
-+
-+static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
-+                                            int bindex)
-+{
-+      struct vfsmount *mnt;
-+
-+      BUG_ON(!dentry || bindex < 0);
-+
-+      mnt = mntget(unionfs_lower_mnt_idx(dentry, bindex));
-+#ifdef CONFIG_UNION_FS_DEBUG
-+      if (!mnt)
-+              pr_debug("unionfs: mntget: mnt=%p bindex=%d\n",
-+                       mnt, bindex);
-+#endif /* CONFIG_UNION_FS_DEBUG */
-+
-+      return mnt;
-+}
-+
-+static inline void unionfs_mntput(struct dentry *dentry, int bindex)
-+{
-+      struct vfsmount *mnt;
-+
-+      if (!dentry && bindex < 0)
-+              return;
-+      BUG_ON(!dentry || bindex < 0);
-+
-+      mnt = unionfs_lower_mnt_idx(dentry, bindex);
-+#ifdef CONFIG_UNION_FS_DEBUG
-+      /*
-+       * Directories can have NULL lower objects in between start/end, but
-+       * NOT if at the start/end range.  We cannot verify that this dentry
-+       * is a type=DIR, because it may already be a negative dentry.  But
-+       * if dbstart is greater than dbend, we know that this couldn't have
-+       * been a regular file: it had to have been a directory.
-+       */
-+      if (!mnt && !(bindex > dbstart(dentry) && bindex < dbend(dentry)))
-+              pr_debug("unionfs: mntput: mnt=%p bindex=%d\n", mnt, bindex);
-+#endif /* CONFIG_UNION_FS_DEBUG */
-+      mntput(mnt);
-+}
-+
-+#ifdef CONFIG_UNION_FS_DEBUG
-+
-+/* useful for tracking code reachability */
-+#define UDBG pr_debug("DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
-+
-+#define unionfs_check_inode(i)        __unionfs_check_inode((i),      \
-+      __FILE__, __func__, __LINE__)
-+#define unionfs_check_dentry(d)       __unionfs_check_dentry((d),     \
-+      __FILE__, __func__, __LINE__)
-+#define unionfs_check_file(f) __unionfs_check_file((f),       \
-+      __FILE__, __func__, __LINE__)
-+#define unionfs_check_nd(n)   __unionfs_check_nd((n),         \
-+      __FILE__, __func__, __LINE__)
-+#define show_branch_counts(sb)        __show_branch_counts((sb),      \
-+      __FILE__, __func__, __LINE__)
-+#define show_inode_times(i)   __show_inode_times((i),         \
-+      __FILE__, __func__, __LINE__)
-+#define show_dinode_times(d)  __show_dinode_times((d),        \
-+      __FILE__, __func__, __LINE__)
-+#define show_inode_counts(i)  __show_inode_counts((i),        \
-+      __FILE__, __func__, __LINE__)
-+
-+extern void __unionfs_check_inode(const struct inode *inode, const char *fname,
-+                                const char *fxn, int line);
-+extern void __unionfs_check_dentry(const struct dentry *dentry,
-+                                 const char *fname, const char *fxn,
-+                                 int line);
-+extern void __unionfs_check_file(const struct file *file,
-+                               const char *fname, const char *fxn, int line);
-+extern void __unionfs_check_nd(const struct nameidata *nd,
-+                             const char *fname, const char *fxn, int line);
-+extern void __show_branch_counts(const struct super_block *sb,
-+                               const char *file, const char *fxn, int line);
-+extern void __show_inode_times(const struct inode *inode,
-+                             const char *file, const char *fxn, int line);
-+extern void __show_dinode_times(const struct dentry *dentry,
-+                              const char *file, const char *fxn, int line);
-+extern void __show_inode_counts(const struct inode *inode,
-+                              const char *file, const char *fxn, int line);
-+
-+#else /* not CONFIG_UNION_FS_DEBUG */
-+
-+/* we leave useful hooks for these check functions throughout the code */
-+#define unionfs_check_inode(i)                do { } while (0)
-+#define unionfs_check_dentry(d)               do { } while (0)
-+#define unionfs_check_file(f)         do { } while (0)
-+#define unionfs_check_nd(n)           do { } while (0)
-+#define show_branch_counts(sb)                do { } while (0)
-+#define show_inode_times(i)           do { } while (0)
-+#define show_dinode_times(d)          do { } while (0)
-+#define show_inode_counts(i)          do { } while (0)
-+
-+#endif /* not CONFIG_UNION_FS_DEBUG */
-+
-+#endif        /* not _UNION_H_ */
-diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
-new file mode 100644
-index 0000000..623f68d
---- /dev/null
-+++ b/fs/unionfs/unlink.c
-@@ -0,0 +1,277 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * Helper function for Unionfs's unlink operation.
-+ *
-+ * The main goal of this function is to optimize the unlinking of non-dir
-+ * objects in unionfs by deleting all possible lower inode objects from the
-+ * underlying branches having same dentry name as the non-dir dentry on
-+ * which this unlink operation is called.  This way we delete as many lower
-+ * inodes as possible, and save space.  Whiteouts need to be created in
-+ * branch0 only if unlinking fails on any of the lower branch other than
-+ * branch0, or if a lower branch is marked read-only.
-+ *
-+ * Also, while unlinking a file, if we encounter any dir type entry in any
-+ * intermediate branch, then we remove the directory by calling vfs_rmdir.
-+ * The following special cases are also handled:
-+
-+ * (1) If an error occurs in branch0 during vfs_unlink, then we return
-+ *     appropriate error.
-+ *
-+ * (2) If we get an error during unlink in any of other lower branch other
-+ *     than branch0, then we create a whiteout in branch0.
-+ *
-+ * (3) If a whiteout already exists in any intermediate branch, we delete
-+ *     all possible inodes only up to that branch (this is an "opaqueness"
-+ *     as as per Documentation/filesystems/unionfs/concepts.txt).
-+ *
-+ */
-+static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry)
-+{
-+      struct dentry *lower_dentry;
-+      struct dentry *lower_dir_dentry;
-+      int bindex;
-+      int err = 0;
-+
-+      err = unionfs_partial_lookup(dentry);
-+      if (err)
-+              goto out;
-+
-+      /* trying to unlink all possible valid instances */
-+      for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!lower_dentry || !lower_dentry->d_inode)
-+                      continue;
-+
-+              lower_dir_dentry = lock_parent(lower_dentry);
-+
-+              /* avoid destroying the lower inode if the object is in use */
-+              dget(lower_dentry);
-+              err = is_robranch_super(dentry->d_sb, bindex);
-+              if (!err) {
-+                      /* see Documentation/filesystems/unionfs/issues.txt */
-+                      lockdep_off();
-+                      if (!S_ISDIR(lower_dentry->d_inode->i_mode))
-+                              err = vfs_unlink(lower_dir_dentry->d_inode,
-+                                                              lower_dentry);
-+                      else
-+                              err = vfs_rmdir(lower_dir_dentry->d_inode,
-+                                                              lower_dentry);
-+                      lockdep_on();
-+              }
-+
-+              /* if lower object deletion succeeds, update inode's times */
-+              if (!err)
-+                      unionfs_copy_attr_times(dentry->d_inode);
-+              dput(lower_dentry);
-+              fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-+              unlock_dir(lower_dir_dentry);
-+
-+              if (err)
-+                      break;
-+      }
-+
-+      /*
-+       * Create the whiteout in branch 0 (highest priority) only if (a)
-+       * there was an error in any intermediate branch other than branch 0
-+       * due to failure of vfs_unlink/vfs_rmdir or (b) a branch marked or
-+       * mounted read-only.
-+       */
-+      if (err) {
-+              if ((bindex == 0) ||
-+                  ((bindex == dbstart(dentry)) &&
-+                   (!IS_COPYUP_ERR(err))))
-+                      goto out;
-+              else {
-+                      if (!IS_COPYUP_ERR(err))
-+                              pr_debug("unionfs: lower object deletion "
-+                                           "failed in branch:%d\n", bindex);
-+                      err = create_whiteout(dentry, sbstart(dentry->d_sb));
-+              }
-+      }
-+
-+out:
-+      if (!err)
-+              inode_dec_link_count(dentry->d_inode);
-+
-+      /* We don't want to leave negative leftover dentries for revalidate. */
-+      if (!err && (dbopaque(dentry) != -1))
-+              update_bstart(dentry);
-+
-+      return err;
-+}
-+
-+int unionfs_unlink(struct inode *dir, struct dentry *dentry)
-+{
-+      int err = 0;
-+      struct inode *inode = dentry->d_inode;
-+      int valid;
-+
-+      BUG_ON(S_ISDIR(inode->i_mode));
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_PARENT);
-+
-+      valid = __unionfs_d_revalidate_chain(dentry->d_parent, NULL, false);
-+      if (unlikely(!valid)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      valid = __unionfs_d_revalidate_one_locked(dentry, NULL, false);
-+      if (unlikely(!valid)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      unionfs_check_dentry(dentry);
-+
-+      err = unionfs_unlink_whiteout(dir, dentry);
-+      /* call d_drop so the system "forgets" about us */
-+      if (!err) {
-+              unionfs_postcopyup_release(dentry);
-+              if (inode->i_nlink == 0) /* drop lower inodes */
-+                      iput_lowers_all(inode, false);
-+              d_drop(dentry);
-+              /*
-+               * if unlink/whiteout succeeded, parent dir mtime has
-+               * changed
-+               */
-+              unionfs_copy_attr_times(dir);
-+      }
-+
-+out:
-+      if (!err) {
-+              unionfs_check_dentry(dentry);
-+              unionfs_check_inode(dir);
-+      }
-+      unionfs_unlock_dentry(dentry->d_parent);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry,
-+                             struct unionfs_dir_state *namelist)
-+{
-+      int err;
-+      struct dentry *lower_dentry;
-+      struct dentry *lower_dir_dentry = NULL;
-+
-+      /* Here we need to remove whiteout entries. */
-+      err = delete_whiteouts(dentry, dbstart(dentry), namelist);
-+      if (err)
-+              goto out;
-+
-+      lower_dentry = unionfs_lower_dentry(dentry);
-+
-+      lower_dir_dentry = lock_parent(lower_dentry);
-+
-+      /* avoid destroying the lower inode if the file is in use */
-+      dget(lower_dentry);
-+      err = is_robranch(dentry);
-+      if (!err) {
-+              /* see Documentation/filesystems/unionfs/issues.txt */
-+              lockdep_off();
-+              err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
-+              lockdep_on();
-+      }
-+      dput(lower_dentry);
-+
-+      fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-+      /* propagate number of hard-links */
-+      dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode);
-+
-+out:
-+      if (lower_dir_dentry)
-+              unlock_dir(lower_dir_dentry);
-+      return err;
-+}
-+
-+int unionfs_rmdir(struct inode *dir, struct dentry *dentry)
-+{
-+      int err = 0;
-+      struct unionfs_dir_state *namelist = NULL;
-+      int dstart, dend;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      unionfs_check_dentry(dentry);
-+
-+      /* check if this unionfs directory is empty or not */
-+      err = check_empty(dentry, &namelist);
-+      if (err)
-+              goto out;
-+
-+      err = unionfs_rmdir_first(dir, dentry, namelist);
-+      dstart = dbstart(dentry);
-+      dend = dbend(dentry);
-+      /*
-+       * We create a whiteout for the directory if there was an error to
-+       * rmdir the first directory entry in the union.  Otherwise, we
-+       * create a whiteout only if there is no chance that a lower
-+       * priority branch might also have the same named directory.  IOW,
-+       * if there is not another same-named directory at a lower priority
-+       * branch, then we don't need to create a whiteout for it.
-+       */
-+      if (!err) {
-+              if (dstart < dend)
-+                      err = create_whiteout(dentry, dstart);
-+      } else {
-+              int new_err;
-+
-+              if (dstart == 0)
-+                      goto out;
-+
-+              /* exit if the error returned was NOT -EROFS */
-+              if (!IS_COPYUP_ERR(err))
-+                      goto out;
-+
-+              new_err = create_whiteout(dentry, dstart - 1);
-+              if (new_err != -EEXIST)
-+                      err = new_err;
-+      }
-+
-+out:
-+      /*
-+       * Drop references to lower dentry/inode so storage space for them
-+       * can be reclaimed.  Then, call d_drop so the system "forgets"
-+       * about us.
-+       */
-+      if (!err) {
-+              iput_lowers_all(dentry->d_inode, false);
-+              dput(unionfs_lower_dentry_idx(dentry, dstart));
-+              unionfs_set_lower_dentry_idx(dentry, dstart, NULL);
-+              d_drop(dentry);
-+              /* update our lower vfsmnts, in case a copyup took place */
-+              unionfs_postcopyup_setmnt(dentry);
-+      }
-+
-+      if (namelist)
-+              free_rdstate(namelist);
-+
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-diff --git a/fs/unionfs/whiteout.c b/fs/unionfs/whiteout.c
-new file mode 100644
-index 0000000..db7a21e
---- /dev/null
-+++ b/fs/unionfs/whiteout.c
-@@ -0,0 +1,577 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/*
-+ * whiteout and opaque directory helpers
-+ */
-+
-+/* What do we use for whiteouts. */
-+#define UNIONFS_WHPFX ".wh."
-+#define UNIONFS_WHLEN 4
-+/*
-+ * If a directory contains this file, then it is opaque.  We start with the
-+ * .wh. flag so that it is blocked by lookup.
-+ */
-+#define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque"
-+#define UNIONFS_DIR_OPAQUE UNIONFS_WHPFX UNIONFS_DIR_OPAQUE_NAME
-+
-+/* construct whiteout filename */
-+char *alloc_whname(const char *name, int len)
-+{
-+      char *buf;
-+
-+      buf = kmalloc(len + UNIONFS_WHLEN + 1, GFP_KERNEL);
-+      if (unlikely(!buf))
-+              return ERR_PTR(-ENOMEM);
-+
-+      strcpy(buf, UNIONFS_WHPFX);
-+      strlcat(buf, name, len + UNIONFS_WHLEN + 1);
-+
-+      return buf;
-+}
-+
-+/*
-+ * XXX: this can be inline or CPP macro, but is here to keep all whiteout
-+ * code in one place.
-+ */
-+void unionfs_set_max_namelen(long *namelen)
-+{
-+      *namelen -= UNIONFS_WHLEN;
-+}
-+
-+/* check if @namep is a whiteout, update @namep and @namelenp accordingly */
-+bool is_whiteout_name(char **namep, int *namelenp)
-+{
-+      if (*namelenp > UNIONFS_WHLEN &&
-+          !strncmp(*namep, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
-+              *namep += UNIONFS_WHLEN;
-+              *namelenp -= UNIONFS_WHLEN;
-+              return true;
-+      }
-+      return false;
-+}
-+
-+/* is the filename valid == !(whiteout for a file or opaque dir marker) */
-+bool is_validname(const char *name)
-+{
-+      if (!strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN))
-+              return false;
-+      if (!strncmp(name, UNIONFS_DIR_OPAQUE_NAME,
-+                   sizeof(UNIONFS_DIR_OPAQUE_NAME) - 1))
-+              return false;
-+      return true;
-+}
-+
-+/*
-+ * Look for a whiteout @name in @lower_parent directory.  If error, return
-+ * ERR_PTR.  Caller must dput() the returned dentry if not an error.
-+ *
-+ * XXX: some callers can reuse the whname allocated buffer to avoid repeated
-+ * free then re-malloc calls.  Need to provide a different API for those
-+ * callers.
-+ */
-+struct dentry *lookup_whiteout(const char *name, struct dentry *lower_parent)
-+{
-+      char *whname = NULL;
-+      int err = 0, namelen;
-+      struct dentry *wh_dentry = NULL;
-+
-+      namelen = strlen(name);
-+      whname = alloc_whname(name, namelen);
-+      if (unlikely(IS_ERR(whname))) {
-+              err = PTR_ERR(whname);
-+              goto out;
-+      }
-+
-+      /* check if whiteout exists in this branch: lookup .wh.foo */
-+      wh_dentry = lookup_one_len(whname, lower_parent, strlen(whname));
-+      if (IS_ERR(wh_dentry)) {
-+              err = PTR_ERR(wh_dentry);
-+              goto out;
-+      }
-+
-+      /* check if negative dentry (ENOENT) */
-+      if (!wh_dentry->d_inode)
-+              goto out;
-+
-+      /* whiteout found: check if valid type */
-+      if (!S_ISREG(wh_dentry->d_inode->i_mode)) {
-+              printk(KERN_ERR "unionfs: invalid whiteout %s entry type %d\n",
-+                     whname, wh_dentry->d_inode->i_mode);
-+              dput(wh_dentry);
-+              err = -EIO;
-+              goto out;
-+      }
-+
-+out:
-+      kfree(whname);
-+      if (err)
-+              wh_dentry = ERR_PTR(err);
-+      return wh_dentry;
-+}
-+
-+/* find and return first whiteout in parent directory, else ENOENT */
-+struct dentry *find_first_whiteout(struct dentry *dentry)
-+{
-+      int bindex, bstart, bend;
-+      struct dentry *parent, *lower_parent, *wh_dentry;
-+
-+      parent = dget_parent(dentry);
-+      unionfs_lock_dentry(parent, UNIONFS_DMUTEX_WHITEOUT);
-+      bstart = dbstart(parent);
-+      bend = dbend(parent);
-+      wh_dentry = ERR_PTR(-ENOENT);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              lower_parent = unionfs_lower_dentry_idx(parent, bindex);
-+              if (!lower_parent)
-+                      continue;
-+              wh_dentry = lookup_whiteout(dentry->d_name.name, lower_parent);
-+              if (IS_ERR(wh_dentry))
-+                      continue;
-+              if (wh_dentry->d_inode)
-+                      break;
-+              dput(wh_dentry);
-+              wh_dentry = ERR_PTR(-ENOENT);
-+      }
-+      unionfs_unlock_dentry(parent);
-+      dput(parent);
-+
-+      return wh_dentry;
-+}
-+
-+/*
-+ * Unlink a whiteout dentry.  Returns 0 or -errno.  Caller must hold and
-+ * release dentry reference.
-+ */
-+int unlink_whiteout(struct dentry *wh_dentry)
-+{
-+      int err;
-+      struct dentry *lower_dir_dentry;
-+
-+      /* dget and lock parent dentry */
-+      lower_dir_dentry = lock_parent_wh(wh_dentry);
-+
-+      /* see Documentation/filesystems/unionfs/issues.txt */
-+      lockdep_off();
-+      err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry);
-+      lockdep_on();
-+      unlock_dir(lower_dir_dentry);
-+
-+      /*
-+       * Whiteouts are special files and should be deleted no matter what
-+       * (as if they never existed), in order to allow this create
-+       * operation to succeed.  This is especially important in sticky
-+       * directories: a whiteout may have been created by one user, but
-+       * the newly created file may be created by another user.
-+       * Therefore, in order to maintain Unix semantics, if the vfs_unlink
-+       * above failed, then we have to try to directly unlink the
-+       * whiteout.  Note: in the ODF version of unionfs, whiteout are
-+       * handled much more cleanly.
-+       */
-+      if (err == -EPERM) {
-+              struct inode *inode = lower_dir_dentry->d_inode;
-+              err = inode->i_op->unlink(inode, wh_dentry);
-+      }
-+      if (err)
-+              printk(KERN_ERR "unionfs: could not unlink whiteout %s, "
-+                     "err = %d\n", wh_dentry->d_name.name, err);
-+
-+      return err;
-+
-+}
-+
-+/*
-+ * Helper function when creating new objects (create, symlink, mknod, etc.).
-+ * Checks to see if there's a whiteout in @lower_dentry's parent directory,
-+ * whose name is taken from @dentry.  Then tries to remove that whiteout, if
-+ * found.  If <dentry,bindex> is a branch marked readonly, return -EROFS.
-+ * If it finds both a regular file and a whiteout, return -EIO (this should
-+ * never happen).
-+ *
-+ * Return 0 if no whiteout was found.  Return 1 if one was found and
-+ * successfully removed.  Therefore a value >= 0 tells the caller that
-+ * @lower_dentry belongs to a good branch to create the new object in).
-+ * Return -ERRNO if an error occurred during whiteout lookup or in trying to
-+ * unlink the whiteout.
-+ */
-+int check_unlink_whiteout(struct dentry *dentry, struct dentry *lower_dentry,
-+                        int bindex)
-+{
-+      int err;
-+      struct dentry *wh_dentry = NULL;
-+      struct dentry *lower_dir_dentry = NULL;
-+
-+      /* look for whiteout dentry first */
-+      lower_dir_dentry = dget_parent(lower_dentry);
-+      wh_dentry = lookup_whiteout(dentry->d_name.name, lower_dir_dentry);
-+      dput(lower_dir_dentry);
-+      if (IS_ERR(wh_dentry)) {
-+              err = PTR_ERR(wh_dentry);
-+              goto out;
-+      }
-+
-+      if (!wh_dentry->d_inode) { /* no whiteout exists*/
-+              err = 0;
-+              goto out_dput;
-+      }
-+
-+      /* check if regular file and whiteout were both found */
-+      if (unlikely(lower_dentry->d_inode)) {
-+              err = -EIO;
-+              printk(KERN_ERR "unionfs: found both whiteout and regular "
-+                     "file in directory %s (branch %d)\n",
-+                     lower_dentry->d_parent->d_name.name, bindex);
-+              goto out_dput;
-+      }
-+
-+      /* check if branch is writeable */
-+      err = is_robranch_super(dentry->d_sb, bindex);
-+      if (err)
-+              goto out_dput;
-+
-+      /* .wh.foo has been found, so let's unlink it */
-+      err = unlink_whiteout(wh_dentry);
-+      if (!err)
-+              err = 1; /* a whiteout was found and successfully removed */
-+out_dput:
-+      dput(wh_dentry);
-+out:
-+      return err;
-+}
-+
-+/*
-+ * Pass an unionfs dentry and an index.  It will try to create a whiteout
-+ * for the filename in dentry, and will try in branch 'index'.  On error,
-+ * it will proceed to a branch to the left.
-+ */
-+int create_whiteout(struct dentry *dentry, int start)
-+{
-+      int bstart, bend, bindex;
-+      struct dentry *lower_dir_dentry;
-+      struct dentry *lower_dentry;
-+      struct dentry *lower_wh_dentry;
-+      struct nameidata nd;
-+      char *name = NULL;
-+      int err = -EINVAL;
-+
-+      verify_locked(dentry);
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      /* create dentry's whiteout equivalent */
-+      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-+      if (unlikely(IS_ERR(name))) {
-+              err = PTR_ERR(name);
-+              goto out;
-+      }
-+
-+      for (bindex = start; bindex >= 0; bindex--) {
-+              lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+
-+              if (!lower_dentry) {
-+                      /*
-+                       * if lower dentry is not present, create the
-+                       * entire lower dentry directory structure and go
-+                       * ahead.  Since we want to just create whiteout, we
-+                       * only want the parent dentry, and hence get rid of
-+                       * this dentry.
-+                       */
-+                      lower_dentry = create_parents(dentry->d_inode,
-+                                                    dentry,
-+                                                    dentry->d_name.name,
-+                                                    bindex);
-+                      if (!lower_dentry || IS_ERR(lower_dentry)) {
-+                              int ret = PTR_ERR(lower_dentry);
-+                              if (!IS_COPYUP_ERR(ret))
-+                                      printk(KERN_ERR
-+                                             "unionfs: create_parents for "
-+                                             "whiteout failed: bindex=%d "
-+                                             "err=%d\n", bindex, ret);
-+                              continue;
-+                      }
-+              }
-+
-+              lower_wh_dentry =
-+                      lookup_one_len(name, lower_dentry->d_parent,
-+                                     dentry->d_name.len + UNIONFS_WHLEN);
-+              if (IS_ERR(lower_wh_dentry))
-+                      continue;
-+
-+              /*
-+               * The whiteout already exists. This used to be impossible,
-+               * but now is possible because of opaqueness.
-+               */
-+              if (lower_wh_dentry->d_inode) {
-+                      dput(lower_wh_dentry);
-+                      err = 0;
-+                      goto out;
-+              }
-+
-+              err = init_lower_nd(&nd, LOOKUP_CREATE);
-+              if (unlikely(err < 0))
-+                      goto out;
-+              lower_dir_dentry = lock_parent_wh(lower_wh_dentry);
-+              err = is_robranch_super(dentry->d_sb, bindex);
-+              if (!err)
-+                      err = vfs_create(lower_dir_dentry->d_inode,
-+                                       lower_wh_dentry,
-+                                       ~current->fs->umask & S_IRUGO,
-+                                       &nd);
-+              unlock_dir(lower_dir_dentry);
-+              dput(lower_wh_dentry);
-+              release_lower_nd(&nd, err);
-+
-+              if (!err || !IS_COPYUP_ERR(err))
-+                      break;
-+      }
-+
-+      /* set dbopaque so that lookup will not proceed after this branch */
-+      if (!err)
-+              dbopaque(dentry) = bindex;
-+
-+out:
-+      kfree(name);
-+      return err;
-+}
-+
-+/*
-+ * Delete all of the whiteouts in a given directory for rmdir.
-+ *
-+ * lower directory inode should be locked
-+ */
-+static int do_delete_whiteouts(struct dentry *dentry, int bindex,
-+                             struct unionfs_dir_state *namelist)
-+{
-+      int err = 0;
-+      struct dentry *lower_dir_dentry = NULL;
-+      struct dentry *lower_dentry;
-+      char *name = NULL, *p;
-+      struct inode *lower_dir;
-+      int i;
-+      struct list_head *pos;
-+      struct filldir_node *cursor;
-+
-+      /* Find out lower parent dentry */
-+      lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+      BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode));
-+      lower_dir = lower_dir_dentry->d_inode;
-+      BUG_ON(!S_ISDIR(lower_dir->i_mode));
-+
-+      err = -ENOMEM;
-+      name = __getname();
-+      if (unlikely(!name))
-+              goto out;
-+      strcpy(name, UNIONFS_WHPFX);
-+      p = name + UNIONFS_WHLEN;
-+
-+      err = 0;
-+      for (i = 0; !err && i < namelist->size; i++) {
-+              list_for_each(pos, &namelist->list[i]) {
-+                      cursor =
-+                              list_entry(pos, struct filldir_node,
-+                                         file_list);
-+                      /* Only operate on whiteouts in this branch. */
-+                      if (cursor->bindex != bindex)
-+                              continue;
-+                      if (!cursor->whiteout)
-+                              continue;
-+
-+                      strlcpy(p, cursor->name, PATH_MAX - UNIONFS_WHLEN);
-+                      lower_dentry =
-+                              lookup_one_len(name, lower_dir_dentry,
-+                                             cursor->namelen +
-+                                             UNIONFS_WHLEN);
-+                      if (IS_ERR(lower_dentry)) {
-+                              err = PTR_ERR(lower_dentry);
-+                              break;
-+                      }
-+                      if (lower_dentry->d_inode)
-+                              err = vfs_unlink(lower_dir, lower_dentry);
-+                      dput(lower_dentry);
-+                      if (err)
-+                              break;
-+              }
-+      }
-+
-+      __putname(name);
-+
-+      /* After all of the removals, we should copy the attributes once. */
-+      fsstack_copy_attr_times(dentry->d_inode, lower_dir_dentry->d_inode);
-+
-+out:
-+      return err;
-+}
-+
-+
-+void __delete_whiteouts(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct deletewh_args *d = &args->deletewh;
-+
-+      args->err = do_delete_whiteouts(d->dentry, d->bindex, d->namelist);
-+      complete(&args->comp);
-+}
-+
-+/* delete whiteouts in a dir (for rmdir operation) using sioq if necessary */
-+int delete_whiteouts(struct dentry *dentry, int bindex,
-+                   struct unionfs_dir_state *namelist)
-+{
-+      int err;
-+      struct super_block *sb;
-+      struct dentry *lower_dir_dentry;
-+      struct inode *lower_dir;
-+      struct sioq_args args;
-+
-+      sb = dentry->d_sb;
-+
-+      BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
-+      BUG_ON(bindex < dbstart(dentry));
-+      BUG_ON(bindex > dbend(dentry));
-+      err = is_robranch_super(sb, bindex);
-+      if (err)
-+              goto out;
-+
-+      lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+      BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode));
-+      lower_dir = lower_dir_dentry->d_inode;
-+      BUG_ON(!S_ISDIR(lower_dir->i_mode));
-+
-+      if (!inode_permission(lower_dir, MAY_WRITE | MAY_EXEC)) {
-+              err = do_delete_whiteouts(dentry, bindex, namelist);
-+      } else {
-+              args.deletewh.namelist = namelist;
-+              args.deletewh.dentry = dentry;
-+              args.deletewh.bindex = bindex;
-+              run_sioq(__delete_whiteouts, &args);
-+              err = args.err;
-+      }
-+
-+out:
-+      return err;
-+}
-+
-+/****************************************************************************
-+ * Opaque directory helpers                                                 *
-+ ****************************************************************************/
-+
-+/*
-+ * is_opaque_dir: returns 0 if it is NOT an opaque dir, 1 if it is, and
-+ * -errno if an error occurred trying to figure this out.
-+ */
-+int is_opaque_dir(struct dentry *dentry, int bindex)
-+{
-+      int err = 0;
-+      struct dentry *lower_dentry;
-+      struct dentry *wh_lower_dentry;
-+      struct inode *lower_inode;
-+      struct sioq_args args;
-+
-+      lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+      lower_inode = lower_dentry->d_inode;
-+
-+      BUG_ON(!S_ISDIR(lower_inode->i_mode));
-+
-+      mutex_lock(&lower_inode->i_mutex);
-+
-+      if (!inode_permission(lower_inode, MAY_EXEC)) {
-+              wh_lower_dentry =
-+                      lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry,
-+                                     sizeof(UNIONFS_DIR_OPAQUE) - 1);
-+      } else {
-+              args.is_opaque.dentry = lower_dentry;
-+              run_sioq(__is_opaque_dir, &args);
-+              wh_lower_dentry = args.ret;
-+      }
-+
-+      mutex_unlock(&lower_inode->i_mutex);
-+
-+      if (IS_ERR(wh_lower_dentry)) {
-+              err = PTR_ERR(wh_lower_dentry);
-+              goto out;
-+      }
-+
-+      /* This is an opaque dir iff wh_lower_dentry is positive */
-+      err = !!wh_lower_dentry->d_inode;
-+
-+      dput(wh_lower_dentry);
-+out:
-+      return err;
-+}
-+
-+void __is_opaque_dir(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+
-+      args->ret = lookup_one_len(UNIONFS_DIR_OPAQUE, args->is_opaque.dentry,
-+                                 sizeof(UNIONFS_DIR_OPAQUE) - 1);
-+      complete(&args->comp);
-+}
-+
-+int make_dir_opaque(struct dentry *dentry, int bindex)
-+{
-+      int err = 0;
-+      struct dentry *lower_dentry, *diropq;
-+      struct inode *lower_dir;
-+      struct nameidata nd;
-+      kernel_cap_t orig_cap;
-+
-+      /*
-+       * Opaque directory whiteout markers are special files (like regular
-+       * whiteouts), and should appear to the users as if they don't
-+       * exist.  They should be created/deleted regardless of directory
-+       * search/create permissions, but only for the duration of this
-+       * creation of the .wh.__dir_opaque: file.  Note, this does not
-+       * circumvent normal ->permission).
-+       */
-+      orig_cap = current->cap_effective;
-+      cap_raise(current->cap_effective, CAP_DAC_READ_SEARCH);
-+      cap_raise(current->cap_effective, CAP_DAC_OVERRIDE);
-+
-+      lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+      lower_dir = lower_dentry->d_inode;
-+      BUG_ON(!S_ISDIR(dentry->d_inode->i_mode) ||
-+             !S_ISDIR(lower_dir->i_mode));
-+
-+      mutex_lock(&lower_dir->i_mutex);
-+      diropq = lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry,
-+                              sizeof(UNIONFS_DIR_OPAQUE) - 1);
-+      if (IS_ERR(diropq)) {
-+              err = PTR_ERR(diropq);
-+              goto out;
-+      }
-+
-+      err = init_lower_nd(&nd, LOOKUP_CREATE);
-+      if (unlikely(err < 0))
-+              goto out;
-+      if (!diropq->d_inode)
-+              err = vfs_create(lower_dir, diropq, S_IRUGO, &nd);
-+      if (!err)
-+              dbopaque(dentry) = bindex;
-+      release_lower_nd(&nd, err);
-+
-+      dput(diropq);
-+
-+out:
-+      mutex_unlock(&lower_dir->i_mutex);
-+      current->cap_effective = orig_cap;
-+      return err;
-+}
-diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c
-new file mode 100644
-index 0000000..93a8fce
---- /dev/null
-+++ b/fs/unionfs/xattr.c
-@@ -0,0 +1,153 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "union.h"
-+
-+/* This is lifted from fs/xattr.c */
-+void *unionfs_xattr_alloc(size_t size, size_t limit)
-+{
-+      void *ptr;
-+
-+      if (size > limit)
-+              return ERR_PTR(-E2BIG);
-+
-+      if (!size)              /* size request, no buffer is needed */
-+              return NULL;
-+
-+      ptr = kmalloc(size, GFP_KERNEL);
-+      if (unlikely(!ptr))
-+              return ERR_PTR(-ENOMEM);
-+      return ptr;
-+}
-+
-+/*
-+ * BKL held by caller.
-+ * dentry->d_inode->i_mutex locked
-+ */
-+ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value,
-+                       size_t size)
-+{
-+      struct dentry *lower_dentry = NULL;
-+      int err = -EOPNOTSUPP;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      lower_dentry = unionfs_lower_dentry(dentry);
-+
-+      err = vfs_getxattr(lower_dentry, (char *) name, value, size);
-+
-+out:
-+      unionfs_check_dentry(dentry);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+/*
-+ * BKL held by caller.
-+ * dentry->d_inode->i_mutex locked
-+ */
-+int unionfs_setxattr(struct dentry *dentry, const char *name,
-+                   const void *value, size_t size, int flags)
-+{
-+      struct dentry *lower_dentry = NULL;
-+      int err = -EOPNOTSUPP;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      lower_dentry = unionfs_lower_dentry(dentry);
-+
-+      err = vfs_setxattr(lower_dentry, (char *) name, (void *) value,
-+                         size, flags);
-+
-+out:
-+      unionfs_check_dentry(dentry);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+/*
-+ * BKL held by caller.
-+ * dentry->d_inode->i_mutex locked
-+ */
-+int unionfs_removexattr(struct dentry *dentry, const char *name)
-+{
-+      struct dentry *lower_dentry = NULL;
-+      int err = -EOPNOTSUPP;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      lower_dentry = unionfs_lower_dentry(dentry);
-+
-+      err = vfs_removexattr(lower_dentry, (char *) name);
-+
-+out:
-+      unionfs_check_dentry(dentry);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+/*
-+ * BKL held by caller.
-+ * dentry->d_inode->i_mutex locked
-+ */
-+ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size)
-+{
-+      struct dentry *lower_dentry = NULL;
-+      int err = -EOPNOTSUPP;
-+      char *encoded_list = NULL;
-+
-+      unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
-+      unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
-+
-+      if (unlikely(!__unionfs_d_revalidate_chain(dentry, NULL, false))) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      lower_dentry = unionfs_lower_dentry(dentry);
-+
-+      encoded_list = list;
-+      err = vfs_listxattr(lower_dentry, encoded_list, size);
-+
-+out:
-+      unionfs_check_dentry(dentry);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
-index bb516ce..6615a52 100644
---- a/include/linux/fs_stack.h
-+++ b/include/linux/fs_stack.h
-@@ -1,17 +1,27 @@
-+/*
-+ * Copyright (c) 2006-2007 Erez Zadok
-+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2006-2007 Stony Brook University
-+ * Copyright (c) 2006-2007 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
- #ifndef _LINUX_FS_STACK_H
- #define _LINUX_FS_STACK_H
--/* This file defines generic functions used primarily by stackable
-+/*
-+ * This file defines generic functions used primarily by stackable
-  * filesystems; none of these functions require i_mutex to be held.
-  */
- #include <linux/fs.h>
- /* externs for fs/stack.c */
--extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
--                              int (*get_nlinks)(struct inode *));
--
--extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
-+extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src);
-+extern void fsstack_copy_inode_size(struct inode *dst, struct inode *src);
- /* inlines */
- static inline void fsstack_copy_attr_atime(struct inode *dest,
-diff --git a/include/linux/magic.h b/include/linux/magic.h
-index 1fa0c2c..67043ed 100644
---- a/include/linux/magic.h
-+++ b/include/linux/magic.h
-@@ -35,6 +35,8 @@
- #define REISER2FS_SUPER_MAGIC_STRING  "ReIsEr2Fs"
- #define REISER2FS_JR_SUPER_MAGIC_STRING       "ReIsEr3Fs"
-+#define UNIONFS_SUPER_MAGIC 0xf15f083d
-+
- #define SMB_SUPER_MAGIC               0x517B
- #define USBDEVICE_SUPER_MAGIC 0x9fa2
- #define CGROUP_SUPER_MAGIC    0x27e0eb
-diff --git a/include/linux/splice.h b/include/linux/splice.h
-index 528dcb9..4b5727c 100644
---- a/include/linux/splice.h
-+++ b/include/linux/splice.h
-@@ -70,5 +70,10 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
-                             struct splice_pipe_desc *);
- extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
-                                     splice_direct_actor *);
-+extern long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out,
-+                          loff_t *ppos, size_t len, unsigned int flags);
-+extern long vfs_splice_to(struct file *in, loff_t *ppos,
-+                        struct pipe_inode_info *pipe, size_t len,
-+                        unsigned int flags);
- #endif
-diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
-new file mode 100644
-index 0000000..bc15a16
---- /dev/null
-+++ b/include/linux/union_fs.h
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright (c) 2003-2008 Erez Zadok
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2003-2008 Stony Brook University
-+ * Copyright (c) 2003-2008 The Research Foundation of SUNY
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef _LINUX_UNION_FS_H
-+#define _LINUX_UNION_FS_H
-+
-+/*
-+ * DEFINITIONS FOR USER AND KERNEL CODE:
-+ */
-+# define UNIONFS_IOCTL_INCGEN         _IOR(0x15, 11, int)
-+# define UNIONFS_IOCTL_QUERYFILE      _IOR(0x15, 15, int)
-+
-+#endif /* _LINUX_UNIONFS_H */
-+
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0011_workaround_unidef_step.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0011_workaround_unidef_step.patch
deleted file mode 100644 (file)
index a77ff3c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
---- linux.trees.git/include/linux/videodev2.h.org      2008-08-15 16:31:03.000000000 -0700
-+++ linux.trees.git/include/linux/videodev2.h  2008-08-15 16:31:11.000000000 -0700
-@@ -59,7 +59,6 @@
- #include <linux/time.h>     /* need struct timeval */
- #include <linux/compiler.h> /* need __user */
- #else
--#define __user
- #include <sys/time.h>
- #endif
- #include <linux/ioctl.h>
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0012_intelfb_945gme.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0012_intelfb_945gme.patch
deleted file mode 100644 (file)
index 15ebe56..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-The following patch adds support for Intel's 945GME graphics chip to
-the intelfb driver.  I have assumed that the 945GME is identical to the
-already-supported 945GM apart from its PCI IDs; this is based on a quick
-look at the X driver for these chips which seems to treat them
-identically.
-
-Signed-off-by: Phil Endecott <spam_from_intelfb@chezphil.org>
-
----
-
-The 945GME is used in the ASUS Eee 901, and I coded this in the hope that 
-I'd be able to use it to get a console at the native 1024x600 resolution 
-which is not known to the BIOS.  I realised too late that the intelfb 
-driver does not support mode changing on laptops, so it won't be any 
-use for me.  But rather than throw it away I will post it here as 
-essentially "untested"; maybe someone who knows more about this driver, 
-and with more useful hardware to test on, can pick it up.
-
-diff --git a/Documentation/fb/intelfb.txt b/Documentation/fb/intelfb.txt
-index 27a3160..dd9e944 100644
---- a/Documentation/fb/intelfb.txt
-+++ b/Documentation/fb/intelfb.txt
-@@ -14,6 +14,7 @@ graphics devices.  These would include:
-       Intel 915GM
-       Intel 945G
-       Intel 945GM
-+      Intel 945GME
-       Intel 965G
-       Intel 965GM
-diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
-index 3325fbd..a50bea6 100644
---- a/drivers/video/intelfb/intelfb.h
-+++ b/drivers/video/intelfb/intelfb.h
-@@ -12,9 +12,9 @@
- #endif
- /*** Version/name ***/
--#define INTELFB_VERSION                       "0.9.5"
-+#define INTELFB_VERSION                       "0.9.6"
- #define INTELFB_MODULE_NAME           "intelfb"
--#define SUPPORTED_CHIPSETS            "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM"
-+#define SUPPORTED_CHIPSETS            "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM"
- /*** Debug/feature defines ***/
-@@ -58,6 +58,7 @@
- #define PCI_DEVICE_ID_INTEL_915GM     0x2592
- #define PCI_DEVICE_ID_INTEL_945G      0x2772
- #define PCI_DEVICE_ID_INTEL_945GM     0x27A2
-+#define PCI_DEVICE_ID_INTEL_945GME    0x27AE
- #define PCI_DEVICE_ID_INTEL_965G      0x29A2
- #define PCI_DEVICE_ID_INTEL_965GM     0x2A02
-@@ -160,6 +161,7 @@ enum intel_chips {
-       INTEL_915GM,
-       INTEL_945G,
-       INTEL_945GM,
-+      INTEL_945GME,
-       INTEL_965G,
-       INTEL_965GM,
- };
-@@ -363,6 +365,7 @@ struct intelfb_info {
-                       ((dinfo)->chipset == INTEL_915GM) ||    \
-                       ((dinfo)->chipset == INTEL_945G) ||     \
-                       ((dinfo)->chipset == INTEL_945GM) ||    \
-+                      ((dinfo)->chipset == INTEL_945GME) ||   \
-                       ((dinfo)->chipset == INTEL_965G) ||     \
-                       ((dinfo)->chipset == INTEL_965GM))
-diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
-index fcf9fad..5d896b8 100644
---- a/drivers/video/intelfb/intelfb_i2c.c
-+++ b/drivers/video/intelfb/intelfb_i2c.c
-@@ -171,6 +171,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
-               /* has some LVDS + tv-out */
-       case INTEL_945G:
-       case INTEL_945GM:
-+      case INTEL_945GME:
-       case INTEL_965G:
-       case INTEL_965GM:
-               /* SDVO ports have a single control bus - 2 devices */
-diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
-index e44303f..a09e236 100644
---- a/drivers/video/intelfb/intelfbdrv.c
-+++ b/drivers/video/intelfb/intelfbdrv.c
-@@ -2,7 +2,7 @@
-  * intelfb
-  *
-  * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
-- * 945G/945GM/965G/965GM integrated graphics chips.
-+ * 945G/945GM/945GME/965G/965GM integrated graphics chips.
-  *
-  * Copyright Â© 2002, 2003 David Dawes <dawes@xfree86.org>
-  *                   2004 Sylvain Meyer
-@@ -102,6 +102,9 @@
-  *
-  *    04/2008 - Version 0.9.5
-  *              Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>)
-+ *
-+ *    08/2008 - Version 0.9.6
-+ *              Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
-  */
- #include <linux/module.h>
-@@ -183,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
-+      { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
-       { 0, }
-@@ -555,6 +559,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
-           (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
-           (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||
-           (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
-+          (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
-           (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
-           (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
-diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
-index 8e6d6a4..8b26b27 100644
---- a/drivers/video/intelfb/intelfbhw.c
-+++ b/drivers/video/intelfb/intelfbhw.c
-@@ -143,6 +143,12 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
-               dinfo->mobile = 1;
-               dinfo->pll_index = PLLS_I9xx;
-               return 0;
-+      case PCI_DEVICE_ID_INTEL_945GME:
-+              dinfo->name = "Intel(R) 945GME";
-+              dinfo->chipset = INTEL_945GME;
-+              dinfo->mobile = 1;
-+              dinfo->pll_index = PLLS_I9xx;
-+              return 0;
-       case PCI_DEVICE_ID_INTEL_965G:
-               dinfo->name = "Intel(R) 965G";
-               dinfo->chipset = INTEL_965G;
-@@ -186,6 +192,7 @@ int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
-       case PCI_DEVICE_ID_INTEL_915GM:
-       case PCI_DEVICE_ID_INTEL_945G:
-       case PCI_DEVICE_ID_INTEL_945GM:
-+      case PCI_DEVICE_ID_INTEL_945GME:
-       case PCI_DEVICE_ID_INTEL_965G:
-       case PCI_DEVICE_ID_INTEL_965GM:
-               /* 915, 945 and 965 chipsets support a 256MB aperture.
-
-
---
-To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at  http://vger.kernel.org/majordomo-info.html
-Please read the FAQ at  http://www.tux.org/lkml/
\ No newline at end of file
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/defconfig-netbook b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/defconfig-netbook
deleted file mode 100644 (file)
index 666a14c..0000000
+++ /dev/null
@@ -1,2419 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc1
-# Wed Oct  1 17:20:02 2008
-#
-# CONFIG_64BIT is not set
-CONFIG_X86_32=y
-# CONFIG_X86_64 is not set
-CONFIG_X86=y
-CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
-# CONFIG_GENERIC_LOCKBREAK is not set
-CONFIG_GENERIC_TIME=y
-CONFIG_GENERIC_CMOS_UPDATE=y
-CONFIG_CLOCKSOURCE_WATCHDOG=y
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_FAST_CMPXCHG_LOCAL=y
-CONFIG_MMU=y
-CONFIG_ZONE_DMA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_GENERIC_IOMAP=y
-CONFIG_GENERIC_BUG=y
-CONFIG_GENERIC_HWEIGHT=y
-# CONFIG_GENERIC_GPIO is not set
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_GENERIC_TIME_VSYSCALL is not set
-CONFIG_ARCH_HAS_CPU_RELAX=y
-CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
-CONFIG_HAVE_SETUP_PER_CPU_AREA=y
-# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set
-CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_ZONE_DMA32 is not set
-CONFIG_ARCH_POPULATES_NODE_MAP=y
-# CONFIG_AUDIT_ARCH is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_PENDING_IRQ=y
-CONFIG_X86_SMP=y
-CONFIG_X86_32_SMP=y
-CONFIG_X86_HT=y
-CONFIG_X86_BIOS_REBOOT=y
-CONFIG_X86_TRAMPOLINE=y
-CONFIG_KTIME_SCALAR=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_LOCALVERSION="-netbook"
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_TASKSTATS=y
-CONFIG_TASK_DELAY_ACCT=y
-CONFIG_TASK_XACCT=y
-CONFIG_TASK_IO_ACCOUNTING=y
-CONFIG_AUDIT=y
-CONFIG_AUDITSYSCALL=y
-CONFIG_AUDIT_TREE=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_CGROUPS is not set
-CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
-# CONFIG_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED_V2 is not set
-CONFIG_RELAY=y
-CONFIG_NAMESPACES=y
-# CONFIG_UTS_NS is not set
-# CONFIG_IPC_NS is not set
-CONFIG_USER_NS=y
-# CONFIG_PID_NS is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SYSCTL=y
-# CONFIG_EMBEDDED is not set
-CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_PCSPKR_PLATFORM=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-CONFIG_PROFILING=y
-# CONFIG_MARKERS is not set
-# CONFIG_OPROFILE is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_USE_GENERIC_SMP_HELPERS=y
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-CONFIG_BLK_DEV_IO_TRACE=y
-# CONFIG_LSF is not set
-CONFIG_BLK_DEV_BSG=y
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-
-#
-# Processor type and features
-#
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_SMP=y
-CONFIG_X86_FIND_SMP_CONFIG=y
-CONFIG_X86_MPPARSE=y
-CONFIG_X86_PC=y
-# CONFIG_X86_ELAN is not set
-# CONFIG_X86_VOYAGER is not set
-# CONFIG_X86_GENERICARCH is not set
-# CONFIG_X86_VSMP is not set
-# CONFIG_X86_RDC321X is not set
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_PARAVIRT_GUEST is not set
-# CONFIG_MEMTEST is not set
-# CONFIG_M386 is not set
-# CONFIG_M486 is not set
-# CONFIG_M586 is not set
-# CONFIG_M586TSC is not set
-# CONFIG_M586MMX is not set
-CONFIG_M686=y
-# CONFIG_MPENTIUMII is not set
-# CONFIG_MPENTIUMIII is not set
-# CONFIG_MPENTIUMM is not set
-# CONFIG_MPENTIUM4 is not set
-# CONFIG_MK6 is not set
-# CONFIG_MK7 is not set
-# CONFIG_MK8 is not set
-# CONFIG_MCRUSOE is not set
-# CONFIG_MEFFICEON is not set
-# CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
-# CONFIG_MWINCHIP3D is not set
-# CONFIG_MGEODEGX1 is not set
-# CONFIG_MGEODE_LX is not set
-# CONFIG_MCYRIXIII is not set
-# CONFIG_MVIAC3_2 is not set
-# CONFIG_MVIAC7 is not set
-# CONFIG_MPSC is not set
-# CONFIG_MCORE2 is not set
-# CONFIG_GENERIC_CPU is not set
-# CONFIG_X86_GENERIC is not set
-CONFIG_X86_CPU=y
-CONFIG_X86_CMPXCHG=y
-CONFIG_X86_L1_CACHE_SHIFT=5
-CONFIG_X86_XADD=y
-# CONFIG_X86_PPRO_FENCE is not set
-CONFIG_X86_WP_WORKS_OK=y
-CONFIG_X86_INVLPG=y
-CONFIG_X86_BSWAP=y
-CONFIG_X86_POPAD_OK=y
-CONFIG_X86_USE_PPRO_CHECKSUM=y
-CONFIG_X86_P6_NOP=y
-CONFIG_X86_TSC=y
-CONFIG_X86_CMOV=y
-CONFIG_X86_MINIMUM_CPU_FAMILY=6
-CONFIG_X86_DEBUGCTLMSR=y
-CONFIG_HPET_TIMER=y
-CONFIG_HPET_EMULATE_RTC=y
-CONFIG_DMI=y
-# CONFIG_IOMMU_HELPER is not set
-CONFIG_NR_CPUS=2
-CONFIG_SCHED_SMT=y
-CONFIG_SCHED_MC=y
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
-# CONFIG_PREEMPT is not set
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_MCE=y
-# CONFIG_X86_MCE_NONFATAL is not set
-# CONFIG_X86_MCE_P4THERMAL is not set
-CONFIG_VM86=y
-# CONFIG_TOSHIBA is not set
-# CONFIG_I8K is not set
-# CONFIG_X86_REBOOTFIXUPS is not set
-CONFIG_MICROCODE=y
-CONFIG_MICROCODE_OLD_INTERFACE=y
-CONFIG_X86_MSR=y
-CONFIG_X86_CPUID=y
-# CONFIG_NOHIGHMEM is not set
-CONFIG_HIGHMEM4G=y
-# CONFIG_HIGHMEM64G is not set
-CONFIG_PAGE_OFFSET=0xC0000000
-CONFIG_HIGHMEM=y
-CONFIG_NEED_NODE_MEMMAP_SIZE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_SELECT_MEMORY_MODEL=y
-CONFIG_SELECT_MEMORY_MODEL=y
-# CONFIG_FLATMEM_MANUAL is not set
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-CONFIG_SPARSEMEM_MANUAL=y
-CONFIG_SPARSEMEM=y
-CONFIG_HAVE_GET_USER_PAGES_FAST=y
-CONFIG_HAVE_MEMORY_PRESENT=y
-CONFIG_SPARSEMEM_STATIC=y
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
-
-#
-# Memory hotplug is currently incompatible with Software Suspend
-#
-CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-# CONFIG_HIGHPTE is not set
-# CONFIG_MATH_EMULATION is not set
-CONFIG_MTRR=y
-# CONFIG_MTRR_SANITIZER is not set
-# CONFIG_X86_PAT is not set
-# CONFIG_EFI is not set
-# CONFIG_IRQBALANCE is not set
-# CONFIG_SECCOMP is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_300 is not set
-CONFIG_HZ_1000=y
-CONFIG_HZ=1000
-CONFIG_SCHED_HRTICK=y
-CONFIG_KEXEC=y
-CONFIG_CRASH_DUMP=y
-# CONFIG_KEXEC_JUMP is not set
-CONFIG_PHYSICAL_START=0x400000
-CONFIG_RELOCATABLE=y
-CONFIG_PHYSICAL_ALIGN=0x200000
-CONFIG_HOTPLUG_CPU=y
-CONFIG_COMPAT_VDSO=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-# CONFIG_PM_VERBOSE is not set
-CONFIG_CAN_PM_TRACE=y
-CONFIG_PM_TRACE=y
-CONFIG_PM_TRACE_RTC=y
-CONFIG_PM_SLEEP_SMP=y
-CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND=y
-# CONFIG_PM_TEST_SUSPEND is not set
-CONFIG_SUSPEND_FREEZER=y
-CONFIG_HIBERNATION=y
-CONFIG_PM_STD_PARTITION=""
-CONFIG_ACPI=y
-CONFIG_ACPI_SLEEP=y
-CONFIG_ACPI_PROCFS=y
-CONFIG_ACPI_PROCFS_POWER=y
-CONFIG_ACPI_SYSFS_POWER=y
-CONFIG_ACPI_PROC_EVENT=y
-CONFIG_ACPI_AC=y
-CONFIG_ACPI_BATTERY=m
-CONFIG_ACPI_BUTTON=y
-CONFIG_ACPI_VIDEO=y
-CONFIG_ACPI_FAN=y
-CONFIG_ACPI_DOCK=y
-# CONFIG_ACPI_BAY is not set
-CONFIG_ACPI_PROCESSOR=y
-CONFIG_ACPI_HOTPLUG_CPU=y
-CONFIG_ACPI_THERMAL=y
-CONFIG_ACPI_WMI=m
-CONFIG_ACPI_ASUS=y
-# CONFIG_ACPI_TOSHIBA is not set
-# CONFIG_ACPI_CUSTOM_DSDT is not set
-CONFIG_ACPI_BLACKLIST_YEAR=0
-# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_EC=y
-# CONFIG_ACPI_PCI_SLOT is not set
-CONFIG_ACPI_POWER=y
-CONFIG_ACPI_SYSTEM=y
-CONFIG_X86_PM_TIMER=y
-CONFIG_ACPI_CONTAINER=y
-CONFIG_ACPI_SBS=m
-# CONFIG_APM is not set
-
-#
-# CPU Frequency scaling
-#
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-CONFIG_CPU_FREQ_DEBUG=y
-CONFIG_CPU_FREQ_STAT=m
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
-
-#
-# CPUFreq processor drivers
-#
-CONFIG_X86_ACPI_CPUFREQ=y
-# CONFIG_X86_POWERNOW_K6 is not set
-# CONFIG_X86_POWERNOW_K7 is not set
-# CONFIG_X86_POWERNOW_K8 is not set
-# CONFIG_X86_GX_SUSPMOD is not set
-# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
-# CONFIG_X86_SPEEDSTEP_ICH is not set
-# CONFIG_X86_SPEEDSTEP_SMI is not set
-# CONFIG_X86_P4_CLOCKMOD is not set
-# CONFIG_X86_CPUFREQ_NFORCE2 is not set
-# CONFIG_X86_LONGRUN is not set
-# CONFIG_X86_LONGHAUL is not set
-# CONFIG_X86_E_POWERSAVER is not set
-
-#
-# shared options
-#
-# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
-# CONFIG_X86_SPEEDSTEP_LIB is not set
-CONFIG_CPU_IDLE=y
-CONFIG_CPU_IDLE_GOV_LADDER=y
-CONFIG_CPU_IDLE_GOV_MENU=y
-
-#
-# Bus options (PCI etc.)
-#
-CONFIG_PCI=y
-# CONFIG_PCI_GOBIOS is not set
-# CONFIG_PCI_GOMMCONFIG is not set
-# CONFIG_PCI_GODIRECT is not set
-# CONFIG_PCI_GOOLPC is not set
-CONFIG_PCI_GOANY=y
-CONFIG_PCI_BIOS=y
-CONFIG_PCI_DIRECT=y
-CONFIG_PCI_MMCONFIG=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_PCIEAER=y
-CONFIG_PCIEASPM=y
-# CONFIG_PCIEASPM_DEBUG is not set
-CONFIG_ARCH_SUPPORTS_MSI=y
-CONFIG_PCI_MSI=y
-CONFIG_PCI_LEGACY=y
-# CONFIG_PCI_DEBUG is not set
-CONFIG_HT_IRQ=y
-CONFIG_ISA_DMA_API=y
-# CONFIG_ISA is not set
-# CONFIG_MCA is not set
-# CONFIG_SCx200 is not set
-# CONFIG_OLPC is not set
-CONFIG_K8_NB=y
-# CONFIG_PCCARD is not set
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats / Emulations
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_AOUT is not set
-CONFIG_BINFMT_MISC=y
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-CONFIG_XFRM_SUB_POLICY=y
-CONFIG_XFRM_MIGRATE=y
-CONFIG_XFRM_STATISTICS=y
-CONFIG_XFRM_IPCOMP=m
-CONFIG_NET_KEY=m
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_TUNNEL=m
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_LRO=y
-CONFIG_INET_DIAG=m
-CONFIG_INET_TCP_DIAG=m
-CONFIG_TCP_CONG_ADVANCED=y
-CONFIG_TCP_CONG_BIC=m
-CONFIG_TCP_CONG_CUBIC=y
-# CONFIG_TCP_CONG_WESTWOOD is not set
-# CONFIG_TCP_CONG_HTCP is not set
-# CONFIG_TCP_CONG_HSTCP is not set
-# CONFIG_TCP_CONG_HYBLA is not set
-# CONFIG_TCP_CONG_VEGAS is not set
-# CONFIG_TCP_CONG_SCALABLE is not set
-# CONFIG_TCP_CONG_LP is not set
-# CONFIG_TCP_CONG_VENO is not set
-# CONFIG_TCP_CONG_YEAH is not set
-# CONFIG_TCP_CONG_ILLINOIS is not set
-# CONFIG_DEFAULT_BIC is not set
-CONFIG_DEFAULT_CUBIC=y
-# CONFIG_DEFAULT_HTCP is not set
-# CONFIG_DEFAULT_VEGAS is not set
-# CONFIG_DEFAULT_WESTWOOD is not set
-# CONFIG_DEFAULT_RENO is not set
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-CONFIG_IPV6_OPTIMISTIC_DAD=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_TUNNEL=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-CONFIG_IPV6_NDISC_NODETYPE=y
-CONFIG_IPV6_TUNNEL=m
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-# CONFIG_IPV6_MROUTE is not set
-CONFIG_NETLABEL=y
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_NETFILTER_ADVANCED=y
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK=y
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-# CONFIG_NF_CT_PROTO_DCCP is not set
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-CONFIG_NF_CONNTRACK_NETBIOS_NS=m
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=y
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
-CONFIG_NETFILTER_XT_TARGET_DSCP=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
-CONFIG_NETFILTER_XT_TARGET_RATEEST=m
-CONFIG_NETFILTER_XT_TARGET_TRACE=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_OWNER=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_RATEEST=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_TIME=m
-CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV4=y
-# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_AH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
-CONFIG_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_NF_NAT_SNMP_BASIC=m
-CONFIG_NF_NAT_PROTO_GRE=m
-CONFIG_NF_NAT_PROTO_UDPLITE=m
-CONFIG_NF_NAT_PROTO_SCTP=m
-CONFIG_NF_NAT_FTP=m
-CONFIG_NF_NAT_IRC=m
-CONFIG_NF_NAT_TFTP=m
-CONFIG_NF_NAT_AMANDA=m
-CONFIG_NF_NAT_PPTP=m
-CONFIG_NF_NAT_H323=m
-CONFIG_NF_NAT_SIP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-# CONFIG_IP_NF_SECURITY is not set
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV6=y
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
-CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=y
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_TARGET_REJECT=y
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_RAW=m
-# CONFIG_IP6_NF_SECURITY is not set
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
-# CONFIG_BT_BNEP_MC_FILTER is not set
-# CONFIG_BT_BNEP_PROTO_FILTER is not set
-# CONFIG_BT_HIDP is not set
-
-#
-# Bluetooth device drivers
-#
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
-CONFIG_BT_HCIBTSDIO=m
-CONFIG_BT_HCIUART=m
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIUART_BCSP=y
-CONFIG_BT_HCIUART_LL=y
-CONFIG_BT_HCIBCM203X=m
-CONFIG_BT_HCIBPA10X=m
-CONFIG_BT_HCIBFUSB=m
-CONFIG_BT_HCIVHCI=m
-# CONFIG_AF_RXRPC is not set
-CONFIG_FIB_RULES=y
-
-#
-# Wireless
-#
-CONFIG_CFG80211=m
-CONFIG_NL80211=y
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-CONFIG_MAC80211=m
-
-#
-# Rate control algorithm selection
-#
-CONFIG_MAC80211_RC_PID=y
-CONFIG_MAC80211_RC_DEFAULT_PID=y
-CONFIG_MAC80211_RC_DEFAULT="pid"
-CONFIG_MAC80211_MESH=y
-CONFIG_MAC80211_LEDS=y
-CONFIG_MAC80211_DEBUGFS=y
-# CONFIG_MAC80211_DEBUG_MENU is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_RFKILL=m
-CONFIG_RFKILL_INPUT=m
-CONFIG_RFKILL_LEDS=y
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_DEBUG_DRIVER is not set
-CONFIG_DEBUG_DEVRES=y
-# CONFIG_SYS_HYPERVISOR is not set
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
-# CONFIG_PARPORT is not set
-CONFIG_PNP=y
-# CONFIG_PNP_DEBUG is not set
-
-#
-# Protocols
-#
-CONFIG_PNPACPI=y
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=262144
-# CONFIG_BLK_DEV_XIP is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_IBM_ASM is not set
-# CONFIG_PHANTOM is not set
-CONFIG_EEPROM_93CX6=m
-# CONFIG_SGI_IOC4 is not set
-CONFIG_TIFM_CORE=m
-CONFIG_TIFM_7XX1=m
-# CONFIG_ACER_WMI is not set
-# CONFIG_FUJITSU_LAPTOP is not set
-# CONFIG_TC1100_WMI is not set
-# CONFIG_HP_WMI is not set
-# CONFIG_MSI_LAPTOP is not set
-# CONFIG_COMPAL_LAPTOP is not set
-# CONFIG_SONY_LAPTOP is not set
-# CONFIG_THINKPAD_ACPI is not set
-# CONFIG_INTEL_MENLOW is not set
-CONFIG_EEEPC_LAPTOP=y
-# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HP_ILO is not set
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=y
-CONFIG_SCSI_DMA=y
-# CONFIG_SCSI_TGT is not set
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
-CONFIG_CHR_DEV_SCH=m
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_SCSI_WAIT_SCAN=m
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
-# CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_SRP is not set
-# CONFIG_SCSI_DH is not set
-CONFIG_ATA=y
-# CONFIG_ATA_NONSTANDARD is not set
-CONFIG_ATA_ACPI=y
-# CONFIG_SATA_PMP is not set
-CONFIG_SATA_AHCI=y
-# CONFIG_SATA_SIL24 is not set
-CONFIG_ATA_SFF=y
-# CONFIG_SATA_SVW is not set
-CONFIG_ATA_PIIX=y
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_PDC_ADMA is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
-# CONFIG_SATA_INIC162X is not set
-# CONFIG_PATA_ACPI is not set
-# CONFIG_PATA_ALI is not set
-# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
-# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_CMD640_PCI is not set
-# CONFIG_PATA_CMD64X is not set
-# CONFIG_PATA_CS5520 is not set
-# CONFIG_PATA_CS5530 is not set
-# CONFIG_PATA_CS5535 is not set
-# CONFIG_PATA_CS5536 is not set
-# CONFIG_PATA_CYPRESS is not set
-# CONFIG_PATA_EFAR is not set
-# CONFIG_ATA_GENERIC is not set
-# CONFIG_PATA_HPT366 is not set
-# CONFIG_PATA_HPT37X is not set
-# CONFIG_PATA_HPT3X2N is not set
-# CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_TRIFLEX is not set
-# CONFIG_PATA_MARVELL is not set
-# CONFIG_PATA_MPIIX is not set
-# CONFIG_PATA_OLDPIIX is not set
-# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NINJA32 is not set
-# CONFIG_PATA_NS87410 is not set
-# CONFIG_PATA_NS87415 is not set
-# CONFIG_PATA_OPTI is not set
-# CONFIG_PATA_OPTIDMA is not set
-# CONFIG_PATA_PDC_OLD is not set
-# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RZ1000 is not set
-# CONFIG_PATA_SC1200 is not set
-# CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
-# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
-CONFIG_PATA_SCH=y
-# CONFIG_MD is not set
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# Enable only one of the two stacks, unless you know what you are doing
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
-# CONFIG_I2O is not set
-# CONFIG_MACINTOSH_DRIVERS is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-CONFIG_MACVLAN=m
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_VETH is not set
-# CONFIG_NET_SB1000 is not set
-# CONFIG_ARCNET is not set
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-CONFIG_BROADCOM_PHY=m
-CONFIG_ICPLUS_PHY=m
-CONFIG_REALTEK_PHY=m
-CONFIG_MDIO_BITBANG=m
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
-CONFIG_HAPPYMEAL=m
-CONFIG_SUNGEM=m
-CONFIG_CASSINI=m
-CONFIG_NET_VENDOR_3COM=y
-# CONFIG_VORTEX is not set
-# CONFIG_TYPHOON is not set
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_IBM_NEW_EMAC_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_E1000E is not set
-# CONFIG_IP1000 is not set
-# CONFIG_IGB is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_QLA3XXX is not set
-CONFIG_ATL1=m
-CONFIG_ATL1E=m
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
-CONFIG_WLAN_PRE80211=y
-# CONFIG_STRIP is not set
-CONFIG_WLAN_80211=y
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 is not set
-# CONFIG_LIBERTAS is not set
-# CONFIG_AIRO is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-# CONFIG_PRISM54 is not set
-CONFIG_USB_ZD1201=m
-CONFIG_USB_NET_RNDIS_WLAN=m
-CONFIG_RTL8180=m
-CONFIG_RTL8187=m
-# CONFIG_ADM8211 is not set
-# CONFIG_MAC80211_HWSIM is not set
-# CONFIG_P54_COMMON is not set
-CONFIG_ATH5K=m
-# CONFIG_ATH5K_DEBUG is not set
-CONFIG_IWLWIFI=m
-CONFIG_IWLCORE=m
-# CONFIG_IWLWIFI_LEDS is not set
-CONFIG_IWLWIFI_RFKILL=y
-CONFIG_IWL4965=m
-# CONFIG_IWL4965_LEDS is not set
-# CONFIG_IWL4965_SPECTRUM_MEASUREMENT is not set
-# CONFIG_IWLWIFI_DEBUG is not set
-CONFIG_IWL5000=y
-CONFIG_IWL3945=m
-CONFIG_IWL3945_RFKILL=y
-# CONFIG_IWL3945_SPECTRUM_MEASUREMENT is not set
-# CONFIG_IWL3945_LEDS is not set
-# CONFIG_IWL3945_DEBUG is not set
-# CONFIG_HOSTAP is not set
-# CONFIG_B43 is not set
-# CONFIG_B43LEGACY is not set
-# CONFIG_ZD1211RW is not set
-CONFIG_RT2X00=m
-CONFIG_RT2X00_LIB=m
-CONFIG_RT2X00_LIB_PCI=m
-CONFIG_RT2X00_LIB_USB=m
-CONFIG_RT2X00_LIB_FIRMWARE=y
-CONFIG_RT2X00_LIB_RFKILL=y
-CONFIG_RT2X00_LIB_LEDS=y
-CONFIG_RT2400PCI=m
-CONFIG_RT2400PCI_RFKILL=y
-CONFIG_RT2400PCI_LEDS=y
-CONFIG_RT2500PCI=m
-CONFIG_RT2500PCI_RFKILL=y
-CONFIG_RT2500PCI_LEDS=y
-CONFIG_RT61PCI=m
-CONFIG_RT61PCI_RFKILL=y
-CONFIG_RT61PCI_LEDS=y
-CONFIG_RT2500USB=m
-CONFIG_RT2500USB_LEDS=y
-CONFIG_RT73USB=m
-CONFIG_RT73USB_LEDS=y
-CONFIG_RT2X00_LIB_DEBUGFS=y
-# CONFIG_RT2X00_DEBUG is not set
-
-#
-# USB Network Adapters
-#
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_NET_AX8817X=m
-# CONFIG_USB_HSO is not set
-CONFIG_USB_NET_CDCETHER=m
-CONFIG_USB_NET_DM9601=m
-CONFIG_USB_NET_GL620A=m
-CONFIG_USB_NET_NET1080=m
-CONFIG_USB_NET_PLUSB=m
-CONFIG_USB_NET_MCS7830=m
-CONFIG_USB_NET_RNDIS_HOST=m
-CONFIG_USB_NET_CDC_SUBSET=m
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_BELKIN=y
-CONFIG_USB_ARMLINUX=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_KC2190=y
-CONFIG_USB_NET_ZAURUS=m
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_PPPOL2TP=m
-# CONFIG_SLIP is not set
-CONFIG_SLHC=m
-CONFIG_NET_FC=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_FF_MEMLESS=y
-CONFIG_INPUT_POLLDEV=m
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=m
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-CONFIG_MOUSE_PS2_ALPS=y
-CONFIG_MOUSE_PS2_LOGIPS2PP=y
-CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
-CONFIG_MOUSE_PS2_TRACKPOINT=y
-# CONFIG_MOUSE_PS2_TOUCHKIT is not set
-CONFIG_MOUSE_SERIAL=m
-# CONFIG_MOUSE_APPLETOUCH is not set
-CONFIG_MOUSE_VSXXXAA=m
-CONFIG_INPUT_JOYSTICK=y
-# CONFIG_JOYSTICK_ANALOG is not set
-# CONFIG_JOYSTICK_A3D is not set
-# CONFIG_JOYSTICK_ADI is not set
-# CONFIG_JOYSTICK_COBRA is not set
-# CONFIG_JOYSTICK_GF2K is not set
-# CONFIG_JOYSTICK_GRIP is not set
-# CONFIG_JOYSTICK_GRIP_MP is not set
-# CONFIG_JOYSTICK_GUILLEMOT is not set
-# CONFIG_JOYSTICK_INTERACT is not set
-# CONFIG_JOYSTICK_SIDEWINDER is not set
-# CONFIG_JOYSTICK_TMDC is not set
-# CONFIG_JOYSTICK_IFORCE is not set
-# CONFIG_JOYSTICK_WARRIOR is not set
-# CONFIG_JOYSTICK_MAGELLAN is not set
-# CONFIG_JOYSTICK_SPACEORB is not set
-# CONFIG_JOYSTICK_SPACEBALL is not set
-# CONFIG_JOYSTICK_STINGER is not set
-# CONFIG_JOYSTICK_TWIDJOY is not set
-# CONFIG_JOYSTICK_ZHENHUA is not set
-# CONFIG_JOYSTICK_JOYDUMP is not set
-# CONFIG_JOYSTICK_XPAD is not set
-# CONFIG_INPUT_TABLET is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_FUJITSU=m
-CONFIG_TOUCHSCREEN_GUNZE=m
-CONFIG_TOUCHSCREEN_ELO=m
-CONFIG_TOUCHSCREEN_MTOUCH=m
-CONFIG_TOUCHSCREEN_INEXIO=m
-CONFIG_TOUCHSCREEN_MK712=m
-CONFIG_TOUCHSCREEN_PENMOUNT=m
-CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
-CONFIG_TOUCHSCREEN_TOUCHWIN=m
-CONFIG_TOUCHSCREEN_UCB1400=m
-# CONFIG_TOUCHSCREEN_WM97XX is not set
-CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
-CONFIG_TOUCHSCREEN_USB_EGALAX=y
-CONFIG_TOUCHSCREEN_USB_PANJIT=y
-CONFIG_TOUCHSCREEN_USB_3M=y
-CONFIG_TOUCHSCREEN_USB_ITM=y
-CONFIG_TOUCHSCREEN_USB_ETURBO=y
-CONFIG_TOUCHSCREEN_USB_GUNZE=y
-CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
-CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
-CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
-CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
-CONFIG_TOUCHSCREEN_USB_GOTOP=y
-CONFIG_TOUCHSCREEN_TOUCHIT213=m
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_PCSPKR is not set
-# CONFIG_INPUT_APANEL is not set
-# CONFIG_INPUT_WISTRON_BTNS is not set
-CONFIG_INPUT_ATLAS_BTNS=m
-CONFIG_INPUT_ATI_REMOTE=m
-CONFIG_INPUT_ATI_REMOTE2=m
-CONFIG_INPUT_KEYSPAN_REMOTE=m
-CONFIG_INPUT_POWERMATE=m
-CONFIG_INPUT_YEALINK=m
-CONFIG_INPUT_UINPUT=m
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_DEVKMEM is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-CONFIG_FIX_EARLYCON_MEM=y
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_SONYPI is not set
-# CONFIG_MWAVE is not set
-# CONFIG_PC8736x_GPIO is not set
-# CONFIG_NSC_GPIO is not set
-# CONFIG_CS5535_GPIO is not set
-# CONFIG_RAW_DRIVER is not set
-CONFIG_HPET=y
-# CONFIG_HPET_MMAP is not set
-# CONFIG_HANGCHECK_TIMER is not set
-# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_CHARDEV is not set
-CONFIG_I2C_ALGOBIT=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
-
-#
-# External I2C/SMBus adapter drivers
-#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_TINY_USB is not set
-
-#
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Other I2C/SMBus bus drivers
-#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_SCx200_ACB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
-# CONFIG_W1 is not set
-CONFIG_POWER_SUPPLY=y
-# CONFIG_POWER_SUPPLY_DEBUG is not set
-# CONFIG_PDA_POWER is not set
-# CONFIG_BATTERY_DS2760 is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7473 is not set
-# CONFIG_SENSORS_K8TEMP is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_I5K_AMB is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_FSCHMD is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-CONFIG_SENSORS_CORETEMP=y
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_VT8231 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_SENSORS_HDAPS is not set
-# CONFIG_SENSORS_APPLESMC is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-CONFIG_THERMAL=y
-# CONFIG_THERMAL_HWMON is not set
-# CONFIG_WATCHDOG is not set
-
-#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_PASIC3 is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
-CONFIG_VIDEO_V4L1_COMPAT=y
-CONFIG_DVB_CORE=y
-CONFIG_VIDEO_MEDIA=y
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=y
-# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=y
-CONFIG_MEDIA_TUNER_TDA8290=y
-CONFIG_MEDIA_TUNER_TDA9887=y
-CONFIG_MEDIA_TUNER_TEA5761=y
-CONFIG_MEDIA_TUNER_TEA5767=y
-CONFIG_MEDIA_TUNER_MT20XX=y
-CONFIG_MEDIA_TUNER_XC2028=y
-CONFIG_MEDIA_TUNER_XC5000=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_BT848 is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_VIDEO_SAA7134 is not set
-# CONFIG_VIDEO_HEXIUM_ORION is not set
-# CONFIG_VIDEO_HEXIUM_GEMINI is not set
-# CONFIG_VIDEO_CX88 is not set
-# CONFIG_VIDEO_CX23885 is not set
-# CONFIG_VIDEO_AU0828 is not set
-# CONFIG_VIDEO_CX18 is not set
-# CONFIG_VIDEO_CAFE_CCIC is not set
-CONFIG_V4L_USB_DRIVERS=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
-# CONFIG_USB_GSPCA is not set
-# CONFIG_VIDEO_PVRUSB2 is not set
-# CONFIG_VIDEO_EM28XX is not set
-# CONFIG_VIDEO_USBVISION is not set
-# CONFIG_USB_ET61X251 is not set
-# CONFIG_USB_SN9C102 is not set
-# CONFIG_USB_ZC0301 is not set
-# CONFIG_USB_ZR364XX is not set
-# CONFIG_USB_STKWEBCAM is not set
-# CONFIG_USB_S2255 is not set
-# CONFIG_SOC_CAMERA is not set
-# CONFIG_VIDEO_SH_MOBILE_CEU is not set
-# CONFIG_RADIO_ADAPTERS is not set
-# CONFIG_DVB_CAPTURE_DRIVERS is not set
-# CONFIG_DAB is not set
-
-#
-# Graphics support
-#
-CONFIG_AGP=y
-# CONFIG_AGP_ALI is not set
-# CONFIG_AGP_ATI is not set
-# CONFIG_AGP_AMD is not set
-CONFIG_AGP_AMD64=y
-CONFIG_AGP_INTEL=y
-# CONFIG_AGP_NVIDIA is not set
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_SWORKS is not set
-# CONFIG_AGP_VIA is not set
-# CONFIG_AGP_EFFICEON is not set
-CONFIG_DRM=y
-# CONFIG_DRM_TDFX is not set
-# CONFIG_DRM_R128 is not set
-# CONFIG_DRM_RADEON is not set
-CONFIG_DRM_I810=y
-# CONFIG_DRM_I830 is not set
-CONFIG_DRM_I915=y
-# CONFIG_DRM_MGA is not set
-# CONFIG_DRM_SIS is not set
-# CONFIG_DRM_VIA is not set
-# CONFIG_DRM_SAVAGE is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-CONFIG_FB_DDC=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
-# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-
-#
-# Frame buffer hardware drivers
-#
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ARC is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_UVESA is not set
-# CONFIG_FB_VESA is not set
-# CONFIG_FB_EFI is not set
-# CONFIG_FB_N411 is not set
-# CONFIG_FB_HGA is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_I810 is not set
-# CONFIG_FB_LE80578 is not set
-CONFIG_FB_INTEL=y
-CONFIG_FB_INTEL_DEBUG=y
-CONFIG_FB_INTEL_I2C=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_VT8623 is not set
-# CONFIG_FB_CYBLA is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_ARK is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_CARMINE is not set
-# CONFIG_FB_GEODE is not set
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-# CONFIG_LCD_ILI9320 is not set
-CONFIG_LCD_PLATFORM=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_CORGI is not set
-# CONFIG_BACKLIGHT_PROGEAR is not set
-CONFIG_BACKLIGHT_MBP_NVIDIA=y
-
-#
-# Display device support
-#
-CONFIG_DISPLAY_SUPPORT=y
-
-#
-# Display hardware drivers
-#
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_VGACON_SOFT_SCROLLBACK=y
-CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
-CONFIG_VIDEO_SELECT=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-# CONFIG_LOGO is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-CONFIG_SND_HWDEP=y
-CONFIG_SND_RAWMIDI=m
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_SEQ_DUMMY=y
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
-# CONFIG_SND_SEQUENCER_OSS is not set
-CONFIG_SND_DYNAMIC_MINORS=y
-# CONFIG_SND_SUPPORT_OLD_API is not set
-CONFIG_SND_VERBOSE_PROCFS=y
-CONFIG_SND_VERBOSE_PRINTK=y
-CONFIG_SND_DEBUG=y
-# CONFIG_SND_DEBUG_VERBOSE is not set
-CONFIG_SND_PCM_XRUN_DEBUG=y
-CONFIG_SND_VMASTER=y
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_DRIVERS=y
-# CONFIG_SND_PCSP is not set
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-CONFIG_SND_AC97_POWER_SAVE=y
-CONFIG_SND_AC97_POWER_SAVE_DEFAULT=5
-CONFIG_SND_PCI=y
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS300 is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_ATIIXP_MODEM is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AW2 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_OXYGEN is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS5530 is not set
-# CONFIG_SND_CS5535AUDIO is not set
-# CONFIG_SND_DARLA20 is not set
-# CONFIG_SND_GINA20 is not set
-# CONFIG_SND_LAYLA20 is not set
-# CONFIG_SND_DARLA24 is not set
-# CONFIG_SND_GINA24 is not set
-# CONFIG_SND_LAYLA24 is not set
-# CONFIG_SND_MONA is not set
-# CONFIG_SND_MIA is not set
-# CONFIG_SND_ECHO3G is not set
-# CONFIG_SND_INDIGO is not set
-# CONFIG_SND_INDIGOIO is not set
-# CONFIG_SND_INDIGODJ is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_FM801 is not set
-CONFIG_SND_HDA_INTEL=y
-CONFIG_SND_HDA_HWDEP=y
-CONFIG_SND_HDA_CODEC_REALTEK=y
-CONFIG_SND_HDA_CODEC_ANALOG=y
-CONFIG_SND_HDA_CODEC_SIGMATEL=y
-CONFIG_SND_HDA_CODEC_VIA=y
-CONFIG_SND_HDA_CODEC_ATIHDMI=y
-CONFIG_SND_HDA_CODEC_CONEXANT=y
-CONFIG_SND_HDA_CODEC_CMEDIA=y
-CONFIG_SND_HDA_CODEC_SI3054=y
-CONFIG_SND_HDA_GENERIC=y
-CONFIG_SND_HDA_POWER_SAVE=y
-CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_HIFIER is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-CONFIG_SND_INTEL8X0=y
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_PCXHR is not set
-# CONFIG_SND_RIPTIDE is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_SIS7019 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VIRTUOSO is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_USB=y
-CONFIG_SND_USB_AUDIO=m
-CONFIG_SND_USB_USX2Y=m
-CONFIG_SND_USB_CAIAQ=m
-CONFIG_SND_USB_CAIAQ_INPUT=y
-# CONFIG_SND_SOC is not set
-# CONFIG_SOUND_PRIME is not set
-CONFIG_AC97_BUS=y
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-CONFIG_HID_DEBUG=y
-CONFIG_HIDRAW=y
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT_POWERBOOK=y
-CONFIG_HID_FF=y
-CONFIG_HID_PID=y
-CONFIG_LOGITECH_FF=y
-# CONFIG_LOGIRUMBLEPAD2_FF is not set
-CONFIG_PANTHERLORD_FF=y
-CONFIG_THRUSTMASTER_FF=y
-CONFIG_ZEROPLUS_FF=y
-CONFIG_USB_HIDDEV=y
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-CONFIG_USB_SUSPEND=y
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_C67X00_HCD is not set
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
-CONFIG_USB_ISP116X_HCD=m
-# CONFIG_USB_ISP1760_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
-# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_U132_HCD=m
-CONFIG_USB_SL811_HCD=m
-# CONFIG_USB_R8A66597_HCD is not set
-
-#
-# USB Device Class drivers
-#
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-# CONFIG_USB_WDM is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# may also be needed; see USB_STORAGE Help for more information
-#
-CONFIG_USB_STORAGE=y
-# CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_DPCM=y
-CONFIG_USB_STORAGE_USBAT=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_STORAGE_ALAUDA=y
-# CONFIG_USB_STORAGE_ONETOUCH is not set
-CONFIG_USB_STORAGE_KARMA=y
-# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Imaging devices
-#
-CONFIG_USB_MDC800=m
-CONFIG_USB_MICROTEK=m
-CONFIG_USB_MON=y
-
-#
-# USB port drivers
-#
-CONFIG_USB_SERIAL=m
-CONFIG_USB_EZUSB=y
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_AIRCABLE=m
-CONFIG_USB_SERIAL_ARK3116=m
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_CH341=m
-CONFIG_USB_SERIAL_WHITEHEAT=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_CP2101=m
-CONFIG_USB_SERIAL_CYPRESS_M8=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_FUNSOFT=m
-CONFIG_USB_SERIAL_VISOR=m
-CONFIG_USB_SERIAL_IPAQ=m
-CONFIG_USB_SERIAL_IR=m
-CONFIG_USB_SERIAL_EDGEPORT=m
-CONFIG_USB_SERIAL_EDGEPORT_TI=m
-CONFIG_USB_SERIAL_GARMIN=m
-CONFIG_USB_SERIAL_IPW=m
-CONFIG_USB_SERIAL_IUU=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19=y
-CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-CONFIG_USB_SERIAL_KLSI=m
-CONFIG_USB_SERIAL_KOBIL_SCT=m
-CONFIG_USB_SERIAL_MCT_U232=m
-CONFIG_USB_SERIAL_MOS7720=m
-CONFIG_USB_SERIAL_MOS7840=m
-# CONFIG_USB_SERIAL_MOTOROLA is not set
-CONFIG_USB_SERIAL_NAVMAN=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_OTI6858=m
-# CONFIG_USB_SERIAL_SPCP8X5 is not set
-CONFIG_USB_SERIAL_HP4X=m
-CONFIG_USB_SERIAL_SAFE=m
-CONFIG_USB_SERIAL_SAFE_PADDED=y
-CONFIG_USB_SERIAL_SIERRAWIRELESS=m
-CONFIG_USB_SERIAL_TI=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_OPTION=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_SERIAL_DEBUG=m
-
-#
-# USB Miscellaneous drivers
-#
-CONFIG_USB_EMI62=m
-CONFIG_USB_EMI26=m
-CONFIG_USB_ADUTUX=m
-CONFIG_USB_AUERSWALD=m
-# CONFIG_USB_RIO500 is not set
-CONFIG_USB_LEGOTOWER=m
-CONFIG_USB_LCD=m
-CONFIG_USB_BERRY_CHARGE=m
-CONFIG_USB_LED=m
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-CONFIG_USB_PHIDGET=m
-CONFIG_USB_PHIDGETKIT=m
-CONFIG_USB_PHIDGETMOTORCONTROL=m
-CONFIG_USB_PHIDGETSERVO=m
-CONFIG_USB_IDMOUSE=m
-CONFIG_USB_FTDI_ELAN=m
-CONFIG_USB_APPLEDISPLAY=m
-CONFIG_USB_SISUSBVGA=m
-CONFIG_USB_SISUSBVGA_CON=y
-CONFIG_USB_LD=m
-CONFIG_USB_TRANCEVIBRATOR=m
-CONFIG_USB_IOWARRIOR=m
-# CONFIG_USB_TEST is not set
-# CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_GADGET is not set
-CONFIG_MMC=m
-# CONFIG_MMC_DEBUG is not set
-# CONFIG_MMC_UNSAFE_RESUME is not set
-
-#
-# MMC/SD Card Drivers
-#
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_BLOCK_BOUNCE=y
-CONFIG_SDIO_UART=m
-# CONFIG_MMC_TEST is not set
-
-#
-# MMC/SD Host Controller Drivers
-#
-CONFIG_MMC_SDHCI=m
-# CONFIG_MMC_SDHCI_PCI is not set
-CONFIG_MMC_WBSD=m
-CONFIG_MMC_TIFM_SD=m
-CONFIG_MEMSTICK=m
-CONFIG_MEMSTICK_DEBUG=y
-
-#
-# MemoryStick drivers
-#
-# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
-CONFIG_MSPRO_BLOCK=m
-
-#
-# MemoryStick Host Controller Drivers
-#
-# CONFIG_MEMSTICK_TIFM_MS is not set
-# CONFIG_MEMSTICK_JMICRON_38X is not set
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=m
-
-#
-# LED drivers
-#
-# CONFIG_LEDS_PCA9532 is not set
-# CONFIG_LEDS_CLEVO_MAIL is not set
-# CONFIG_LEDS_PCA955X is not set
-
-#
-# LED Triggers
-#
-CONFIG_LEDS_TRIGGERS=y
-# CONFIG_LEDS_TRIGGER_TIMER is not set
-# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
-# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
-# CONFIG_ACCESSIBILITY is not set
-# CONFIG_INFINIBAND is not set
-# CONFIG_EDAC is not set
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_HCTOSYS is not set
-# CONFIG_RTC_DEBUG is not set
-
-#
-# RTC interfaces
-#
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
-# CONFIG_RTC_DRV_TEST is not set
-
-#
-# I2C RTC drivers
-#
-# CONFIG_RTC_DRV_DS1307 is not set
-# CONFIG_RTC_DRV_DS1374 is not set
-# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_MAX6900 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
-# CONFIG_RTC_DRV_X1205 is not set
-# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
-# CONFIG_RTC_DRV_M41T80 is not set
-# CONFIG_RTC_DRV_S35390A is not set
-# CONFIG_RTC_DRV_FM3130 is not set
-
-#
-# SPI RTC drivers
-#
-
-#
-# Platform RTC drivers
-#
-CONFIG_RTC_DRV_CMOS=y
-# CONFIG_RTC_DRV_DS1511 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-
-#
-# on-CPU RTC drivers
-#
-# CONFIG_DMADEVICES is not set
-# CONFIG_UIO is not set
-
-#
-# Firmware Drivers
-#
-# CONFIG_EDD is not set
-CONFIG_FIRMWARE_MEMMAP=y
-# CONFIG_DELL_RBU is not set
-# CONFIG_DCDBAS is not set
-# CONFIG_DMIID is not set
-# CONFIG_ISCSI_IBFT_FIND is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-CONFIG_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-# CONFIG_PRINT_QUOTA_WARNING is not set
-# CONFIG_QFMT_V1 is not set
-CONFIG_QFMT_V2=y
-CONFIG_QUOTACTL=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_VMCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_HUGETLBFS=y
-CONFIG_HUGETLB_PAGE=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Layered filesystems
-#
-# CONFIG_ECRYPT_FS is not set
-CONFIG_UNION_FS=y
-# CONFIG_UNION_FS_XATTR is not set
-# CONFIG_UNION_FS_DEBUG is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-CONFIG_SQUASHFS=y
-# CONFIG_SQUASHFS_EMBEDDED is not set
-CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
-# CONFIG_VXFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-CONFIG_AMIGA_PARTITION=y
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-CONFIG_KARMA_PARTITION=y
-CONFIG_EFI_PARTITION=y
-# CONFIG_SYSV68_PARTITION is not set
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="utf8"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-# CONFIG_DLM is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-CONFIG_PRINTK_TIME=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_UNUSED_SYMBOLS=y
-CONFIG_DEBUG_FS=y
-# CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SHIRQ=y
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_LOCK_ALLOC is not set
-# CONFIG_PROVE_LOCKING is not set
-# CONFIG_LOCK_STAT is not set
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-CONFIG_STACKTRACE=y
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_HIGHMEM is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
-CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_DEBUG_LIST=y
-# CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
-CONFIG_BOOT_PRINTK_DELAY=y
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_FAULT_INJECTION is not set
-CONFIG_LATENCYTOP=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_TRACING=y
-# CONFIG_FTRACE is not set
-# CONFIG_IRQSOFF_TRACER is not set
-CONFIG_SYSPROF_TRACER=y
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
-# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-# CONFIG_STRICT_DEVMEM is not set
-CONFIG_X86_VERBOSE_BOOTUP=y
-CONFIG_EARLY_PRINTK=y
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUG_PER_CPU_MAPS is not set
-CONFIG_X86_PTDUMP=y
-CONFIG_DEBUG_RODATA=y
-# CONFIG_DEBUG_RODATA_TEST is not set
-# CONFIG_DEBUG_NX_TEST is not set
-# CONFIG_4KSTACKS is not set
-CONFIG_DOUBLEFAULT=y
-# CONFIG_MMIOTRACE is not set
-CONFIG_IO_DELAY_TYPE_0X80=0
-CONFIG_IO_DELAY_TYPE_0XED=1
-CONFIG_IO_DELAY_TYPE_UDELAY=2
-CONFIG_IO_DELAY_TYPE_NONE=3
-CONFIG_IO_DELAY_0X80=y
-# CONFIG_IO_DELAY_0XED is not set
-# CONFIG_IO_DELAY_UDELAY is not set
-# CONFIG_IO_DELAY_NONE is not set
-CONFIG_DEFAULT_IO_DELAY_TYPE=0
-CONFIG_DEBUG_BOOT_PARAMS=y
-# CONFIG_CPA_DEBUG is not set
-# CONFIG_OPTIMIZE_INLINING is not set
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
-CONFIG_SECURITY_NETWORK_XFRM=y
-CONFIG_SECURITY_FILE_CAPABILITIES=y
-# CONFIG_SECURITY_ROOTPLUG is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=65536
-# CONFIG_SECURITY_SELINUX is not set
-# CONFIG_SECURITY_SMACK is not set
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_NULL=m
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_AUTHENC=m
-CONFIG_CRYPTO_TEST=m
-
-#
-# Authenticated Encryption with Associated Data
-#
-CONFIG_CRYPTO_CCM=m
-CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_SEQIV=m
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_CTR=m
-# CONFIG_CRYPTO_CTS is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-
-#
-# Hash modes
-#
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-
-#
-# Digest
-#
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-
-#
-# Ciphers
-#
-CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_AES_586 is not set
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
-# CONFIG_CRYPTO_SALSA20_586 is not set
-CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-# CONFIG_CRYPTO_TWOFISH_586 is not set
-
-#
-# Compression
-#
-CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_LZO is not set
-CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_PADLOCK is not set
-# CONFIG_CRYPTO_DEV_GEODE is not set
-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-CONFIG_HAVE_KVM=y
-# CONFIG_VIRTUALIZATION is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_GENERIC_FIND_FIRST_BIT=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=m
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-CONFIG_LIBCRC32C=m
-CONFIG_AUDIT_GENERIC=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0001-drm-remove-define-for-non-linux-systems.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0001-drm-remove-define-for-non-linux-systems.patch
deleted file mode 100644 (file)
index 588c1af..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-commit 2e6ec7cdc09f36be1cbe9aeaccfc45f307fc0060
-Author: Carlos R. Mafra <crmafra2@gmail.com>
-Date:   Wed Jul 30 12:29:37 2008 -0700
-
-    drm: remove #define's for non-linux systems
-    
-    There is no point in considering FreeBSD et al.  in the linux kernel
-    source code.
-    
-    Signed-off-by: Carlos R. Mafra <crmafra@gmail.com>
-    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/include/drm/drm.h b/include/drm/drm.h
-index 38d3c6b..0864c69 100644
---- a/include/drm/drm.h
-+++ b/include/drm/drm.h
-@@ -36,7 +36,6 @@
- #ifndef _DRM_H_
- #define _DRM_H_
--#if defined(__linux__)
- #if defined(__KERNEL__)
- #endif
- #include <asm/ioctl.h>                /* For _IO* macros */
-@@ -46,22 +45,6 @@
- #define DRM_IOC_WRITE         _IOC_WRITE
- #define DRM_IOC_READWRITE     _IOC_READ|_IOC_WRITE
- #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
--#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
--#if defined(__FreeBSD__) && defined(IN_MODULE)
--/* Prevent name collision when including sys/ioccom.h */
--#undef ioctl
--#include <sys/ioccom.h>
--#define ioctl(a,b,c)          xf86ioctl(a,b,c)
--#else
--#include <sys/ioccom.h>
--#endif                                /* __FreeBSD__ && xf86ioctl */
--#define DRM_IOCTL_NR(n)               ((n) & 0xff)
--#define DRM_IOC_VOID          IOC_VOID
--#define DRM_IOC_READ          IOC_OUT
--#define DRM_IOC_WRITE         IOC_IN
--#define DRM_IOC_READWRITE     IOC_INOUT
--#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
--#endif
- #define DRM_MAJOR       226
- #define DRM_MAX_MINOR   15
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0002-i915-remove-settable-use_mi_batchbuffer_start.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0002-i915-remove-settable-use_mi_batchbuffer_start.patch
deleted file mode 100644 (file)
index f3c41f7..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-commit 91019197abbfde388d0b71b0fc8979a936c23fe3
-Author: Keith Packard <keithp@keithp.com>
-Date:   Wed Jul 30 12:28:47 2008 -0700
-
-    i915: remove settable use_mi_batchbuffer_start
-    
-    The driver can know what hardware requires MI_BATCH_BUFFER vs
-    MI_BATCH_BUFFER_START; there's no reason to let user mode configure this.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 8897434..24adbde 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -159,13 +159,6 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
-       dev_priv->current_page = 0;
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
--      /* We are using separate values as placeholders for mechanisms for
--       * private backbuffer/depthbuffer usage.
--       */
--      dev_priv->use_mi_batchbuffer_start = 0;
--      if (IS_I965G(dev)) /* 965 doesn't support older method */
--              dev_priv->use_mi_batchbuffer_start = 1;
--
-       /* Allow hardware batchbuffers unless told otherwise.
-        */
-       dev_priv->allow_batchbuffer = 1;
-@@ -486,7 +479,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
-                               return ret;
-               }
--              if (dev_priv->use_mi_batchbuffer_start) {
-+              if (!IS_I830(dev) && !IS_845G(dev)) {
-                       BEGIN_LP_RING(2);
-                       if (IS_I965G(dev)) {
-                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
-@@ -697,8 +690,6 @@ static int i915_setparam(struct drm_device *dev, void *data,
-       switch (param->param) {
-       case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
--              if (!IS_I965G(dev))
--                      dev_priv->use_mi_batchbuffer_start = param->value;
-               break;
-       case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
-               dev_priv->tex_lru_log_granularity = param->value;
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index d7326d9..2d441d3 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -99,7 +99,6 @@ typedef struct drm_i915_private {
-       int front_offset;
-       int current_page;
-       int page_flipping;
--      int use_mi_batchbuffer_start;
-       wait_queue_head_t irq_queue;
-       atomic_t irq_received;
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0003-i915-Ignore-X-server-provided-mmio-address.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0003-i915-Ignore-X-server-provided-mmio-address.patch
deleted file mode 100644 (file)
index 9f7e0b4..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-commit 20ae3cf7d4a9ae8d23bcffa67c9a34fc2640d217
-Author: Keith Packard <keithp@keithp.com>
-Date:   Wed Jul 30 12:36:08 2008 -0700
-
-    i915: Ignore X server provided mmio address
-    
-    It is already correctly detected by the kernel for use in suspend/resume.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 24adbde..01a869b 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -121,13 +121,6 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
-               return -EINVAL;
-       }
--      dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
--      if (!dev_priv->mmio_map) {
--              i915_dma_cleanup(dev);
--              DRM_ERROR("can not find mmio map!\n");
--              return -EINVAL;
--      }
--
-       dev_priv->sarea_priv = (drm_i915_sarea_t *)
-           ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
-@@ -194,11 +187,6 @@ static int i915_dma_resume(struct drm_device * dev)
-               return -EINVAL;
-       }
--      if (!dev_priv->mmio_map) {
--              DRM_ERROR("can not find mmio map!\n");
--              return -EINVAL;
--      }
--
-       if (dev_priv->ring.map.handle == NULL) {
-               DRM_ERROR("can not ioremap virtual address for"
-                         " ring buffer\n");
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0004-i915-Use-more-consistent-names-for-regs-and-store.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0004-i915-Use-more-consistent-names-for-regs-and-store.patch
deleted file mode 100644 (file)
index f7a310e..0000000
+++ /dev/null
@@ -1,2746 +0,0 @@
-commit 573e91575687018b4307f53a50f4da0084dbdf3d
-Author: Jesse Barnes <jbarnes@virtuousgeek.org>
-Date:   Tue Jul 29 11:54:06 2008 -0700
-
-    i915: Use more consistent names for regs, and store them in a separate file.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 01a869b..7be580b 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -40,11 +40,11 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
--      u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-+      u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-       int i;
-       for (i = 0; i < 10000; i++) {
--              ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-+              ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->Size;
-@@ -67,8 +67,8 @@ void i915_kernel_lost_context(struct drm_device * dev)
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
--      ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
--      ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
-+      ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-+      ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
-       ring->space = ring->head - (ring->tail + 8);
-       if (ring->space < 0)
-               ring->space += ring->Size;
-@@ -98,13 +98,13 @@ static int i915_dma_cleanup(struct drm_device * dev)
-               drm_pci_free(dev, dev_priv->status_page_dmah);
-               dev_priv->status_page_dmah = NULL;
-               /* Need to rewrite hardware status page */
--              I915_WRITE(0x02080, 0x1ffff000);
-+              I915_WRITE(HWS_PGA, 0x1ffff000);
-       }
-       if (dev_priv->status_gfx_addr) {
-               dev_priv->status_gfx_addr = 0;
-               drm_core_ioremapfree(&dev_priv->hws_map, dev);
--              I915_WRITE(0x2080, 0x1ffff000);
-+              I915_WRITE(HWS_PGA, 0x1ffff000);
-       }
-       return 0;
-@@ -170,7 +170,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
-               dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-               memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
--              I915_WRITE(0x02080, dev_priv->dma_status_page);
-+              I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-       }
-       DRM_DEBUG("Enabled hardware status page\n");
-       return 0;
-@@ -201,9 +201,9 @@ static int i915_dma_resume(struct drm_device * dev)
-       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-       if (dev_priv->status_gfx_addr != 0)
--              I915_WRITE(0x02080, dev_priv->status_gfx_addr);
-+              I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-       else
--              I915_WRITE(0x02080, dev_priv->dma_status_page);
-+              I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-       DRM_DEBUG("Enabled hardware status page\n");
-       return 0;
-@@ -402,8 +402,8 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
-               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
-       BEGIN_LP_RING(4);
--      OUT_RING(CMD_STORE_DWORD_IDX);
--      OUT_RING(20);
-+      OUT_RING(MI_STORE_DWORD_INDEX);
-+      OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-@@ -505,7 +505,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
-       i915_kernel_lost_context(dev);
-       BEGIN_LP_RING(2);
--      OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-+      OUT_RING(MI_FLUSH | MI_READ_FLUSH);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-@@ -530,8 +530,8 @@ static int i915_dispatch_flip(struct drm_device * dev)
-       dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
-       BEGIN_LP_RING(4);
--      OUT_RING(CMD_STORE_DWORD_IDX);
--      OUT_RING(20);
-+      OUT_RING(MI_STORE_DWORD_INDEX);
-+      OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-@@ -728,8 +728,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
-       dev_priv->hw_status_page = dev_priv->hws_map.handle;
-       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
--      I915_WRITE(0x02080, dev_priv->status_gfx_addr);
--      DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
-+      I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-+      DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n",
-                       dev_priv->status_gfx_addr);
-       DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
-       return 0;
-diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
-index 93aed1c..6c99aab 100644
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -279,13 +279,13 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
-       dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
-       dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
-       dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
--      dev_priv->saveDSPABASE = I915_READ(DSPABASE);
-+      dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
-       if (IS_I965G(dev)) {
-               dev_priv->saveDSPASURF = I915_READ(DSPASURF);
-               dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
-       }
-       i915_save_palette(dev, PIPE_A);
--      dev_priv->savePIPEASTAT = I915_READ(I915REG_PIPEASTAT);
-+      dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
-       /* Pipe & plane B info */
-       dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
-@@ -307,13 +307,13 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
-       dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
-       dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
-       dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
--      dev_priv->saveDSPBBASE = I915_READ(DSPBBASE);
-+      dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
-       if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
-               dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
-               dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
-       }
-       i915_save_palette(dev, PIPE_B);
--      dev_priv->savePIPEBSTAT = I915_READ(I915REG_PIPEBSTAT);
-+      dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
-       /* CRT state */
-       dev_priv->saveADPA = I915_READ(ADPA);
-@@ -328,9 +328,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
-               dev_priv->saveLVDS = I915_READ(LVDS);
-       if (!IS_I830(dev) && !IS_845G(dev))
-               dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
--      dev_priv->saveLVDSPP_ON = I915_READ(LVDSPP_ON);
--      dev_priv->saveLVDSPP_OFF = I915_READ(LVDSPP_OFF);
--      dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE);
-+      dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
-+      dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
-+      dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
-       /* FIXME: save TV & SDVO state */
-@@ -341,19 +341,19 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
-       dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
-       /* Interrupt state */
--      dev_priv->saveIIR = I915_READ(I915REG_INT_IDENTITY_R);
--      dev_priv->saveIER = I915_READ(I915REG_INT_ENABLE_R);
--      dev_priv->saveIMR = I915_READ(I915REG_INT_MASK_R);
-+      dev_priv->saveIIR = I915_READ(IIR);
-+      dev_priv->saveIER = I915_READ(IER);
-+      dev_priv->saveIMR = I915_READ(IMR);
-       /* VGA state */
--      dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0);
--      dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1);
--      dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV);
-+      dev_priv->saveVGA0 = I915_READ(VGA0);
-+      dev_priv->saveVGA1 = I915_READ(VGA1);
-+      dev_priv->saveVGA_PD = I915_READ(VGA_PD);
-       dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
-       /* Clock gating state */
-       dev_priv->saveD_STATE = I915_READ(D_STATE);
--      dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
-+      dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
-       /* Cache mode state */
-       dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
-@@ -363,7 +363,7 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
-       /* Scratch space */
-       for (i = 0; i < 16; i++) {
--              dev_priv->saveSWF0[i] = I915_READ(SWF0 + (i << 2));
-+              dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
-               dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
-       }
-       for (i = 0; i < 3; i++)
-@@ -424,7 +424,7 @@ static int i915_resume(struct drm_device *dev)
-       I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
-       I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
-       I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
--      I915_WRITE(DSPABASE, dev_priv->saveDSPABASE);
-+      I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
-       I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
-       if (IS_I965G(dev)) {
-               I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
-@@ -436,7 +436,7 @@ static int i915_resume(struct drm_device *dev)
-       i915_restore_palette(dev, PIPE_A);
-       /* Enable the plane */
-       I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
--      I915_WRITE(DSPABASE, I915_READ(DSPABASE));
-+      I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
-       /* Pipe & plane B info */
-       if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
-@@ -466,7 +466,7 @@ static int i915_resume(struct drm_device *dev)
-       I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
-       I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
-       I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
--      I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE);
-+      I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
-       I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
-       if (IS_I965G(dev)) {
-               I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
-@@ -478,7 +478,7 @@ static int i915_resume(struct drm_device *dev)
-       i915_restore_palette(dev, PIPE_B);
-       /* Enable the plane */
-       I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
--      I915_WRITE(DSPBBASE, I915_READ(DSPBBASE));
-+      I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
-       /* CRT state */
-       I915_WRITE(ADPA, dev_priv->saveADPA);
-@@ -493,9 +493,9 @@ static int i915_resume(struct drm_device *dev)
-       I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
-       I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
--      I915_WRITE(LVDSPP_ON, dev_priv->saveLVDSPP_ON);
--      I915_WRITE(LVDSPP_OFF, dev_priv->saveLVDSPP_OFF);
--      I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE);
-+      I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
-+      I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
-+      I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
-       I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
-       /* FIXME: restore TV & SDVO state */
-@@ -508,14 +508,14 @@ static int i915_resume(struct drm_device *dev)
-       /* VGA state */
-       I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
--      I915_WRITE(VCLK_DIVISOR_VGA0, dev_priv->saveVCLK_DIVISOR_VGA0);
--      I915_WRITE(VCLK_DIVISOR_VGA1, dev_priv->saveVCLK_DIVISOR_VGA1);
--      I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV);
-+      I915_WRITE(VGA0, dev_priv->saveVGA0);
-+      I915_WRITE(VGA1, dev_priv->saveVGA1);
-+      I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
-       udelay(150);
-       /* Clock gating state */
-       I915_WRITE (D_STATE, dev_priv->saveD_STATE);
--      I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
-+      I915_WRITE(CG_2D_DIS, dev_priv->saveCG_2D_DIS);
-       /* Cache mode state */
-       I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
-@@ -524,7 +524,7 @@ static int i915_resume(struct drm_device *dev)
-       I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
-       for (i = 0; i < 16; i++) {
--              I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]);
-+              I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
-               I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
-       }
-       for (i = 0; i < 3; i++)
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index 2d441d3..afb51a3 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -30,6 +30,8 @@
- #ifndef _I915_DRV_H_
- #define _I915_DRV_H_
-+#include "i915_reg.h"
-+
- /* General customization:
-  */
-@@ -138,7 +140,7 @@ typedef struct drm_i915_private {
-       u32 saveDSPASTRIDE;
-       u32 saveDSPASIZE;
-       u32 saveDSPAPOS;
--      u32 saveDSPABASE;
-+      u32 saveDSPAADDR;
-       u32 saveDSPASURF;
-       u32 saveDSPATILEOFF;
-       u32 savePFIT_PGM_RATIOS;
-@@ -159,24 +161,24 @@ typedef struct drm_i915_private {
-       u32 saveDSPBSTRIDE;
-       u32 saveDSPBSIZE;
-       u32 saveDSPBPOS;
--      u32 saveDSPBBASE;
-+      u32 saveDSPBADDR;
-       u32 saveDSPBSURF;
-       u32 saveDSPBTILEOFF;
--      u32 saveVCLK_DIVISOR_VGA0;
--      u32 saveVCLK_DIVISOR_VGA1;
--      u32 saveVCLK_POST_DIV;
-+      u32 saveVGA0;
-+      u32 saveVGA1;
-+      u32 saveVGA_PD;
-       u32 saveVGACNTRL;
-       u32 saveADPA;
-       u32 saveLVDS;
--      u32 saveLVDSPP_ON;
--      u32 saveLVDSPP_OFF;
-+      u32 savePP_ON_DELAYS;
-+      u32 savePP_OFF_DELAYS;
-       u32 saveDVOA;
-       u32 saveDVOB;
-       u32 saveDVOC;
-       u32 savePP_ON;
-       u32 savePP_OFF;
-       u32 savePP_CONTROL;
--      u32 savePP_CYCLE;
-+      u32 savePP_DIVISOR;
-       u32 savePFIT_CONTROL;
-       u32 save_palette_a[256];
-       u32 save_palette_b[256];
-@@ -189,7 +191,7 @@ typedef struct drm_i915_private {
-       u32 saveIMR;
-       u32 saveCACHE_MODE_0;
-       u32 saveD_STATE;
--      u32 saveDSPCLK_GATE_D;
-+      u32 saveCG_2D_DIS;
-       u32 saveMI_ARB_STATE;
-       u32 saveSWF0[16];
-       u32 saveSWF1[16];
-@@ -283,816 +285,26 @@ extern void i915_mem_release(struct drm_device * dev,
-       if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring);   \
-       dev_priv->ring.tail = outring;                                  \
-       dev_priv->ring.space -= outcount * 4;                           \
--      I915_WRITE(LP_RING + RING_TAIL, outring);                       \
-+      I915_WRITE(PRB0_TAIL, outring);                 \
- } while(0)
--extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
--
--/* Extended config space */
--#define LBB 0xf4
--
--/* VGA stuff */
--
--#define VGA_ST01_MDA 0x3ba
--#define VGA_ST01_CGA 0x3da
--
--#define VGA_MSR_WRITE 0x3c2
--#define VGA_MSR_READ 0x3cc
--#define   VGA_MSR_MEM_EN (1<<1)
--#define   VGA_MSR_CGA_MODE (1<<0)
--
--#define VGA_SR_INDEX 0x3c4
--#define VGA_SR_DATA 0x3c5
--
--#define VGA_AR_INDEX 0x3c0
--#define   VGA_AR_VID_EN (1<<5)
--#define VGA_AR_DATA_WRITE 0x3c0
--#define VGA_AR_DATA_READ 0x3c1
--
--#define VGA_GR_INDEX 0x3ce
--#define VGA_GR_DATA 0x3cf
--/* GR05 */
--#define   VGA_GR_MEM_READ_MODE_SHIFT 3
--#define     VGA_GR_MEM_READ_MODE_PLANE 1
--/* GR06 */
--#define   VGA_GR_MEM_MODE_MASK 0xc
--#define   VGA_GR_MEM_MODE_SHIFT 2
--#define   VGA_GR_MEM_A0000_AFFFF 0
--#define   VGA_GR_MEM_A0000_BFFFF 1
--#define   VGA_GR_MEM_B0000_B7FFF 2
--#define   VGA_GR_MEM_B0000_BFFFF 3
--
--#define VGA_DACMASK 0x3c6
--#define VGA_DACRX 0x3c7
--#define VGA_DACWX 0x3c8
--#define VGA_DACDATA 0x3c9
--
--#define VGA_CR_INDEX_MDA 0x3b4
--#define VGA_CR_DATA_MDA 0x3b5
--#define VGA_CR_INDEX_CGA 0x3d4
--#define VGA_CR_DATA_CGA 0x3d5
--
--#define GFX_OP_USER_INTERRUPT         ((0<<29)|(2<<23))
--#define GFX_OP_BREAKPOINT_INTERRUPT   ((0<<29)|(1<<23))
--#define CMD_REPORT_HEAD                       (7<<23)
--#define CMD_STORE_DWORD_IDX           ((0x21<<23) | 0x1)
--#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
--
--#define INST_PARSER_CLIENT   0x00000000
--#define INST_OP_FLUSH        0x02000000
--#define INST_FLUSH_MAP_CACHE 0x00000001
--
--#define BB1_START_ADDR_MASK   (~0x7)
--#define BB1_PROTECTED         (1<<0)
--#define BB1_UNPROTECTED       (0<<0)
--#define BB2_END_ADDR_MASK     (~0x7)
--
--/* Framebuffer compression */
--#define FBC_CFB_BASE          0x03200 /* 4k page aligned */
--#define FBC_LL_BASE           0x03204 /* 4k page aligned */
--#define FBC_CONTROL           0x03208
--#define   FBC_CTL_EN          (1<<31)
--#define   FBC_CTL_PERIODIC    (1<<30)
--#define   FBC_CTL_INTERVAL_SHIFT (16)
--#define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
--#define   FBC_CTL_STRIDE_SHIFT        (5)
--#define   FBC_CTL_FENCENO     (1<<0)
--#define FBC_COMMAND           0x0320c
--#define   FBC_CMD_COMPRESS    (1<<0)
--#define FBC_STATUS            0x03210
--#define   FBC_STAT_COMPRESSING        (1<<31)
--#define   FBC_STAT_COMPRESSED (1<<30)
--#define   FBC_STAT_MODIFIED   (1<<29)
--#define   FBC_STAT_CURRENT_LINE       (1<<0)
--#define FBC_CONTROL2          0x03214
--#define   FBC_CTL_FENCE_DBL   (0<<4)
--#define   FBC_CTL_IDLE_IMM    (0<<2)
--#define   FBC_CTL_IDLE_FULL   (1<<2)
--#define   FBC_CTL_IDLE_LINE   (2<<2)
--#define   FBC_CTL_IDLE_DEBUG  (3<<2)
--#define   FBC_CTL_CPU_FENCE   (1<<1)
--#define   FBC_CTL_PLANEA      (0<<0)
--#define   FBC_CTL_PLANEB      (1<<0)
--#define FBC_FENCE_OFF         0x0321b
--
--#define FBC_LL_SIZE           (1536)
--#define FBC_LL_PAD            (32)
--
--/* Interrupt bits:
-- */
--#define USER_INT_FLAG    (1<<1)
--#define VSYNC_PIPEB_FLAG (1<<5)
--#define VSYNC_PIPEA_FLAG (1<<7)
--#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
--
--#define I915REG_HWSTAM                0x02098
--#define I915REG_INT_IDENTITY_R        0x020a4
--#define I915REG_INT_MASK_R    0x020a8
--#define I915REG_INT_ENABLE_R  0x020a0
--
--#define I915REG_PIPEASTAT     0x70024
--#define I915REG_PIPEBSTAT     0x71024
--
--#define I915_VBLANK_INTERRUPT_ENABLE  (1UL<<17)
--#define I915_VBLANK_CLEAR             (1UL<<1)
--
--#define SRX_INDEX             0x3c4
--#define SRX_DATA              0x3c5
--#define SR01                  1
--#define SR01_SCREEN_OFF               (1<<5)
--
--#define PPCR                  0x61204
--#define PPCR_ON                       (1<<0)
--
--#define DVOB                  0x61140
--#define DVOB_ON                       (1<<31)
--#define DVOC                  0x61160
--#define DVOC_ON                       (1<<31)
--#define LVDS                  0x61180
--#define LVDS_ON                       (1<<31)
--
--#define ADPA                  0x61100
--#define ADPA_DPMS_MASK                (~(3<<10))
--#define ADPA_DPMS_ON          (0<<10)
--#define ADPA_DPMS_SUSPEND     (1<<10)
--#define ADPA_DPMS_STANDBY     (2<<10)
--#define ADPA_DPMS_OFF         (3<<10)
--
--#define NOPID                   0x2094
--#define LP_RING                       0x2030
--#define HP_RING                       0x2040
--/* The binner has its own ring buffer:
-- */
--#define HWB_RING              0x2400
--
--#define RING_TAIL             0x00
--#define TAIL_ADDR             0x001FFFF8
--#define RING_HEAD             0x04
--#define HEAD_WRAP_COUNT               0xFFE00000
--#define HEAD_WRAP_ONE         0x00200000
--#define HEAD_ADDR             0x001FFFFC
--#define RING_START            0x08
--#define START_ADDR            0x0xFFFFF000
--#define RING_LEN              0x0C
--#define RING_NR_PAGES         0x001FF000
--#define RING_REPORT_MASK      0x00000006
--#define RING_REPORT_64K               0x00000002
--#define RING_REPORT_128K      0x00000004
--#define RING_NO_REPORT                0x00000000
--#define RING_VALID_MASK               0x00000001
--#define RING_VALID            0x00000001
--#define RING_INVALID          0x00000000
--
--/* Instruction parser error reg:
-- */
--#define IPEIR                 0x2088
--
--/* Scratch pad debug 0 reg:
-- */
--#define SCPD0                 0x209c
--
--/* Error status reg:
-- */
--#define ESR                   0x20b8
--
--/* Secondary DMA fetch address debug reg:
-- */
--#define DMA_FADD_S            0x20d4
--
--/* Memory Interface Arbitration State
-- */
--#define MI_ARB_STATE          0x20e4
--
--/* Cache mode 0 reg.
-- *  - Manipulating render cache behaviour is central
-- *    to the concept of zone rendering, tuning this reg can help avoid
-- *    unnecessary render cache reads and even writes (for z/stencil)
-- *    at beginning and end of scene.
-- *
-- * - To change a bit, write to this reg with a mask bit set and the
-- * bit of interest either set or cleared.  EG: (BIT<<16) | BIT to set.
-- */
--#define Cache_Mode_0          0x2120
--#define CACHE_MODE_0          0x2120
--#define CM0_MASK_SHIFT          16
--#define CM0_IZ_OPT_DISABLE      (1<<6)
--#define CM0_ZR_OPT_DISABLE      (1<<5)
--#define CM0_DEPTH_EVICT_DISABLE (1<<4)
--#define CM0_COLOR_EVICT_DISABLE (1<<3)
--#define CM0_DEPTH_WRITE_DISABLE (1<<1)
--#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
--
--
--/* Graphics flush control.  A CPU write flushes the GWB of all writes.
-- * The data is discarded.
-- */
--#define GFX_FLSH_CNTL         0x2170
--
--/* Binner control.  Defines the location of the bin pointer list:
-- */
--#define BINCTL                        0x2420
--#define BC_MASK                       (1 << 9)
--
--/* Binned scene info.
-- */
--#define BINSCENE              0x2428
--#define BS_OP_LOAD            (1 << 8)
--#define BS_MASK                       (1 << 22)
--
--/* Bin command parser debug reg:
-- */
--#define BCPD                  0x2480
--
--/* Bin memory control debug reg:
-- */
--#define BMCD                  0x2484
--
--/* Bin data cache debug reg:
-- */
--#define BDCD                  0x2488
--
--/* Binner pointer cache debug reg:
-- */
--#define BPCD                  0x248c
--
--/* Binner scratch pad debug reg:
-- */
--#define BINSKPD                       0x24f0
--
--/* HWB scratch pad debug reg:
-- */
--#define HWBSKPD                       0x24f4
--
--/* Binner memory pool reg:
-- */
--#define BMP_BUFFER            0x2430
--#define BMP_PAGE_SIZE_4K      (0 << 10)
--#define BMP_BUFFER_SIZE_SHIFT 1
--#define BMP_ENABLE            (1 << 0)
--
--/* Get/put memory from the binner memory pool:
-- */
--#define BMP_GET                       0x2438
--#define BMP_PUT                       0x2440
--#define BMP_OFFSET_SHIFT      5
--
--/* 3D state packets:
-- */
--#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
--
--#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
--#define SC_UPDATE_SCISSOR       (0x1<<1)
--#define SC_ENABLE_MASK          (0x1<<0)
--#define SC_ENABLE               (0x1<<0)
--
--#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
--
--#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
--#define SCI_YMIN_MASK      (0xffff<<16)
--#define SCI_XMIN_MASK      (0xffff<<0)
--#define SCI_YMAX_MASK      (0xffff<<16)
--#define SCI_XMAX_MASK      (0xffff<<0)
--
--#define GFX_OP_SCISSOR_ENABLE  ((0x3<<29)|(0x1c<<24)|(0x10<<19))
--#define GFX_OP_SCISSOR_RECT    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
--#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
--#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
--#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
--#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
--#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
--
--#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
--
--#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
--#define XY_SRC_COPY_BLT_CMD           ((2<<29)|(0x53<<22)|6)
--#define XY_SRC_COPY_BLT_WRITE_ALPHA   (1<<21)
--#define XY_SRC_COPY_BLT_WRITE_RGB     (1<<20)
--#define XY_SRC_COPY_BLT_SRC_TILED     (1<<15)
--#define XY_SRC_COPY_BLT_DST_TILED     (1<<11)
--
--#define MI_BATCH_BUFFER               ((0x30<<23)|1)
--#define MI_BATCH_BUFFER_START (0x31<<23)
--#define MI_BATCH_BUFFER_END   (0xA<<23)
--#define MI_BATCH_NON_SECURE   (1)
--#define MI_BATCH_NON_SECURE_I965 (1<<8)
--
--#define MI_WAIT_FOR_EVENT       ((0x3<<23))
--#define MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
--#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
--#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
--
--#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
--
--#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
--#define ASYNC_FLIP                (1<<22)
--#define DISPLAY_PLANE_A           (0<<20)
--#define DISPLAY_PLANE_B           (1<<20)
--
--/* Display regs */
--#define DSPACNTR                0x70180
--#define DSPBCNTR                0x71180
--#define DISPPLANE_SEL_PIPE_MASK                 (1<<24)
--
--/* Define the region of interest for the binner:
-- */
--#define CMD_OP_BIN_CONTROL     ((0x3<<29)|(0x1d<<24)|(0x84<<16)|4)
--
--#define CMD_OP_DESTBUFFER_INFO         ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
--
--#define CMD_MI_FLUSH         (0x04 << 23)
--#define MI_NO_WRITE_FLUSH    (1 << 2)
--#define MI_READ_FLUSH        (1 << 0)
--#define MI_EXE_FLUSH         (1 << 1)
--#define MI_END_SCENE         (1 << 4) /* flush binner and incr scene count */
--#define MI_SCENE_COUNT       (1 << 3) /* just increment scene count */
--
--#define BREADCRUMB_BITS 31
--#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
--
--#define READ_BREADCRUMB(dev_priv)  (((volatile u32*)(dev_priv->hw_status_page))[5])
--#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
--
--#define BLC_PWM_CTL           0x61254
--#define BACKLIGHT_MODULATION_FREQ_SHIFT               (17)
--
--#define BLC_PWM_CTL2          0x61250
- /**
-- * This is the most significant 15 bits of the number of backlight cycles in a
-- * complete cycle of the modulated backlight control.
-+ * Reads a dword out of the status page, which is written to from the command
-+ * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
-+ * MI_STORE_DATA_IMM.
-  *
-- * The actual value is this field multiplied by two.
-- */
--#define BACKLIGHT_MODULATION_FREQ_MASK                (0x7fff << 17)
--#define BLM_LEGACY_MODE                               (1 << 16)
--/**
-- * This is the number of cycles out of the backlight modulation cycle for which
-- * the backlight is on.
-+ * The following dwords have a reserved meaning:
-+ * 0: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
-+ * 4: ring 0 head pointer
-+ * 5: ring 1 head pointer (915-class)
-+ * 6: ring 2 head pointer (915-class)
-  *
-- * This field must be no greater than the number of cycles in the complete
-- * backlight modulation cycle.
-- */
--#define BACKLIGHT_DUTY_CYCLE_SHIFT            (0)
--#define BACKLIGHT_DUTY_CYCLE_MASK             (0xffff)
--
--#define I915_GCFGC                    0xf0
--#define I915_LOW_FREQUENCY_ENABLE             (1 << 7)
--#define I915_DISPLAY_CLOCK_190_200_MHZ                (0 << 4)
--#define I915_DISPLAY_CLOCK_333_MHZ            (4 << 4)
--#define I915_DISPLAY_CLOCK_MASK                       (7 << 4)
--
--#define I855_HPLLCC                   0xc0
--#define I855_CLOCK_CONTROL_MASK                       (3 << 0)
--#define I855_CLOCK_133_200                    (0 << 0)
--#define I855_CLOCK_100_200                    (1 << 0)
--#define I855_CLOCK_100_133                    (2 << 0)
--#define I855_CLOCK_166_250                    (3 << 0)
--
--/* p317, 319
-+ * The area from dword 0x10 to 0x3ff is available for driver usage.
-  */
--#define VCLK2_VCO_M        0x6008 /* treat as 16 bit? (includes msbs) */
--#define VCLK2_VCO_N        0x600a
--#define VCLK2_VCO_DIV_SEL  0x6012
--
--#define VCLK_DIVISOR_VGA0   0x6000
--#define VCLK_DIVISOR_VGA1   0x6004
--#define VCLK_POST_DIV     0x6010
--/** Selects a post divisor of 4 instead of 2. */
--# define VGA1_PD_P2_DIV_4     (1 << 15)
--/** Overrides the p2 post divisor field */
--# define VGA1_PD_P1_DIV_2     (1 << 13)
--# define VGA1_PD_P1_SHIFT     8
--/** P1 value is 2 greater than this field */
--# define VGA1_PD_P1_MASK      (0x1f << 8)
--/** Selects a post divisor of 4 instead of 2. */
--# define VGA0_PD_P2_DIV_4     (1 << 7)
--/** Overrides the p2 post divisor field */
--# define VGA0_PD_P1_DIV_2     (1 << 5)
--# define VGA0_PD_P1_SHIFT     0
--/** P1 value is 2 greater than this field */
--# define VGA0_PD_P1_MASK      (0x1f << 0)
--
--/* PCI D state control register */
--#define D_STATE               0x6104
--#define DSPCLK_GATE_D 0x6200
--
--/* I830 CRTC registers */
--#define HTOTAL_A      0x60000
--#define HBLANK_A      0x60004
--#define HSYNC_A               0x60008
--#define VTOTAL_A      0x6000c
--#define VBLANK_A      0x60010
--#define VSYNC_A               0x60014
--#define PIPEASRC      0x6001c
--#define BCLRPAT_A     0x60020
--#define VSYNCSHIFT_A  0x60028
--
--#define HTOTAL_B      0x61000
--#define HBLANK_B      0x61004
--#define HSYNC_B               0x61008
--#define VTOTAL_B      0x6100c
--#define VBLANK_B      0x61010
--#define VSYNC_B               0x61014
--#define PIPEBSRC      0x6101c
--#define BCLRPAT_B     0x61020
--#define VSYNCSHIFT_B  0x61028
--
--#define PP_STATUS     0x61200
--# define PP_ON                                        (1 << 31)
--/**
-- * Indicates that all dependencies of the panel are on:
-- *
-- * - PLL enabled
-- * - pipe enabled
-- * - LVDS/DVOB/DVOC on
-- */
--# define PP_READY                             (1 << 30)
--# define PP_SEQUENCE_NONE                     (0 << 28)
--# define PP_SEQUENCE_ON                               (1 << 28)
--# define PP_SEQUENCE_OFF                      (2 << 28)
--# define PP_SEQUENCE_MASK                     0x30000000
--#define PP_CONTROL    0x61204
--# define POWER_TARGET_ON                      (1 << 0)
--
--#define LVDSPP_ON       0x61208
--#define LVDSPP_OFF      0x6120c
--#define PP_CYCLE        0x61210
--
--#define PFIT_CONTROL  0x61230
--# define PFIT_ENABLE                          (1 << 31)
--# define PFIT_PIPE_MASK                               (3 << 29)
--# define PFIT_PIPE_SHIFT                      29
--# define VERT_INTERP_DISABLE                  (0 << 10)
--# define VERT_INTERP_BILINEAR                 (1 << 10)
--# define VERT_INTERP_MASK                     (3 << 10)
--# define VERT_AUTO_SCALE                      (1 << 9)
--# define HORIZ_INTERP_DISABLE                 (0 << 6)
--# define HORIZ_INTERP_BILINEAR                        (1 << 6)
--# define HORIZ_INTERP_MASK                    (3 << 6)
--# define HORIZ_AUTO_SCALE                     (1 << 5)
--# define PANEL_8TO6_DITHER_ENABLE             (1 << 3)
--
--#define PFIT_PGM_RATIOS       0x61234
--# define PFIT_VERT_SCALE_MASK                 0xfff00000
--# define PFIT_HORIZ_SCALE_MASK                        0x0000fff0
--
--#define PFIT_AUTO_RATIOS      0x61238
--
--
--#define DPLL_A                0x06014
--#define DPLL_B                0x06018
--# define DPLL_VCO_ENABLE                      (1 << 31)
--# define DPLL_DVO_HIGH_SPEED                  (1 << 30)
--# define DPLL_SYNCLOCK_ENABLE                 (1 << 29)
--# define DPLL_VGA_MODE_DIS                    (1 << 28)
--# define DPLLB_MODE_DAC_SERIAL                        (1 << 26) /* i915 */
--# define DPLLB_MODE_LVDS                      (2 << 26) /* i915 */
--# define DPLL_MODE_MASK                               (3 << 26)
--# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10      (0 << 24) /* i915 */
--# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5               (1 << 24) /* i915 */
--# define DPLLB_LVDS_P2_CLOCK_DIV_14           (0 << 24) /* i915 */
--# define DPLLB_LVDS_P2_CLOCK_DIV_7            (1 << 24) /* i915 */
--# define DPLL_P2_CLOCK_DIV_MASK                       0x03000000 /* i915 */
--# define DPLL_FPA01_P1_POST_DIV_MASK          0x00ff0000 /* i915 */
--/**
-- *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
-- * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
-- */
--# define DPLL_FPA01_P1_POST_DIV_MASK_I830     0x001f0000
--/**
-- * The i830 generation, in LVDS mode, defines P1 as the bit number set within
-- * this field (only one bit may be set).
-- */
--# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS        0x003f0000
--# define DPLL_FPA01_P1_POST_DIV_SHIFT         16
--# define PLL_P2_DIVIDE_BY_4                   (1 << 23) /* i830, required in DVO non-gang */
--# define PLL_P1_DIVIDE_BY_TWO                 (1 << 21) /* i830 */
--# define PLL_REF_INPUT_DREFCLK                        (0 << 13)
--# define PLL_REF_INPUT_TVCLKINA                       (1 << 13) /* i830 */
--# define PLL_REF_INPUT_TVCLKINBC              (2 << 13) /* SDVO TVCLKIN */
--# define PLLB_REF_INPUT_SPREADSPECTRUMIN      (3 << 13)
--# define PLL_REF_INPUT_MASK                   (3 << 13)
--# define PLL_LOAD_PULSE_PHASE_SHIFT           9
--/*
-- * Parallel to Serial Load Pulse phase selection.
-- * Selects the phase for the 10X DPLL clock for the PCIe
-- * digital display port. The range is 4 to 13; 10 or more
-- * is just a flip delay. The default is 6
-- */
--# define PLL_LOAD_PULSE_PHASE_MASK            (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
--# define DISPLAY_RATE_SELECT_FPA1             (1 << 8)
--
--/**
-- * SDVO multiplier for 945G/GM. Not used on 965.
-- *
-- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
-- */
--# define SDVO_MULTIPLIER_MASK                 0x000000ff
--# define SDVO_MULTIPLIER_SHIFT_HIRES          4
--# define SDVO_MULTIPLIER_SHIFT_VGA            0
--
--/** @defgroup DPLL_MD
-- * @{
-- */
--/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
--#define DPLL_A_MD             0x0601c
--/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
--#define DPLL_B_MD             0x06020
--/**
-- * UDI pixel divider, controlling how many pixels are stuffed into a packet.
-- *
-- * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
-- */
--# define DPLL_MD_UDI_DIVIDER_MASK             0x3f000000
--# define DPLL_MD_UDI_DIVIDER_SHIFT            24
--/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
--# define DPLL_MD_VGA_UDI_DIVIDER_MASK         0x003f0000
--# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT                16
--/**
-- * SDVO/UDI pixel multiplier.
-- *
-- * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
-- * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
-- * modes, the bus rate would be below the limits, so SDVO allows for stuffing
-- * dummy bytes in the datastream at an increased clock rate, with both sides of
-- * the link knowing how many bytes are fill.
-- *
-- * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
-- * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
-- * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
-- * through an SDVO command.
-- *
-- * This register field has values of multiplication factor minus 1, with
-- * a maximum multiplier of 5 for SDVO.
-- */
--# define DPLL_MD_UDI_MULTIPLIER_MASK          0x00003f00
--# define DPLL_MD_UDI_MULTIPLIER_SHIFT         8
--/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
-- * This best be set to the default value (3) or the CRT won't work. No,
-- * I don't entirely understand what this does...
-- */
--# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK      0x0000003f
--# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT     0
--/** @} */
--
--#define DPLL_TEST             0x606c
--# define DPLLB_TEST_SDVO_DIV_1                        (0 << 22)
--# define DPLLB_TEST_SDVO_DIV_2                        (1 << 22)
--# define DPLLB_TEST_SDVO_DIV_4                        (2 << 22)
--# define DPLLB_TEST_SDVO_DIV_MASK             (3 << 22)
--# define DPLLB_TEST_N_BYPASS                  (1 << 19)
--# define DPLLB_TEST_M_BYPASS                  (1 << 18)
--# define DPLLB_INPUT_BUFFER_ENABLE            (1 << 16)
--# define DPLLA_TEST_N_BYPASS                  (1 << 3)
--# define DPLLA_TEST_M_BYPASS                  (1 << 2)
--# define DPLLA_INPUT_BUFFER_ENABLE            (1 << 0)
--
--#define ADPA                  0x61100
--#define ADPA_DAC_ENABLE               (1<<31)
--#define ADPA_DAC_DISABLE      0
--#define ADPA_PIPE_SELECT_MASK (1<<30)
--#define ADPA_PIPE_A_SELECT    0
--#define ADPA_PIPE_B_SELECT    (1<<30)
--#define ADPA_USE_VGA_HVPOLARITY (1<<15)
--#define ADPA_SETS_HVPOLARITY  0
--#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
--#define ADPA_VSYNC_CNTL_ENABLE        0
--#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
--#define ADPA_HSYNC_CNTL_ENABLE        0
--#define ADPA_VSYNC_ACTIVE_HIGH        (1<<4)
--#define ADPA_VSYNC_ACTIVE_LOW 0
--#define ADPA_HSYNC_ACTIVE_HIGH        (1<<3)
--#define ADPA_HSYNC_ACTIVE_LOW 0
--
--#define FPA0          0x06040
--#define FPA1          0x06044
--#define FPB0          0x06048
--#define FPB1          0x0604c
--# define FP_N_DIV_MASK                                0x003f0000
--# define FP_N_DIV_SHIFT                               16
--# define FP_M1_DIV_MASK                               0x00003f00
--# define FP_M1_DIV_SHIFT                      8
--# define FP_M2_DIV_MASK                               0x0000003f
--# define FP_M2_DIV_SHIFT                      0
--
--
--#define PORT_HOTPLUG_EN               0x61110
--# define SDVOB_HOTPLUG_INT_EN                 (1 << 26)
--# define SDVOC_HOTPLUG_INT_EN                 (1 << 25)
--# define TV_HOTPLUG_INT_EN                    (1 << 18)
--# define CRT_HOTPLUG_INT_EN                   (1 << 9)
--# define CRT_HOTPLUG_FORCE_DETECT             (1 << 3)
--
--#define PORT_HOTPLUG_STAT     0x61114
--# define CRT_HOTPLUG_INT_STATUS                       (1 << 11)
--# define TV_HOTPLUG_INT_STATUS                        (1 << 10)
--# define CRT_HOTPLUG_MONITOR_MASK             (3 << 8)
--# define CRT_HOTPLUG_MONITOR_COLOR            (3 << 8)
--# define CRT_HOTPLUG_MONITOR_MONO             (2 << 8)
--# define CRT_HOTPLUG_MONITOR_NONE             (0 << 8)
--# define SDVOC_HOTPLUG_INT_STATUS             (1 << 7)
--# define SDVOB_HOTPLUG_INT_STATUS             (1 << 6)
--
--#define SDVOB                 0x61140
--#define SDVOC                 0x61160
--#define SDVO_ENABLE                           (1 << 31)
--#define SDVO_PIPE_B_SELECT                    (1 << 30)
--#define SDVO_STALL_SELECT                     (1 << 29)
--#define SDVO_INTERRUPT_ENABLE                 (1 << 26)
--/**
-- * 915G/GM SDVO pixel multiplier.
-- *
-- * Programmed value is multiplier - 1, up to 5x.
-- *
-- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
-- */
--#define SDVO_PORT_MULTIPLY_MASK                       (7 << 23)
--#define SDVO_PORT_MULTIPLY_SHIFT              23
--#define SDVO_PHASE_SELECT_MASK                        (15 << 19)
--#define SDVO_PHASE_SELECT_DEFAULT             (6 << 19)
--#define SDVO_CLOCK_OUTPUT_INVERT              (1 << 18)
--#define SDVOC_GANG_MODE                               (1 << 16)
--#define SDVO_BORDER_ENABLE                    (1 << 7)
--#define SDVOB_PCIE_CONCURRENCY                        (1 << 3)
--#define SDVO_DETECTED                         (1 << 2)
--/* Bits to be preserved when writing */
--#define SDVOB_PRESERVE_MASK                   ((1 << 17) | (1 << 16) | (1 << 14))
--#define SDVOC_PRESERVE_MASK                   (1 << 17)
--
--/** @defgroup LVDS
-- * @{
-- */
--/**
-- * This register controls the LVDS output enable, pipe selection, and data
-- * format selection.
-- *
-- * All of the clock/data pairs are force powered down by power sequencing.
-- */
--#define LVDS                  0x61180
--/**
-- * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
-- * the DPLL semantics change when the LVDS is assigned to that pipe.
-- */
--# define LVDS_PORT_EN                 (1 << 31)
--/** Selects pipe B for LVDS data.  Must be set on pre-965. */
--# define LVDS_PIPEB_SELECT            (1 << 30)
--
--/**
-- * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
-- * pixel.
-- */
--# define LVDS_A0A2_CLKA_POWER_MASK    (3 << 8)
--# define LVDS_A0A2_CLKA_POWER_DOWN    (0 << 8)
--# define LVDS_A0A2_CLKA_POWER_UP      (3 << 8)
--/**
-- * Controls the A3 data pair, which contains the additional LSBs for 24 bit
-- * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
-- * on.
-- */
--# define LVDS_A3_POWER_MASK           (3 << 6)
--# define LVDS_A3_POWER_DOWN           (0 << 6)
--# define LVDS_A3_POWER_UP             (3 << 6)
--/**
-- * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
-- * is set.
-- */
--# define LVDS_CLKB_POWER_MASK         (3 << 4)
--# define LVDS_CLKB_POWER_DOWN         (0 << 4)
--# define LVDS_CLKB_POWER_UP           (3 << 4)
--
--/**
-- * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
-- * setting for whether we are in dual-channel mode.  The B3 pair will
-- * additionally only be powered up when LVDS_A3_POWER_UP is set.
-- */
--# define LVDS_B0B3_POWER_MASK         (3 << 2)
--# define LVDS_B0B3_POWER_DOWN         (0 << 2)
--# define LVDS_B0B3_POWER_UP           (3 << 2)
--
--#define PIPEACONF 0x70008
--#define PIPEACONF_ENABLE      (1<<31)
--#define PIPEACONF_DISABLE     0
--#define PIPEACONF_DOUBLE_WIDE (1<<30)
--#define I965_PIPECONF_ACTIVE  (1<<30)
--#define PIPEACONF_SINGLE_WIDE 0
--#define PIPEACONF_PIPE_UNLOCKED 0
--#define PIPEACONF_PIPE_LOCKED (1<<25)
--#define PIPEACONF_PALETTE     0
--#define PIPEACONF_GAMMA               (1<<24)
--#define PIPECONF_FORCE_BORDER (1<<25)
--#define PIPECONF_PROGRESSIVE  (0 << 21)
--#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
--#define PIPECONF_INTERLACE_FIELD_0_ONLY               (7 << 21)
--
--#define DSPARB          0x70030
--#define DSPARB_CSTART_MASK    (0x7f << 7)
--#define DSPARB_CSTART_SHIFT   7
--#define DSPARB_BSTART_MASK    (0x7f)           
--#define DSPARB_BSTART_SHIFT   0
--
--#define PIPEBCONF 0x71008
--#define PIPEBCONF_ENABLE      (1<<31)
--#define PIPEBCONF_DISABLE     0
--#define PIPEBCONF_DOUBLE_WIDE (1<<30)
--#define PIPEBCONF_DISABLE     0
--#define PIPEBCONF_GAMMA               (1<<24)
--#define PIPEBCONF_PALETTE     0
--
--#define PIPEBGCMAXRED         0x71010
--#define PIPEBGCMAXGREEN               0x71014
--#define PIPEBGCMAXBLUE                0x71018
--#define PIPEBSTAT             0x71024
--#define PIPEBFRAMEHIGH                0x71040
--#define PIPEBFRAMEPIXEL               0x71044
--
--#define DSPACNTR              0x70180
--#define DSPBCNTR              0x71180
--#define DISPLAY_PLANE_ENABLE                  (1<<31)
--#define DISPLAY_PLANE_DISABLE                 0
--#define DISPPLANE_GAMMA_ENABLE                        (1<<30)
--#define DISPPLANE_GAMMA_DISABLE                       0
--#define DISPPLANE_PIXFORMAT_MASK              (0xf<<26)
--#define DISPPLANE_8BPP                                (0x2<<26)
--#define DISPPLANE_15_16BPP                    (0x4<<26)
--#define DISPPLANE_16BPP                               (0x5<<26)
--#define DISPPLANE_32BPP_NO_ALPHA              (0x6<<26)
--#define DISPPLANE_32BPP                               (0x7<<26)
--#define DISPPLANE_STEREO_ENABLE                       (1<<25)
--#define DISPPLANE_STEREO_DISABLE              0
--#define DISPPLANE_SEL_PIPE_MASK                       (1<<24)
--#define DISPPLANE_SEL_PIPE_A                  0
--#define DISPPLANE_SEL_PIPE_B                  (1<<24)
--#define DISPPLANE_SRC_KEY_ENABLE              (1<<22)
--#define DISPPLANE_SRC_KEY_DISABLE             0
--#define DISPPLANE_LINE_DOUBLE                 (1<<20)
--#define DISPPLANE_NO_LINE_DOUBLE              0
--#define DISPPLANE_STEREO_POLARITY_FIRST               0
--#define DISPPLANE_STEREO_POLARITY_SECOND      (1<<18)
--/* plane B only */
--#define DISPPLANE_ALPHA_TRANS_ENABLE          (1<<15)
--#define DISPPLANE_ALPHA_TRANS_DISABLE         0
--#define DISPPLANE_SPRITE_ABOVE_DISPLAYA               0
--#define DISPPLANE_SPRITE_ABOVE_OVERLAY                (1)
--
--#define DSPABASE              0x70184
--#define DSPASTRIDE            0x70188
--
--#define DSPBBASE              0x71184
--#define DSPBADDR              DSPBBASE
--#define DSPBSTRIDE            0x71188
--
--#define DSPAKEYVAL            0x70194
--#define DSPAKEYMASK           0x70198
--
--#define DSPAPOS                       0x7018C /* reserved */
--#define DSPASIZE              0x70190
--#define DSPBPOS                       0x7118C
--#define DSPBSIZE              0x71190
--
--#define DSPASURF              0x7019C
--#define DSPATILEOFF           0x701A4
--
--#define DSPBSURF              0x7119C
--#define DSPBTILEOFF           0x711A4
--
--#define VGACNTRL              0x71400
--# define VGA_DISP_DISABLE                     (1 << 31)
--# define VGA_2X_MODE                          (1 << 30)
--# define VGA_PIPE_B_SELECT                    (1 << 29)
--
--/*
-- * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
-- * of video memory available to the BIOS in SWF1.
-- */
--
--#define SWF0                  0x71410
--
--/*
-- * 855 scratch registers.
-- */
--#define SWF10                 0x70410
--
--#define SWF30                 0x72414
--
--/*
-- * Overlay registers.  These are overlay registers accessed via MMIO.
-- * Those loaded via the overlay register page are defined in i830_video.c.
-- */
--#define OVADD                 0x30000
--
--#define DOVSTA                        0x30008
--#define OC_BUF                        (0x3<<20)
-+#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
-+#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, 5)
--#define OGAMC5                        0x30010
--#define OGAMC4                        0x30014
--#define OGAMC3                        0x30018
--#define OGAMC2                        0x3001c
--#define OGAMC1                        0x30020
--#define OGAMC0                        0x30024
--/*
-- * Palette registers
-- */
--#define PALETTE_A             0x0a000
--#define PALETTE_B             0x0a800
-+extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
- #define IS_I830(dev) ((dev)->pci_device == 0x3577)
- #define IS_845G(dev) ((dev)->pci_device == 0x2562)
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index df03611..4a2de78 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -31,10 +31,6 @@
- #include "i915_drm.h"
- #include "i915_drv.h"
--#define USER_INT_FLAG (1<<1)
--#define VSYNC_PIPEB_FLAG (1<<5)
--#define VSYNC_PIPEA_FLAG (1<<7)
--
- #define MAX_NOPID ((u32)~0)
- /**
-@@ -236,40 +232,43 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-       u16 temp;
-       u32 pipea_stats, pipeb_stats;
--      pipea_stats = I915_READ(I915REG_PIPEASTAT);
--      pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
-+      pipea_stats = I915_READ(PIPEASTAT);
-+      pipeb_stats = I915_READ(PIPEBSTAT);
--      temp = I915_READ16(I915REG_INT_IDENTITY_R);
-+      temp = I915_READ16(IIR);
--      temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
-+      temp &= (I915_USER_INTERRUPT |
-+               I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
-+               I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT);
-       DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
-       if (temp == 0)
-               return IRQ_NONE;
--      I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
--      (void) I915_READ16(I915REG_INT_IDENTITY_R);
-+      I915_WRITE16(IIR, temp);
-+      (void) I915_READ16(IIR);
-       DRM_READMEMORYBARRIER();
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
--      if (temp & USER_INT_FLAG)
-+      if (temp & I915_USER_INTERRUPT)
-               DRM_WAKEUP(&dev_priv->irq_queue);
--      if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
-+      if (temp & (I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
-+                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)) {
-               int vblank_pipe = dev_priv->vblank_pipe;
-               if ((vblank_pipe &
-                    (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
-                   == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
--                      if (temp & VSYNC_PIPEA_FLAG)
-+                      if (temp & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-                               atomic_inc(&dev->vbl_received);
--                      if (temp & VSYNC_PIPEB_FLAG)
-+                      if (temp & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-                               atomic_inc(&dev->vbl_received2);
--              } else if (((temp & VSYNC_PIPEA_FLAG) &&
-+              } else if (((temp & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
--                         ((temp & VSYNC_PIPEB_FLAG) &&
-+                         ((temp & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
-                       atomic_inc(&dev->vbl_received);
-@@ -278,12 +277,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-               if (dev_priv->swaps_pending > 0)
-                       drm_locked_tasklet(dev, i915_vblank_tasklet);
--              I915_WRITE(I915REG_PIPEASTAT,
-+              I915_WRITE(PIPEASTAT,
-                       pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
--                      I915_VBLANK_CLEAR);
--              I915_WRITE(I915REG_PIPEBSTAT,
-+                      PIPE_VBLANK_INTERRUPT_STATUS);
-+              I915_WRITE(PIPEBSTAT,
-                       pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
--                      I915_VBLANK_CLEAR);
-+                      PIPE_VBLANK_INTERRUPT_STATUS);
-       }
-       return IRQ_HANDLED;
-@@ -304,12 +303,12 @@ static int i915_emit_irq(struct drm_device * dev)
-               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
-       BEGIN_LP_RING(6);
--      OUT_RING(CMD_STORE_DWORD_IDX);
--      OUT_RING(20);
-+      OUT_RING(MI_STORE_DWORD_INDEX);
-+      OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
-       OUT_RING(0);
--      OUT_RING(GFX_OP_USER_INTERRUPT);
-+      OUT_RING(MI_USER_INTERRUPT);
-       ADVANCE_LP_RING();
-       return dev_priv->counter;
-@@ -421,11 +420,11 @@ static void i915_enable_interrupt (struct drm_device *dev)
-       flag = 0;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
--              flag |= VSYNC_PIPEA_FLAG;
-+              flag |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
--              flag |= VSYNC_PIPEB_FLAG;
-+              flag |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
--      I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
-+      I915_WRITE16(IER, I915_USER_INTERRUPT | flag);
- }
- /* Set the vblank monitor pipe
-@@ -465,11 +464,11 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
-               return -EINVAL;
-       }
--      flag = I915_READ(I915REG_INT_ENABLE_R);
-+      flag = I915_READ(IER);
-       pipe->pipe = 0;
--      if (flag & VSYNC_PIPEA_FLAG)
-+      if (flag & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-               pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
--      if (flag & VSYNC_PIPEB_FLAG)
-+      if (flag & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-               pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
-       return 0;
-@@ -587,9 +586,9 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      I915_WRITE16(I915REG_HWSTAM, 0xfffe);
--      I915_WRITE16(I915REG_INT_MASK_R, 0x0);
--      I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
-+      I915_WRITE16(HWSTAM, 0xfffe);
-+      I915_WRITE16(IMR, 0x0);
-+      I915_WRITE16(IER, 0x0);
- }
- void i915_driver_irq_postinstall(struct drm_device * dev)
-@@ -614,10 +613,10 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
-       if (!dev_priv)
-               return;
--      I915_WRITE16(I915REG_HWSTAM, 0xffff);
--      I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
--      I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
-+      I915_WRITE16(HWSTAM, 0xffff);
-+      I915_WRITE16(IMR, 0xffff);
-+      I915_WRITE16(IER, 0x0);
--      temp = I915_READ16(I915REG_INT_IDENTITY_R);
--      I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
-+      temp = I915_READ16(IIR);
-+      I915_WRITE16(IIR, temp);
- }
-diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
-new file mode 100644
-index 0000000..477c64e
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_reg.h
-@@ -0,0 +1,1405 @@
-+/* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
-+ * All Rights Reserved.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the
-+ * "Software"), to deal in the Software without restriction, including
-+ * without limitation the rights to use, copy, modify, merge, publish,
-+ * distribute, sub license, and/or sell copies of the Software, and to
-+ * permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the
-+ * next paragraph) shall be included in all copies or substantial portions
-+ * of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
-+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-+ */
-+
-+#ifndef _I915_REG_H_
-+#define _I915_REG_H_
-+
-+/* MCH MMIO space */
-+/** 915-945 and GM965 MCH register controlling DRAM channel access */
-+#define DCC           0x200
-+#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL            (0 << 0)
-+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC   (1 << 0)
-+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED  (2 << 0)
-+#define DCC_ADDRESSING_MODE_MASK                      (3 << 0)
-+#define DCC_CHANNEL_XOR_DISABLE                               (1 << 10)
-+
-+/** 965 MCH register controlling DRAM channel configuration */
-+#define CHDECMISC             0x111
-+#define CHDECMISC_FLEXMEMORY          (1 << 1)
-+
-+/*
-+ * The Bridge device's PCI config space has information about the
-+ * fb aperture size and the amount of pre-reserved memory.
-+ */
-+#define INTEL_GMCH_CTRL               0x52
-+#define INTEL_GMCH_ENABLED    0x4
-+#define INTEL_GMCH_MEM_MASK   0x1
-+#define INTEL_GMCH_MEM_64M    0x1
-+#define INTEL_GMCH_MEM_128M   0
-+
-+#define INTEL_855_GMCH_GMS_MASK               (0x7 << 4)
-+#define INTEL_855_GMCH_GMS_DISABLED   (0x0 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_1M  (0x1 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_4M  (0x2 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_8M  (0x3 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4)
-+#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4)
-+
-+#define INTEL_915G_GMCH_GMS_STOLEN_48M        (0x6 << 4)
-+#define INTEL_915G_GMCH_GMS_STOLEN_64M        (0x7 << 4)
-+
-+/* PCI config space */
-+
-+#define HPLLCC        0xc0 /* 855 only */
-+#define   GC_CLOCK_CONTROL_MASK               (3 << 0)
-+#define   GC_CLOCK_133_200            (0 << 0)
-+#define   GC_CLOCK_100_200            (1 << 0)
-+#define   GC_CLOCK_100_133            (2 << 0)
-+#define   GC_CLOCK_166_250            (3 << 0)
-+#define GCFGC 0xf0 /* 915+ only */
-+#define   GC_LOW_FREQUENCY_ENABLE     (1 << 7)
-+#define   GC_DISPLAY_CLOCK_190_200_MHZ        (0 << 4)
-+#define   GC_DISPLAY_CLOCK_333_MHZ    (4 << 4)
-+#define   GC_DISPLAY_CLOCK_MASK               (7 << 4)
-+#define LBB   0xf4
-+
-+/* VGA stuff */
-+
-+#define VGA_ST01_MDA 0x3ba
-+#define VGA_ST01_CGA 0x3da
-+
-+#define VGA_MSR_WRITE 0x3c2
-+#define VGA_MSR_READ 0x3cc
-+#define   VGA_MSR_MEM_EN (1<<1)
-+#define   VGA_MSR_CGA_MODE (1<<0)
-+
-+#define VGA_SR_INDEX 0x3c4
-+#define VGA_SR_DATA 0x3c5
-+
-+#define VGA_AR_INDEX 0x3c0
-+#define   VGA_AR_VID_EN (1<<5)
-+#define VGA_AR_DATA_WRITE 0x3c0
-+#define VGA_AR_DATA_READ 0x3c1
-+
-+#define VGA_GR_INDEX 0x3ce
-+#define VGA_GR_DATA 0x3cf
-+/* GR05 */
-+#define   VGA_GR_MEM_READ_MODE_SHIFT 3
-+#define     VGA_GR_MEM_READ_MODE_PLANE 1
-+/* GR06 */
-+#define   VGA_GR_MEM_MODE_MASK 0xc
-+#define   VGA_GR_MEM_MODE_SHIFT 2
-+#define   VGA_GR_MEM_A0000_AFFFF 0
-+#define   VGA_GR_MEM_A0000_BFFFF 1
-+#define   VGA_GR_MEM_B0000_B7FFF 2
-+#define   VGA_GR_MEM_B0000_BFFFF 3
-+
-+#define VGA_DACMASK 0x3c6
-+#define VGA_DACRX 0x3c7
-+#define VGA_DACWX 0x3c8
-+#define VGA_DACDATA 0x3c9
-+
-+#define VGA_CR_INDEX_MDA 0x3b4
-+#define VGA_CR_DATA_MDA 0x3b5
-+#define VGA_CR_INDEX_CGA 0x3d4
-+#define VGA_CR_DATA_CGA 0x3d5
-+
-+/*
-+ * Memory interface instructions used by the kernel
-+ */
-+#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
-+
-+#define MI_NOOP                       MI_INSTR(0, 0)
-+#define MI_USER_INTERRUPT     MI_INSTR(0x02, 0)
-+#define MI_WAIT_FOR_EVENT       MI_INSTR(0x03, 0)
-+#define   MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
-+#define   MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
-+#define   MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-+#define MI_FLUSH              MI_INSTR(0x04, 0)
-+#define   MI_READ_FLUSH               (1 << 0)
-+#define   MI_EXE_FLUSH                (1 << 1)
-+#define   MI_NO_WRITE_FLUSH   (1 << 2)
-+#define   MI_SCENE_COUNT      (1 << 3) /* just increment scene count */
-+#define   MI_END_SCENE                (1 << 4) /* flush binner and incr scene count */
-+#define MI_BATCH_BUFFER_END   MI_INSTR(0x0a, 0)
-+#define MI_REPORT_HEAD                MI_INSTR(0x07, 0)
-+#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
-+#define MI_STORE_DWORD_IMM    MI_INSTR(0x20, 1)
-+#define   MI_MEM_VIRTUAL      (1 << 22) /* 965+ only */
-+#define MI_STORE_DWORD_INDEX  MI_INSTR(0x21, 1)
-+#define   MI_STORE_DWORD_INDEX_SHIFT 2
-+#define MI_LOAD_REGISTER_IMM  MI_INSTR(0x22, 1)
-+#define MI_BATCH_BUFFER               MI_INSTR(0x30, 1)
-+#define   MI_BATCH_NON_SECURE (1)
-+#define   MI_BATCH_NON_SECURE_I965 (1<<8)
-+#define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0)
-+
-+/*
-+ * 3D instructions used by the kernel
-+ */
-+#define GFX_INSTR(opcode, flags) ((0x3 << 29) | ((opcode) << 24) | (flags))
-+
-+#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
-+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-+#define   SC_UPDATE_SCISSOR       (0x1<<1)
-+#define   SC_ENABLE_MASK          (0x1<<0)
-+#define   SC_ENABLE               (0x1<<0)
-+#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
-+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-+#define   SCI_YMIN_MASK      (0xffff<<16)
-+#define   SCI_XMIN_MASK      (0xffff<<0)
-+#define   SCI_YMAX_MASK      (0xffff<<16)
-+#define   SCI_XMAX_MASK      (0xffff<<0)
-+#define GFX_OP_SCISSOR_ENABLE  ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-+#define GFX_OP_SCISSOR_RECT    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
-+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
-+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-+#define GFX_OP_DESTBUFFER_INFO         ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
-+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-+#define GFX_OP_DRAWRECT_INFO_I965  ((0x7900<<16)|0x2)
-+#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
-+#define XY_SRC_COPY_BLT_CMD           ((2<<29)|(0x53<<22)|6)
-+#define XY_MONO_SRC_COPY_IMM_BLT      ((2<<29)|(0x71<<22)|5)
-+#define XY_SRC_COPY_BLT_WRITE_ALPHA   (1<<21)
-+#define XY_SRC_COPY_BLT_WRITE_RGB     (1<<20)
-+#define   BLT_DEPTH_8                 (0<<24)
-+#define   BLT_DEPTH_16_565            (1<<24)
-+#define   BLT_DEPTH_16_1555           (2<<24)
-+#define   BLT_DEPTH_32                        (3<<24)
-+#define   BLT_ROP_GXCOPY              (0xcc<<16)
-+#define XY_SRC_COPY_BLT_SRC_TILED     (1<<15) /* 965+ only */
-+#define XY_SRC_COPY_BLT_DST_TILED     (1<<11) /* 965+ only */
-+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
-+#define   ASYNC_FLIP                (1<<22)
-+#define   DISPLAY_PLANE_A           (0<<20)
-+#define   DISPLAY_PLANE_B           (1<<20)
-+
-+/*
-+ * Instruction and interrupt control regs
-+ */
-+
-+#define PRB0_TAIL     0x02030
-+#define PRB0_HEAD     0x02034
-+#define PRB0_START    0x02038
-+#define PRB0_CTL      0x0203c
-+#define   TAIL_ADDR           0x001FFFF8
-+#define   HEAD_WRAP_COUNT     0xFFE00000
-+#define   HEAD_WRAP_ONE               0x00200000
-+#define   HEAD_ADDR           0x001FFFFC
-+#define   RING_NR_PAGES               0x001FF000
-+#define   RING_REPORT_MASK    0x00000006
-+#define   RING_REPORT_64K     0x00000002
-+#define   RING_REPORT_128K    0x00000004
-+#define   RING_NO_REPORT      0x00000000
-+#define   RING_VALID_MASK     0x00000001
-+#define   RING_VALID          0x00000001
-+#define   RING_INVALID                0x00000000
-+#define PRB1_TAIL     0x02040 /* 915+ only */
-+#define PRB1_HEAD     0x02044 /* 915+ only */
-+#define PRB1_START    0x02048 /* 915+ only */
-+#define PRB1_CTL      0x0204c /* 915+ only */
-+#define ACTHD_I965    0x02074
-+#define HWS_PGA               0x02080
-+#define HWS_ADDRESS_MASK      0xfffff000
-+#define HWS_START_ADDRESS_SHIFT       4
-+#define IPEIR         0x02088
-+#define NOPID         0x02094
-+#define HWSTAM                0x02098
-+#define SCPD0         0x0209c /* 915+ only */
-+#define IER           0x020a0
-+#define IIR           0x020a4
-+#define IMR           0x020a8
-+#define ISR           0x020ac
-+#define   I915_PIPE_CONTROL_NOTIFY_INTERRUPT          (1<<18)
-+#define   I915_DISPLAY_PORT_INTERRUPT                 (1<<17)
-+#define   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT  (1<<15)
-+#define   I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT    (1<<14)
-+#define   I915_HWB_OOM_INTERRUPT                      (1<<13)
-+#define   I915_SYNC_STATUS_INTERRUPT                  (1<<12)
-+#define   I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11)
-+#define   I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10)
-+#define   I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT   (1<<9)
-+#define   I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8)
-+#define   I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT                (1<<7)
-+#define   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT         (1<<6)
-+#define   I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT                (1<<5)
-+#define   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT         (1<<4)
-+#define   I915_DEBUG_INTERRUPT                                (1<<2)
-+#define   I915_USER_INTERRUPT                         (1<<1)
-+#define   I915_ASLE_INTERRUPT                         (1<<0)
-+#define EIR           0x020b0
-+#define EMR           0x020b4
-+#define ESR           0x020b8
-+#define INSTPM                0x020c0
-+#define ACTHD         0x020c8
-+#define FW_BLC                0x020d8
-+#define FW_BLC_SELF   0x020e0 /* 915+ only */
-+#define MI_ARB_STATE  0x020e4 /* 915+ only */
-+#define CACHE_MODE_0  0x02120 /* 915+ only */
-+#define   CM0_MASK_SHIFT          16
-+#define   CM0_IZ_OPT_DISABLE      (1<<6)
-+#define   CM0_ZR_OPT_DISABLE      (1<<5)
-+#define   CM0_DEPTH_EVICT_DISABLE (1<<4)
-+#define   CM0_COLOR_EVICT_DISABLE (1<<3)
-+#define   CM0_DEPTH_WRITE_DISABLE (1<<1)
-+#define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
-+#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
-+
-+/*
-+ * Framebuffer compression (915+ only)
-+ */
-+
-+#define FBC_CFB_BASE          0x03200 /* 4k page aligned */
-+#define FBC_LL_BASE           0x03204 /* 4k page aligned */
-+#define FBC_CONTROL           0x03208
-+#define   FBC_CTL_EN          (1<<31)
-+#define   FBC_CTL_PERIODIC    (1<<30)
-+#define   FBC_CTL_INTERVAL_SHIFT (16)
-+#define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
-+#define   FBC_CTL_STRIDE_SHIFT        (5)
-+#define   FBC_CTL_FENCENO     (1<<0)
-+#define FBC_COMMAND           0x0320c
-+#define   FBC_CMD_COMPRESS    (1<<0)
-+#define FBC_STATUS            0x03210
-+#define   FBC_STAT_COMPRESSING        (1<<31)
-+#define   FBC_STAT_COMPRESSED (1<<30)
-+#define   FBC_STAT_MODIFIED   (1<<29)
-+#define   FBC_STAT_CURRENT_LINE       (1<<0)
-+#define FBC_CONTROL2          0x03214
-+#define   FBC_CTL_FENCE_DBL   (0<<4)
-+#define   FBC_CTL_IDLE_IMM    (0<<2)
-+#define   FBC_CTL_IDLE_FULL   (1<<2)
-+#define   FBC_CTL_IDLE_LINE   (2<<2)
-+#define   FBC_CTL_IDLE_DEBUG  (3<<2)
-+#define   FBC_CTL_CPU_FENCE   (1<<1)
-+#define   FBC_CTL_PLANEA      (0<<0)
-+#define   FBC_CTL_PLANEB      (1<<0)
-+#define FBC_FENCE_OFF         0x0321b
-+
-+#define FBC_LL_SIZE           (1536)
-+
-+/*
-+ * GPIO regs
-+ */
-+#define GPIOA                 0x5010
-+#define GPIOB                 0x5014
-+#define GPIOC                 0x5018
-+#define GPIOD                 0x501c
-+#define GPIOE                 0x5020
-+#define GPIOF                 0x5024
-+#define GPIOG                 0x5028
-+#define GPIOH                 0x502c
-+# define GPIO_CLOCK_DIR_MASK          (1 << 0)
-+# define GPIO_CLOCK_DIR_IN            (0 << 1)
-+# define GPIO_CLOCK_DIR_OUT           (1 << 1)
-+# define GPIO_CLOCK_VAL_MASK          (1 << 2)
-+# define GPIO_CLOCK_VAL_OUT           (1 << 3)
-+# define GPIO_CLOCK_VAL_IN            (1 << 4)
-+# define GPIO_CLOCK_PULLUP_DISABLE    (1 << 5)
-+# define GPIO_DATA_DIR_MASK           (1 << 8)
-+# define GPIO_DATA_DIR_IN             (0 << 9)
-+# define GPIO_DATA_DIR_OUT            (1 << 9)
-+# define GPIO_DATA_VAL_MASK           (1 << 10)
-+# define GPIO_DATA_VAL_OUT            (1 << 11)
-+# define GPIO_DATA_VAL_IN             (1 << 12)
-+# define GPIO_DATA_PULLUP_DISABLE     (1 << 13)
-+
-+/*
-+ * Clock control & power management
-+ */
-+
-+#define VGA0  0x6000
-+#define VGA1  0x6004
-+#define VGA_PD        0x6010
-+#define   VGA0_PD_P2_DIV_4    (1 << 7)
-+#define   VGA0_PD_P1_DIV_2    (1 << 5)
-+#define   VGA0_PD_P1_SHIFT    0
-+#define   VGA0_PD_P1_MASK     (0x1f << 0)
-+#define   VGA1_PD_P2_DIV_4    (1 << 15)
-+#define   VGA1_PD_P1_DIV_2    (1 << 13)
-+#define   VGA1_PD_P1_SHIFT    8
-+#define   VGA1_PD_P1_MASK     (0x1f << 8)
-+#define DPLL_A        0x06014
-+#define DPLL_B        0x06018
-+#define   DPLL_VCO_ENABLE             (1 << 31)
-+#define   DPLL_DVO_HIGH_SPEED         (1 << 30)
-+#define   DPLL_SYNCLOCK_ENABLE                (1 << 29)
-+#define   DPLL_VGA_MODE_DIS           (1 << 28)
-+#define   DPLLB_MODE_DAC_SERIAL               (1 << 26) /* i915 */
-+#define   DPLLB_MODE_LVDS             (2 << 26) /* i915 */
-+#define   DPLL_MODE_MASK              (3 << 26)
-+#define   DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
-+#define   DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
-+#define   DPLLB_LVDS_P2_CLOCK_DIV_14  (0 << 24) /* i915 */
-+#define   DPLLB_LVDS_P2_CLOCK_DIV_7   (1 << 24) /* i915 */
-+#define   DPLL_P2_CLOCK_DIV_MASK      0x03000000 /* i915 */
-+#define   DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
-+
-+#define I915_FIFO_UNDERRUN_STATUS             (1UL<<31)
-+#define I915_CRC_ERROR_ENABLE                 (1UL<<29)
-+#define I915_CRC_DONE_ENABLE                  (1UL<<28)
-+#define I915_GMBUS_EVENT_ENABLE                       (1UL<<27)
-+#define I915_VSYNC_INTERRUPT_ENABLE           (1UL<<25)
-+#define I915_DISPLAY_LINE_COMPARE_ENABLE      (1UL<<24)
-+#define I915_DPST_EVENT_ENABLE                        (1UL<<23)
-+#define I915_LEGACY_BLC_EVENT_ENABLE          (1UL<<22)
-+#define I915_ODD_FIELD_INTERRUPT_ENABLE               (1UL<<21)
-+#define I915_EVEN_FIELD_INTERRUPT_ENABLE      (1UL<<20)
-+#define I915_START_VBLANK_INTERRUPT_ENABLE    (1UL<<18)       /* 965 or later */
-+#define I915_VBLANK_INTERRUPT_ENABLE          (1UL<<17)
-+#define I915_OVERLAY_UPDATED_ENABLE           (1UL<<16)
-+#define I915_CRC_ERROR_INTERRUPT_STATUS               (1UL<<13)
-+#define I915_CRC_DONE_INTERRUPT_STATUS                (1UL<<12)
-+#define I915_GMBUS_INTERRUPT_STATUS           (1UL<<11)
-+#define I915_VSYNC_INTERRUPT_STATUS           (1UL<<9)
-+#define I915_DISPLAY_LINE_COMPARE_STATUS      (1UL<<8)
-+#define I915_DPST_EVENT_STATUS                        (1UL<<7)
-+#define I915_LEGACY_BLC_EVENT_STATUS          (1UL<<6)
-+#define I915_ODD_FIELD_INTERRUPT_STATUS               (1UL<<5)
-+#define I915_EVEN_FIELD_INTERRUPT_STATUS      (1UL<<4)
-+#define I915_START_VBLANK_INTERRUPT_STATUS    (1UL<<2)        /* 965 or later */
-+#define I915_VBLANK_INTERRUPT_STATUS          (1UL<<1)
-+#define I915_OVERLAY_UPDATED_STATUS           (1UL<<0)
-+
-+#define SRX_INDEX             0x3c4
-+#define SRX_DATA              0x3c5
-+#define SR01                  1
-+#define SR01_SCREEN_OFF               (1<<5)
-+
-+#define PPCR                  0x61204
-+#define PPCR_ON                       (1<<0)
-+
-+#define DVOB                  0x61140
-+#define DVOB_ON                       (1<<31)
-+#define DVOC                  0x61160
-+#define DVOC_ON                       (1<<31)
-+#define LVDS                  0x61180
-+#define LVDS_ON                       (1<<31)
-+
-+#define ADPA                  0x61100
-+#define ADPA_DPMS_MASK                (~(3<<10))
-+#define ADPA_DPMS_ON          (0<<10)
-+#define ADPA_DPMS_SUSPEND     (1<<10)
-+#define ADPA_DPMS_STANDBY     (2<<10)
-+#define ADPA_DPMS_OFF         (3<<10)
-+
-+#define RING_TAIL             0x00
-+#define TAIL_ADDR             0x001FFFF8
-+#define RING_HEAD             0x04
-+#define HEAD_WRAP_COUNT               0xFFE00000
-+#define HEAD_WRAP_ONE         0x00200000
-+#define HEAD_ADDR             0x001FFFFC
-+#define RING_START            0x08
-+#define START_ADDR            0xFFFFF000
-+#define RING_LEN              0x0C
-+#define RING_NR_PAGES         0x001FF000
-+#define RING_REPORT_MASK      0x00000006
-+#define RING_REPORT_64K               0x00000002
-+#define RING_REPORT_128K      0x00000004
-+#define RING_NO_REPORT                0x00000000
-+#define RING_VALID_MASK               0x00000001
-+#define RING_VALID            0x00000001
-+#define RING_INVALID          0x00000000
-+
-+/* Scratch pad debug 0 reg:
-+ */
-+#define   DPLL_FPA01_P1_POST_DIV_MASK_I830    0x001f0000
-+/*
-+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
-+ * this field (only one bit may be set).
-+ */
-+#define   DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS       0x003f0000
-+#define   DPLL_FPA01_P1_POST_DIV_SHIFT        16
-+/* i830, required in DVO non-gang */
-+#define   PLL_P2_DIVIDE_BY_4          (1 << 23)
-+#define   PLL_P1_DIVIDE_BY_TWO                (1 << 21) /* i830 */
-+#define   PLL_REF_INPUT_DREFCLK               (0 << 13)
-+#define   PLL_REF_INPUT_TVCLKINA      (1 << 13) /* i830 */
-+#define   PLL_REF_INPUT_TVCLKINBC     (2 << 13) /* SDVO TVCLKIN */
-+#define   PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
-+#define   PLL_REF_INPUT_MASK          (3 << 13)
-+#define   PLL_LOAD_PULSE_PHASE_SHIFT          9
-+/*
-+ * Parallel to Serial Load Pulse phase selection.
-+ * Selects the phase for the 10X DPLL clock for the PCIe
-+ * digital display port. The range is 4 to 13; 10 or more
-+ * is just a flip delay. The default is 6
-+ */
-+#define   PLL_LOAD_PULSE_PHASE_MASK           (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-+#define   DISPLAY_RATE_SELECT_FPA1            (1 << 8)
-+/*
-+ * SDVO multiplier for 945G/GM. Not used on 965.
-+ */
-+#define   SDVO_MULTIPLIER_MASK                        0x000000ff
-+#define   SDVO_MULTIPLIER_SHIFT_HIRES         4
-+#define   SDVO_MULTIPLIER_SHIFT_VGA           0
-+#define DPLL_A_MD 0x0601c /* 965+ only */
-+/*
-+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
-+ *
-+ * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
-+ */
-+#define   DPLL_MD_UDI_DIVIDER_MASK            0x3f000000
-+#define   DPLL_MD_UDI_DIVIDER_SHIFT           24
-+/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-+#define   DPLL_MD_VGA_UDI_DIVIDER_MASK                0x003f0000
-+#define   DPLL_MD_VGA_UDI_DIVIDER_SHIFT               16
-+/*
-+ * SDVO/UDI pixel multiplier.
-+ *
-+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
-+ * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
-+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
-+ * dummy bytes in the datastream at an increased clock rate, with both sides of
-+ * the link knowing how many bytes are fill.
-+ *
-+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
-+ * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
-+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
-+ * through an SDVO command.
-+ *
-+ * This register field has values of multiplication factor minus 1, with
-+ * a maximum multiplier of 5 for SDVO.
-+ */
-+#define   DPLL_MD_UDI_MULTIPLIER_MASK         0x00003f00
-+#define   DPLL_MD_UDI_MULTIPLIER_SHIFT                8
-+/*
-+ * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
-+ * This best be set to the default value (3) or the CRT won't work. No,
-+ * I don't entirely understand what this does...
-+ */
-+#define   DPLL_MD_VGA_UDI_MULTIPLIER_MASK     0x0000003f
-+#define   DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT    0
-+#define DPLL_B_MD 0x06020 /* 965+ only */
-+#define FPA0  0x06040
-+#define FPA1  0x06044
-+#define FPB0  0x06048
-+#define FPB1  0x0604c
-+#define   FP_N_DIV_MASK               0x003f0000
-+#define   FP_N_DIV_SHIFT              16
-+#define   FP_M1_DIV_MASK      0x00003f00
-+#define   FP_M1_DIV_SHIFT              8
-+#define   FP_M2_DIV_MASK      0x0000003f
-+#define   FP_M2_DIV_SHIFT              0
-+#define DPLL_TEST     0x606c
-+#define   DPLLB_TEST_SDVO_DIV_1               (0 << 22)
-+#define   DPLLB_TEST_SDVO_DIV_2               (1 << 22)
-+#define   DPLLB_TEST_SDVO_DIV_4               (2 << 22)
-+#define   DPLLB_TEST_SDVO_DIV_MASK    (3 << 22)
-+#define   DPLLB_TEST_N_BYPASS         (1 << 19)
-+#define   DPLLB_TEST_M_BYPASS         (1 << 18)
-+#define   DPLLB_INPUT_BUFFER_ENABLE   (1 << 16)
-+#define   DPLLA_TEST_N_BYPASS         (1 << 3)
-+#define   DPLLA_TEST_M_BYPASS         (1 << 2)
-+#define   DPLLA_INPUT_BUFFER_ENABLE   (1 << 0)
-+#define D_STATE               0x6104
-+#define CG_2D_DIS     0x6200
-+#define CG_3D_DIS     0x6204
-+
-+/*
-+ * Palette regs
-+ */
-+
-+#define PALETTE_A             0x0a000
-+#define PALETTE_B             0x0a800
-+
-+/*
-+ * Overlay regs
-+ */
-+
-+#define OVADD                 0x30000
-+#define DOVSTA                        0x30008
-+#define OC_BUF                        (0x3<<20)
-+#define OGAMC5                        0x30010
-+#define OGAMC4                        0x30014
-+#define OGAMC3                        0x30018
-+#define OGAMC2                        0x3001c
-+#define OGAMC1                        0x30020
-+#define OGAMC0                        0x30024
-+
-+/*
-+ * Display engine regs
-+ */
-+
-+/* Pipe A timing regs */
-+#define HTOTAL_A      0x60000
-+#define HBLANK_A      0x60004
-+#define HSYNC_A               0x60008
-+#define VTOTAL_A      0x6000c
-+#define VBLANK_A      0x60010
-+#define VSYNC_A               0x60014
-+#define PIPEASRC      0x6001c
-+#define BCLRPAT_A     0x60020
-+
-+/* Pipe B timing regs */
-+#define HTOTAL_B      0x61000
-+#define HBLANK_B      0x61004
-+#define HSYNC_B               0x61008
-+#define VTOTAL_B      0x6100c
-+#define VBLANK_B      0x61010
-+#define VSYNC_B               0x61014
-+#define PIPEBSRC      0x6101c
-+#define BCLRPAT_B     0x61020
-+
-+/* VGA port control */
-+#define ADPA                  0x61100
-+#define   ADPA_DAC_ENABLE     (1<<31)
-+#define   ADPA_DAC_DISABLE    0
-+#define   ADPA_PIPE_SELECT_MASK       (1<<30)
-+#define   ADPA_PIPE_A_SELECT  0
-+#define   ADPA_PIPE_B_SELECT  (1<<30)
-+#define   ADPA_USE_VGA_HVPOLARITY (1<<15)
-+#define   ADPA_SETS_HVPOLARITY        0
-+#define   ADPA_VSYNC_CNTL_DISABLE (1<<11)
-+#define   ADPA_VSYNC_CNTL_ENABLE 0
-+#define   ADPA_HSYNC_CNTL_DISABLE (1<<10)
-+#define   ADPA_HSYNC_CNTL_ENABLE 0
-+#define   ADPA_VSYNC_ACTIVE_HIGH (1<<4)
-+#define   ADPA_VSYNC_ACTIVE_LOW       0
-+#define   ADPA_HSYNC_ACTIVE_HIGH (1<<3)
-+#define   ADPA_HSYNC_ACTIVE_LOW       0
-+#define   ADPA_DPMS_MASK      (~(3<<10))
-+#define   ADPA_DPMS_ON                (0<<10)
-+#define   ADPA_DPMS_SUSPEND   (1<<10)
-+#define   ADPA_DPMS_STANDBY   (2<<10)
-+#define   ADPA_DPMS_OFF               (3<<10)
-+
-+/* Hotplug control (945+ only) */
-+#define PORT_HOTPLUG_EN               0x61110
-+#define   SDVOB_HOTPLUG_INT_EN                        (1 << 26)
-+#define   SDVOC_HOTPLUG_INT_EN                        (1 << 25)
-+#define   TV_HOTPLUG_INT_EN                   (1 << 18)
-+#define   CRT_HOTPLUG_INT_EN                  (1 << 9)
-+#define   CRT_HOTPLUG_FORCE_DETECT            (1 << 3)
-+
-+#define PORT_HOTPLUG_STAT     0x61114
-+#define   CRT_HOTPLUG_INT_STATUS              (1 << 11)
-+#define   TV_HOTPLUG_INT_STATUS                       (1 << 10)
-+#define   CRT_HOTPLUG_MONITOR_MASK            (3 << 8)
-+#define   CRT_HOTPLUG_MONITOR_COLOR           (3 << 8)
-+#define   CRT_HOTPLUG_MONITOR_MONO            (2 << 8)
-+#define   CRT_HOTPLUG_MONITOR_NONE            (0 << 8)
-+#define   SDVOC_HOTPLUG_INT_STATUS            (1 << 7)
-+#define   SDVOB_HOTPLUG_INT_STATUS            (1 << 6)
-+
-+/* SDVO port control */
-+#define SDVOB                 0x61140
-+#define SDVOC                 0x61160
-+#define   SDVO_ENABLE         (1 << 31)
-+#define   SDVO_PIPE_B_SELECT  (1 << 30)
-+#define   SDVO_STALL_SELECT   (1 << 29)
-+#define   SDVO_INTERRUPT_ENABLE       (1 << 26)
-+/**
-+ * 915G/GM SDVO pixel multiplier.
-+ *
-+ * Programmed value is multiplier - 1, up to 5x.
-+ *
-+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
-+ */
-+#define   SDVO_PORT_MULTIPLY_MASK     (7 << 23)
-+#define   SDVO_PORT_MULTIPLY_SHIFT            23
-+#define   SDVO_PHASE_SELECT_MASK      (15 << 19)
-+#define   SDVO_PHASE_SELECT_DEFAULT   (6 << 19)
-+#define   SDVO_CLOCK_OUTPUT_INVERT    (1 << 18)
-+#define   SDVOC_GANG_MODE             (1 << 16)
-+#define   SDVO_BORDER_ENABLE          (1 << 7)
-+#define   SDVOB_PCIE_CONCURRENCY      (1 << 3)
-+#define   SDVO_DETECTED                       (1 << 2)
-+/* Bits to be preserved when writing */
-+#define   SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26))
-+#define   SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26))
-+
-+/* DVO port control */
-+#define DVOA                  0x61120
-+#define DVOB                  0x61140
-+#define DVOC                  0x61160
-+#define   DVO_ENABLE                  (1 << 31)
-+#define   DVO_PIPE_B_SELECT           (1 << 30)
-+#define   DVO_PIPE_STALL_UNUSED               (0 << 28)
-+#define   DVO_PIPE_STALL              (1 << 28)
-+#define   DVO_PIPE_STALL_TV           (2 << 28)
-+#define   DVO_PIPE_STALL_MASK         (3 << 28)
-+#define   DVO_USE_VGA_SYNC            (1 << 15)
-+#define   DVO_DATA_ORDER_I740         (0 << 14)
-+#define   DVO_DATA_ORDER_FP           (1 << 14)
-+#define   DVO_VSYNC_DISABLE           (1 << 11)
-+#define   DVO_HSYNC_DISABLE           (1 << 10)
-+#define   DVO_VSYNC_TRISTATE          (1 << 9)
-+#define   DVO_HSYNC_TRISTATE          (1 << 8)
-+#define   DVO_BORDER_ENABLE           (1 << 7)
-+#define   DVO_DATA_ORDER_GBRG         (1 << 6)
-+#define   DVO_DATA_ORDER_RGGB         (0 << 6)
-+#define   DVO_DATA_ORDER_GBRG_ERRATA  (0 << 6)
-+#define   DVO_DATA_ORDER_RGGB_ERRATA  (1 << 6)
-+#define   DVO_VSYNC_ACTIVE_HIGH               (1 << 4)
-+#define   DVO_HSYNC_ACTIVE_HIGH               (1 << 3)
-+#define   DVO_BLANK_ACTIVE_HIGH               (1 << 2)
-+#define   DVO_OUTPUT_CSTATE_PIXELS    (1 << 1)        /* SDG only */
-+#define   DVO_OUTPUT_SOURCE_SIZE_PIXELS       (1 << 0)        /* SDG only */
-+#define   DVO_PRESERVE_MASK           (0x7<<24)
-+#define DVOA_SRCDIM           0x61124
-+#define DVOB_SRCDIM           0x61144
-+#define DVOC_SRCDIM           0x61164
-+#define   DVO_SRCDIM_HORIZONTAL_SHIFT 12
-+#define   DVO_SRCDIM_VERTICAL_SHIFT   0
-+
-+/* LVDS port control */
-+#define LVDS                  0x61180
-+/*
-+ * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
-+ * the DPLL semantics change when the LVDS is assigned to that pipe.
-+ */
-+#define   LVDS_PORT_EN                        (1 << 31)
-+/* Selects pipe B for LVDS data.  Must be set on pre-965. */
-+#define   LVDS_PIPEB_SELECT           (1 << 30)
-+/*
-+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
-+ * pixel.
-+ */
-+#define   LVDS_A0A2_CLKA_POWER_MASK   (3 << 8)
-+#define   LVDS_A0A2_CLKA_POWER_DOWN   (0 << 8)
-+#define   LVDS_A0A2_CLKA_POWER_UP     (3 << 8)
-+/*
-+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
-+ * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
-+ * on.
-+ */
-+#define   LVDS_A3_POWER_MASK          (3 << 6)
-+#define   LVDS_A3_POWER_DOWN          (0 << 6)
-+#define   LVDS_A3_POWER_UP            (3 << 6)
-+/*
-+ * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
-+ * is set.
-+ */
-+#define   LVDS_CLKB_POWER_MASK                (3 << 4)
-+#define   LVDS_CLKB_POWER_DOWN                (0 << 4)
-+#define   LVDS_CLKB_POWER_UP          (3 << 4)
-+/*
-+ * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
-+ * setting for whether we are in dual-channel mode.  The B3 pair will
-+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
-+ */
-+#define   LVDS_B0B3_POWER_MASK                (3 << 2)
-+#define   LVDS_B0B3_POWER_DOWN                (0 << 2)
-+#define   LVDS_B0B3_POWER_UP          (3 << 2)
-+
-+/* Panel power sequencing */
-+#define PP_STATUS     0x61200
-+#define   PP_ON               (1 << 31)
-+/*
-+ * Indicates that all dependencies of the panel are on:
-+ *
-+ * - PLL enabled
-+ * - pipe enabled
-+ * - LVDS/DVOB/DVOC on
-+ */
-+#define   PP_READY            (1 << 30)
-+#define   PP_SEQUENCE_NONE    (0 << 28)
-+#define   PP_SEQUENCE_ON      (1 << 28)
-+#define   PP_SEQUENCE_OFF     (2 << 28)
-+#define   PP_SEQUENCE_MASK    0x30000000
-+#define PP_CONTROL    0x61204
-+#define   POWER_TARGET_ON     (1 << 0)
-+#define PP_ON_DELAYS  0x61208
-+#define PP_OFF_DELAYS 0x6120c
-+#define PP_DIVISOR    0x61210
-+
-+/* Panel fitting */
-+#define PFIT_CONTROL  0x61230
-+#define   PFIT_ENABLE         (1 << 31)
-+#define   PFIT_PIPE_MASK      (3 << 29)
-+#define   PFIT_PIPE_SHIFT     29
-+#define   VERT_INTERP_DISABLE (0 << 10)
-+#define   VERT_INTERP_BILINEAR        (1 << 10)
-+#define   VERT_INTERP_MASK    (3 << 10)
-+#define   VERT_AUTO_SCALE     (1 << 9)
-+#define   HORIZ_INTERP_DISABLE        (0 << 6)
-+#define   HORIZ_INTERP_BILINEAR       (1 << 6)
-+#define   HORIZ_INTERP_MASK   (3 << 6)
-+#define   HORIZ_AUTO_SCALE    (1 << 5)
-+#define   PANEL_8TO6_DITHER_ENABLE (1 << 3)
-+#define PFIT_PGM_RATIOS       0x61234
-+#define   PFIT_VERT_SCALE_MASK                        0xfff00000
-+#define   PFIT_HORIZ_SCALE_MASK                       0x0000fff0
-+#define PFIT_AUTO_RATIOS 0x61238
-+
-+/* Backlight control */
-+#define BLC_PWM_CTL           0x61254
-+#define   BACKLIGHT_MODULATION_FREQ_SHIFT             (17)
-+#define BLC_PWM_CTL2          0x61250 /* 965+ only */
-+/*
-+ * This is the most significant 15 bits of the number of backlight cycles in a
-+ * complete cycle of the modulated backlight control.
-+ *
-+ * The actual value is this field multiplied by two.
-+ */
-+#define   BACKLIGHT_MODULATION_FREQ_MASK              (0x7fff << 17)
-+#define   BLM_LEGACY_MODE                             (1 << 16)
-+/*
-+ * This is the number of cycles out of the backlight modulation cycle for which
-+ * the backlight is on.
-+ *
-+ * This field must be no greater than the number of cycles in the complete
-+ * backlight modulation cycle.
-+ */
-+#define   BACKLIGHT_DUTY_CYCLE_SHIFT          (0)
-+#define   BACKLIGHT_DUTY_CYCLE_MASK           (0xffff)
-+
-+/* TV port control */
-+#define TV_CTL                        0x68000
-+/** Enables the TV encoder */
-+# define TV_ENC_ENABLE                        (1 << 31)
-+/** Sources the TV encoder input from pipe B instead of A. */
-+# define TV_ENC_PIPEB_SELECT          (1 << 30)
-+/** Outputs composite video (DAC A only) */
-+# define TV_ENC_OUTPUT_COMPOSITE      (0 << 28)
-+/** Outputs SVideo video (DAC B/C) */
-+# define TV_ENC_OUTPUT_SVIDEO         (1 << 28)
-+/** Outputs Component video (DAC A/B/C) */
-+# define TV_ENC_OUTPUT_COMPONENT      (2 << 28)
-+/** Outputs Composite and SVideo (DAC A/B/C) */
-+# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE       (3 << 28)
-+# define TV_TRILEVEL_SYNC             (1 << 21)
-+/** Enables slow sync generation (945GM only) */
-+# define TV_SLOW_SYNC                 (1 << 20)
-+/** Selects 4x oversampling for 480i and 576p */
-+# define TV_OVERSAMPLE_4X             (0 << 18)
-+/** Selects 2x oversampling for 720p and 1080i */
-+# define TV_OVERSAMPLE_2X             (1 << 18)
-+/** Selects no oversampling for 1080p */
-+# define TV_OVERSAMPLE_NONE           (2 << 18)
-+/** Selects 8x oversampling */
-+# define TV_OVERSAMPLE_8X             (3 << 18)
-+/** Selects progressive mode rather than interlaced */
-+# define TV_PROGRESSIVE                       (1 << 17)
-+/** Sets the colorburst to PAL mode.  Required for non-M PAL modes. */
-+# define TV_PAL_BURST                 (1 << 16)
-+/** Field for setting delay of Y compared to C */
-+# define TV_YC_SKEW_MASK              (7 << 12)
-+/** Enables a fix for 480p/576p standard definition modes on the 915GM only */
-+# define TV_ENC_SDP_FIX                       (1 << 11)
-+/**
-+ * Enables a fix for the 915GM only.
-+ *
-+ * Not sure what it does.
-+ */
-+# define TV_ENC_C0_FIX                        (1 << 10)
-+/** Bits that must be preserved by software */
-+# define TV_CTL_SAVE                  ((3 << 8) | (3 << 6))
-+# define TV_FUSE_STATE_MASK           (3 << 4)
-+/** Read-only state that reports all features enabled */
-+# define TV_FUSE_STATE_ENABLED                (0 << 4)
-+/** Read-only state that reports that Macrovision is disabled in hardware*/
-+# define TV_FUSE_STATE_NO_MACROVISION (1 << 4)
-+/** Read-only state that reports that TV-out is disabled in hardware. */
-+# define TV_FUSE_STATE_DISABLED               (2 << 4)
-+/** Normal operation */
-+# define TV_TEST_MODE_NORMAL          (0 << 0)
-+/** Encoder test pattern 1 - combo pattern */
-+# define TV_TEST_MODE_PATTERN_1               (1 << 0)
-+/** Encoder test pattern 2 - full screen vertical 75% color bars */
-+# define TV_TEST_MODE_PATTERN_2               (2 << 0)
-+/** Encoder test pattern 3 - full screen horizontal 75% color bars */
-+# define TV_TEST_MODE_PATTERN_3               (3 << 0)
-+/** Encoder test pattern 4 - random noise */
-+# define TV_TEST_MODE_PATTERN_4               (4 << 0)
-+/** Encoder test pattern 5 - linear color ramps */
-+# define TV_TEST_MODE_PATTERN_5               (5 << 0)
-+/**
-+ * This test mode forces the DACs to 50% of full output.
-+ *
-+ * This is used for load detection in combination with TVDAC_SENSE_MASK
-+ */
-+# define TV_TEST_MODE_MONITOR_DETECT  (7 << 0)
-+# define TV_TEST_MODE_MASK            (7 << 0)
-+
-+#define TV_DAC                        0x68004
-+/**
-+ * Reports that DAC state change logic has reported change (RO).
-+ *
-+ * This gets cleared when TV_DAC_STATE_EN is cleared
-+*/
-+# define TVDAC_STATE_CHG              (1 << 31)
-+# define TVDAC_SENSE_MASK             (7 << 28)
-+/** Reports that DAC A voltage is above the detect threshold */
-+# define TVDAC_A_SENSE                        (1 << 30)
-+/** Reports that DAC B voltage is above the detect threshold */
-+# define TVDAC_B_SENSE                        (1 << 29)
-+/** Reports that DAC C voltage is above the detect threshold */
-+# define TVDAC_C_SENSE                        (1 << 28)
-+/**
-+ * Enables DAC state detection logic, for load-based TV detection.
-+ *
-+ * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set
-+ * to off, for load detection to work.
-+ */
-+# define TVDAC_STATE_CHG_EN           (1 << 27)
-+/** Sets the DAC A sense value to high */
-+# define TVDAC_A_SENSE_CTL            (1 << 26)
-+/** Sets the DAC B sense value to high */
-+# define TVDAC_B_SENSE_CTL            (1 << 25)
-+/** Sets the DAC C sense value to high */
-+# define TVDAC_C_SENSE_CTL            (1 << 24)
-+/** Overrides the ENC_ENABLE and DAC voltage levels */
-+# define DAC_CTL_OVERRIDE             (1 << 7)
-+/** Sets the slew rate.  Must be preserved in software */
-+# define ENC_TVDAC_SLEW_FAST          (1 << 6)
-+# define DAC_A_1_3_V                  (0 << 4)
-+# define DAC_A_1_1_V                  (1 << 4)
-+# define DAC_A_0_7_V                  (2 << 4)
-+# define DAC_A_OFF                    (3 << 4)
-+# define DAC_B_1_3_V                  (0 << 2)
-+# define DAC_B_1_1_V                  (1 << 2)
-+# define DAC_B_0_7_V                  (2 << 2)
-+# define DAC_B_OFF                    (3 << 2)
-+# define DAC_C_1_3_V                  (0 << 0)
-+# define DAC_C_1_1_V                  (1 << 0)
-+# define DAC_C_0_7_V                  (2 << 0)
-+# define DAC_C_OFF                    (3 << 0)
-+
-+/**
-+ * CSC coefficients are stored in a floating point format with 9 bits of
-+ * mantissa and 2 or 3 bits of exponent.  The exponent is represented as 2**-n,
-+ * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
-+ * -1 (0x3) being the only legal negative value.
-+ */
-+#define TV_CSC_Y              0x68010
-+# define TV_RY_MASK                   0x07ff0000
-+# define TV_RY_SHIFT                  16
-+# define TV_GY_MASK                   0x00000fff
-+# define TV_GY_SHIFT                  0
-+
-+#define TV_CSC_Y2             0x68014
-+# define TV_BY_MASK                   0x07ff0000
-+# define TV_BY_SHIFT                  16
-+/**
-+ * Y attenuation for component video.
-+ *
-+ * Stored in 1.9 fixed point.
-+ */
-+# define TV_AY_MASK                   0x000003ff
-+# define TV_AY_SHIFT                  0
-+
-+#define TV_CSC_U              0x68018
-+# define TV_RU_MASK                   0x07ff0000
-+# define TV_RU_SHIFT                  16
-+# define TV_GU_MASK                   0x000007ff
-+# define TV_GU_SHIFT                  0
-+
-+#define TV_CSC_U2             0x6801c
-+# define TV_BU_MASK                   0x07ff0000
-+# define TV_BU_SHIFT                  16
-+/**
-+ * U attenuation for component video.
-+ *
-+ * Stored in 1.9 fixed point.
-+ */
-+# define TV_AU_MASK                   0x000003ff
-+# define TV_AU_SHIFT                  0
-+
-+#define TV_CSC_V              0x68020
-+# define TV_RV_MASK                   0x0fff0000
-+# define TV_RV_SHIFT                  16
-+# define TV_GV_MASK                   0x000007ff
-+# define TV_GV_SHIFT                  0
-+
-+#define TV_CSC_V2             0x68024
-+# define TV_BV_MASK                   0x07ff0000
-+# define TV_BV_SHIFT                  16
-+/**
-+ * V attenuation for component video.
-+ *
-+ * Stored in 1.9 fixed point.
-+ */
-+# define TV_AV_MASK                   0x000007ff
-+# define TV_AV_SHIFT                  0
-+
-+#define TV_CLR_KNOBS          0x68028
-+/** 2s-complement brightness adjustment */
-+# define TV_BRIGHTNESS_MASK           0xff000000
-+# define TV_BRIGHTNESS_SHIFT          24
-+/** Contrast adjustment, as a 2.6 unsigned floating point number */
-+# define TV_CONTRAST_MASK             0x00ff0000
-+# define TV_CONTRAST_SHIFT            16
-+/** Saturation adjustment, as a 2.6 unsigned floating point number */
-+# define TV_SATURATION_MASK           0x0000ff00
-+# define TV_SATURATION_SHIFT          8
-+/** Hue adjustment, as an integer phase angle in degrees */
-+# define TV_HUE_MASK                  0x000000ff
-+# define TV_HUE_SHIFT                 0
-+
-+#define TV_CLR_LEVEL          0x6802c
-+/** Controls the DAC level for black */
-+# define TV_BLACK_LEVEL_MASK          0x01ff0000
-+# define TV_BLACK_LEVEL_SHIFT         16
-+/** Controls the DAC level for blanking */
-+# define TV_BLANK_LEVEL_MASK          0x000001ff
-+# define TV_BLANK_LEVEL_SHIFT         0
-+
-+#define TV_H_CTL_1            0x68030
-+/** Number of pixels in the hsync. */
-+# define TV_HSYNC_END_MASK            0x1fff0000
-+# define TV_HSYNC_END_SHIFT           16
-+/** Total number of pixels minus one in the line (display and blanking). */
-+# define TV_HTOTAL_MASK                       0x00001fff
-+# define TV_HTOTAL_SHIFT              0
-+
-+#define TV_H_CTL_2            0x68034
-+/** Enables the colorburst (needed for non-component color) */
-+# define TV_BURST_ENA                 (1 << 31)
-+/** Offset of the colorburst from the start of hsync, in pixels minus one. */
-+# define TV_HBURST_START_SHIFT                16
-+# define TV_HBURST_START_MASK         0x1fff0000
-+/** Length of the colorburst */
-+# define TV_HBURST_LEN_SHIFT          0
-+# define TV_HBURST_LEN_MASK           0x0001fff
-+
-+#define TV_H_CTL_3            0x68038
-+/** End of hblank, measured in pixels minus one from start of hsync */
-+# define TV_HBLANK_END_SHIFT          16
-+# define TV_HBLANK_END_MASK           0x1fff0000
-+/** Start of hblank, measured in pixels minus one from start of hsync */
-+# define TV_HBLANK_START_SHIFT                0
-+# define TV_HBLANK_START_MASK         0x0001fff
-+
-+#define TV_V_CTL_1            0x6803c
-+/** XXX */
-+# define TV_NBR_END_SHIFT             16
-+# define TV_NBR_END_MASK              0x07ff0000
-+/** XXX */
-+# define TV_VI_END_F1_SHIFT           8
-+# define TV_VI_END_F1_MASK            0x00003f00
-+/** XXX */
-+# define TV_VI_END_F2_SHIFT           0
-+# define TV_VI_END_F2_MASK            0x0000003f
-+
-+#define TV_V_CTL_2            0x68040
-+/** Length of vsync, in half lines */
-+# define TV_VSYNC_LEN_MASK            0x07ff0000
-+# define TV_VSYNC_LEN_SHIFT           16
-+/** Offset of the start of vsync in field 1, measured in one less than the
-+ * number of half lines.
-+ */
-+# define TV_VSYNC_START_F1_MASK               0x00007f00
-+# define TV_VSYNC_START_F1_SHIFT      8
-+/**
-+ * Offset of the start of vsync in field 2, measured in one less than the
-+ * number of half lines.
-+ */
-+# define TV_VSYNC_START_F2_MASK               0x0000007f
-+# define TV_VSYNC_START_F2_SHIFT      0
-+
-+#define TV_V_CTL_3            0x68044
-+/** Enables generation of the equalization signal */
-+# define TV_EQUAL_ENA                 (1 << 31)
-+/** Length of vsync, in half lines */
-+# define TV_VEQ_LEN_MASK              0x007f0000
-+# define TV_VEQ_LEN_SHIFT             16
-+/** Offset of the start of equalization in field 1, measured in one less than
-+ * the number of half lines.
-+ */
-+# define TV_VEQ_START_F1_MASK         0x0007f00
-+# define TV_VEQ_START_F1_SHIFT                8
-+/**
-+ * Offset of the start of equalization in field 2, measured in one less than
-+ * the number of half lines.
-+ */
-+# define TV_VEQ_START_F2_MASK         0x000007f
-+# define TV_VEQ_START_F2_SHIFT                0
-+
-+#define TV_V_CTL_4            0x68048
-+/**
-+ * Offset to start of vertical colorburst, measured in one less than the
-+ * number of lines from vertical start.
-+ */
-+# define TV_VBURST_START_F1_MASK      0x003f0000
-+# define TV_VBURST_START_F1_SHIFT     16
-+/**
-+ * Offset to the end of vertical colorburst, measured in one less than the
-+ * number of lines from the start of NBR.
-+ */
-+# define TV_VBURST_END_F1_MASK                0x000000ff
-+# define TV_VBURST_END_F1_SHIFT               0
-+
-+#define TV_V_CTL_5            0x6804c
-+/**
-+ * Offset to start of vertical colorburst, measured in one less than the
-+ * number of lines from vertical start.
-+ */
-+# define TV_VBURST_START_F2_MASK      0x003f0000
-+# define TV_VBURST_START_F2_SHIFT     16
-+/**
-+ * Offset to the end of vertical colorburst, measured in one less than the
-+ * number of lines from the start of NBR.
-+ */
-+# define TV_VBURST_END_F2_MASK                0x000000ff
-+# define TV_VBURST_END_F2_SHIFT               0
-+
-+#define TV_V_CTL_6            0x68050
-+/**
-+ * Offset to start of vertical colorburst, measured in one less than the
-+ * number of lines from vertical start.
-+ */
-+# define TV_VBURST_START_F3_MASK      0x003f0000
-+# define TV_VBURST_START_F3_SHIFT     16
-+/**
-+ * Offset to the end of vertical colorburst, measured in one less than the
-+ * number of lines from the start of NBR.
-+ */
-+# define TV_VBURST_END_F3_MASK                0x000000ff
-+# define TV_VBURST_END_F3_SHIFT               0
-+
-+#define TV_V_CTL_7            0x68054
-+/**
-+ * Offset to start of vertical colorburst, measured in one less than the
-+ * number of lines from vertical start.
-+ */
-+# define TV_VBURST_START_F4_MASK      0x003f0000
-+# define TV_VBURST_START_F4_SHIFT     16
-+/**
-+ * Offset to the end of vertical colorburst, measured in one less than the
-+ * number of lines from the start of NBR.
-+ */
-+# define TV_VBURST_END_F4_MASK                0x000000ff
-+# define TV_VBURST_END_F4_SHIFT               0
-+
-+#define TV_SC_CTL_1           0x68060
-+/** Turns on the first subcarrier phase generation DDA */
-+# define TV_SC_DDA1_EN                        (1 << 31)
-+/** Turns on the first subcarrier phase generation DDA */
-+# define TV_SC_DDA2_EN                        (1 << 30)
-+/** Turns on the first subcarrier phase generation DDA */
-+# define TV_SC_DDA3_EN                        (1 << 29)
-+/** Sets the subcarrier DDA to reset frequency every other field */
-+# define TV_SC_RESET_EVERY_2          (0 << 24)
-+/** Sets the subcarrier DDA to reset frequency every fourth field */
-+# define TV_SC_RESET_EVERY_4          (1 << 24)
-+/** Sets the subcarrier DDA to reset frequency every eighth field */
-+# define TV_SC_RESET_EVERY_8          (2 << 24)
-+/** Sets the subcarrier DDA to never reset the frequency */
-+# define TV_SC_RESET_NEVER            (3 << 24)
-+/** Sets the peak amplitude of the colorburst.*/
-+# define TV_BURST_LEVEL_MASK          0x00ff0000
-+# define TV_BURST_LEVEL_SHIFT         16
-+/** Sets the increment of the first subcarrier phase generation DDA */
-+# define TV_SCDDA1_INC_MASK           0x00000fff
-+# define TV_SCDDA1_INC_SHIFT          0
-+
-+#define TV_SC_CTL_2           0x68064
-+/** Sets the rollover for the second subcarrier phase generation DDA */
-+# define TV_SCDDA2_SIZE_MASK          0x7fff0000
-+# define TV_SCDDA2_SIZE_SHIFT         16
-+/** Sets the increent of the second subcarrier phase generation DDA */
-+# define TV_SCDDA2_INC_MASK           0x00007fff
-+# define TV_SCDDA2_INC_SHIFT          0
-+
-+#define TV_SC_CTL_3           0x68068
-+/** Sets the rollover for the third subcarrier phase generation DDA */
-+# define TV_SCDDA3_SIZE_MASK          0x7fff0000
-+# define TV_SCDDA3_SIZE_SHIFT         16
-+/** Sets the increent of the third subcarrier phase generation DDA */
-+# define TV_SCDDA3_INC_MASK           0x00007fff
-+# define TV_SCDDA3_INC_SHIFT          0
-+
-+#define TV_WIN_POS            0x68070
-+/** X coordinate of the display from the start of horizontal active */
-+# define TV_XPOS_MASK                 0x1fff0000
-+# define TV_XPOS_SHIFT                        16
-+/** Y coordinate of the display from the start of vertical active (NBR) */
-+# define TV_YPOS_MASK                 0x00000fff
-+# define TV_YPOS_SHIFT                        0
-+
-+#define TV_WIN_SIZE           0x68074
-+/** Horizontal size of the display window, measured in pixels*/
-+# define TV_XSIZE_MASK                        0x1fff0000
-+# define TV_XSIZE_SHIFT                       16
-+/**
-+ * Vertical size of the display window, measured in pixels.
-+ *
-+ * Must be even for interlaced modes.
-+ */
-+# define TV_YSIZE_MASK                        0x00000fff
-+# define TV_YSIZE_SHIFT                       0
-+
-+#define TV_FILTER_CTL_1               0x68080
-+/**
-+ * Enables automatic scaling calculation.
-+ *
-+ * If set, the rest of the registers are ignored, and the calculated values can
-+ * be read back from the register.
-+ */
-+# define TV_AUTO_SCALE                        (1 << 31)
-+/**
-+ * Disables the vertical filter.
-+ *
-+ * This is required on modes more than 1024 pixels wide */
-+# define TV_V_FILTER_BYPASS           (1 << 29)
-+/** Enables adaptive vertical filtering */
-+# define TV_VADAPT                    (1 << 28)
-+# define TV_VADAPT_MODE_MASK          (3 << 26)
-+/** Selects the least adaptive vertical filtering mode */
-+# define TV_VADAPT_MODE_LEAST         (0 << 26)
-+/** Selects the moderately adaptive vertical filtering mode */
-+# define TV_VADAPT_MODE_MODERATE      (1 << 26)
-+/** Selects the most adaptive vertical filtering mode */
-+# define TV_VADAPT_MODE_MOST          (3 << 26)
-+/**
-+ * Sets the horizontal scaling factor.
-+ *
-+ * This should be the fractional part of the horizontal scaling factor divided
-+ * by the oversampling rate.  TV_HSCALE should be less than 1, and set to:
-+ *
-+ * (src width - 1) / ((oversample * dest width) - 1)
-+ */
-+# define TV_HSCALE_FRAC_MASK          0x00003fff
-+# define TV_HSCALE_FRAC_SHIFT         0
-+
-+#define TV_FILTER_CTL_2               0x68084
-+/**
-+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
-+ *
-+ * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1)
-+ */
-+# define TV_VSCALE_INT_MASK           0x00038000
-+# define TV_VSCALE_INT_SHIFT          15
-+/**
-+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
-+ *
-+ * \sa TV_VSCALE_INT_MASK
-+ */
-+# define TV_VSCALE_FRAC_MASK          0x00007fff
-+# define TV_VSCALE_FRAC_SHIFT         0
-+
-+#define TV_FILTER_CTL_3               0x68088
-+/**
-+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
-+ *
-+ * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1))
-+ *
-+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
-+ */
-+# define TV_VSCALE_IP_INT_MASK                0x00038000
-+# define TV_VSCALE_IP_INT_SHIFT               15
-+/**
-+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
-+ *
-+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
-+ *
-+ * \sa TV_VSCALE_IP_INT_MASK
-+ */
-+# define TV_VSCALE_IP_FRAC_MASK               0x00007fff
-+# define TV_VSCALE_IP_FRAC_SHIFT              0
-+
-+#define TV_CC_CONTROL         0x68090
-+# define TV_CC_ENABLE                 (1 << 31)
-+/**
-+ * Specifies which field to send the CC data in.
-+ *
-+ * CC data is usually sent in field 0.
-+ */
-+# define TV_CC_FID_MASK                       (1 << 27)
-+# define TV_CC_FID_SHIFT              27
-+/** Sets the horizontal position of the CC data.  Usually 135. */
-+# define TV_CC_HOFF_MASK              0x03ff0000
-+# define TV_CC_HOFF_SHIFT             16
-+/** Sets the vertical position of the CC data.  Usually 21 */
-+# define TV_CC_LINE_MASK              0x0000003f
-+# define TV_CC_LINE_SHIFT             0
-+
-+#define TV_CC_DATA            0x68094
-+# define TV_CC_RDY                    (1 << 31)
-+/** Second word of CC data to be transmitted. */
-+# define TV_CC_DATA_2_MASK            0x007f0000
-+# define TV_CC_DATA_2_SHIFT           16
-+/** First word of CC data to be transmitted. */
-+# define TV_CC_DATA_1_MASK            0x0000007f
-+# define TV_CC_DATA_1_SHIFT           0
-+
-+#define TV_H_LUMA_0           0x68100
-+#define TV_H_LUMA_59          0x681ec
-+#define TV_H_CHROMA_0         0x68200
-+#define TV_H_CHROMA_59                0x682ec
-+#define TV_V_LUMA_0           0x68300
-+#define TV_V_LUMA_42          0x683a8
-+#define TV_V_CHROMA_0         0x68400
-+#define TV_V_CHROMA_42                0x684a8
-+
-+/* Display & cursor control */
-+
-+/* Pipe A */
-+#define PIPEADSL              0x70000
-+#define PIPEACONF             0x70008
-+#define   PIPEACONF_ENABLE    (1<<31)
-+#define   PIPEACONF_DISABLE   0
-+#define   PIPEACONF_DOUBLE_WIDE       (1<<30)
-+#define   I965_PIPECONF_ACTIVE        (1<<30)
-+#define   PIPEACONF_SINGLE_WIDE       0
-+#define   PIPEACONF_PIPE_UNLOCKED 0
-+#define   PIPEACONF_PIPE_LOCKED       (1<<25)
-+#define   PIPEACONF_PALETTE   0
-+#define   PIPEACONF_GAMMA             (1<<24)
-+#define   PIPECONF_FORCE_BORDER       (1<<25)
-+#define   PIPECONF_PROGRESSIVE        (0 << 21)
-+#define   PIPECONF_INTERLACE_W_FIELD_INDICATION       (6 << 21)
-+#define   PIPECONF_INTERLACE_FIELD_0_ONLY             (7 << 21)
-+#define PIPEASTAT             0x70024
-+#define   PIPE_FIFO_UNDERRUN_STATUS           (1UL<<31)
-+#define   PIPE_CRC_ERROR_ENABLE                       (1UL<<29)
-+#define   PIPE_CRC_DONE_ENABLE                        (1UL<<28)
-+#define   PIPE_GMBUS_EVENT_ENABLE             (1UL<<27)
-+#define   PIPE_HOTPLUG_INTERRUPT_ENABLE               (1UL<<26)
-+#define   PIPE_VSYNC_INTERRUPT_ENABLE         (1UL<<25)
-+#define   PIPE_DISPLAY_LINE_COMPARE_ENABLE    (1UL<<24)
-+#define   PIPE_DPST_EVENT_ENABLE              (1UL<<23)
-+#define   PIPE_LEGACY_BLC_EVENT_ENABLE                (1UL<<22)
-+#define   PIPE_ODD_FIELD_INTERRUPT_ENABLE     (1UL<<21)
-+#define   PIPE_EVEN_FIELD_INTERRUPT_ENABLE    (1UL<<20)
-+#define   PIPE_HOTPLUG_TV_INTERRUPT_ENABLE    (1UL<<18) /* pre-965 */
-+#define   PIPE_START_VBLANK_INTERRUPT_ENABLE  (1UL<<18) /* 965 or later */
-+#define   PIPE_VBLANK_INTERRUPT_ENABLE                (1UL<<17)
-+#define   PIPE_OVERLAY_UPDATED_ENABLE         (1UL<<16)
-+#define   PIPE_CRC_ERROR_INTERRUPT_STATUS     (1UL<<13)
-+#define   PIPE_CRC_DONE_INTERRUPT_STATUS      (1UL<<12)
-+#define   PIPE_GMBUS_INTERRUPT_STATUS         (1UL<<11)
-+#define   PIPE_HOTPLUG_INTERRUPT_STATUS               (1UL<<10)
-+#define   PIPE_VSYNC_INTERRUPT_STATUS         (1UL<<9)
-+#define   PIPE_DISPLAY_LINE_COMPARE_STATUS    (1UL<<8)
-+#define   PIPE_DPST_EVENT_STATUS              (1UL<<7)
-+#define   PIPE_LEGACY_BLC_EVENT_STATUS                (1UL<<6)
-+#define   PIPE_ODD_FIELD_INTERRUPT_STATUS     (1UL<<5)
-+#define   PIPE_EVEN_FIELD_INTERRUPT_STATUS    (1UL<<4)
-+#define   PIPE_HOTPLUG_TV_INTERRUPT_STATUS    (1UL<<2) /* pre-965 */
-+#define   PIPE_START_VBLANK_INTERRUPT_STATUS  (1UL<<2) /* 965 or later */
-+#define   PIPE_VBLANK_INTERRUPT_STATUS                (1UL<<1)
-+#define   PIPE_OVERLAY_UPDATED_STATUS         (1UL<<0)
-+
-+#define DSPARB                        0x70030
-+#define   DSPARB_CSTART_MASK  (0x7f << 7)
-+#define   DSPARB_CSTART_SHIFT 7
-+#define   DSPARB_BSTART_MASK  (0x7f)
-+#define   DSPARB_BSTART_SHIFT 0
-+/*
-+ * The two pipe frame counter registers are not synchronized, so
-+ * reading a stable value is somewhat tricky. The following code
-+ * should work:
-+ *
-+ *  do {
-+ *    high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
-+ *             PIPE_FRAME_HIGH_SHIFT;
-+ *    low1 =  ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
-+ *             PIPE_FRAME_LOW_SHIFT);
-+ *    high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
-+ *             PIPE_FRAME_HIGH_SHIFT);
-+ *  } while (high1 != high2);
-+ *  frame = (high1 << 8) | low1;
-+ */
-+#define PIPEAFRAMEHIGH          0x70040
-+#define   PIPE_FRAME_HIGH_MASK    0x0000ffff
-+#define   PIPE_FRAME_HIGH_SHIFT   0
-+#define PIPEAFRAMEPIXEL         0x70044
-+#define   PIPE_FRAME_LOW_MASK     0xff000000
-+#define   PIPE_FRAME_LOW_SHIFT    24
-+#define   PIPE_PIXEL_MASK         0x00ffffff
-+#define   PIPE_PIXEL_SHIFT        0
-+
-+/* Cursor A & B regs */
-+#define CURACNTR              0x70080
-+#define   CURSOR_MODE_DISABLE   0x00
-+#define   CURSOR_MODE_64_32B_AX 0x07
-+#define   CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
-+#define   MCURSOR_GAMMA_ENABLE  (1 << 26)
-+#define CURABASE              0x70084
-+#define CURAPOS                       0x70088
-+#define   CURSOR_POS_MASK       0x007FF
-+#define   CURSOR_POS_SIGN       0x8000
-+#define   CURSOR_X_SHIFT        0
-+#define   CURSOR_Y_SHIFT        16
-+#define CURBCNTR              0x700c0
-+#define CURBBASE              0x700c4
-+#define CURBPOS                       0x700c8
-+
-+/* Display A control */
-+#define DSPACNTR                0x70180
-+#define   DISPLAY_PLANE_ENABLE                        (1<<31)
-+#define   DISPLAY_PLANE_DISABLE                       0
-+#define   DISPPLANE_GAMMA_ENABLE              (1<<30)
-+#define   DISPPLANE_GAMMA_DISABLE             0
-+#define   DISPPLANE_PIXFORMAT_MASK            (0xf<<26)
-+#define   DISPPLANE_8BPP                      (0x2<<26)
-+#define   DISPPLANE_15_16BPP                  (0x4<<26)
-+#define   DISPPLANE_16BPP                     (0x5<<26)
-+#define   DISPPLANE_32BPP_NO_ALPHA            (0x6<<26)
-+#define   DISPPLANE_32BPP                     (0x7<<26)
-+#define   DISPPLANE_STEREO_ENABLE             (1<<25)
-+#define   DISPPLANE_STEREO_DISABLE            0
-+#define   DISPPLANE_SEL_PIPE_MASK             (1<<24)
-+#define   DISPPLANE_SEL_PIPE_A                        0
-+#define   DISPPLANE_SEL_PIPE_B                        (1<<24)
-+#define   DISPPLANE_SRC_KEY_ENABLE            (1<<22)
-+#define   DISPPLANE_SRC_KEY_DISABLE           0
-+#define   DISPPLANE_LINE_DOUBLE                       (1<<20)
-+#define   DISPPLANE_NO_LINE_DOUBLE            0
-+#define   DISPPLANE_STEREO_POLARITY_FIRST     0
-+#define   DISPPLANE_STEREO_POLARITY_SECOND    (1<<18)
-+#define DSPAADDR              0x70184
-+#define DSPASTRIDE            0x70188
-+#define DSPAPOS                       0x7018C /* reserved */
-+#define DSPASIZE              0x70190
-+#define DSPASURF              0x7019C /* 965+ only */
-+#define DSPATILEOFF           0x701A4 /* 965+ only */
-+
-+/* VBIOS flags */
-+#define SWF00                 0x71410
-+#define SWF01                 0x71414
-+#define SWF02                 0x71418
-+#define SWF03                 0x7141c
-+#define SWF04                 0x71420
-+#define SWF05                 0x71424
-+#define SWF06                 0x71428
-+#define SWF10                 0x70410
-+#define SWF11                 0x70414
-+#define SWF14                 0x71420
-+#define SWF30                 0x72414
-+#define SWF31                 0x72418
-+#define SWF32                 0x7241c
-+
-+/* Pipe B */
-+#define PIPEBDSL              0x71000
-+#define PIPEBCONF             0x71008
-+#define PIPEBSTAT             0x71024
-+#define PIPEBFRAMEHIGH                0x71040
-+#define PIPEBFRAMEPIXEL               0x71044
-+
-+/* Display B control */
-+#define DSPBCNTR              0x71180
-+#define   DISPPLANE_ALPHA_TRANS_ENABLE                (1<<15)
-+#define   DISPPLANE_ALPHA_TRANS_DISABLE               0
-+#define   DISPPLANE_SPRITE_ABOVE_DISPLAY      0
-+#define   DISPPLANE_SPRITE_ABOVE_OVERLAY      (1)
-+#define DSPBADDR              0x71184
-+#define DSPBSTRIDE            0x71188
-+#define DSPBPOS                       0x7118C
-+#define DSPBSIZE              0x71190
-+#define DSPBSURF              0x7119C
-+#define DSPBTILEOFF           0x711A4
-+
-+/* VBIOS regs */
-+#define VGACNTRL              0x71400
-+# define VGA_DISP_DISABLE                     (1 << 31)
-+# define VGA_2X_MODE                          (1 << 30)
-+# define VGA_PIPE_B_SELECT                    (1 << 29)
-+
-+#endif /* _I915_REG_H_ */
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0005-i915-Add-support-for-MSI-and-interrupt-mitigation.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0005-i915-Add-support-for-MSI-and-interrupt-mitigation.patch
deleted file mode 100644 (file)
index 9337475..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-commit 4f99970852559935b27bc634318f34c18c5fd143
-Author: Eric Anholt <eric@anholt.net>
-Date:   Tue Jul 29 12:10:39 2008 -0700
-
-    i915: Add support for MSI and interrupt mitigation.
-    
-    Previous attempts at interrupt mitigation had been foiled by i915_wait_irq's
-    failure to update the sarea seqno value when the status page indicated that
-    the seqno had already been passed.  MSI support has been seen to cut CPU
-    costs by up to 40% in some workloads by avoiding other expensive interrupt
-    handlers for frequent graphics interrupts.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
-index 53f0e5a..61ed515 100644
---- a/drivers/gpu/drm/drm_irq.c
-+++ b/drivers/gpu/drm/drm_irq.c
-@@ -63,7 +63,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
-           p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
-               return -EINVAL;
--      p->irq = dev->irq;
-+      p->irq = dev->pdev->irq;
-       DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
-                 p->irq);
-@@ -89,7 +89,7 @@ static int drm_irq_install(struct drm_device * dev)
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-               return -EINVAL;
--      if (dev->irq == 0)
-+      if (dev->pdev->irq == 0)
-               return -EINVAL;
-       mutex_lock(&dev->struct_mutex);
-@@ -107,7 +107,7 @@ static int drm_irq_install(struct drm_device * dev)
-       dev->irq_enabled = 1;
-       mutex_unlock(&dev->struct_mutex);
--      DRM_DEBUG("irq=%d\n", dev->irq);
-+      DRM_DEBUG("irq=%d\n", dev->pdev->irq);
-       if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
-               init_waitqueue_head(&dev->vbl_queue);
-@@ -127,8 +127,12 @@ static int drm_irq_install(struct drm_device * dev)
-       if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
-               sh_flags = IRQF_SHARED;
--      ret = request_irq(dev->irq, dev->driver->irq_handler,
-+      ret = request_irq(dev->pdev->irq, dev->driver->irq_handler,
-                         sh_flags, dev->devname, dev);
-+      /* Expose the device irq number to drivers that want to export it for
-+       * whatever reason.
-+       */
-+      dev->irq = dev->pdev->irq;
-       if (ret < 0) {
-               mutex_lock(&dev->struct_mutex);
-               dev->irq_enabled = 0;
-@@ -164,11 +168,11 @@ int drm_irq_uninstall(struct drm_device * dev)
-       if (!irq_enabled)
-               return -EINVAL;
--      DRM_DEBUG("irq=%d\n", dev->irq);
-+      DRM_DEBUG("irq=%d\n", dev->pdev->irq);
-       dev->driver->irq_uninstall(dev);
--      free_irq(dev->irq, dev);
-+      free_irq(dev->pdev->irq, dev);
-       dev->locked_tasklet_func = NULL;
-@@ -201,7 +205,7 @@ int drm_control(struct drm_device *dev, void *data,
-               if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-                       return 0;
-               if (dev->if_version < DRM_IF_VERSION(1, 2) &&
--                  ctl->irq != dev->irq)
-+                  ctl->irq != dev->pdev->irq)
-                       return -EINVAL;
-               return drm_irq_install(dev);
-       case DRM_UNINST_HANDLER:
-@@ -239,7 +243,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
-       int ret = 0;
-       unsigned int flags, seq;
--      if ((!dev->irq) || (!dev->irq_enabled))
-+      if ((!dev->pdev->irq) || (!dev->irq_enabled))
-               return -EINVAL;
-       if (vblwait->request.type &
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 7be580b..10bfb0c 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -84,7 +84,7 @@ static int i915_dma_cleanup(struct drm_device * dev)
-        * may not have been called from userspace and after dev_private
-        * is freed, it's too late.
-        */
--      if (dev->irq)
-+      if (dev->irq_enabled)
-               drm_irq_uninstall(dev);
-       if (dev_priv->ring.virtual_start) {
-@@ -644,7 +644,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
-       switch (param->param) {
-       case I915_PARAM_IRQ_ACTIVE:
--              value = dev->irq ? 1 : 0;
-+              value = dev->irq_enabled;
-               break;
-       case I915_PARAM_ALLOW_BATCHBUFFER:
-               value = dev_priv->allow_batchbuffer ? 1 : 0;
-@@ -763,6 +763,20 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
-       ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
-                        _DRM_KERNEL | _DRM_DRIVER,
-                        &dev_priv->mmio_map);
-+
-+
-+      /* On the 945G/GM, the chipset reports the MSI capability on the
-+       * integrated graphics even though the support isn't actually there
-+       * according to the published specs.  It doesn't appear to function
-+       * correctly in testing on 945G.
-+       * This may be a side effect of MSI having been made available for PEG
-+       * and the registers being closely associated.
-+       */
-+      if (!IS_I945G(dev) && !IS_I945GM(dev))
-+              pci_enable_msi(dev->pdev);
-+
-+      spin_lock_init(&dev_priv->user_irq_lock);
-+
-       return ret;
- }
-@@ -770,6 +784,9 @@ int i915_driver_unload(struct drm_device *dev)
- {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-+      if (dev->pdev->msi_enabled)
-+              pci_disable_msi(dev->pdev);
-+
-       if (dev_priv->mmio_map)
-               drm_rmmap(dev, dev_priv->mmio_map);
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index afb51a3..8daf0d8 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -105,6 +105,12 @@ typedef struct drm_i915_private {
-       wait_queue_head_t irq_queue;
-       atomic_t irq_received;
-       atomic_t irq_emitted;
-+      /** Protects user_irq_refcount and irq_mask_reg */
-+      spinlock_t user_irq_lock;
-+      /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
-+      int user_irq_refcount;
-+      /** Cached value of IMR to avoid reads in updating the bitfield */
-+      u32 irq_mask_reg;
-       int tex_lru_log_granularity;
-       int allow_batchbuffer;
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index 4a2de78..24d11ed 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -33,6 +33,31 @@
- #define MAX_NOPID ((u32)~0)
-+/** These are the interrupts used by the driver */
-+#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT |             \
-+                                  I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \
-+                                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-+
-+static inline void
-+i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
-+{
-+      if ((dev_priv->irq_mask_reg & mask) != 0) {
-+              dev_priv->irq_mask_reg &= ~mask;
-+              I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+              (void) I915_READ(IMR);
-+      }
-+}
-+
-+static inline void
-+i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
-+{
-+      if ((dev_priv->irq_mask_reg & mask) != mask) {
-+              dev_priv->irq_mask_reg |= mask;
-+              I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+              (void) I915_READ(IMR);
-+      }
-+}
-+
- /**
-  * Emit blits for scheduled buffer swaps.
-  *
-@@ -229,46 +254,50 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
- {
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      u16 temp;
-       u32 pipea_stats, pipeb_stats;
-+      u32 iir;
-       pipea_stats = I915_READ(PIPEASTAT);
-       pipeb_stats = I915_READ(PIPEBSTAT);
--      temp = I915_READ16(IIR);
--
--      temp &= (I915_USER_INTERRUPT |
--               I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
--               I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT);
-+      if (dev->pdev->msi_enabled)
-+              I915_WRITE(IMR, ~0);
-+      iir = I915_READ(IIR);
--      DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
-+      DRM_DEBUG("iir=%08x\n", iir);
--      if (temp == 0)
-+      if (iir == 0) {
-+              if (dev->pdev->msi_enabled) {
-+                      I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+                      (void) I915_READ(IMR);
-+              }
-               return IRQ_NONE;
-+      }
--      I915_WRITE16(IIR, temp);
--      (void) I915_READ16(IIR);
--      DRM_READMEMORYBARRIER();
-+      I915_WRITE(IIR, iir);
-+      if (dev->pdev->msi_enabled)
-+              I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+      (void) I915_READ(IIR); /* Flush posted writes */
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
--      if (temp & I915_USER_INTERRUPT)
-+      if (iir & I915_USER_INTERRUPT)
-               DRM_WAKEUP(&dev_priv->irq_queue);
--      if (temp & (I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
--                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)) {
-+      if (iir & (I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
-+                 I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)) {
-               int vblank_pipe = dev_priv->vblank_pipe;
-               if ((vblank_pipe &
-                    (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
-                   == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
--                      if (temp & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-+                      if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-                               atomic_inc(&dev->vbl_received);
--                      if (temp & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-+                      if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-                               atomic_inc(&dev->vbl_received2);
--              } else if (((temp & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) &&
-+              } else if (((iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
--                         ((temp & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) &&
-+                         ((iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
-                       atomic_inc(&dev->vbl_received);
-@@ -314,6 +343,27 @@ static int i915_emit_irq(struct drm_device * dev)
-       return dev_priv->counter;
- }
-+static void i915_user_irq_get(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+
-+      spin_lock(&dev_priv->user_irq_lock);
-+      if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
-+              i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
-+      spin_unlock(&dev_priv->user_irq_lock);
-+}
-+
-+static void i915_user_irq_put(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+
-+      spin_lock(&dev_priv->user_irq_lock);
-+      BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
-+      if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
-+              i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
-+      spin_unlock(&dev_priv->user_irq_lock);
-+}
-+
- static int i915_wait_irq(struct drm_device * dev, int irq_nr)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-@@ -322,13 +372,17 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
-       DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
-                 READ_BREADCRUMB(dev_priv));
--      if (READ_BREADCRUMB(dev_priv) >= irq_nr)
-+      if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
-+              dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-               return 0;
-+      }
-       dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-+      i915_user_irq_get(dev);
-       DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
-                   READ_BREADCRUMB(dev_priv) >= irq_nr);
-+      i915_user_irq_put(dev);
-       if (ret == -EBUSY) {
-               DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
-@@ -413,20 +467,6 @@ int i915_irq_wait(struct drm_device *dev, void *data,
-       return i915_wait_irq(dev, irqwait->irq_seq);
- }
--static void i915_enable_interrupt (struct drm_device *dev)
--{
--      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      u16 flag;
--
--      flag = 0;
--      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
--              flag |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
--      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
--              flag |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
--
--      I915_WRITE16(IER, I915_USER_INTERRUPT | flag);
--}
--
- /* Set the vblank monitor pipe
-  */
- int i915_vblank_pipe_set(struct drm_device *dev, void *data,
-@@ -434,6 +474,7 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_pipe_t *pipe = data;
-+      u32 enable_mask = 0, disable_mask = 0;
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-@@ -445,9 +486,20 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
-               return -EINVAL;
-       }
--      dev_priv->vblank_pipe = pipe->pipe;
-+      if (pipe->pipe & DRM_I915_VBLANK_PIPE_A)
-+              enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-+      else
-+              disable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-+
-+      if (pipe->pipe & DRM_I915_VBLANK_PIPE_B)
-+              enable_mask |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-+      else
-+              disable_mask |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
--      i915_enable_interrupt (dev);
-+      i915_enable_irq(dev_priv, enable_mask);
-+      i915_disable_irq(dev_priv, disable_mask);
-+
-+      dev_priv->vblank_pipe = pipe->pipe;
-       return 0;
- }
-@@ -464,7 +516,7 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
-               return -EINVAL;
-       }
--      flag = I915_READ(IER);
-+      flag = I915_READ(IMR);
-       pipe->pipe = 0;
-       if (flag & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
-               pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
-@@ -586,9 +638,9 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      I915_WRITE16(HWSTAM, 0xfffe);
--      I915_WRITE16(IMR, 0x0);
--      I915_WRITE16(IER, 0x0);
-+      I915_WRITE(HWSTAM, 0xfffe);
-+      I915_WRITE(IMR, 0x0);
-+      I915_WRITE(IER, 0x0);
- }
- void i915_driver_irq_postinstall(struct drm_device * dev)
-@@ -601,7 +653,18 @@ void i915_driver_irq_postinstall(struct drm_device * dev)
-       if (!dev_priv->vblank_pipe)
-               dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
--      i915_enable_interrupt(dev);
-+
-+      /* Set initial unmasked IRQs to just the selected vblank pipes. */
-+      dev_priv->irq_mask_reg = ~0;
-+      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
-+              dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-+      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
-+              dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-+
-+      I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+      I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
-+      (void) I915_READ(IER);
-+
-       DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
- }
-@@ -613,10 +676,10 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
-       if (!dev_priv)
-               return;
--      I915_WRITE16(HWSTAM, 0xffff);
--      I915_WRITE16(IMR, 0xffff);
--      I915_WRITE16(IER, 0x0);
-+      I915_WRITE(HWSTAM, 0xffff);
-+      I915_WRITE(IMR, 0xffff);
-+      I915_WRITE(IER, 0x0);
--      temp = I915_READ16(IIR);
--      I915_WRITE16(IIR, temp);
-+      temp = I915_READ(IIR);
-+      I915_WRITE(IIR, temp);
- }
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0006-i915-Track-progress-inside-of-batchbuffers-for-dete.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0006-i915-Track-progress-inside-of-batchbuffers-for-dete.patch
deleted file mode 100644 (file)
index 8736250..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-commit 1236e8610ab9c6f9f8297e60530bedb2640c7224
-Author: Keith Packard <keithp@keithp.com>
-Date:   Wed Jul 30 12:21:20 2008 -0700
-
-    i915: Track progress inside of batchbuffers for determining wedgedness.
-    
-    This avoids early termination for long-running commands.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 10bfb0c..4c72a01 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -40,11 +40,15 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
-+      u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
-+      u32 last_acthd = I915_READ(acthd_reg);
-+      u32 acthd;
-       u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-       int i;
--      for (i = 0; i < 10000; i++) {
-+      for (i = 0; i < 100000; i++) {
-               ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-+              acthd = I915_READ(acthd_reg);
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->Size;
-@@ -55,8 +59,13 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
-               if (ring->head != last_head)
-                       i = 0;
-+              if (acthd != last_acthd)
-+                      i = 0;
-               last_head = ring->head;
-+              last_acthd = acthd;
-+              msleep_interruptible(10);
-+
-       }
-       return -EBUSY;
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0007-i915-Initialize-hardware-status-page-at-device-load.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0007-i915-Initialize-hardware-status-page-at-device-load.patch
deleted file mode 100644 (file)
index 79f068f..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-commit 75fed4ae8454aa975c274b2585ec2287dd15773d
-Author: Keith Packard <keithp@keithp.com>
-Date:   Wed Jul 30 13:03:43 2008 -0700
-
-    i915: Initialize hardware status page at device load when possible.
-    
-    Some chips were unstable with repeated setup/teardown of the hardware status
-    page.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 4c72a01..b3c4ac9 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -71,6 +71,52 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
-       return -EBUSY;
- }
-+/**
-+ * Sets up the hardware status page for devices that need a physical address
-+ * in the register.
-+ */
-+int i915_init_phys_hws(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      /* Program Hardware Status Page */
-+      dev_priv->status_page_dmah =
-+              drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
-+
-+      if (!dev_priv->status_page_dmah) {
-+              DRM_ERROR("Can not allocate hardware status page\n");
-+              return -ENOMEM;
-+      }
-+      dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
-+      dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-+
-+      memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-+
-+      I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-+      DRM_DEBUG("Enabled hardware status page\n");
-+      return 0;
-+}
-+
-+/**
-+ * Frees the hardware status page, whether it's a physical address or a virtual
-+ * address set up by the X Server.
-+ */
-+void i915_free_hws(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      if (dev_priv->status_page_dmah) {
-+              drm_pci_free(dev, dev_priv->status_page_dmah);
-+              dev_priv->status_page_dmah = NULL;
-+      }
-+
-+      if (dev_priv->status_gfx_addr) {
-+              dev_priv->status_gfx_addr = 0;
-+              drm_core_ioremapfree(&dev_priv->hws_map, dev);
-+      }
-+
-+      /* Need to rewrite hardware status page */
-+      I915_WRITE(HWS_PGA, 0x1ffff000);
-+}
-+
- void i915_kernel_lost_context(struct drm_device * dev)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-@@ -103,18 +149,9 @@ static int i915_dma_cleanup(struct drm_device * dev)
-               dev_priv->ring.map.size = 0;
-       }
--      if (dev_priv->status_page_dmah) {
--              drm_pci_free(dev, dev_priv->status_page_dmah);
--              dev_priv->status_page_dmah = NULL;
--              /* Need to rewrite hardware status page */
--              I915_WRITE(HWS_PGA, 0x1ffff000);
--      }
--
--      if (dev_priv->status_gfx_addr) {
--              dev_priv->status_gfx_addr = 0;
--              drm_core_ioremapfree(&dev_priv->hws_map, dev);
--              I915_WRITE(HWS_PGA, 0x1ffff000);
--      }
-+      /* Clear the HWS virtual address at teardown */
-+      if (I915_NEED_GFX_HWS(dev))
-+              i915_free_hws(dev);
-       return 0;
- }
-@@ -165,23 +202,6 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
-        */
-       dev_priv->allow_batchbuffer = 1;
--      /* Program Hardware Status Page */
--      if (!I915_NEED_GFX_HWS(dev)) {
--              dev_priv->status_page_dmah =
--                      drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
--
--              if (!dev_priv->status_page_dmah) {
--                      i915_dma_cleanup(dev);
--                      DRM_ERROR("Can not allocate hardware status page\n");
--                      return -ENOMEM;
--              }
--              dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
--              dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
--
--              memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
--              I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
--      }
--      DRM_DEBUG("Enabled hardware status page\n");
-       return 0;
- }
-@@ -773,6 +793,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
-                        _DRM_KERNEL | _DRM_DRIVER,
-                        &dev_priv->mmio_map);
-+      /* Init HWS */
-+      if (!I915_NEED_GFX_HWS(dev)) {
-+              ret = i915_init_phys_hws(dev);
-+              if (ret != 0)
-+                      return ret;
-+      }
-       /* On the 945G/GM, the chipset reports the MSI capability on the
-        * integrated graphics even though the support isn't actually there
-@@ -796,6 +822,8 @@ int i915_driver_unload(struct drm_device *dev)
-       if (dev->pdev->msi_enabled)
-               pci_disable_msi(dev->pdev);
-+      i915_free_hws(dev);
-+
-       if (dev_priv->mmio_map)
-               drm_rmmap(dev, dev_priv->mmio_map);
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0008-Add-Intel-ACPI-IGD-OpRegion-support.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0008-Add-Intel-ACPI-IGD-OpRegion-support.patch
deleted file mode 100644 (file)
index afa6f96..0000000
+++ /dev/null
@@ -1,572 +0,0 @@
-commit 91c2ebb8e78aa64f4807399b506ec0090ae5f3d6
-Author: Matthew Garrett <mjg59@srcf.ucam.org>
-Date:   Tue Aug 5 19:37:25 2008 +0100
-
-    Add Intel ACPI IGD OpRegion support
-    
-    This adds the support necessary for allowing ACPI backlight control to
-    work on some newer Intel-based graphics systems. Tested on Thinkpad T61
-    and HP 2510p hardware.
-    
-    Signed-off-by: Matthew Garrett <mjg@redhat.com>
-    Signed-off-by: Dave Airlie <airlied@linux.ie>
-
-diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
-index a9e6046..b032808 100644
---- a/drivers/gpu/drm/i915/Makefile
-+++ b/drivers/gpu/drm/i915/Makefile
-@@ -3,7 +3,7 @@
- # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
- ccflags-y := -Iinclude/drm
--i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
-+i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o
- i915-$(CONFIG_COMPAT)   += i915_ioc32.o
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index b3c4ac9..cead62f 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -810,6 +810,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
-       if (!IS_I945G(dev) && !IS_I945GM(dev))
-               pci_enable_msi(dev->pdev);
-+      intel_opregion_init(dev);
-+
-       spin_lock_init(&dev_priv->user_irq_lock);
-       return ret;
-@@ -827,6 +829,8 @@ int i915_driver_unload(struct drm_device *dev)
-       if (dev_priv->mmio_map)
-               drm_rmmap(dev, dev_priv->mmio_map);
-+      intel_opregion_free(dev);
-+
-       drm_free(dev->dev_private, sizeof(drm_i915_private_t),
-                DRM_MEM_DRIVER);
-diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
-index 6c99aab..d95eca2 100644
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -371,6 +371,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
-       i915_save_vga(dev);
-+      intel_opregion_free(dev);
-+
-       if (state.event == PM_EVENT_SUSPEND) {
-               /* Shut down the device */
-               pci_disable_device(dev->pdev);
-@@ -532,6 +534,8 @@ static int i915_resume(struct drm_device *dev)
-       i915_restore_vga(dev);
-+      intel_opregion_init(dev);
-+
-       return 0;
- }
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index 8daf0d8..e4bd01c 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -82,6 +82,14 @@ typedef struct _drm_i915_vbl_swap {
-       unsigned int sequence;
- } drm_i915_vbl_swap_t;
-+struct intel_opregion {
-+      struct opregion_header *header;
-+      struct opregion_acpi *acpi;
-+      struct opregion_swsci *swsci;
-+      struct opregion_asle *asle;
-+      int enabled;
-+};
-+
- typedef struct drm_i915_private {
-       drm_local_map_t *sarea;
-       drm_local_map_t *mmio_map;
-@@ -122,6 +130,8 @@ typedef struct drm_i915_private {
-       drm_i915_vbl_swap_t vbl_swaps;
-       unsigned int swaps_pending;
-+      struct intel_opregion opregion;
-+
-       /* Register state */
-       u8 saveLBB;
-       u32 saveDSPACNTR;
-@@ -244,6 +254,7 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
- extern int i915_vblank_swap(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv);
-+extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
- /* i915_mem.c */
- extern int i915_mem_alloc(struct drm_device *dev, void *data,
-@@ -258,6 +269,12 @@ extern void i915_mem_takedown(struct mem_block **heap);
- extern void i915_mem_release(struct drm_device * dev,
-                            struct drm_file *file_priv, struct mem_block *heap);
-+/* i915_opregion.c */
-+extern int intel_opregion_init(struct drm_device *dev);
-+extern void intel_opregion_free(struct drm_device *dev);
-+extern void opregion_asle_intr(struct drm_device *dev);
-+extern void opregion_enable_asle(struct drm_device *dev);
-+
- #define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
- #define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
- #define I915_READ16(reg)      DRM_READ16(dev_priv->mmio_map, (reg))
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index 24d11ed..ae7d3a8 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -36,9 +36,11 @@
- /** These are the interrupts used by the driver */
- #define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT |             \
-                                   I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \
--                                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
-+                                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT | \
-+                                  I915_ASLE_INTERRUPT |               \
-+                                  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
--static inline void
-+void
- i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
- {
-       if ((dev_priv->irq_mask_reg & mask) != 0) {
-@@ -274,6 +276,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-               return IRQ_NONE;
-       }
-+      I915_WRITE(PIPEASTAT, pipea_stats);
-+      I915_WRITE(PIPEBSTAT, pipeb_stats);
-+
-       I915_WRITE(IIR, iir);
-       if (dev->pdev->msi_enabled)
-               I915_WRITE(IMR, dev_priv->irq_mask_reg);
-@@ -306,14 +311,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-               if (dev_priv->swaps_pending > 0)
-                       drm_locked_tasklet(dev, i915_vblank_tasklet);
--              I915_WRITE(PIPEASTAT,
--                      pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
--                      PIPE_VBLANK_INTERRUPT_STATUS);
--              I915_WRITE(PIPEBSTAT,
--                      pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
--                      PIPE_VBLANK_INTERRUPT_STATUS);
-       }
-+      if (iir & I915_ASLE_INTERRUPT)
-+              opregion_asle_intr(dev);
-+
-+      if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
-+              opregion_asle_intr(dev);
-+
-       return IRQ_HANDLED;
- }
-@@ -661,10 +666,14 @@ void i915_driver_irq_postinstall(struct drm_device * dev)
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
-               dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-+      dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
-+
-       I915_WRITE(IMR, dev_priv->irq_mask_reg);
-       I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
-       (void) I915_READ(IER);
-+      opregion_enable_asle(dev);
-+
-       DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
- }
-diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
-new file mode 100644
-index 0000000..1787a0c
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_opregion.c
-@@ -0,0 +1,371 @@
-+/*
-+ * Copyright 2008 Intel Corporation <hong.liu@intel.com>
-+ * Copyright 2008 Red Hat <mjg@redhat.com>
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining
-+ * a copy of this software and associated documentation files (the
-+ * "Software"), to deal in the Software without restriction, including
-+ * without limitation the rights to use, copy, modify, merge, publish,
-+ * distribute, sub license, and/or sell copies of the Software, and to
-+ * permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the
-+ * next paragraph) shall be included in all copies or substantial
-+ * portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ * NON-INFRINGEMENT.  IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE
-+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-+ * SOFTWARE.
-+ *
-+ */
-+
-+#include <linux/acpi.h>
-+
-+#include "drmP.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+
-+#define PCI_ASLE 0xe4
-+#define PCI_LBPC 0xf4
-+#define PCI_ASLS 0xfc
-+
-+#define OPREGION_SZ            (8*1024)
-+#define OPREGION_HEADER_OFFSET 0
-+#define OPREGION_ACPI_OFFSET   0x100
-+#define OPREGION_SWSCI_OFFSET  0x200
-+#define OPREGION_ASLE_OFFSET   0x300
-+#define OPREGION_VBT_OFFSET    0x1000
-+
-+#define OPREGION_SIGNATURE "IntelGraphicsMem"
-+#define MBOX_ACPI      (1<<0)
-+#define MBOX_SWSCI     (1<<1)
-+#define MBOX_ASLE      (1<<2)
-+
-+struct opregion_header {
-+       u8 signature[16];
-+       u32 size;
-+       u32 opregion_ver;
-+       u8 bios_ver[32];
-+       u8 vbios_ver[16];
-+       u8 driver_ver[16];
-+       u32 mboxes;
-+       u8 reserved[164];
-+} __attribute__((packed));
-+
-+/* OpRegion mailbox #1: public ACPI methods */
-+struct opregion_acpi {
-+       u32 drdy;       /* driver readiness */
-+       u32 csts;       /* notification status */
-+       u32 cevt;       /* current event */
-+       u8 rsvd1[20];
-+       u32 didl[8];    /* supported display devices ID list */
-+       u32 cpdl[8];    /* currently presented display list */
-+       u32 cadl[8];    /* currently active display list */
-+       u32 nadl[8];    /* next active devices list */
-+       u32 aslp;       /* ASL sleep time-out */
-+       u32 tidx;       /* toggle table index */
-+       u32 chpd;       /* current hotplug enable indicator */
-+       u32 clid;       /* current lid state*/
-+       u32 cdck;       /* current docking state */
-+       u32 sxsw;       /* Sx state resume */
-+       u32 evts;       /* ASL supported events */
-+       u32 cnot;       /* current OS notification */
-+       u32 nrdy;       /* driver status */
-+       u8 rsvd2[60];
-+} __attribute__((packed));
-+
-+/* OpRegion mailbox #2: SWSCI */
-+struct opregion_swsci {
-+       u32 scic;       /* SWSCI command|status|data */
-+       u32 parm;       /* command parameters */
-+       u32 dslp;       /* driver sleep time-out */
-+       u8 rsvd[244];
-+} __attribute__((packed));
-+
-+/* OpRegion mailbox #3: ASLE */
-+struct opregion_asle {
-+       u32 ardy;       /* driver readiness */
-+       u32 aslc;       /* ASLE interrupt command */
-+       u32 tche;       /* technology enabled indicator */
-+       u32 alsi;       /* current ALS illuminance reading */
-+       u32 bclp;       /* backlight brightness to set */
-+       u32 pfit;       /* panel fitting state */
-+       u32 cblv;       /* current brightness level */
-+       u16 bclm[20];   /* backlight level duty cycle mapping table */
-+       u32 cpfm;       /* current panel fitting mode */
-+       u32 epfm;       /* enabled panel fitting modes */
-+       u8 plut[74];    /* panel LUT and identifier */
-+       u32 pfmb;       /* PWM freq and min brightness */
-+       u8 rsvd[102];
-+} __attribute__((packed));
-+
-+/* ASLE irq request bits */
-+#define ASLE_SET_ALS_ILLUM     (1 << 0)
-+#define ASLE_SET_BACKLIGHT     (1 << 1)
-+#define ASLE_SET_PFIT          (1 << 2)
-+#define ASLE_SET_PWM_FREQ      (1 << 3)
-+#define ASLE_REQ_MSK           0xf
-+
-+/* response bits of ASLE irq request */
-+#define ASLE_ALS_ILLUM_FAIL    (2<<10)
-+#define ASLE_BACKLIGHT_FAIL    (2<<12)
-+#define ASLE_PFIT_FAIL         (2<<14)
-+#define ASLE_PWM_FREQ_FAIL     (2<<16)
-+
-+/* ASLE backlight brightness to set */
-+#define ASLE_BCLP_VALID                (1<<31)
-+#define ASLE_BCLP_MSK          (~(1<<31))
-+
-+/* ASLE panel fitting request */
-+#define ASLE_PFIT_VALID         (1<<31)
-+#define ASLE_PFIT_CENTER (1<<0)
-+#define ASLE_PFIT_STRETCH_TEXT (1<<1)
-+#define ASLE_PFIT_STRETCH_GFX (1<<2)
-+
-+/* PWM frequency and minimum brightness */
-+#define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
-+#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
-+#define ASLE_PFMB_PWM_MASK (0x7ffffe00)
-+#define ASLE_PFMB_PWM_VALID (1<<31)
-+
-+#define ASLE_CBLV_VALID         (1<<31)
-+
-+static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      struct opregion_asle *asle = dev_priv->opregion.asle;
-+      u32 blc_pwm_ctl, blc_pwm_ctl2;
-+
-+      if (!(bclp & ASLE_BCLP_VALID))
-+              return ASLE_BACKLIGHT_FAIL;
-+
-+      bclp &= ASLE_BCLP_MSK;
-+      if (bclp < 0 || bclp > 255)
-+              return ASLE_BACKLIGHT_FAIL;
-+
-+      blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
-+      blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
-+      blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2);
-+
-+      if (blc_pwm_ctl2 & BLM_COMBINATION_MODE)
-+              pci_write_config_dword(dev->pdev, PCI_LBPC, bclp);
-+      else
-+              I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | ((bclp * 0x101)-1));
-+
-+      asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
-+
-+      return 0;
-+}
-+
-+static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
-+{
-+      /* alsi is the current ALS reading in lux. 0 indicates below sensor
-+         range, 0xffff indicates above sensor range. 1-0xfffe are valid */
-+      return 0;
-+}
-+
-+static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      if (pfmb & ASLE_PFMB_PWM_VALID) {
-+              u32 blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
-+              u32 pwm = pfmb & ASLE_PFMB_PWM_MASK;
-+              blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK;
-+              pwm = pwm >> 9;
-+              /* FIXME - what do we do with the PWM? */
-+      }
-+      return 0;
-+}
-+
-+static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
-+{
-+      /* Panel fitting is currently controlled by the X code, so this is a
-+         noop until modesetting support works fully */
-+      if (!(pfit & ASLE_PFIT_VALID))
-+              return ASLE_PFIT_FAIL;
-+      return 0;
-+}
-+
-+void opregion_asle_intr(struct drm_device *dev)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      struct opregion_asle *asle = dev_priv->opregion.asle;
-+      u32 asle_stat = 0;
-+      u32 asle_req;
-+
-+      if (!asle)
-+              return;
-+
-+      asle_req = asle->aslc & ASLE_REQ_MSK;
-+
-+      if (!asle_req) {
-+              DRM_DEBUG("non asle set request??\n");
-+              return;
-+      }
-+
-+      if (asle_req & ASLE_SET_ALS_ILLUM)
-+              asle_stat |= asle_set_als_illum(dev, asle->alsi);
-+
-+      if (asle_req & ASLE_SET_BACKLIGHT)
-+              asle_stat |= asle_set_backlight(dev, asle->bclp);
-+
-+      if (asle_req & ASLE_SET_PFIT)
-+              asle_stat |= asle_set_pfit(dev, asle->pfit);
-+
-+      if (asle_req & ASLE_SET_PWM_FREQ)
-+              asle_stat |= asle_set_pwm_freq(dev, asle->pfmb);
-+
-+      asle->aslc = asle_stat;
-+}
-+
-+#define ASLE_ALS_EN    (1<<0)
-+#define ASLE_BLC_EN    (1<<1)
-+#define ASLE_PFIT_EN   (1<<2)
-+#define ASLE_PFMB_EN   (1<<3)
-+
-+void opregion_enable_asle(struct drm_device *dev)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      struct opregion_asle *asle = dev_priv->opregion.asle;
-+
-+      if (asle) {
-+              u32 pipeb_stats = I915_READ(PIPEBSTAT);
-+              if (IS_MOBILE(dev)) {
-+                      /* Many devices trigger events with a write to the
-+                         legacy backlight controller, so we need to ensure
-+                         that it's able to generate interrupts */
-+                      I915_WRITE(PIPEBSTAT, pipeb_stats |=
-+                                 I915_LEGACY_BLC_EVENT_ENABLE);
-+                      i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT |
-+                                      I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
-+              } else
-+                      i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT);
-+
-+              asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
-+                      ASLE_PFMB_EN;
-+              asle->ardy = 1;
-+      }
-+}
-+
-+#define ACPI_EV_DISPLAY_SWITCH (1<<0)
-+#define ACPI_EV_LID            (1<<1)
-+#define ACPI_EV_DOCK           (1<<2)
-+
-+static struct intel_opregion *system_opregion;
-+
-+int intel_opregion_video_event(struct notifier_block *nb, unsigned long val,
-+                             void *data)
-+{
-+      /* The only video events relevant to opregion are 0x80. These indicate
-+         either a docking event, lid switch or display switch request. In
-+         Linux, these are handled by the dock, button and video drivers.
-+         We might want to fix the video driver to be opregion-aware in
-+         future, but right now we just indicate to the firmware that the
-+         request has been handled */
-+
-+      struct opregion_acpi *acpi;
-+
-+      if (!system_opregion)
-+              return NOTIFY_DONE;
-+
-+      acpi = system_opregion->acpi;
-+      acpi->csts = 0;
-+
-+      return NOTIFY_OK;
-+}
-+
-+static struct notifier_block intel_opregion_notifier = {
-+      .notifier_call = intel_opregion_video_event,
-+};
-+
-+int intel_opregion_init(struct drm_device *dev)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      struct intel_opregion *opregion = &dev_priv->opregion;
-+      void *base;
-+      u32 asls, mboxes;
-+      int err = 0;
-+
-+      pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
-+      DRM_DEBUG("graphic opregion physical addr: 0x%x\n", asls);
-+      if (asls == 0) {
-+              DRM_DEBUG("ACPI OpRegion not supported!\n");
-+              return -ENOTSUPP;
-+      }
-+
-+      base = ioremap(asls, OPREGION_SZ);
-+      if (!base)
-+              return -ENOMEM;
-+
-+      opregion->header = base;
-+      if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) {
-+              DRM_DEBUG("opregion signature mismatch\n");
-+              err = -EINVAL;
-+              goto err_out;
-+      }
-+
-+      mboxes = opregion->header->mboxes;
-+      if (mboxes & MBOX_ACPI) {
-+              DRM_DEBUG("Public ACPI methods supported\n");
-+              opregion->acpi = base + OPREGION_ACPI_OFFSET;
-+      } else {
-+              DRM_DEBUG("Public ACPI methods not supported\n");
-+              err = -ENOTSUPP;
-+              goto err_out;
-+      }
-+      opregion->enabled = 1;
-+
-+      if (mboxes & MBOX_SWSCI) {
-+              DRM_DEBUG("SWSCI supported\n");
-+              opregion->swsci = base + OPREGION_SWSCI_OFFSET;
-+      }
-+      if (mboxes & MBOX_ASLE) {
-+              DRM_DEBUG("ASLE supported\n");
-+              opregion->asle = base + OPREGION_ASLE_OFFSET;
-+      }
-+
-+      /* Notify BIOS we are ready to handle ACPI video ext notifs.
-+       * Right now, all the events are handled by the ACPI video module.
-+       * We don't actually need to do anything with them. */
-+      opregion->acpi->csts = 0;
-+      opregion->acpi->drdy = 1;
-+
-+      system_opregion = opregion;
-+      register_acpi_notifier(&intel_opregion_notifier);
-+
-+      return 0;
-+
-+err_out:
-+      iounmap(opregion->header);
-+      opregion->header = NULL;
-+      return err;
-+}
-+
-+void intel_opregion_free(struct drm_device *dev)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      struct intel_opregion *opregion = &dev_priv->opregion;
-+
-+      if (!opregion->enabled)
-+              return;
-+
-+      opregion->acpi->drdy = 0;
-+
-+      system_opregion = NULL;
-+      unregister_acpi_notifier(&intel_opregion_notifier);
-+
-+      /* just clear all opregion memory pointers now */
-+      iounmap(opregion->header);
-+      opregion->header = NULL;
-+      opregion->acpi = NULL;
-+      opregion->swsci = NULL;
-+      opregion->asle = NULL;
-+
-+      opregion->enabled = 0;
-+}
-diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
-index 477c64e..43ad2cb 100644
---- a/drivers/gpu/drm/i915/i915_reg.h
-+++ b/drivers/gpu/drm/i915/i915_reg.h
-@@ -740,6 +740,7 @@
- #define BLC_PWM_CTL           0x61254
- #define   BACKLIGHT_MODULATION_FREQ_SHIFT             (17)
- #define BLC_PWM_CTL2          0x61250 /* 965+ only */
-+#define   BLM_COMBINATION_MODE (1 << 30)
- /*
-  * This is the most significant 15 bits of the number of backlight cycles in a
-  * complete cycle of the modulated backlight control.
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0009-drm-fix-sysfs-error-path.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0009-drm-fix-sysfs-error-path.patch
deleted file mode 100644 (file)
index 8dea824..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-commit 2e9c9eedfe0be777c051a2198dddf459adcc407b
-Author: Dave Airlie <airlied@redhat.com>
-Date:   Tue Sep 2 10:06:06 2008 +1000
-
-    drm: fix sysfs error path.
-    
-    Pointed out by Roel Kluin on dri-devel.
-    
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
-index af211a0..1611b9b 100644
---- a/drivers/gpu/drm/drm_sysfs.c
-+++ b/drivers/gpu/drm/drm_sysfs.c
-@@ -184,7 +184,7 @@ int drm_sysfs_device_add(struct drm_minor *minor)
- err_out_files:
-       if (i > 0)
-               for (j = 0; j < i; j++)
--                      device_remove_file(&minor->kdev, &device_attrs[i]);
-+                      device_remove_file(&minor->kdev, &device_attrs[j]);
-       device_unregister(&minor->kdev);
- err_out:
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0010-i915-separate-suspend-resume-functions.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0010-i915-separate-suspend-resume-functions.patch
deleted file mode 100644 (file)
index 897d50c..0000000
+++ /dev/null
@@ -1,1079 +0,0 @@
-commit a850828c640735fb410c782717c9eb7f8474e356
-Author: Jesse Barnes <jbarnes@virtuousgeek.org>
-Date:   Mon Aug 25 15:11:06 2008 -0700
-
-    separate i915 suspend/resume functions into their own file
-    
-    [Patch against drm-next.  Consider this a trial balloon for our new Linux
-    development model.]
-    
-    This is a big chunk of code.  Separating it out makes it easier to change
-    without churn on the main i915_drv.c file (and there will be churn as we
-    fix bugs and add things like kernel mode setting).  Also makes it easier
-    to share this file with BSD.
-    
-    Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
-index b032808..c4bbda6 100644
---- a/drivers/gpu/drm/i915/Makefile
-+++ b/drivers/gpu/drm/i915/Makefile
-@@ -3,7 +3,8 @@
- # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
- ccflags-y := -Iinclude/drm
--i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o
-+i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o \
-+          i915_suspend.o
- i915-$(CONFIG_COMPAT)   += i915_ioc32.o
-diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
-index d95eca2..eff66ed 100644
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -38,211 +38,9 @@ static struct pci_device_id pciidlist[] = {
-       i915_PCI_IDS
- };
--enum pipe {
--    PIPE_A = 0,
--    PIPE_B,
--};
--
--static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
--{
--      struct drm_i915_private *dev_priv = dev->dev_private;
--
--      if (pipe == PIPE_A)
--              return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
--      else
--              return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
--}
--
--static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
--{
--      struct drm_i915_private *dev_priv = dev->dev_private;
--      unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
--      u32 *array;
--      int i;
--
--      if (!i915_pipe_enabled(dev, pipe))
--              return;
--
--      if (pipe == PIPE_A)
--              array = dev_priv->save_palette_a;
--      else
--              array = dev_priv->save_palette_b;
--
--      for(i = 0; i < 256; i++)
--              array[i] = I915_READ(reg + (i << 2));
--}
--
--static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
--{
--      struct drm_i915_private *dev_priv = dev->dev_private;
--      unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
--      u32 *array;
--      int i;
--
--      if (!i915_pipe_enabled(dev, pipe))
--              return;
--
--      if (pipe == PIPE_A)
--              array = dev_priv->save_palette_a;
--      else
--              array = dev_priv->save_palette_b;
--
--      for(i = 0; i < 256; i++)
--              I915_WRITE(reg + (i << 2), array[i]);
--}
--
--static u8 i915_read_indexed(u16 index_port, u16 data_port, u8 reg)
--{
--      outb(reg, index_port);
--      return inb(data_port);
--}
--
--static u8 i915_read_ar(u16 st01, u8 reg, u16 palette_enable)
--{
--      inb(st01);
--      outb(palette_enable | reg, VGA_AR_INDEX);
--      return inb(VGA_AR_DATA_READ);
--}
--
--static void i915_write_ar(u8 st01, u8 reg, u8 val, u16 palette_enable)
--{
--      inb(st01);
--      outb(palette_enable | reg, VGA_AR_INDEX);
--      outb(val, VGA_AR_DATA_WRITE);
--}
--
--static void i915_write_indexed(u16 index_port, u16 data_port, u8 reg, u8 val)
--{
--      outb(reg, index_port);
--      outb(val, data_port);
--}
--
--static void i915_save_vga(struct drm_device *dev)
--{
--      struct drm_i915_private *dev_priv = dev->dev_private;
--      int i;
--      u16 cr_index, cr_data, st01;
--
--      /* VGA color palette registers */
--      dev_priv->saveDACMASK = inb(VGA_DACMASK);
--      /* DACCRX automatically increments during read */
--      outb(0, VGA_DACRX);
--      /* Read 3 bytes of color data from each index */
--      for (i = 0; i < 256 * 3; i++)
--              dev_priv->saveDACDATA[i] = inb(VGA_DACDATA);
--
--      /* MSR bits */
--      dev_priv->saveMSR = inb(VGA_MSR_READ);
--      if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
--              cr_index = VGA_CR_INDEX_CGA;
--              cr_data = VGA_CR_DATA_CGA;
--              st01 = VGA_ST01_CGA;
--      } else {
--              cr_index = VGA_CR_INDEX_MDA;
--              cr_data = VGA_CR_DATA_MDA;
--              st01 = VGA_ST01_MDA;
--      }
--
--      /* CRT controller regs */
--      i915_write_indexed(cr_index, cr_data, 0x11,
--                         i915_read_indexed(cr_index, cr_data, 0x11) &
--                         (~0x80));
--      for (i = 0; i <= 0x24; i++)
--              dev_priv->saveCR[i] =
--                      i915_read_indexed(cr_index, cr_data, i);
--      /* Make sure we don't turn off CR group 0 writes */
--      dev_priv->saveCR[0x11] &= ~0x80;
--
--      /* Attribute controller registers */
--      inb(st01);
--      dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX);
--      for (i = 0; i <= 0x14; i++)
--              dev_priv->saveAR[i] = i915_read_ar(st01, i, 0);
--      inb(st01);
--      outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX);
--      inb(st01);
--
--      /* Graphics controller registers */
--      for (i = 0; i < 9; i++)
--              dev_priv->saveGR[i] =
--                      i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, i);
--
--      dev_priv->saveGR[0x10] =
--              i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10);
--      dev_priv->saveGR[0x11] =
--              i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11);
--      dev_priv->saveGR[0x18] =
--              i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18);
--
--      /* Sequencer registers */
--      for (i = 0; i < 8; i++)
--              dev_priv->saveSR[i] =
--                      i915_read_indexed(VGA_SR_INDEX, VGA_SR_DATA, i);
--}
--
--static void i915_restore_vga(struct drm_device *dev)
--{
--      struct drm_i915_private *dev_priv = dev->dev_private;
--      int i;
--      u16 cr_index, cr_data, st01;
--
--      /* MSR bits */
--      outb(dev_priv->saveMSR, VGA_MSR_WRITE);
--      if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
--              cr_index = VGA_CR_INDEX_CGA;
--              cr_data = VGA_CR_DATA_CGA;
--              st01 = VGA_ST01_CGA;
--      } else {
--              cr_index = VGA_CR_INDEX_MDA;
--              cr_data = VGA_CR_DATA_MDA;
--              st01 = VGA_ST01_MDA;
--      }
--
--      /* Sequencer registers, don't write SR07 */
--      for (i = 0; i < 7; i++)
--              i915_write_indexed(VGA_SR_INDEX, VGA_SR_DATA, i,
--                                 dev_priv->saveSR[i]);
--
--      /* CRT controller regs */
--      /* Enable CR group 0 writes */
--      i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
--      for (i = 0; i <= 0x24; i++)
--              i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]);
--
--      /* Graphics controller regs */
--      for (i = 0; i < 9; i++)
--              i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, i,
--                                 dev_priv->saveGR[i]);
--
--      i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10,
--                         dev_priv->saveGR[0x10]);
--      i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11,
--                         dev_priv->saveGR[0x11]);
--      i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18,
--                         dev_priv->saveGR[0x18]);
--
--      /* Attribute controller registers */
--      inb(st01);
--      for (i = 0; i <= 0x14; i++)
--              i915_write_ar(st01, i, dev_priv->saveAR[i], 0);
--      inb(st01); /* switch back to index mode */
--      outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX);
--      inb(st01);
--
--      /* VGA color palette registers */
--      outb(dev_priv->saveDACMASK, VGA_DACMASK);
--      /* DACCRX automatically increments during read */
--      outb(0, VGA_DACWX);
--      /* Read 3 bytes of color data from each index */
--      for (i = 0; i < 256 * 3; i++)
--              outb(dev_priv->saveDACDATA[i], VGA_DACDATA);
--
--}
--
- static int i915_suspend(struct drm_device *dev, pm_message_t state)
- {
-       struct drm_i915_private *dev_priv = dev->dev_private;
--      int i;
-       if (!dev || !dev_priv) {
-               printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv);
-@@ -254,122 +52,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
-               return 0;
-       pci_save_state(dev->pdev);
--      pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
--
--      /* Display arbitration control */
--      dev_priv->saveDSPARB = I915_READ(DSPARB);
--
--      /* Pipe & plane A info */
--      dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
--      dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
--      dev_priv->saveFPA0 = I915_READ(FPA0);
--      dev_priv->saveFPA1 = I915_READ(FPA1);
--      dev_priv->saveDPLL_A = I915_READ(DPLL_A);
--      if (IS_I965G(dev))
--              dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
--      dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
--      dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
--      dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
--      dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
--      dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
--      dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
--      dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
--
--      dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
--      dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
--      dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
--      dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
--      dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
--      if (IS_I965G(dev)) {
--              dev_priv->saveDSPASURF = I915_READ(DSPASURF);
--              dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
--      }
--      i915_save_palette(dev, PIPE_A);
--      dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
--
--      /* Pipe & plane B info */
--      dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
--      dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
--      dev_priv->saveFPB0 = I915_READ(FPB0);
--      dev_priv->saveFPB1 = I915_READ(FPB1);
--      dev_priv->saveDPLL_B = I915_READ(DPLL_B);
--      if (IS_I965G(dev))
--              dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
--      dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
--      dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
--      dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
--      dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
--      dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
--      dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
--      dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
--
--      dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
--      dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
--      dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
--      dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
--      dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
--      if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
--              dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
--              dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
--      }
--      i915_save_palette(dev, PIPE_B);
--      dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
--
--      /* CRT state */
--      dev_priv->saveADPA = I915_READ(ADPA);
--      /* LVDS state */
--      dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
--      dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
--      dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
--      if (IS_I965G(dev))
--              dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
--      if (IS_MOBILE(dev) && !IS_I830(dev))
--              dev_priv->saveLVDS = I915_READ(LVDS);
--      if (!IS_I830(dev) && !IS_845G(dev))
--              dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
--      dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
--      dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
--      dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
--
--      /* FIXME: save TV & SDVO state */
--
--      /* FBC state */
--      dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
--      dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
--      dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
--      dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
--
--      /* Interrupt state */
--      dev_priv->saveIIR = I915_READ(IIR);
--      dev_priv->saveIER = I915_READ(IER);
--      dev_priv->saveIMR = I915_READ(IMR);
--
--      /* VGA state */
--      dev_priv->saveVGA0 = I915_READ(VGA0);
--      dev_priv->saveVGA1 = I915_READ(VGA1);
--      dev_priv->saveVGA_PD = I915_READ(VGA_PD);
--      dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
--
--      /* Clock gating state */
--      dev_priv->saveD_STATE = I915_READ(D_STATE);
--      dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
--
--      /* Cache mode state */
--      dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
--
--      /* Memory Arbitration state */
--      dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
--
--      /* Scratch space */
--      for (i = 0; i < 16; i++) {
--              dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
--              dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
--      }
--      for (i = 0; i < 3; i++)
--              dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
--
--      i915_save_vga(dev);
-+      i915_save_state(dev);
-       intel_opregion_free(dev);
-@@ -384,155 +68,13 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
- static int i915_resume(struct drm_device *dev)
- {
--      struct drm_i915_private *dev_priv = dev->dev_private;
--      int i;
--
-       pci_set_power_state(dev->pdev, PCI_D0);
-       pci_restore_state(dev->pdev);
-       if (pci_enable_device(dev->pdev))
-               return -1;
-       pci_set_master(dev->pdev);
--      pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
--
--      I915_WRITE(DSPARB, dev_priv->saveDSPARB);
--
--      /* Pipe & plane A info */
--      /* Prime the clock */
--      if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
--              I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
--                         ~DPLL_VCO_ENABLE);
--              udelay(150);
--      }
--      I915_WRITE(FPA0, dev_priv->saveFPA0);
--      I915_WRITE(FPA1, dev_priv->saveFPA1);
--      /* Actually enable it */
--      I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
--      udelay(150);
--      if (IS_I965G(dev))
--              I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
--      udelay(150);
--
--      /* Restore mode */
--      I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
--      I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
--      I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
--      I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
--      I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
--      I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
--      I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
--
--      /* Restore plane info */
--      I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
--      I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
--      I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
--      I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
--      I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
--      if (IS_I965G(dev)) {
--              I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
--              I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
--      }
--
--      I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
--
--      i915_restore_palette(dev, PIPE_A);
--      /* Enable the plane */
--      I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
--      I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
--
--      /* Pipe & plane B info */
--      if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
--              I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
--                         ~DPLL_VCO_ENABLE);
--              udelay(150);
--      }
--      I915_WRITE(FPB0, dev_priv->saveFPB0);
--      I915_WRITE(FPB1, dev_priv->saveFPB1);
--      /* Actually enable it */
--      I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
--      udelay(150);
--      if (IS_I965G(dev))
--              I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
--      udelay(150);
--
--      /* Restore mode */
--      I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
--      I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
--      I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
--      I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
--      I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
--      I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
--      I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
--
--      /* Restore plane info */
--      I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
--      I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
--      I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
--      I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
--      I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
--      if (IS_I965G(dev)) {
--              I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
--              I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
--      }
--
--      I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
--
--      i915_restore_palette(dev, PIPE_B);
--      /* Enable the plane */
--      I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
--      I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
--
--      /* CRT state */
--      I915_WRITE(ADPA, dev_priv->saveADPA);
--
--      /* LVDS state */
--      if (IS_I965G(dev))
--              I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
--      if (IS_MOBILE(dev) && !IS_I830(dev))
--              I915_WRITE(LVDS, dev_priv->saveLVDS);
--      if (!IS_I830(dev) && !IS_845G(dev))
--              I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
--
--      I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
--      I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
--      I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
--      I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
--      I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
--      I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
--
--      /* FIXME: restore TV & SDVO state */
--
--      /* FBC info */
--      I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
--      I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
--      I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
--      I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
--
--      /* VGA state */
--      I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
--      I915_WRITE(VGA0, dev_priv->saveVGA0);
--      I915_WRITE(VGA1, dev_priv->saveVGA1);
--      I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
--      udelay(150);
--
--      /* Clock gating state */
--      I915_WRITE (D_STATE, dev_priv->saveD_STATE);
--      I915_WRITE(CG_2D_DIS, dev_priv->saveCG_2D_DIS);
--
--      /* Cache mode state */
--      I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
--
--      /* Memory arbitration state */
--      I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
--
--      for (i = 0; i < 16; i++) {
--              I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
--              I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
--      }
--      for (i = 0; i < 3; i++)
--              I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
--
--      i915_restore_vga(dev);
-+      i915_restore_state(dev);
-       intel_opregion_init(dev);
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index e4bd01c..a82b487 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -41,6 +41,11 @@
- #define DRIVER_DESC           "Intel Graphics"
- #define DRIVER_DATE           "20060119"
-+enum pipe {
-+      PIPE_A = 0,
-+      PIPE_B,
-+};
-+
- /* Interface history:
-  *
-  * 1.1: Original.
-@@ -269,6 +274,10 @@ extern void i915_mem_takedown(struct mem_block **heap);
- extern void i915_mem_release(struct drm_device * dev,
-                            struct drm_file *file_priv, struct mem_block *heap);
-+/* i915_suspend.c */
-+extern int i915_save_state(struct drm_device *dev);
-+extern int i915_restore_state(struct drm_device *dev);
-+
- /* i915_opregion.c */
- extern int intel_opregion_init(struct drm_device *dev);
- extern void intel_opregion_free(struct drm_device *dev);
-@@ -279,6 +288,8 @@ extern void opregion_enable_asle(struct drm_device *dev);
- #define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
- #define I915_READ16(reg)      DRM_READ16(dev_priv->mmio_map, (reg))
- #define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
-+#define I915_READ8(reg)               DRM_READ8(dev_priv->mmio_map, (reg))
-+#define I915_WRITE8(reg,val)  DRM_WRITE8(dev_priv->mmio_map, (reg), (val))
- #define I915_VERBOSE 0
-diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
-new file mode 100644
-index 0000000..e0c1fe4
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_suspend.c
-@@ -0,0 +1,509 @@
-+/*
-+ *
-+ * Copyright 2008 (c) Intel Corporation
-+ *   Jesse Barnes <jbarnes@virtuousgeek.org>
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the
-+ * "Software"), to deal in the Software without restriction, including
-+ * without limitation the rights to use, copy, modify, merge, publish,
-+ * distribute, sub license, and/or sell copies of the Software, and to
-+ * permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the
-+ * next paragraph) shall be included in all copies or substantial portions
-+ * of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
-+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-+ */
-+
-+#include "drmP.h"
-+#include "drm.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+
-+static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+
-+      if (pipe == PIPE_A)
-+              return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
-+      else
-+              return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
-+}
-+
-+static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
-+      u32 *array;
-+      int i;
-+
-+      if (!i915_pipe_enabled(dev, pipe))
-+              return;
-+
-+      if (pipe == PIPE_A)
-+              array = dev_priv->save_palette_a;
-+      else
-+              array = dev_priv->save_palette_b;
-+
-+      for(i = 0; i < 256; i++)
-+              array[i] = I915_READ(reg + (i << 2));
-+}
-+
-+static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
-+      u32 *array;
-+      int i;
-+
-+      if (!i915_pipe_enabled(dev, pipe))
-+              return;
-+
-+      if (pipe == PIPE_A)
-+              array = dev_priv->save_palette_a;
-+      else
-+              array = dev_priv->save_palette_b;
-+
-+      for(i = 0; i < 256; i++)
-+              I915_WRITE(reg + (i << 2), array[i]);
-+}
-+
-+static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+
-+      I915_WRITE8(index_port, reg);
-+      return I915_READ8(data_port);
-+}
-+
-+static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+
-+      I915_READ8(st01);
-+      I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
-+      return I915_READ8(VGA_AR_DATA_READ);
-+}
-+
-+static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+
-+      I915_READ8(st01);
-+      I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
-+      I915_WRITE8(VGA_AR_DATA_WRITE, val);
-+}
-+
-+static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+
-+      I915_WRITE8(index_port, reg);
-+      I915_WRITE8(data_port, val);
-+}
-+
-+static void i915_save_vga(struct drm_device *dev)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      int i;
-+      u16 cr_index, cr_data, st01;
-+
-+      /* VGA color palette registers */
-+      dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
-+      /* DACCRX automatically increments during read */
-+      I915_WRITE8(VGA_DACRX, 0);
-+      /* Read 3 bytes of color data from each index */
-+      for (i = 0; i < 256 * 3; i++)
-+              dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);
-+
-+      /* MSR bits */
-+      dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
-+      if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
-+              cr_index = VGA_CR_INDEX_CGA;
-+              cr_data = VGA_CR_DATA_CGA;
-+              st01 = VGA_ST01_CGA;
-+      } else {
-+              cr_index = VGA_CR_INDEX_MDA;
-+              cr_data = VGA_CR_DATA_MDA;
-+              st01 = VGA_ST01_MDA;
-+      }
-+
-+      /* CRT controller regs */
-+      i915_write_indexed(dev, cr_index, cr_data, 0x11,
-+                         i915_read_indexed(dev, cr_index, cr_data, 0x11) &
-+                         (~0x80));
-+      for (i = 0; i <= 0x24; i++)
-+              dev_priv->saveCR[i] =
-+                      i915_read_indexed(dev, cr_index, cr_data, i);
-+      /* Make sure we don't turn off CR group 0 writes */
-+      dev_priv->saveCR[0x11] &= ~0x80;
-+
-+      /* Attribute controller registers */
-+      I915_READ8(st01);
-+      dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
-+      for (i = 0; i <= 0x14; i++)
-+              dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0);
-+      I915_READ8(st01);
-+      I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX);
-+      I915_READ8(st01);
-+
-+      /* Graphics controller registers */
-+      for (i = 0; i < 9; i++)
-+              dev_priv->saveGR[i] =
-+                      i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
-+
-+      dev_priv->saveGR[0x10] =
-+              i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
-+      dev_priv->saveGR[0x11] =
-+              i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
-+      dev_priv->saveGR[0x18] =
-+              i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
-+
-+      /* Sequencer registers */
-+      for (i = 0; i < 8; i++)
-+              dev_priv->saveSR[i] =
-+                      i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
-+}
-+
-+static void i915_restore_vga(struct drm_device *dev)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      int i;
-+      u16 cr_index, cr_data, st01;
-+
-+      /* MSR bits */
-+      I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR);
-+      if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
-+              cr_index = VGA_CR_INDEX_CGA;
-+              cr_data = VGA_CR_DATA_CGA;
-+              st01 = VGA_ST01_CGA;
-+      } else {
-+              cr_index = VGA_CR_INDEX_MDA;
-+              cr_data = VGA_CR_DATA_MDA;
-+              st01 = VGA_ST01_MDA;
-+      }
-+
-+      /* Sequencer registers, don't write SR07 */
-+      for (i = 0; i < 7; i++)
-+              i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
-+                                 dev_priv->saveSR[i]);
-+
-+      /* CRT controller regs */
-+      /* Enable CR group 0 writes */
-+      i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
-+      for (i = 0; i <= 0x24; i++)
-+              i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]);
-+
-+      /* Graphics controller regs */
-+      for (i = 0; i < 9; i++)
-+              i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
-+                                 dev_priv->saveGR[i]);
-+
-+      i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
-+                         dev_priv->saveGR[0x10]);
-+      i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
-+                         dev_priv->saveGR[0x11]);
-+      i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
-+                         dev_priv->saveGR[0x18]);
-+
-+      /* Attribute controller registers */
-+      I915_READ8(st01); /* switch back to index mode */
-+      for (i = 0; i <= 0x14; i++)
-+              i915_write_ar(dev, st01, i, dev_priv->saveAR[i], 0);
-+      I915_READ8(st01); /* switch back to index mode */
-+      I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX | 0x20);
-+      I915_READ8(st01);
-+
-+      /* VGA color palette registers */
-+      I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
-+      /* DACCRX automatically increments during read */
-+      I915_WRITE8(VGA_DACWX, 0);
-+      /* Read 3 bytes of color data from each index */
-+      for (i = 0; i < 256 * 3; i++)
-+              I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);
-+
-+}
-+
-+int i915_save_state(struct drm_device *dev)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      int i;
-+
-+      pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
-+
-+      /* Display arbitration control */
-+      dev_priv->saveDSPARB = I915_READ(DSPARB);
-+
-+      /* Pipe & plane A info */
-+      dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
-+      dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
-+      dev_priv->saveFPA0 = I915_READ(FPA0);
-+      dev_priv->saveFPA1 = I915_READ(FPA1);
-+      dev_priv->saveDPLL_A = I915_READ(DPLL_A);
-+      if (IS_I965G(dev))
-+              dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
-+      dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
-+      dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
-+      dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
-+      dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
-+      dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
-+      dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
-+      dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
-+
-+      dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
-+      dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
-+      dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
-+      dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
-+      dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
-+      if (IS_I965G(dev)) {
-+              dev_priv->saveDSPASURF = I915_READ(DSPASURF);
-+              dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
-+      }
-+      i915_save_palette(dev, PIPE_A);
-+      dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
-+
-+      /* Pipe & plane B info */
-+      dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
-+      dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
-+      dev_priv->saveFPB0 = I915_READ(FPB0);
-+      dev_priv->saveFPB1 = I915_READ(FPB1);
-+      dev_priv->saveDPLL_B = I915_READ(DPLL_B);
-+      if (IS_I965G(dev))
-+              dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
-+      dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
-+      dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
-+      dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
-+      dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
-+      dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
-+      dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
-+      dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
-+
-+      dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
-+      dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
-+      dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
-+      dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
-+      dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
-+      if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
-+              dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
-+              dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
-+      }
-+      i915_save_palette(dev, PIPE_B);
-+      dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
-+
-+      /* CRT state */
-+      dev_priv->saveADPA = I915_READ(ADPA);
-+
-+      /* LVDS state */
-+      dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
-+      dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
-+      dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
-+      if (IS_I965G(dev))
-+              dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
-+      if (IS_MOBILE(dev) && !IS_I830(dev))
-+              dev_priv->saveLVDS = I915_READ(LVDS);
-+      if (!IS_I830(dev) && !IS_845G(dev))
-+              dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
-+      dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
-+      dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
-+      dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
-+
-+      /* FIXME: save TV & SDVO state */
-+
-+      /* FBC state */
-+      dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
-+      dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
-+      dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
-+      dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
-+
-+      /* Interrupt state */
-+      dev_priv->saveIIR = I915_READ(IIR);
-+      dev_priv->saveIER = I915_READ(IER);
-+      dev_priv->saveIMR = I915_READ(IMR);
-+
-+      /* VGA state */
-+      dev_priv->saveVGA0 = I915_READ(VGA0);
-+      dev_priv->saveVGA1 = I915_READ(VGA1);
-+      dev_priv->saveVGA_PD = I915_READ(VGA_PD);
-+      dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
-+
-+      /* Clock gating state */
-+      dev_priv->saveD_STATE = I915_READ(D_STATE);
-+      dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
-+
-+      /* Cache mode state */
-+      dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
-+
-+      /* Memory Arbitration state */
-+      dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
-+
-+      /* Scratch space */
-+      for (i = 0; i < 16; i++) {
-+              dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
-+              dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
-+      }
-+      for (i = 0; i < 3; i++)
-+              dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
-+
-+      i915_save_vga(dev);
-+
-+      return 0;
-+}
-+
-+int i915_restore_state(struct drm_device *dev)
-+{
-+      struct drm_i915_private *dev_priv = dev->dev_private;
-+      int i;
-+
-+      pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
-+
-+      I915_WRITE(DSPARB, dev_priv->saveDSPARB);
-+
-+      /* Pipe & plane A info */
-+      /* Prime the clock */
-+      if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
-+              I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
-+                         ~DPLL_VCO_ENABLE);
-+              DRM_UDELAY(150);
-+      }
-+      I915_WRITE(FPA0, dev_priv->saveFPA0);
-+      I915_WRITE(FPA1, dev_priv->saveFPA1);
-+      /* Actually enable it */
-+      I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
-+      DRM_UDELAY(150);
-+      if (IS_I965G(dev))
-+              I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
-+      DRM_UDELAY(150);
-+
-+      /* Restore mode */
-+      I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
-+      I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
-+      I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
-+      I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
-+      I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
-+      I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
-+      I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
-+
-+      /* Restore plane info */
-+      I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
-+      I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
-+      I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
-+      I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
-+      I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
-+      if (IS_I965G(dev)) {
-+              I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
-+              I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
-+      }
-+
-+      I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
-+
-+      i915_restore_palette(dev, PIPE_A);
-+      /* Enable the plane */
-+      I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
-+      I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
-+
-+      /* Pipe & plane B info */
-+      if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
-+              I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
-+                         ~DPLL_VCO_ENABLE);
-+              DRM_UDELAY(150);
-+      }
-+      I915_WRITE(FPB0, dev_priv->saveFPB0);
-+      I915_WRITE(FPB1, dev_priv->saveFPB1);
-+      /* Actually enable it */
-+      I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
-+      DRM_UDELAY(150);
-+      if (IS_I965G(dev))
-+              I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
-+      DRM_UDELAY(150);
-+
-+      /* Restore mode */
-+      I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
-+      I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
-+      I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
-+      I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
-+      I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
-+      I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
-+      I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
-+
-+      /* Restore plane info */
-+      I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
-+      I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
-+      I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
-+      I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
-+      I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
-+      if (IS_I965G(dev)) {
-+              I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
-+              I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
-+      }
-+
-+      I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
-+
-+      i915_restore_palette(dev, PIPE_B);
-+      /* Enable the plane */
-+      I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
-+      I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
-+
-+      /* CRT state */
-+      I915_WRITE(ADPA, dev_priv->saveADPA);
-+
-+      /* LVDS state */
-+      if (IS_I965G(dev))
-+              I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
-+      if (IS_MOBILE(dev) && !IS_I830(dev))
-+              I915_WRITE(LVDS, dev_priv->saveLVDS);
-+      if (!IS_I830(dev) && !IS_845G(dev))
-+              I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
-+
-+      I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
-+      I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
-+      I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
-+      I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
-+      I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
-+      I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
-+
-+      /* FIXME: restore TV & SDVO state */
-+
-+      /* FBC info */
-+      I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
-+      I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
-+      I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
-+      I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
-+
-+      /* VGA state */
-+      I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
-+      I915_WRITE(VGA0, dev_priv->saveVGA0);
-+      I915_WRITE(VGA1, dev_priv->saveVGA1);
-+      I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
-+      DRM_UDELAY(150);
-+
-+      /* Clock gating state */
-+      I915_WRITE (D_STATE, dev_priv->saveD_STATE);
-+      I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS);
-+
-+      /* Cache mode state */
-+      I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
-+
-+      /* Memory arbitration state */
-+      I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
-+
-+      for (i = 0; i < 16; i++) {
-+              I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
-+              I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
-+      }
-+      for (i = 0; i < 3; i++)
-+              I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
-+
-+      i915_restore_vga(dev);
-+
-+      return 0;
-+}
-+
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0011-drm-vblank-rework.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0011-drm-vblank-rework.patch
deleted file mode 100644 (file)
index 6161a71..0000000
+++ /dev/null
@@ -1,1534 +0,0 @@
-commit 2aebb4e4e62d09b4a95be7be7c24a7f6528385b7
-Author: Jesse Barnes <jbarnes@virtuousgeek.org>
-Date:   Tue Sep 30 12:14:26 2008 -0700
-
-    drm: Rework vblank-wait handling to allow interrupt reduction.
-    
-    Previously, drivers supporting vblank interrupt waits would run the interrupt
-    all the time, or all the time that any 3d client was running, preventing the
-    CPU from sleeping for long when the system was otherwise idle.  Now, interrupts
-    are disabled any time that no client is waiting on a vblank event. The new
-    method uses vblank counters on the chipsets when the interrupts are turned
-    off, rather than counting interrupts, so that we can continue to present
-    accurate vblank numbers.
-    
-    Co-author: Michel Dänzer <michel@tungstengraphics.com>
-    Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-    Signed-off-by: Dave Airlie <airlied@redhat.com>
-
-diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
-index 452c2d8..fb45fe7 100644
---- a/drivers/gpu/drm/drm_drv.c
-+++ b/drivers/gpu/drm/drm_drv.c
-@@ -116,6 +116,8 @@ static struct drm_ioctl_desc drm_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
-+      DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
-+
-       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- };
-diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
-index 61ed515..d0c13d9 100644
---- a/drivers/gpu/drm/drm_irq.c
-+++ b/drivers/gpu/drm/drm_irq.c
-@@ -71,19 +71,131 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
-       return 0;
- }
-+static void vblank_disable_fn(unsigned long arg)
-+{
-+      struct drm_device *dev = (struct drm_device *)arg;
-+      unsigned long irqflags;
-+      int i;
-+
-+      if (!dev->vblank_disable_allowed)
-+              return;
-+
-+      for (i = 0; i < dev->num_crtcs; i++) {
-+              spin_lock_irqsave(&dev->vbl_lock, irqflags);
-+              if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
-+                  dev->vblank_enabled[i]) {
-+                      DRM_DEBUG("disabling vblank on crtc %d\n", i);
-+                      dev->last_vblank[i] =
-+                              dev->driver->get_vblank_counter(dev, i);
-+                      dev->driver->disable_vblank(dev, i);
-+                      dev->vblank_enabled[i] = 0;
-+              }
-+              spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-+      }
-+}
-+
-+static void drm_vblank_cleanup(struct drm_device *dev)
-+{
-+      /* Bail if the driver didn't call drm_vblank_init() */
-+      if (dev->num_crtcs == 0)
-+              return;
-+
-+      del_timer(&dev->vblank_disable_timer);
-+
-+      vblank_disable_fn((unsigned long)dev);
-+
-+      drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
-+               DRM_MEM_DRIVER);
-+      drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
-+               DRM_MEM_DRIVER);
-+      drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
-+               dev->num_crtcs, DRM_MEM_DRIVER);
-+      drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
-+               dev->num_crtcs, DRM_MEM_DRIVER);
-+      drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
-+               dev->num_crtcs, DRM_MEM_DRIVER);
-+      drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
-+               DRM_MEM_DRIVER);
-+      drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) *
-+               dev->num_crtcs, DRM_MEM_DRIVER);
-+
-+      dev->num_crtcs = 0;
-+}
-+
-+int drm_vblank_init(struct drm_device *dev, int num_crtcs)
-+{
-+      int i, ret = -ENOMEM;
-+
-+      setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
-+                  (unsigned long)dev);
-+      spin_lock_init(&dev->vbl_lock);
-+      atomic_set(&dev->vbl_signal_pending, 0);
-+      dev->num_crtcs = num_crtcs;
-+
-+      dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
-+                                 DRM_MEM_DRIVER);
-+      if (!dev->vbl_queue)
-+              goto err;
-+
-+      dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
-+                                DRM_MEM_DRIVER);
-+      if (!dev->vbl_sigs)
-+              goto err;
-+
-+      dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
-+                                    DRM_MEM_DRIVER);
-+      if (!dev->_vblank_count)
-+              goto err;
-+
-+      dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
-+                                       DRM_MEM_DRIVER);
-+      if (!dev->vblank_refcount)
-+              goto err;
-+
-+      dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
-+                                       DRM_MEM_DRIVER);
-+      if (!dev->vblank_enabled)
-+              goto err;
-+
-+      dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
-+      if (!dev->last_vblank)
-+              goto err;
-+
-+      dev->vblank_inmodeset = drm_calloc(num_crtcs, sizeof(int),
-+                                       DRM_MEM_DRIVER);
-+      if (!dev->vblank_inmodeset)
-+              goto err;
-+
-+      /* Zero per-crtc vblank stuff */
-+      for (i = 0; i < num_crtcs; i++) {
-+              init_waitqueue_head(&dev->vbl_queue[i]);
-+              INIT_LIST_HEAD(&dev->vbl_sigs[i]);
-+              atomic_set(&dev->_vblank_count[i], 0);
-+              atomic_set(&dev->vblank_refcount[i], 0);
-+      }
-+
-+      dev->vblank_disable_allowed = 0;
-+
-+      return 0;
-+
-+err:
-+      drm_vblank_cleanup(dev);
-+      return ret;
-+}
-+EXPORT_SYMBOL(drm_vblank_init);
-+
- /**
-  * Install IRQ handler.
-  *
-  * \param dev DRM device.
-- * \param irq IRQ number.
-  *
-- * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
-+ * Initializes the IRQ related data. Installs the handler, calling the driver
-  * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
-  * before and after the installation.
-  */
--static int drm_irq_install(struct drm_device * dev)
-+int drm_irq_install(struct drm_device *dev)
- {
--      int ret;
-+      int ret = 0;
-       unsigned long sh_flags = 0;
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-@@ -109,17 +221,6 @@ static int drm_irq_install(struct drm_device * dev)
-       DRM_DEBUG("irq=%d\n", dev->pdev->irq);
--      if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
--              init_waitqueue_head(&dev->vbl_queue);
--
--              spin_lock_init(&dev->vbl_lock);
--
--              INIT_LIST_HEAD(&dev->vbl_sigs);
--              INIT_LIST_HEAD(&dev->vbl_sigs2);
--
--              dev->vbl_pending = 0;
--      }
--
-       /* Before installing handler */
-       dev->driver->irq_preinstall(dev);
-@@ -141,10 +242,16 @@ static int drm_irq_install(struct drm_device * dev)
-       }
-       /* After installing handler */
--      dev->driver->irq_postinstall(dev);
-+      ret = dev->driver->irq_postinstall(dev);
-+      if (ret < 0) {
-+              mutex_lock(&dev->struct_mutex);
-+              dev->irq_enabled = 0;
-+              mutex_unlock(&dev->struct_mutex);
-+      }
--      return 0;
-+      return ret;
- }
-+EXPORT_SYMBOL(drm_irq_install);
- /**
-  * Uninstall the IRQ handler.
-@@ -174,11 +281,12 @@ int drm_irq_uninstall(struct drm_device * dev)
-       free_irq(dev->pdev->irq, dev);
-+      drm_vblank_cleanup(dev);
-+
-       dev->locked_tasklet_func = NULL;
-       return 0;
- }
--
- EXPORT_SYMBOL(drm_irq_uninstall);
- /**
-@@ -218,6 +326,174 @@ int drm_control(struct drm_device *dev, void *data,
- }
- /**
-+ * drm_vblank_count - retrieve "cooked" vblank counter value
-+ * @dev: DRM device
-+ * @crtc: which counter to retrieve
-+ *
-+ * Fetches the "cooked" vblank count value that represents the number of
-+ * vblank events since the system was booted, including lost events due to
-+ * modesetting activity.
-+ */
-+u32 drm_vblank_count(struct drm_device *dev, int crtc)
-+{
-+      return atomic_read(&dev->_vblank_count[crtc]);
-+}
-+EXPORT_SYMBOL(drm_vblank_count);
-+
-+/**
-+ * drm_update_vblank_count - update the master vblank counter
-+ * @dev: DRM device
-+ * @crtc: counter to update
-+ *
-+ * Call back into the driver to update the appropriate vblank counter
-+ * (specified by @crtc).  Deal with wraparound, if it occurred, and
-+ * update the last read value so we can deal with wraparound on the next
-+ * call if necessary.
-+ *
-+ * Only necessary when going from off->on, to account for frames we
-+ * didn't get an interrupt for.
-+ *
-+ * Note: caller must hold dev->vbl_lock since this reads & writes
-+ * device vblank fields.
-+ */
-+static void drm_update_vblank_count(struct drm_device *dev, int crtc)
-+{
-+      u32 cur_vblank, diff;
-+
-+      /*
-+       * Interrupts were disabled prior to this call, so deal with counter
-+       * wrap if needed.
-+       * NOTE!  It's possible we lost a full dev->max_vblank_count events
-+       * here if the register is small or we had vblank interrupts off for
-+       * a long time.
-+       */
-+      cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
-+      diff = cur_vblank - dev->last_vblank[crtc];
-+      if (cur_vblank < dev->last_vblank[crtc]) {
-+              diff += dev->max_vblank_count;
-+
-+              DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
-+                        crtc, dev->last_vblank[crtc], cur_vblank, diff);
-+      }
-+
-+      DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
-+                crtc, diff);
-+
-+      atomic_add(diff, &dev->_vblank_count[crtc]);
-+}
-+
-+/**
-+ * drm_vblank_get - get a reference count on vblank events
-+ * @dev: DRM device
-+ * @crtc: which CRTC to own
-+ *
-+ * Acquire a reference count on vblank events to avoid having them disabled
-+ * while in use.
-+ *
-+ * RETURNS
-+ * Zero on success, nonzero on failure.
-+ */
-+int drm_vblank_get(struct drm_device *dev, int crtc)
-+{
-+      unsigned long irqflags;
-+      int ret = 0;
-+
-+      spin_lock_irqsave(&dev->vbl_lock, irqflags);
-+      /* Going from 0->1 means we have to enable interrupts again */
-+      if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
-+          !dev->vblank_enabled[crtc]) {
-+              ret = dev->driver->enable_vblank(dev, crtc);
-+              DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
-+              if (ret)
-+                      atomic_dec(&dev->vblank_refcount[crtc]);
-+              else {
-+                      dev->vblank_enabled[crtc] = 1;
-+                      drm_update_vblank_count(dev, crtc);
-+              }
-+      }
-+      spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL(drm_vblank_get);
-+
-+/**
-+ * drm_vblank_put - give up ownership of vblank events
-+ * @dev: DRM device
-+ * @crtc: which counter to give up
-+ *
-+ * Release ownership of a given vblank counter, turning off interrupts
-+ * if possible.
-+ */
-+void drm_vblank_put(struct drm_device *dev, int crtc)
-+{
-+      /* Last user schedules interrupt disable */
-+      if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
-+              mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
-+}
-+EXPORT_SYMBOL(drm_vblank_put);
-+
-+/**
-+ * drm_modeset_ctl - handle vblank event counter changes across mode switch
-+ * @DRM_IOCTL_ARGS: standard ioctl arguments
-+ *
-+ * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
-+ * ioctls around modesetting so that any lost vblank events are accounted for.
-+ *
-+ * Generally the counter will reset across mode sets.  If interrupts are
-+ * enabled around this call, we don't have to do anything since the counter
-+ * will have already been incremented.
-+ */
-+int drm_modeset_ctl(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      struct drm_modeset_ctl *modeset = data;
-+      unsigned long irqflags;
-+      int crtc, ret = 0;
-+
-+      /* If drm_vblank_init() hasn't been called yet, just no-op */
-+      if (!dev->num_crtcs)
-+              goto out;
-+
-+      crtc = modeset->crtc;
-+      if (crtc >= dev->num_crtcs) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      /*
-+       * To avoid all the problems that might happen if interrupts
-+       * were enabled/disabled around or between these calls, we just
-+       * have the kernel take a reference on the CRTC (just once though
-+       * to avoid corrupting the count if multiple, mismatch calls occur),
-+       * so that interrupts remain enabled in the interim.
-+       */
-+      switch (modeset->cmd) {
-+      case _DRM_PRE_MODESET:
-+              if (!dev->vblank_inmodeset[crtc]) {
-+                      dev->vblank_inmodeset[crtc] = 1;
-+                      drm_vblank_get(dev, crtc);
-+              }
-+              break;
-+      case _DRM_POST_MODESET:
-+              if (dev->vblank_inmodeset[crtc]) {
-+                      spin_lock_irqsave(&dev->vbl_lock, irqflags);
-+                      dev->vblank_disable_allowed = 1;
-+                      dev->vblank_inmodeset[crtc] = 0;
-+                      spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-+                      drm_vblank_put(dev, crtc);
-+              }
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+out:
-+      return ret;
-+}
-+
-+/**
-  * Wait for VBLANK.
-  *
-  * \param inode device inode.
-@@ -236,12 +512,12 @@ int drm_control(struct drm_device *dev, void *data,
-  *
-  * If a signal is not requested, then calls vblank_wait().
-  */
--int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
-+int drm_wait_vblank(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
- {
-       union drm_wait_vblank *vblwait = data;
--      struct timeval now;
-       int ret = 0;
--      unsigned int flags, seq;
-+      unsigned int flags, seq, crtc;
-       if ((!dev->pdev->irq) || (!dev->irq_enabled))
-               return -EINVAL;
-@@ -255,13 +531,17 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
-       }
-       flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
-+      crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
--      if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
--                                  DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
-+      if (crtc >= dev->num_crtcs)
-               return -EINVAL;
--      seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
--                        : &dev->vbl_received);
-+      ret = drm_vblank_get(dev, crtc);
-+      if (ret) {
-+              DRM_ERROR("failed to acquire vblank counter, %d\n", ret);
-+              return ret;
-+      }
-+      seq = drm_vblank_count(dev, crtc);
-       switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
-       case _DRM_VBLANK_RELATIVE:
-@@ -270,7 +550,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
-       case _DRM_VBLANK_ABSOLUTE:
-               break;
-       default:
--              return -EINVAL;
-+              ret = -EINVAL;
-+              goto done;
-       }
-       if ((flags & _DRM_VBLANK_NEXTONMISS) &&
-@@ -280,8 +561,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
-       if (flags & _DRM_VBLANK_SIGNAL) {
-               unsigned long irqflags;
--              struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
--                                    ? &dev->vbl_sigs2 : &dev->vbl_sigs;
-+              struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
-               struct drm_vbl_sig *vbl_sig;
-               spin_lock_irqsave(&dev->vbl_lock, irqflags);
-@@ -302,22 +582,29 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
-                       }
-               }
--              if (dev->vbl_pending >= 100) {
-+              if (atomic_read(&dev->vbl_signal_pending) >= 100) {
-                       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
--                      return -EBUSY;
-+                      ret = -EBUSY;
-+                      goto done;
-               }
--              dev->vbl_pending++;
--
-               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
--              if (!
--                  (vbl_sig =
--                   drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
--                      return -ENOMEM;
-+              vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
-+                                   DRM_MEM_DRIVER);
-+              if (!vbl_sig) {
-+                      ret = -ENOMEM;
-+                      goto done;
-+              }
-+
-+              ret = drm_vblank_get(dev, crtc);
-+              if (ret) {
-+                      drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
-+                               DRM_MEM_DRIVER);
-+                      return ret;
-               }
--              memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
-+              atomic_inc(&dev->vbl_signal_pending);
-               vbl_sig->sequence = vblwait->request.sequence;
-               vbl_sig->info.si_signo = vblwait->request.signal;
-@@ -331,20 +618,29 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
-               vblwait->reply.sequence = seq;
-       } else {
--              if (flags & _DRM_VBLANK_SECONDARY) {
--                      if (dev->driver->vblank_wait2)
--                              ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
--              } else if (dev->driver->vblank_wait)
--                      ret =
--                          dev->driver->vblank_wait(dev,
--                                                   &vblwait->request.sequence);
--
--              do_gettimeofday(&now);
--              vblwait->reply.tval_sec = now.tv_sec;
--              vblwait->reply.tval_usec = now.tv_usec;
-+              DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
-+                        vblwait->request.sequence, crtc);
-+              DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
-+                          ((drm_vblank_count(dev, crtc)
-+                            - vblwait->request.sequence) <= (1 << 23)));
-+
-+              if (ret != -EINTR) {
-+                      struct timeval now;
-+
-+                      do_gettimeofday(&now);
-+
-+                      vblwait->reply.tval_sec = now.tv_sec;
-+                      vblwait->reply.tval_usec = now.tv_usec;
-+                      vblwait->reply.sequence = drm_vblank_count(dev, crtc);
-+                      DRM_DEBUG("returning %d to client\n",
-+                                vblwait->reply.sequence);
-+              } else {
-+                      DRM_DEBUG("vblank wait interrupted by signal\n");
-+              }
-       }
--      done:
-+done:
-+      drm_vblank_put(dev, crtc);
-       return ret;
- }
-@@ -352,44 +648,57 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
-  * Send the VBLANK signals.
-  *
-  * \param dev DRM device.
-+ * \param crtc CRTC where the vblank event occurred
-  *
-  * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
-  *
-  * If a signal is not requested, then calls vblank_wait().
-  */
--void drm_vbl_send_signals(struct drm_device * dev)
-+static void drm_vbl_send_signals(struct drm_device *dev, int crtc)
- {
-+      struct drm_vbl_sig *vbl_sig, *tmp;
-+      struct list_head *vbl_sigs;
-+      unsigned int vbl_seq;
-       unsigned long flags;
--      int i;
-       spin_lock_irqsave(&dev->vbl_lock, flags);
--      for (i = 0; i < 2; i++) {
--              struct drm_vbl_sig *vbl_sig, *tmp;
--              struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
--              unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
--                                                 &dev->vbl_received);
-+      vbl_sigs = &dev->vbl_sigs[crtc];
-+      vbl_seq = drm_vblank_count(dev, crtc);
--              list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
--                      if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
--                              vbl_sig->info.si_code = vbl_seq;
--                              send_sig_info(vbl_sig->info.si_signo,
--                                            &vbl_sig->info, vbl_sig->task);
-+      list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
-+          if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
-+              vbl_sig->info.si_code = vbl_seq;
-+              send_sig_info(vbl_sig->info.si_signo,
-+                            &vbl_sig->info, vbl_sig->task);
--                              list_del(&vbl_sig->head);
--
--                              drm_free(vbl_sig, sizeof(*vbl_sig),
--                                       DRM_MEM_DRIVER);
-+              list_del(&vbl_sig->head);
--                              dev->vbl_pending--;
--                      }
--              }
-+              drm_free(vbl_sig, sizeof(*vbl_sig),
-+                       DRM_MEM_DRIVER);
-+              atomic_dec(&dev->vbl_signal_pending);
-+              drm_vblank_put(dev, crtc);
-+          }
-       }
-       spin_unlock_irqrestore(&dev->vbl_lock, flags);
- }
--EXPORT_SYMBOL(drm_vbl_send_signals);
-+/**
-+ * drm_handle_vblank - handle a vblank event
-+ * @dev: DRM device
-+ * @crtc: where this event occurred
-+ *
-+ * Drivers should call this routine in their vblank interrupt handlers to
-+ * update the vblank counter and send any signals that may be pending.
-+ */
-+void drm_handle_vblank(struct drm_device *dev, int crtc)
-+{
-+      atomic_inc(&dev->_vblank_count[crtc]);
-+      DRM_WAKEUP(&dev->vbl_queue[crtc]);
-+      drm_vbl_send_signals(dev, crtc);
-+}
-+EXPORT_SYMBOL(drm_handle_vblank);
- /**
-  * Tasklet wrapper function.
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index cead62f..8609ec2 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -673,7 +673,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
-       switch (param->param) {
-       case I915_PARAM_IRQ_ACTIVE:
--              value = dev->irq_enabled;
-+              value = dev->pdev->irq ? 1 : 0;
-               break;
-       case I915_PARAM_ALLOW_BATCHBUFFER:
-               value = dev_priv->allow_batchbuffer ? 1 : 0;
-@@ -808,7 +808,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
-        * and the registers being closely associated.
-        */
-       if (!IS_I945G(dev) && !IS_I945GM(dev))
--              pci_enable_msi(dev->pdev);
-+              if (pci_enable_msi(dev->pdev))
-+                      DRM_ERROR("failed to enable MSI\n");
-       intel_opregion_init(dev);
-diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
-index eff66ed..37af03f 100644
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -85,10 +85,8 @@ static struct drm_driver driver = {
-       /* don't use mtrr's here, the Xserver or user space app should
-        * deal with them for intel hardware.
-        */
--      .driver_features =
--          DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
--          DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
--          DRIVER_IRQ_VBL2,
-+      .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
-+              DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
-       .load = i915_driver_load,
-       .unload = i915_driver_unload,
-       .lastclose = i915_driver_lastclose,
-@@ -96,8 +94,9 @@ static struct drm_driver driver = {
-       .suspend = i915_suspend,
-       .resume = i915_resume,
-       .device_is_agp = i915_driver_device_is_agp,
--      .vblank_wait = i915_driver_vblank_wait,
--      .vblank_wait2 = i915_driver_vblank_wait2,
-+      .get_vblank_counter = i915_get_vblank_counter,
-+      .enable_vblank = i915_enable_vblank,
-+      .disable_vblank = i915_disable_vblank,
-       .irq_preinstall = i915_driver_irq_preinstall,
-       .irq_postinstall = i915_driver_irq_postinstall,
-       .irq_uninstall = i915_driver_irq_uninstall,
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index 71326ca..d1a02be 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -83,10 +83,15 @@ struct mem_block {
- typedef struct _drm_i915_vbl_swap {
-       struct list_head head;
-       drm_drawable_t drw_id;
--      unsigned int pipe;
-+      unsigned int plane;
-       unsigned int sequence;
- } drm_i915_vbl_swap_t;
-+struct opregion_header;
-+struct opregion_acpi;
-+struct opregion_swsci;
-+struct opregion_asle;
-+
- struct intel_opregion {
-       struct opregion_header *header;
-       struct opregion_acpi *acpi;
-@@ -105,7 +110,7 @@ typedef struct drm_i915_private {
-       drm_dma_handle_t *status_page_dmah;
-       void *hw_status_page;
-       dma_addr_t dma_status_page;
--      unsigned long counter;
-+      uint32_t counter;
-       unsigned int status_gfx_addr;
-       drm_local_map_t hws_map;
-@@ -247,16 +252,17 @@ extern int i915_irq_emit(struct drm_device *dev, void *data,
- extern int i915_irq_wait(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
--extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
--extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
- extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
- extern void i915_driver_irq_preinstall(struct drm_device * dev);
--extern void i915_driver_irq_postinstall(struct drm_device * dev);
-+extern int i915_driver_irq_postinstall(struct drm_device *dev);
- extern void i915_driver_irq_uninstall(struct drm_device * dev);
- extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
- extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
-+extern int i915_enable_vblank(struct drm_device *dev, int crtc);
-+extern void i915_disable_vblank(struct drm_device *dev, int crtc);
-+extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
- extern int i915_vblank_swap(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv);
- extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
-@@ -278,6 +284,10 @@ extern void i915_mem_release(struct drm_device * dev,
- extern int i915_save_state(struct drm_device *dev);
- extern int i915_restore_state(struct drm_device *dev);
-+/* i915_suspend.c */
-+extern int i915_save_state(struct drm_device *dev);
-+extern int i915_restore_state(struct drm_device *dev);
-+
- /* i915_opregion.c */
- extern int intel_opregion_init(struct drm_device *dev);
- extern void intel_opregion_free(struct drm_device *dev);
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index ae7d3a8..f875959 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -35,9 +35,8 @@
- /** These are the interrupts used by the driver */
- #define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT |             \
--                                  I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \
--                                  I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT | \
-                                   I915_ASLE_INTERRUPT |               \
-+                                  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
-                                   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
- void
-@@ -61,6 +60,64 @@ i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
- }
- /**
-+ * i915_get_pipe - return the the pipe associated with a given plane
-+ * @dev: DRM device
-+ * @plane: plane to look for
-+ *
-+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
-+ * rather than a pipe number, since they may not always be equal.  This routine
-+ * maps the given @plane back to a pipe number.
-+ */
-+static int
-+i915_get_pipe(struct drm_device *dev, int plane)
-+{
-+      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+      u32 dspcntr;
-+
-+      dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
-+
-+      return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
-+}
-+
-+/**
-+ * i915_get_plane - return the the plane associated with a given pipe
-+ * @dev: DRM device
-+ * @pipe: pipe to look for
-+ *
-+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
-+ * rather than a plane number, since they may not always be equal.  This routine
-+ * maps the given @pipe back to a plane number.
-+ */
-+static int
-+i915_get_plane(struct drm_device *dev, int pipe)
-+{
-+      if (i915_get_pipe(dev, 0) == pipe)
-+              return 0;
-+      return 1;
-+}
-+
-+/**
-+ * i915_pipe_enabled - check if a pipe is enabled
-+ * @dev: DRM device
-+ * @pipe: pipe to check
-+ *
-+ * Reading certain registers when the pipe is disabled can hang the chip.
-+ * Use this routine to make sure the PLL is running and the pipe is active
-+ * before reading such registers if unsure.
-+ */
-+static int
-+i915_pipe_enabled(struct drm_device *dev, int pipe)
-+{
-+      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+      unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
-+
-+      if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
-+              return 1;
-+
-+      return 0;
-+}
-+
-+/**
-  * Emit blits for scheduled buffer swaps.
-  *
-  * This function will be called with the HW lock held.
-@@ -71,8 +128,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
-       unsigned long irqflags;
-       struct list_head *list, *tmp, hits, *hit;
-       int nhits, nrects, slice[2], upper[2], lower[2], i;
--      unsigned counter[2] = { atomic_read(&dev->vbl_received),
--                              atomic_read(&dev->vbl_received2) };
-+      unsigned counter[2];
-       struct drm_drawable_info *drw;
-       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       u32 cpp = dev_priv->cpp;
-@@ -94,6 +150,9 @@ static void i915_vblank_tasklet(struct drm_device *dev)
-               src_pitch >>= 2;
-       }
-+      counter[0] = drm_vblank_count(dev, 0);
-+      counter[1] = drm_vblank_count(dev, 1);
-+
-       DRM_DEBUG("\n");
-       INIT_LIST_HEAD(&hits);
-@@ -106,12 +165,14 @@ static void i915_vblank_tasklet(struct drm_device *dev)
-       list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
-               drm_i915_vbl_swap_t *vbl_swap =
-                       list_entry(list, drm_i915_vbl_swap_t, head);
-+              int pipe = i915_get_pipe(dev, vbl_swap->plane);
--              if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
-+              if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
-                       continue;
-               list_del(list);
-               dev_priv->swaps_pending--;
-+              drm_vblank_put(dev, pipe);
-               spin_unlock(&dev_priv->swaps_lock);
-               spin_lock(&dev->drw_lock);
-@@ -204,7 +265,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
-                       drm_i915_vbl_swap_t *swap_hit =
-                               list_entry(hit, drm_i915_vbl_swap_t, head);
-                       struct drm_clip_rect *rect;
--                      int num_rects, pipe;
-+                      int num_rects, plane;
-                       unsigned short top, bottom;
-                       drw = drm_get_drawable_info(dev, swap_hit->drw_id);
-@@ -213,9 +274,9 @@ static void i915_vblank_tasklet(struct drm_device *dev)
-                               continue;
-                       rect = drw->rects;
--                      pipe = swap_hit->pipe;
--                      top = upper[pipe];
--                      bottom = lower[pipe];
-+                      plane = swap_hit->plane;
-+                      top = upper[plane];
-+                      bottom = lower[plane];
-                       for (num_rects = drw->num_rects; num_rects--; rect++) {
-                               int y1 = max(rect->y1, top);
-@@ -252,22 +313,54 @@ static void i915_vblank_tasklet(struct drm_device *dev)
-       }
- }
-+u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
-+{
-+      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+      unsigned long high_frame;
-+      unsigned long low_frame;
-+      u32 high1, high2, low, count;
-+      int pipe;
-+
-+      pipe = i915_get_pipe(dev, plane);
-+      high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
-+      low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
-+
-+      if (!i915_pipe_enabled(dev, pipe)) {
-+              DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
-+              return 0;
-+      }
-+
-+      /*
-+       * High & low register fields aren't synchronized, so make sure
-+       * we get a low value that's stable across two reads of the high
-+       * register.
-+       */
-+      do {
-+              high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
-+                       PIPE_FRAME_HIGH_SHIFT);
-+              low =  ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
-+                      PIPE_FRAME_LOW_SHIFT);
-+              high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
-+                       PIPE_FRAME_HIGH_SHIFT);
-+      } while (high1 != high2);
-+
-+      count = (high1 << 8) | low;
-+
-+      return count;
-+}
-+
- irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
- {
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      u32 pipea_stats, pipeb_stats;
-       u32 iir;
--
--      pipea_stats = I915_READ(PIPEASTAT);
--      pipeb_stats = I915_READ(PIPEBSTAT);
-+      u32 pipea_stats, pipeb_stats;
-+      int vblank = 0;
-       if (dev->pdev->msi_enabled)
-               I915_WRITE(IMR, ~0);
-       iir = I915_READ(IIR);
--      DRM_DEBUG("iir=%08x\n", iir);
--
-       if (iir == 0) {
-               if (dev->pdev->msi_enabled) {
-                       I915_WRITE(IMR, dev_priv->irq_mask_reg);
-@@ -276,48 +369,56 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-               return IRQ_NONE;
-       }
--      I915_WRITE(PIPEASTAT, pipea_stats);
--      I915_WRITE(PIPEBSTAT, pipeb_stats);
--
--      I915_WRITE(IIR, iir);
--      if (dev->pdev->msi_enabled)
--              I915_WRITE(IMR, dev_priv->irq_mask_reg);
--      (void) I915_READ(IIR); /* Flush posted writes */
--
--      dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
--
--      if (iir & I915_USER_INTERRUPT)
--              DRM_WAKEUP(&dev_priv->irq_queue);
--
--      if (iir & (I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
--                 I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)) {
--              int vblank_pipe = dev_priv->vblank_pipe;
--
--              if ((vblank_pipe &
--                   (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
--                  == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
--                      if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
--                              atomic_inc(&dev->vbl_received);
--                      if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
--                              atomic_inc(&dev->vbl_received2);
--              } else if (((iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) &&
--                          (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
--                         ((iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) &&
--                          (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
--                      atomic_inc(&dev->vbl_received);
-+      /*
-+       * Clear the PIPE(A|B)STAT regs before the IIR otherwise
-+       * we may get extra interrupts.
-+       */
-+      if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
-+              pipea_stats = I915_READ(PIPEASTAT);
-+              if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A))
-+                      pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
-+                                       PIPE_VBLANK_INTERRUPT_ENABLE);
-+              else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
-+                                      PIPE_VBLANK_INTERRUPT_STATUS)) {
-+                      vblank++;
-+                      drm_handle_vblank(dev, i915_get_plane(dev, 0));
-+              }
--              DRM_WAKEUP(&dev->vbl_queue);
--              drm_vbl_send_signals(dev);
-+              I915_WRITE(PIPEASTAT, pipea_stats);
-+      }
-+      if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
-+              pipeb_stats = I915_READ(PIPEBSTAT);
-+              /* Ack the event */
-+              I915_WRITE(PIPEBSTAT, pipeb_stats);
-+
-+              /* The vblank interrupt gets enabled even if we didn't ask for
-+                 it, so make sure it's shut down again */
-+              if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
-+                      pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
-+                                       PIPE_VBLANK_INTERRUPT_ENABLE);
-+              else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
-+                                      PIPE_VBLANK_INTERRUPT_STATUS)) {
-+                      vblank++;
-+                      drm_handle_vblank(dev, i915_get_plane(dev, 1));
-+              }
--              if (dev_priv->swaps_pending > 0)
--                      drm_locked_tasklet(dev, i915_vblank_tasklet);
-+              if (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS)
-+                      opregion_asle_intr(dev);
-+              I915_WRITE(PIPEBSTAT, pipeb_stats);
-       }
-       if (iir & I915_ASLE_INTERRUPT)
-               opregion_asle_intr(dev);
--      if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
--              opregion_asle_intr(dev);
-+      dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-+
-+      if (dev->pdev->msi_enabled)
-+              I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+      I915_WRITE(IIR, iir);
-+      (void) I915_READ(IIR);
-+
-+      if (vblank && dev_priv->swaps_pending > 0)
-+              drm_locked_tasklet(dev, i915_vblank_tasklet);
-       return IRQ_HANDLED;
- }
-@@ -358,7 +459,7 @@ static void i915_user_irq_get(struct drm_device *dev)
-       spin_unlock(&dev_priv->user_irq_lock);
- }
--static void i915_user_irq_put(struct drm_device *dev)
-+void i915_user_irq_put(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-@@ -395,41 +496,10 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
-       }
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
--      return ret;
--}
--
--static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
--                                    atomic_t *counter)
--{
--      drm_i915_private_t *dev_priv = dev->dev_private;
--      unsigned int cur_vblank;
--      int ret = 0;
--
--      if (!dev_priv) {
--              DRM_ERROR("called with no initialization\n");
--              return -EINVAL;
--      }
--
--      DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
--                  (((cur_vblank = atomic_read(counter))
--                      - *sequence) <= (1<<23)));
--
--      *sequence = cur_vblank;
-       return ret;
- }
--
--int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
--{
--      return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
--}
--
--int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
--{
--      return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
--}
--
- /* Needs the lock as it touches the ring.
-  */
- int i915_irq_emit(struct drm_device *dev, void *data,
-@@ -472,40 +542,88 @@ int i915_irq_wait(struct drm_device *dev, void *data,
-       return i915_wait_irq(dev, irqwait->irq_seq);
- }
-+int i915_enable_vblank(struct drm_device *dev, int plane)
-+{
-+      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+      int pipe = i915_get_pipe(dev, plane);
-+      u32     pipestat_reg = 0;
-+      u32     pipestat;
-+
-+      switch (pipe) {
-+      case 0:
-+              pipestat_reg = PIPEASTAT;
-+              i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
-+              break;
-+      case 1:
-+              pipestat_reg = PIPEBSTAT;
-+              i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
-+              break;
-+      default:
-+              DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
-+                        pipe);
-+              break;
-+      }
-+
-+      if (pipestat_reg) {
-+              pipestat = I915_READ(pipestat_reg);
-+              if (IS_I965G(dev))
-+                      pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
-+              else
-+                      pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
-+              /* Clear any stale interrupt status */
-+              pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
-+                           PIPE_VBLANK_INTERRUPT_STATUS);
-+              I915_WRITE(pipestat_reg, pipestat);
-+      }
-+
-+      return 0;
-+}
-+
-+void i915_disable_vblank(struct drm_device *dev, int plane)
-+{
-+      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+      int pipe = i915_get_pipe(dev, plane);
-+      u32     pipestat_reg = 0;
-+      u32     pipestat;
-+
-+      switch (pipe) {
-+      case 0:
-+              pipestat_reg = PIPEASTAT;
-+              i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
-+              break;
-+      case 1:
-+              pipestat_reg = PIPEBSTAT;
-+              i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
-+              break;
-+      default:
-+              DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
-+                        pipe);
-+              break;
-+      }
-+
-+      if (pipestat_reg) {
-+              pipestat = I915_READ(pipestat_reg);
-+              pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
-+                            PIPE_VBLANK_INTERRUPT_ENABLE);
-+              /* Clear any stale interrupt status */
-+              pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
-+                           PIPE_VBLANK_INTERRUPT_STATUS);
-+              I915_WRITE(pipestat_reg, pipestat);
-+      }
-+}
-+
- /* Set the vblank monitor pipe
-  */
- int i915_vblank_pipe_set(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
--      drm_i915_vblank_pipe_t *pipe = data;
--      u32 enable_mask = 0, disable_mask = 0;
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
--      if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
--              DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe);
--              return -EINVAL;
--      }
--
--      if (pipe->pipe & DRM_I915_VBLANK_PIPE_A)
--              enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
--      else
--              disable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
--
--      if (pipe->pipe & DRM_I915_VBLANK_PIPE_B)
--              enable_mask |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
--      else
--              disable_mask |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
--
--      i915_enable_irq(dev_priv, enable_mask);
--      i915_disable_irq(dev_priv, disable_mask);
--
--      dev_priv->vblank_pipe = pipe->pipe;
--
-       return 0;
- }
-@@ -514,19 +632,13 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_pipe_t *pipe = data;
--      u16 flag;
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
--      flag = I915_READ(IMR);
--      pipe->pipe = 0;
--      if (flag & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
--              pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
--      if (flag & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
--              pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
-+      pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
-       return 0;
- }
-@@ -540,9 +652,10 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_swap_t *swap = data;
-       drm_i915_vbl_swap_t *vbl_swap;
--      unsigned int pipe, seqtype, curseq;
-+      unsigned int pipe, seqtype, curseq, plane;
-       unsigned long irqflags;
-       struct list_head *list;
-+      int ret;
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __func__);
-@@ -560,7 +673,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
-               return -EINVAL;
-       }
--      pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
-+      plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
-+      pipe = i915_get_pipe(dev, plane);
-       seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
-@@ -579,7 +693,14 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
-       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
--      curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
-+      /*
-+       * We take the ref here and put it when the swap actually completes
-+       * in the tasklet.
-+       */
-+      ret = drm_vblank_get(dev, pipe);
-+      if (ret)
-+              return ret;
-+      curseq = drm_vblank_count(dev, pipe);
-       if (seqtype == _DRM_VBLANK_RELATIVE)
-               swap->sequence += curseq;
-@@ -589,6 +710,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
-                       swap->sequence = curseq + 1;
-               } else {
-                       DRM_DEBUG("Missed target sequence\n");
-+                      drm_vblank_put(dev, pipe);
-                       return -EINVAL;
-               }
-       }
-@@ -599,7 +721,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
-               vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
-               if (vbl_swap->drw_id == swap->drawable &&
--                  vbl_swap->pipe == pipe &&
-+                  vbl_swap->plane == plane &&
-                   vbl_swap->sequence == swap->sequence) {
-                       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
-                       DRM_DEBUG("Already scheduled\n");
-@@ -611,6 +733,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
-       if (dev_priv->swaps_pending >= 100) {
-               DRM_DEBUG("Too many swaps queued\n");
-+              drm_vblank_put(dev, pipe);
-               return -EBUSY;
-       }
-@@ -618,13 +741,14 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
-       if (!vbl_swap) {
-               DRM_ERROR("Failed to allocate memory to queue swap\n");
-+              drm_vblank_put(dev, pipe);
-               return -ENOMEM;
-       }
-       DRM_DEBUG("\n");
-       vbl_swap->drw_id = swap->drawable;
--      vbl_swap->pipe = pipe;
-+      vbl_swap->plane = plane;
-       vbl_swap->sequence = swap->sequence;
-       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
-@@ -643,28 +767,32 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      I915_WRITE(HWSTAM, 0xfffe);
--      I915_WRITE(IMR, 0x0);
-+      I915_WRITE(HWSTAM, 0xeffe);
-+      I915_WRITE(IMR, 0xffffffff);
-       I915_WRITE(IER, 0x0);
- }
--void i915_driver_irq_postinstall(struct drm_device * dev)
-+int i915_driver_irq_postinstall(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-+      int ret, num_pipes = 2;
-       spin_lock_init(&dev_priv->swaps_lock);
-       INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
-       dev_priv->swaps_pending = 0;
--      if (!dev_priv->vblank_pipe)
--              dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
--
-       /* Set initial unmasked IRQs to just the selected vblank pipes. */
-       dev_priv->irq_mask_reg = ~0;
--      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
--              dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
--      if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
--              dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-+
-+      ret = drm_vblank_init(dev, num_pipes);
-+      if (ret)
-+              return ret;
-+
-+      dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
-+      dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-+      dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-+
-+      dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
-       dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
-@@ -673,22 +801,29 @@ void i915_driver_irq_postinstall(struct drm_device * dev)
-       (void) I915_READ(IER);
-       opregion_enable_asle(dev);
--
-       DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
-+
-+      return 0;
- }
- void i915_driver_irq_uninstall(struct drm_device * dev)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
--      u16 temp;
-+      u32 temp;
-       if (!dev_priv)
-               return;
--      I915_WRITE(HWSTAM, 0xffff);
--      I915_WRITE(IMR, 0xffff);
-+      dev_priv->vblank_pipe = 0;
-+
-+      I915_WRITE(HWSTAM, 0xffffffff);
-+      I915_WRITE(IMR, 0xffffffff);
-       I915_WRITE(IER, 0x0);
-+      temp = I915_READ(PIPEASTAT);
-+      I915_WRITE(PIPEASTAT, temp);
-+      temp = I915_READ(PIPEBSTAT);
-+      I915_WRITE(PIPEBSTAT, temp);
-       temp = I915_READ(IIR);
-       I915_WRITE(IIR, temp);
- }
-diff --git a/include/drm/drm.h b/include/drm/drm.h
-index 0864c69..15e5503 100644
---- a/include/drm/drm.h
-+++ b/include/drm/drm.h
-@@ -454,6 +454,7 @@ struct drm_irq_busid {
- enum drm_vblank_seq_type {
-       _DRM_VBLANK_ABSOLUTE = 0x0,     /**< Wait for specific vblank sequence number */
-       _DRM_VBLANK_RELATIVE = 0x1,     /**< Wait for given number of vblanks */
-+      _DRM_VBLANK_FLIP = 0x8000000,   /**< Scheduled buffer swap should flip */
-       _DRM_VBLANK_NEXTONMISS = 0x10000000,    /**< If missed, wait for next vblank */
-       _DRM_VBLANK_SECONDARY = 0x20000000,     /**< Secondary display controller */
-       _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
-@@ -486,6 +487,19 @@ union drm_wait_vblank {
-       struct drm_wait_vblank_reply reply;
- };
-+#define _DRM_PRE_MODESET 1
-+#define _DRM_POST_MODESET 2
-+
-+/**
-+ * DRM_IOCTL_MODESET_CTL ioctl argument type
-+ *
-+ * \sa drmModesetCtl().
-+ */
-+struct drm_modeset_ctl {
-+      uint32_t crtc;
-+      uint32_t cmd;
-+};
-+
- /**
-  * DRM_IOCTL_AGP_ENABLE ioctl argument type.
-  *
-@@ -570,6 +584,7 @@ struct drm_set_version {
- #define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
- #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
- #define DRM_IOCTL_SET_VERSION         DRM_IOWR(0x07, struct drm_set_version)
-+#define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08, struct drm_modeset_ctl)
- #define DRM_IOCTL_SET_UNIQUE          DRM_IOW( 0x10, struct drm_unique)
- #define DRM_IOCTL_AUTH_MAGIC          DRM_IOW( 0x11, struct drm_auth)
-diff --git a/include/drm/drmP.h b/include/drm/drmP.h
-index 1c1b13e..e79ce07 100644
---- a/include/drm/drmP.h
-+++ b/include/drm/drmP.h
-@@ -580,11 +580,54 @@ struct drm_driver {
-       int (*kernel_context_switch) (struct drm_device *dev, int old,
-                                     int new);
-       void (*kernel_context_switch_unlock) (struct drm_device *dev);
--      int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
--      int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
-       int (*dri_library_name) (struct drm_device *dev, char *buf);
-       /**
-+       * get_vblank_counter - get raw hardware vblank counter
-+       * @dev: DRM device
-+       * @crtc: counter to fetch
-+       *
-+       * Driver callback for fetching a raw hardware vblank counter
-+       * for @crtc.  If a device doesn't have a hardware counter, the
-+       * driver can simply return the value of drm_vblank_count and
-+       * make the enable_vblank() and disable_vblank() hooks into no-ops,
-+       * leaving interrupts enabled at all times.
-+       *
-+       * Wraparound handling and loss of events due to modesetting is dealt
-+       * with in the DRM core code.
-+       *
-+       * RETURNS
-+       * Raw vblank counter value.
-+       */
-+      u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
-+
-+      /**
-+       * enable_vblank - enable vblank interrupt events
-+       * @dev: DRM device
-+       * @crtc: which irq to enable
-+       *
-+       * Enable vblank interrupts for @crtc.  If the device doesn't have
-+       * a hardware vblank counter, this routine should be a no-op, since
-+       * interrupts will have to stay on to keep the count accurate.
-+       *
-+       * RETURNS
-+       * Zero on success, appropriate errno if the given @crtc's vblank
-+       * interrupt cannot be enabled.
-+       */
-+      int (*enable_vblank) (struct drm_device *dev, int crtc);
-+
-+      /**
-+       * disable_vblank - disable vblank interrupt events
-+       * @dev: DRM device
-+       * @crtc: which irq to enable
-+       *
-+       * Disable vblank interrupts for @crtc.  If the device doesn't have
-+       * a hardware vblank counter, this routine should be a no-op, since
-+       * interrupts will have to stay on to keep the count accurate.
-+       */
-+      void (*disable_vblank) (struct drm_device *dev, int crtc);
-+
-+      /**
-        * Called by \c drm_device_is_agp.  Typically used to determine if a
-        * card is really attached to AGP or not.
-        *
-@@ -601,7 +644,7 @@ struct drm_driver {
-       irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
-       void (*irq_preinstall) (struct drm_device *dev);
--      void (*irq_postinstall) (struct drm_device *dev);
-+      int (*irq_postinstall) (struct drm_device *dev);
-       void (*irq_uninstall) (struct drm_device *dev);
-       void (*reclaim_buffers) (struct drm_device *dev,
-                                struct drm_file * file_priv);
-@@ -730,13 +773,28 @@ struct drm_device {
-       /** \name VBLANK IRQ support */
-       /*@{ */
--      wait_queue_head_t vbl_queue;    /**< VBLANK wait queue */
--      atomic_t vbl_received;
--      atomic_t vbl_received2;         /**< number of secondary VBLANK interrupts */
-+      /*
-+       * At load time, disabling the vblank interrupt won't be allowed since
-+       * old clients may not call the modeset ioctl and therefore misbehave.
-+       * Once the modeset ioctl *has* been called though, we can safely
-+       * disable them when unused.
-+       */
-+      int vblank_disable_allowed;
-+
-+      wait_queue_head_t *vbl_queue;   /**< VBLANK wait queue */
-+      atomic_t *_vblank_count;        /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
-       spinlock_t vbl_lock;
--      struct list_head vbl_sigs;              /**< signal list to send on VBLANK */
--      struct list_head vbl_sigs2;     /**< signals to send on secondary VBLANK */
--      unsigned int vbl_pending;
-+      struct list_head *vbl_sigs;     /**< signal list to send on VBLANK */
-+      atomic_t vbl_signal_pending;    /* number of signals pending on all crtcs*/
-+      atomic_t *vblank_refcount;      /* number of users of vblank interruptsper crtc */
-+      u32 *last_vblank;               /* protected by dev->vbl_lock, used */
-+                                      /* for wraparound handling */
-+      int *vblank_enabled;            /* so we don't call enable more than
-+                                         once per disable */
-+      int *vblank_inmodeset;          /* Display driver is setting mode */
-+      struct timer_list vblank_disable_timer;
-+
-+      u32 max_vblank_count;           /**< size of vblank counter register */
-       spinlock_t tasklet_lock;        /**< For drm_locked_tasklet */
-       void (*locked_tasklet_func)(struct drm_device *dev);
-@@ -757,6 +815,7 @@ struct drm_device {
-       struct pci_controller *hose;
- #endif
-       struct drm_sg_mem *sg;  /**< Scatter gather memory */
-+      int num_crtcs;                  /**< Number of CRTCs on this device */
-       void *dev_private;              /**< device private data */
-       struct drm_sigdata sigdata;        /**< For block_all_signals */
-       sigset_t sigmask;
-@@ -990,10 +1049,19 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
- extern void drm_driver_irq_postinstall(struct drm_device *dev);
- extern void drm_driver_irq_uninstall(struct drm_device *dev);
-+extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
- extern int drm_wait_vblank(struct drm_device *dev, void *data,
--                         struct drm_file *file_priv);
-+                         struct drm_file *filp);
- extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
--extern void drm_vbl_send_signals(struct drm_device *dev);
-+extern void drm_locked_tasklet(struct drm_device *dev,
-+                             void(*func)(struct drm_device *));
-+extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
-+extern void drm_handle_vblank(struct drm_device *dev, int crtc);
-+extern int drm_vblank_get(struct drm_device *dev, int crtc);
-+extern void drm_vblank_put(struct drm_device *dev, int crtc);
-+/* Modesetting support */
-+extern int drm_modeset_ctl(struct drm_device *dev, void *data,
-+                         struct drm_file *file_priv);
- extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
-                               /* AGP/GART support (drm_agpsupport.h) */
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0012-Export-shmem_file_setup-for-DRM-GEM.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0012-Export-shmem_file_setup-for-DRM-GEM.patch
deleted file mode 100644 (file)
index 642d89b..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-commit 48e13db26a25ebaf61f1fc28f612d6b35ddf1965
-Author: Keith Packard <keithp@keithp.com>
-Date:   Fri Jun 20 00:08:06 2008 -0700
-
-    Export shmem_file_setup for DRM-GEM
-    
-    GEM needs to create shmem files to back buffer objects.  Though currently
-    creation of files for objects could have been driven from userland, the
-    modesetting work will require allocation of buffer objects before userland
-    is running, for boot-time message display.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/mm/shmem.c b/mm/shmem.c
-index 04fb4f1..515909d 100644
---- a/mm/shmem.c
-+++ b/mm/shmem.c
-@@ -2582,6 +2582,7 @@ put_memory:
-       shmem_unacct_size(flags, size);
-       return ERR_PTR(error);
- }
-+EXPORT_SYMBOL(shmem_file_setup);
- /**
-  * shmem_zero_setup - setup a shared anonymous mapping
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0013-Export-kmap_atomic_pfn-for-DRM-GEM.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0013-Export-kmap_atomic_pfn-for-DRM-GEM.patch
deleted file mode 100644 (file)
index cc90d46..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-commit 25eaa97fc74b225e13cf11ed8d770192ddc9355d
-Author: Eric Anholt <eric@anholt.net>
-Date:   Thu Aug 21 12:53:33 2008 -0700
-
-    Export kmap_atomic_pfn for DRM-GEM.
-    
-    The driver would like to map IO space directly for copying data in when
-    appropriate, to avoid CPU cache flushing for streaming writes.
-    kmap_atomic_pfn lets us avoid IPIs associated with ioremap for this process.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
-index 165c871..d52e91d 100644
---- a/arch/x86/mm/highmem_32.c
-+++ b/arch/x86/mm/highmem_32.c
-@@ -137,6 +137,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
-       return (void*) vaddr;
- }
-+EXPORT_SYMBOL(kmap_atomic_pfn);
- struct page *kmap_atomic_to_page(void *ptr)
- {
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0014-drm-Add-GEM-graphics-execution-manager-to-i915.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0014-drm-Add-GEM-graphics-execution-manager-to-i915.patch
deleted file mode 100644 (file)
index 95cca5d..0000000
+++ /dev/null
@@ -1,5483 +0,0 @@
-commit c97398223c6a505fac2c783a624dc80e0aa5d5d0
-Author: Eric Anholt <eric@anholt.net>
-Date:   Wed Jul 30 12:06:12 2008 -0700
-
-    drm: Add GEM ("graphics execution manager") to i915 driver.
-    
-    GEM allows the creation of persistent buffer objects accessible by the
-    graphics device through new ioctls for managing execution of commands on the
-    device.  The userland API is almost entirely driver-specific to ensure that
-    any driver building on this model can easily map the interface to individual
-    driver requirements.
-    
-    GEM is used by the 2d driver for managing its internal state allocations and
-    will be used for pixmap storage to reduce memory consumption and enable
-    zero-copy GLX_EXT_texture_from_pixmap, and in the 3d driver is used to enable
-    GL_EXT_framebuffer_object and GL_ARB_pixel_buffer_object.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
-index e9f9a97..74da994 100644
---- a/drivers/gpu/drm/Makefile
-+++ b/drivers/gpu/drm/Makefile
-@@ -4,8 +4,9 @@
- ccflags-y := -Iinclude/drm
--drm-y       :=        drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
--              drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
-+drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
-+              drm_context.o drm_dma.o drm_drawable.o \
-+              drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
-               drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
-               drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
-               drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
-diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c
-index aefa5ac..2639be2 100644
---- a/drivers/gpu/drm/drm_agpsupport.c
-+++ b/drivers/gpu/drm/drm_agpsupport.c
-@@ -33,6 +33,7 @@
- #include "drmP.h"
- #include <linux/module.h>
-+#include <asm/agp.h>
- #if __OS_HAS_AGP
-@@ -452,4 +453,52 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
-       return agp_unbind_memory(handle);
- }
--#endif                                /* __OS_HAS_AGP */
-+/**
-+ * Binds a collection of pages into AGP memory at the given offset, returning
-+ * the AGP memory structure containing them.
-+ *
-+ * No reference is held on the pages during this time -- it is up to the
-+ * caller to handle that.
-+ */
-+DRM_AGP_MEM *
-+drm_agp_bind_pages(struct drm_device *dev,
-+                 struct page **pages,
-+                 unsigned long num_pages,
-+                 uint32_t gtt_offset)
-+{
-+      DRM_AGP_MEM *mem;
-+      int ret, i;
-+
-+      DRM_DEBUG("\n");
-+
-+      mem = drm_agp_allocate_memory(dev->agp->bridge, num_pages,
-+                                    AGP_USER_MEMORY);
-+      if (mem == NULL) {
-+              DRM_ERROR("Failed to allocate memory for %ld pages\n",
-+                        num_pages);
-+              return NULL;
-+      }
-+
-+      for (i = 0; i < num_pages; i++)
-+              mem->memory[i] = phys_to_gart(page_to_phys(pages[i]));
-+      mem->page_count = num_pages;
-+
-+      mem->is_flushed = true;
-+      ret = drm_agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
-+      if (ret != 0) {
-+              DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
-+              agp_free_memory(mem);
-+              return NULL;
-+      }
-+
-+      return mem;
-+}
-+EXPORT_SYMBOL(drm_agp_bind_pages);
-+
-+void drm_agp_chipset_flush(struct drm_device *dev)
-+{
-+      agp_flush_chipset(dev->agp->bridge);
-+}
-+EXPORT_SYMBOL(drm_agp_chipset_flush);
-+
-+#endif /* __OS_HAS_AGP */
-diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
-new file mode 100644
-index 0000000..9475f7d
---- /dev/null
-+++ b/drivers/gpu/drm/drm_cache.c
-@@ -0,0 +1,76 @@
-+/**************************************************************************
-+ *
-+ * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
-+ * All Rights Reserved.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the
-+ * "Software"), to deal in the Software without restriction, including
-+ * without limitation the rights to use, copy, modify, merge, publish,
-+ * distribute, sub license, and/or sell copies of the Software, and to
-+ * permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the
-+ * next paragraph) shall be included in all copies or substantial portions
-+ * of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
-+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ **************************************************************************/
-+/*
-+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
-+ */
-+
-+#include "drmP.h"
-+
-+#if defined(CONFIG_X86)
-+static void
-+drm_clflush_page(struct page *page)
-+{
-+      uint8_t *page_virtual;
-+      unsigned int i;
-+
-+      if (unlikely(page == NULL))
-+              return;
-+
-+      page_virtual = kmap_atomic(page, KM_USER0);
-+      for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
-+              clflush(page_virtual + i);
-+      kunmap_atomic(page_virtual, KM_USER0);
-+}
-+#endif
-+
-+static void
-+drm_clflush_ipi_handler(void *null)
-+{
-+      wbinvd();
-+}
-+
-+void
-+drm_clflush_pages(struct page *pages[], unsigned long num_pages)
-+{
-+
-+#if defined(CONFIG_X86)
-+      if (cpu_has_clflush) {
-+              unsigned long i;
-+
-+              mb();
-+              for (i = 0; i < num_pages; ++i)
-+                      drm_clflush_page(*pages++);
-+              mb();
-+
-+              return;
-+      }
-+#endif
-+
-+      if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
-+              DRM_ERROR("Timed out waiting for cache flush.\n");
-+}
-+EXPORT_SYMBOL(drm_clflush_pages);
-diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
-index fb45fe7..96f416a 100644
---- a/drivers/gpu/drm/drm_drv.c
-+++ b/drivers/gpu/drm/drm_drv.c
-@@ -119,6 +119,10 @@ static struct drm_ioctl_desc drm_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-+
-+      DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
- };
- #define DRM_CORE_IOCTL_COUNT  ARRAY_SIZE( drm_ioctls )
-diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
-index dcf8b4d..0d46627 100644
---- a/drivers/gpu/drm/drm_fops.c
-+++ b/drivers/gpu/drm/drm_fops.c
-@@ -256,6 +256,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
-       INIT_LIST_HEAD(&priv->lhead);
-+      if (dev->driver->driver_features & DRIVER_GEM)
-+              drm_gem_open(dev, priv);
-+
-       if (dev->driver->open) {
-               ret = dev->driver->open(dev, priv);
-               if (ret < 0)
-@@ -400,6 +403,9 @@ int drm_release(struct inode *inode, struct file *filp)
-               dev->driver->reclaim_buffers(dev, file_priv);
-       }
-+      if (dev->driver->driver_features & DRIVER_GEM)
-+              drm_gem_release(dev, file_priv);
-+
-       drm_fasync(-1, filp, 0);
-       mutex_lock(&dev->ctxlist_mutex);
-diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
-new file mode 100644
-index 0000000..434155b
---- /dev/null
-+++ b/drivers/gpu/drm/drm_gem.c
-@@ -0,0 +1,420 @@
-+/*
-+ * Copyright Â© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Eric Anholt <eric@anholt.net>
-+ *
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/mm.h>
-+#include <linux/uaccess.h>
-+#include <linux/fs.h>
-+#include <linux/file.h>
-+#include <linux/module.h>
-+#include <linux/mman.h>
-+#include <linux/pagemap.h>
-+#include "drmP.h"
-+
-+/** @file drm_gem.c
-+ *
-+ * This file provides some of the base ioctls and library routines for
-+ * the graphics memory manager implemented by each device driver.
-+ *
-+ * Because various devices have different requirements in terms of
-+ * synchronization and migration strategies, implementing that is left up to
-+ * the driver, and all that the general API provides should be generic --
-+ * allocating objects, reading/writing data with the cpu, freeing objects.
-+ * Even there, platform-dependent optimizations for reading/writing data with
-+ * the CPU mean we'll likely hook those out to driver-specific calls.  However,
-+ * the DRI2 implementation wants to have at least allocate/mmap be generic.
-+ *
-+ * The goal was to have swap-backed object allocation managed through
-+ * struct file.  However, file descriptors as handles to a struct file have
-+ * two major failings:
-+ * - Process limits prevent more than 1024 or so being used at a time by
-+ *   default.
-+ * - Inability to allocate high fds will aggravate the X Server's select()
-+ *   handling, and likely that of many GL client applications as well.
-+ *
-+ * This led to a plan of using our own integer IDs (called handles, following
-+ * DRM terminology) to mimic fds, and implement the fd syscalls we need as
-+ * ioctls.  The objects themselves will still include the struct file so
-+ * that we can transition to fds if the required kernel infrastructure shows
-+ * up at a later date, and as our interface with shmfs for memory allocation.
-+ */
-+
-+/**
-+ * Initialize the GEM device fields
-+ */
-+
-+int
-+drm_gem_init(struct drm_device *dev)
-+{
-+      spin_lock_init(&dev->object_name_lock);
-+      idr_init(&dev->object_name_idr);
-+      atomic_set(&dev->object_count, 0);
-+      atomic_set(&dev->object_memory, 0);
-+      atomic_set(&dev->pin_count, 0);
-+      atomic_set(&dev->pin_memory, 0);
-+      atomic_set(&dev->gtt_count, 0);
-+      atomic_set(&dev->gtt_memory, 0);
-+      return 0;
-+}
-+
-+/**
-+ * Allocate a GEM object of the specified size with shmfs backing store
-+ */
-+struct drm_gem_object *
-+drm_gem_object_alloc(struct drm_device *dev, size_t size)
-+{
-+      struct drm_gem_object *obj;
-+
-+      BUG_ON((size & (PAGE_SIZE - 1)) != 0);
-+
-+      obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
-+
-+      obj->dev = dev;
-+      obj->filp = shmem_file_setup("drm mm object", size, 0);
-+      if (IS_ERR(obj->filp)) {
-+              kfree(obj);
-+              return NULL;
-+      }
-+
-+      kref_init(&obj->refcount);
-+      kref_init(&obj->handlecount);
-+      obj->size = size;
-+      if (dev->driver->gem_init_object != NULL &&
-+          dev->driver->gem_init_object(obj) != 0) {
-+              fput(obj->filp);
-+              kfree(obj);
-+              return NULL;
-+      }
-+      atomic_inc(&dev->object_count);
-+      atomic_add(obj->size, &dev->object_memory);
-+      return obj;
-+}
-+EXPORT_SYMBOL(drm_gem_object_alloc);
-+
-+/**
-+ * Removes the mapping from handle to filp for this object.
-+ */
-+static int
-+drm_gem_handle_delete(struct drm_file *filp, int handle)
-+{
-+      struct drm_device *dev;
-+      struct drm_gem_object *obj;
-+
-+      /* This is gross. The idr system doesn't let us try a delete and
-+       * return an error code.  It just spews if you fail at deleting.
-+       * So, we have to grab a lock around finding the object and then
-+       * doing the delete on it and dropping the refcount, or the user
-+       * could race us to double-decrement the refcount and cause a
-+       * use-after-free later.  Given the frequency of our handle lookups,
-+       * we may want to use ida for number allocation and a hash table
-+       * for the pointers, anyway.
-+       */
-+      spin_lock(&filp->table_lock);
-+
-+      /* Check if we currently have a reference on the object */
-+      obj = idr_find(&filp->object_idr, handle);
-+      if (obj == NULL) {
-+              spin_unlock(&filp->table_lock);
-+              return -EINVAL;
-+      }
-+      dev = obj->dev;
-+
-+      /* Release reference and decrement refcount. */
-+      idr_remove(&filp->object_idr, handle);
-+      spin_unlock(&filp->table_lock);
-+
-+      mutex_lock(&dev->struct_mutex);
-+      drm_gem_object_handle_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+/**
-+ * Create a handle for this object. This adds a handle reference
-+ * to the object, which includes a regular reference count. Callers
-+ * will likely want to dereference the object afterwards.
-+ */
-+int
-+drm_gem_handle_create(struct drm_file *file_priv,
-+                     struct drm_gem_object *obj,
-+                     int *handlep)
-+{
-+      int     ret;
-+
-+      /*
-+       * Get the user-visible handle using idr.
-+       */
-+again:
-+      /* ensure there is space available to allocate a handle */
-+      if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0)
-+              return -ENOMEM;
-+
-+      /* do the allocation under our spinlock */
-+      spin_lock(&file_priv->table_lock);
-+      ret = idr_get_new_above(&file_priv->object_idr, obj, 1, handlep);
-+      spin_unlock(&file_priv->table_lock);
-+      if (ret == -EAGAIN)
-+              goto again;
-+
-+      if (ret != 0)
-+              return ret;
-+
-+      drm_gem_object_handle_reference(obj);
-+      return 0;
-+}
-+EXPORT_SYMBOL(drm_gem_handle_create);
-+
-+/** Returns a reference to the object named by the handle. */
-+struct drm_gem_object *
-+drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
-+                    int handle)
-+{
-+      struct drm_gem_object *obj;
-+
-+      spin_lock(&filp->table_lock);
-+
-+      /* Check if we currently have a reference on the object */
-+      obj = idr_find(&filp->object_idr, handle);
-+      if (obj == NULL) {
-+              spin_unlock(&filp->table_lock);
-+              return NULL;
-+      }
-+
-+      drm_gem_object_reference(obj);
-+
-+      spin_unlock(&filp->table_lock);
-+
-+      return obj;
-+}
-+EXPORT_SYMBOL(drm_gem_object_lookup);
-+
-+/**
-+ * Releases the handle to an mm object.
-+ */
-+int
-+drm_gem_close_ioctl(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      struct drm_gem_close *args = data;
-+      int ret;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      ret = drm_gem_handle_delete(file_priv, args->handle);
-+
-+      return ret;
-+}
-+
-+/**
-+ * Create a global name for an object, returning the name.
-+ *
-+ * Note that the name does not hold a reference; when the object
-+ * is freed, the name goes away.
-+ */
-+int
-+drm_gem_flink_ioctl(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      struct drm_gem_flink *args = data;
-+      struct drm_gem_object *obj;
-+      int ret;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EINVAL;
-+
-+again:
-+      if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
-+              return -ENOMEM;
-+
-+      spin_lock(&dev->object_name_lock);
-+      if (obj->name) {
-+              spin_unlock(&dev->object_name_lock);
-+              return -EEXIST;
-+      }
-+      ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
-+                               &obj->name);
-+      spin_unlock(&dev->object_name_lock);
-+      if (ret == -EAGAIN)
-+              goto again;
-+
-+      if (ret != 0) {
-+              mutex_lock(&dev->struct_mutex);
-+              drm_gem_object_unreference(obj);
-+              mutex_unlock(&dev->struct_mutex);
-+              return ret;
-+      }
-+
-+      /*
-+       * Leave the reference from the lookup around as the
-+       * name table now holds one
-+       */
-+      args->name = (uint64_t) obj->name;
-+
-+      return 0;
-+}
-+
-+/**
-+ * Open an object using the global name, returning a handle and the size.
-+ *
-+ * This handle (of course) holds a reference to the object, so the object
-+ * will not go away until the handle is deleted.
-+ */
-+int
-+drm_gem_open_ioctl(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_gem_open *args = data;
-+      struct drm_gem_object *obj;
-+      int ret;
-+      int handle;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      spin_lock(&dev->object_name_lock);
-+      obj = idr_find(&dev->object_name_idr, (int) args->name);
-+      if (obj)
-+              drm_gem_object_reference(obj);
-+      spin_unlock(&dev->object_name_lock);
-+      if (!obj)
-+              return -ENOENT;
-+
-+      ret = drm_gem_handle_create(file_priv, obj, &handle);
-+      mutex_lock(&dev->struct_mutex);
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      if (ret)
-+              return ret;
-+
-+      args->handle = handle;
-+      args->size = obj->size;
-+
-+      return 0;
-+}
-+
-+/**
-+ * Called at device open time, sets up the structure for handling refcounting
-+ * of mm objects.
-+ */
-+void
-+drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
-+{
-+      idr_init(&file_private->object_idr);
-+      spin_lock_init(&file_private->table_lock);
-+}
-+
-+/**
-+ * Called at device close to release the file's
-+ * handle references on objects.
-+ */
-+static int
-+drm_gem_object_release_handle(int id, void *ptr, void *data)
-+{
-+      struct drm_gem_object *obj = ptr;
-+
-+      drm_gem_object_handle_unreference(obj);
-+
-+      return 0;
-+}
-+
-+/**
-+ * Called at close time when the filp is going away.
-+ *
-+ * Releases any remaining references on objects by this filp.
-+ */
-+void
-+drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
-+{
-+      mutex_lock(&dev->struct_mutex);
-+      idr_for_each(&file_private->object_idr,
-+                   &drm_gem_object_release_handle, NULL);
-+
-+      idr_destroy(&file_private->object_idr);
-+      mutex_unlock(&dev->struct_mutex);
-+}
-+
-+/**
-+ * Called after the last reference to the object has been lost.
-+ *
-+ * Frees the object
-+ */
-+void
-+drm_gem_object_free(struct kref *kref)
-+{
-+      struct drm_gem_object *obj = (struct drm_gem_object *) kref;
-+      struct drm_device *dev = obj->dev;
-+
-+      BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-+
-+      if (dev->driver->gem_free_object != NULL)
-+              dev->driver->gem_free_object(obj);
-+
-+      fput(obj->filp);
-+      atomic_dec(&dev->object_count);
-+      atomic_sub(obj->size, &dev->object_memory);
-+      kfree(obj);
-+}
-+EXPORT_SYMBOL(drm_gem_object_free);
-+
-+/**
-+ * Called after the last handle to the object has been closed
-+ *
-+ * Removes any name for the object. Note that this must be
-+ * called before drm_gem_object_free or we'll be touching
-+ * freed memory
-+ */
-+void
-+drm_gem_object_handle_free(struct kref *kref)
-+{
-+      struct drm_gem_object *obj = container_of(kref,
-+                                                struct drm_gem_object,
-+                                                handlecount);
-+      struct drm_device *dev = obj->dev;
-+
-+      /* Remove any name for this object */
-+      spin_lock(&dev->object_name_lock);
-+      if (obj->name) {
-+              idr_remove(&dev->object_name_idr, obj->name);
-+              spin_unlock(&dev->object_name_lock);
-+              /*
-+               * The object name held a reference to this object, drop
-+               * that now.
-+               */
-+              drm_gem_object_unreference(obj);
-+      } else
-+              spin_unlock(&dev->object_name_lock);
-+
-+}
-+EXPORT_SYMBOL(drm_gem_object_handle_free);
-+
-diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
-index 0177012..803bc9e 100644
---- a/drivers/gpu/drm/drm_memory.c
-+++ b/drivers/gpu/drm/drm_memory.c
-@@ -133,6 +133,7 @@ int drm_free_agp(DRM_AGP_MEM * handle, int pages)
- {
-       return drm_agp_free_memory(handle) ? 0 : -EINVAL;
- }
-+EXPORT_SYMBOL(drm_free_agp);
- /** Wrapper around agp_bind_memory() */
- int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
-@@ -145,6 +146,7 @@ int drm_unbind_agp(DRM_AGP_MEM * handle)
- {
-       return drm_agp_unbind_memory(handle);
- }
-+EXPORT_SYMBOL(drm_unbind_agp);
- #else  /*  __OS_HAS_AGP  */
- static inline void *agp_remap(unsigned long offset, unsigned long size,
-diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
-index dcff9e9..217ad7d 100644
---- a/drivers/gpu/drm/drm_mm.c
-+++ b/drivers/gpu/drm/drm_mm.c
-@@ -169,6 +169,7 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
-       return child;
- }
-+EXPORT_SYMBOL(drm_mm_get_block);
- /*
-  * Put a block. Merge with the previous and / or next block if they are free.
-@@ -217,6 +218,7 @@ void drm_mm_put_block(struct drm_mm_node * cur)
-               drm_free(cur, sizeof(*cur), DRM_MEM_MM);
-       }
- }
-+EXPORT_SYMBOL(drm_mm_put_block);
- struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
-                                 unsigned long size,
-@@ -265,6 +267,7 @@ int drm_mm_clean(struct drm_mm * mm)
-       return (head->next->next == head);
- }
-+EXPORT_SYMBOL(drm_mm_search_free);
- int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
- {
-@@ -273,7 +276,7 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
-       return drm_mm_create_tail_node(mm, start, size);
- }
--
-+EXPORT_SYMBOL(drm_mm_init);
- void drm_mm_takedown(struct drm_mm * mm)
- {
-diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
-index 93b1e04..d490db4 100644
---- a/drivers/gpu/drm/drm_proc.c
-+++ b/drivers/gpu/drm/drm_proc.c
-@@ -49,6 +49,10 @@ static int drm_queues_info(char *buf, char **start, off_t offset,
-                          int request, int *eof, void *data);
- static int drm_bufs_info(char *buf, char **start, off_t offset,
-                        int request, int *eof, void *data);
-+static int drm_gem_name_info(char *buf, char **start, off_t offset,
-+                           int request, int *eof, void *data);
-+static int drm_gem_object_info(char *buf, char **start, off_t offset,
-+                             int request, int *eof, void *data);
- #if DRM_DEBUG_CODE
- static int drm_vma_info(char *buf, char **start, off_t offset,
-                       int request, int *eof, void *data);
-@@ -60,13 +64,16 @@ static int drm_vma_info(char *buf, char **start, off_t offset,
- static struct drm_proc_list {
-       const char *name;       /**< file name */
-       int (*f) (char *, char **, off_t, int, int *, void *);          /**< proc callback*/
-+      u32 driver_features; /**< Required driver features for this entry */
- } drm_proc_list[] = {
--      {"name", drm_name_info},
--      {"mem", drm_mem_info},
--      {"vm", drm_vm_info},
--      {"clients", drm_clients_info},
--      {"queues", drm_queues_info},
--      {"bufs", drm_bufs_info},
-+      {"name", drm_name_info, 0},
-+      {"mem", drm_mem_info, 0},
-+      {"vm", drm_vm_info, 0},
-+      {"clients", drm_clients_info, 0},
-+      {"queues", drm_queues_info, 0},
-+      {"bufs", drm_bufs_info, 0},
-+      {"gem_names", drm_gem_name_info, DRIVER_GEM},
-+      {"gem_objects", drm_gem_object_info, DRIVER_GEM},
- #if DRM_DEBUG_CODE
-       {"vma", drm_vma_info},
- #endif
-@@ -90,8 +97,9 @@ static struct drm_proc_list {
- int drm_proc_init(struct drm_minor *minor, int minor_id,
-                 struct proc_dir_entry *root)
- {
-+      struct drm_device *dev = minor->dev;
-       struct proc_dir_entry *ent;
--      int i, j;
-+      int i, j, ret;
-       char name[64];
-       sprintf(name, "%d", minor_id);
-@@ -102,23 +110,42 @@ int drm_proc_init(struct drm_minor *minor, int minor_id,
-       }
-       for (i = 0; i < DRM_PROC_ENTRIES; i++) {
-+              u32 features = drm_proc_list[i].driver_features;
-+
-+              if (features != 0 &&
-+                  (dev->driver->driver_features & features) != features)
-+                      continue;
-+
-               ent = create_proc_entry(drm_proc_list[i].name,
-                                       S_IFREG | S_IRUGO, minor->dev_root);
-               if (!ent) {
-                       DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
-                                 name, drm_proc_list[i].name);
--                      for (j = 0; j < i; j++)
--                              remove_proc_entry(drm_proc_list[i].name,
--                                                minor->dev_root);
--                      remove_proc_entry(name, root);
--                      minor->dev_root = NULL;
--                      return -1;
-+                      ret = -1;
-+                      goto fail;
-               }
-               ent->read_proc = drm_proc_list[i].f;
-               ent->data = minor;
-       }
-+      if (dev->driver->proc_init) {
-+              ret = dev->driver->proc_init(minor);
-+              if (ret) {
-+                      DRM_ERROR("DRM: Driver failed to initialize "
-+                                "/proc/dri.\n");
-+                      goto fail;
-+              }
-+      }
-+
-       return 0;
-+ fail:
-+
-+      for (j = 0; j < i; j++)
-+              remove_proc_entry(drm_proc_list[i].name,
-+                                minor->dev_root);
-+      remove_proc_entry(name, root);
-+      minor->dev_root = NULL;
-+      return ret;
- }
- /**
-@@ -133,12 +160,16 @@ int drm_proc_init(struct drm_minor *minor, int minor_id,
-  */
- int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
- {
-+      struct drm_device *dev = minor->dev;
-       int i;
-       char name[64];
-       if (!root || !minor->dev_root)
-               return 0;
-+      if (dev->driver->proc_cleanup)
-+              dev->driver->proc_cleanup(minor);
-+
-       for (i = 0; i < DRM_PROC_ENTRIES; i++)
-               remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
-       sprintf(name, "%d", minor->index);
-@@ -480,6 +511,84 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
-       return ret;
- }
-+struct drm_gem_name_info_data {
-+       int                     len;
-+       char                    *buf;
-+       int                     eof;
-+};
-+
-+static int drm_gem_one_name_info(int id, void *ptr, void *data)
-+{
-+      struct drm_gem_object *obj = ptr;
-+      struct drm_gem_name_info_data   *nid = data;
-+
-+      DRM_INFO("name %d size %d\n", obj->name, obj->size);
-+      if (nid->eof)
-+              return 0;
-+
-+      nid->len += sprintf(&nid->buf[nid->len],
-+                          "%6d%9d%8d%9d\n",
-+                          obj->name, obj->size,
-+                          atomic_read(&obj->handlecount.refcount),
-+                          atomic_read(&obj->refcount.refcount));
-+      if (nid->len > DRM_PROC_LIMIT) {
-+              nid->eof = 1;
-+              return 0;
-+      }
-+      return 0;
-+}
-+
-+static int drm_gem_name_info(char *buf, char **start, off_t offset,
-+                           int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      struct drm_gem_name_info_data nid;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      nid.len = sprintf(buf, "  name     size handles refcount\n");
-+      nid.buf = buf;
-+      nid.eof = 0;
-+      idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, &nid);
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      if (nid.len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return nid.len - offset;
-+}
-+
-+static int drm_gem_object_info(char *buf, char **start, off_t offset,
-+                             int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("%d objects\n", atomic_read(&dev->object_count));
-+      DRM_PROC_PRINT("%d object bytes\n", atomic_read(&dev->object_memory));
-+      DRM_PROC_PRINT("%d pinned\n", atomic_read(&dev->pin_count));
-+      DRM_PROC_PRINT("%d pin bytes\n", atomic_read(&dev->pin_memory));
-+      DRM_PROC_PRINT("%d gtt bytes\n", atomic_read(&dev->gtt_memory));
-+      DRM_PROC_PRINT("%d gtt total\n", dev->gtt_total);
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
- #if DRM_DEBUG_CODE
- static int drm__vma_info(char *buf, char **start, off_t offset, int request,
-diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
-index c2f584f..82f4657 100644
---- a/drivers/gpu/drm/drm_stub.c
-+++ b/drivers/gpu/drm/drm_stub.c
-@@ -152,6 +152,15 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
-               goto error_out_unreg;
-       }
-+      if (driver->driver_features & DRIVER_GEM) {
-+              retcode = drm_gem_init(dev);
-+              if (retcode) {
-+                      DRM_ERROR("Cannot initialize graphics execution "
-+                                "manager (GEM)\n");
-+                      goto error_out_unreg;
-+              }
-+      }
-+
-       return 0;
-       error_out_unreg:
-@@ -317,6 +326,7 @@ int drm_put_dev(struct drm_device * dev)
- int drm_put_minor(struct drm_minor **minor_p)
- {
-       struct drm_minor *minor = *minor_p;
-+
-       DRM_DEBUG("release secondary minor %d\n", minor->index);
-       if (minor->type == DRM_MINOR_LEGACY)
-diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
-index c4bbda6..5ba78e4 100644
---- a/drivers/gpu/drm/i915/Makefile
-+++ b/drivers/gpu/drm/i915/Makefile
-@@ -4,7 +4,11 @@
- ccflags-y := -Iinclude/drm
- i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o \
--          i915_suspend.o
-+          i915_suspend.o \
-+        i915_gem.o \
-+        i915_gem_debug.o \
-+        i915_gem_proc.o \
-+        i915_gem_tiling.o
- i915-$(CONFIG_COMPAT)   += i915_ioc32.o
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 8609ec2..3b5aa74 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -170,24 +170,31 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
-       dev_priv->sarea_priv = (drm_i915_sarea_t *)
-           ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
--      dev_priv->ring.Start = init->ring_start;
--      dev_priv->ring.End = init->ring_end;
--      dev_priv->ring.Size = init->ring_size;
--      dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-+      if (init->ring_size != 0) {
-+              if (dev_priv->ring.ring_obj != NULL) {
-+                      i915_dma_cleanup(dev);
-+                      DRM_ERROR("Client tried to initialize ringbuffer in "
-+                                "GEM mode\n");
-+                      return -EINVAL;
-+              }
--      dev_priv->ring.map.offset = init->ring_start;
--      dev_priv->ring.map.size = init->ring_size;
--      dev_priv->ring.map.type = 0;
--      dev_priv->ring.map.flags = 0;
--      dev_priv->ring.map.mtrr = 0;
-+              dev_priv->ring.Size = init->ring_size;
-+              dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
--      drm_core_ioremap(&dev_priv->ring.map, dev);
-+              dev_priv->ring.map.offset = init->ring_start;
-+              dev_priv->ring.map.size = init->ring_size;
-+              dev_priv->ring.map.type = 0;
-+              dev_priv->ring.map.flags = 0;
-+              dev_priv->ring.map.mtrr = 0;
--      if (dev_priv->ring.map.handle == NULL) {
--              i915_dma_cleanup(dev);
--              DRM_ERROR("can not ioremap virtual address for"
--                        " ring buffer\n");
--              return -ENOMEM;
-+              drm_core_ioremap(&dev_priv->ring.map, dev);
-+
-+              if (dev_priv->ring.map.handle == NULL) {
-+                      i915_dma_cleanup(dev);
-+                      DRM_ERROR("can not ioremap virtual address for"
-+                                " ring buffer\n");
-+                      return -ENOMEM;
-+              }
-       }
-       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-@@ -377,9 +384,10 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor
-       return 0;
- }
--static int i915_emit_box(struct drm_device * dev,
--                       struct drm_clip_rect __user * boxes,
--                       int i, int DR1, int DR4)
-+int
-+i915_emit_box(struct drm_device *dev,
-+            struct drm_clip_rect __user *boxes,
-+            int i, int DR1, int DR4)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_clip_rect box;
-@@ -681,6 +689,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
-       case I915_PARAM_LAST_DISPATCH:
-               value = READ_BREADCRUMB(dev_priv);
-               break;
-+      case I915_PARAM_HAS_GEM:
-+              value = 1;
-+              break;
-       default:
-               DRM_ERROR("Unknown parameter %d\n", param->param);
-               return -EINVAL;
-@@ -784,6 +795,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
-       memset(dev_priv, 0, sizeof(drm_i915_private_t));
-       dev->dev_private = (void *)dev_priv;
-+      dev_priv->dev = dev;
-       /* Add register map (needed for suspend/resume) */
-       base = drm_get_resource_start(dev, mmio_bar);
-@@ -793,6 +805,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
-                        _DRM_KERNEL | _DRM_DRIVER,
-                        &dev_priv->mmio_map);
-+      i915_gem_load(dev);
-+
-       /* Init HWS */
-       if (!I915_NEED_GFX_HWS(dev)) {
-               ret = i915_init_phys_hws(dev);
-@@ -838,6 +852,25 @@ int i915_driver_unload(struct drm_device *dev)
-       return 0;
- }
-+int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
-+{
-+      struct drm_i915_file_private *i915_file_priv;
-+
-+      DRM_DEBUG("\n");
-+      i915_file_priv = (struct drm_i915_file_private *)
-+          drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
-+
-+      if (!i915_file_priv)
-+              return -ENOMEM;
-+
-+      file_priv->driver_priv = i915_file_priv;
-+
-+      i915_file_priv->mm.last_gem_seqno = 0;
-+      i915_file_priv->mm.last_gem_throttle_seqno = 0;
-+
-+      return 0;
-+}
-+
- void i915_driver_lastclose(struct drm_device * dev)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-@@ -845,6 +878,8 @@ void i915_driver_lastclose(struct drm_device * dev)
-       if (!dev_priv)
-               return;
-+      i915_gem_lastclose(dev);
-+
-       if (dev_priv->agp_heap)
-               i915_mem_takedown(&(dev_priv->agp_heap));
-@@ -857,6 +892,13 @@ void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
-       i915_mem_release(dev, file_priv, dev_priv->agp_heap);
- }
-+void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
-+{
-+      struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
-+
-+      drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
-+}
-+
- struct drm_ioctl_desc i915_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
-@@ -875,6 +917,22 @@ struct drm_ioctl_desc i915_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
-       DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
-+      DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
- };
- int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
-diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
-index 37af03f..a80ead2 100644
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -85,12 +85,15 @@ static struct drm_driver driver = {
-       /* don't use mtrr's here, the Xserver or user space app should
-        * deal with them for intel hardware.
-        */
--      .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
--              DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
-+      .driver_features =
-+          DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
-+          DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
-       .load = i915_driver_load,
-       .unload = i915_driver_unload,
-+      .open = i915_driver_open,
-       .lastclose = i915_driver_lastclose,
-       .preclose = i915_driver_preclose,
-+      .postclose = i915_driver_postclose,
-       .suspend = i915_suspend,
-       .resume = i915_resume,
-       .device_is_agp = i915_driver_device_is_agp,
-@@ -104,6 +107,10 @@ static struct drm_driver driver = {
-       .reclaim_buffers = drm_core_reclaim_buffers,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-+      .proc_init = i915_gem_proc_init,
-+      .proc_cleanup = i915_gem_proc_cleanup,
-+      .gem_init_object = i915_gem_init_object,
-+      .gem_free_object = i915_gem_free_object,
-       .ioctls = i915_ioctls,
-       .fops = {
-                .owner = THIS_MODULE,
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index d1a02be..87b071a 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -39,7 +39,7 @@
- #define DRIVER_NAME           "i915"
- #define DRIVER_DESC           "Intel Graphics"
--#define DRIVER_DATE           "20060119"
-+#define DRIVER_DATE           "20080730"
- enum pipe {
-       PIPE_A = 0,
-@@ -60,16 +60,23 @@ enum pipe {
- #define DRIVER_MINOR          6
- #define DRIVER_PATCHLEVEL     0
-+#define WATCH_COHERENCY       0
-+#define WATCH_BUF     0
-+#define WATCH_EXEC    0
-+#define WATCH_LRU     0
-+#define WATCH_RELOC   0
-+#define WATCH_INACTIVE        0
-+#define WATCH_PWRITE  0
-+
- typedef struct _drm_i915_ring_buffer {
-       int tail_mask;
--      unsigned long Start;
--      unsigned long End;
-       unsigned long Size;
-       u8 *virtual_start;
-       int head;
-       int tail;
-       int space;
-       drm_local_map_t map;
-+      struct drm_gem_object *ring_obj;
- } drm_i915_ring_buffer_t;
- struct mem_block {
-@@ -101,6 +108,8 @@ struct intel_opregion {
- };
- typedef struct drm_i915_private {
-+      struct drm_device *dev;
-+
-       drm_local_map_t *sarea;
-       drm_local_map_t *mmio_map;
-@@ -113,6 +122,7 @@ typedef struct drm_i915_private {
-       uint32_t counter;
-       unsigned int status_gfx_addr;
-       drm_local_map_t hws_map;
-+      struct drm_gem_object *hws_obj;
-       unsigned int cpp;
-       int back_offset;
-@@ -122,7 +132,6 @@ typedef struct drm_i915_private {
-       wait_queue_head_t irq_queue;
-       atomic_t irq_received;
--      atomic_t irq_emitted;
-       /** Protects user_irq_refcount and irq_mask_reg */
-       spinlock_t user_irq_lock;
-       /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
-@@ -230,8 +239,174 @@ typedef struct drm_i915_private {
-       u8 saveDACMASK;
-       u8 saveDACDATA[256*3]; /* 256 3-byte colors */
-       u8 saveCR[37];
-+
-+      struct {
-+              struct drm_mm gtt_space;
-+
-+              /**
-+               * List of objects currently involved in rendering from the
-+               * ringbuffer.
-+               *
-+               * A reference is held on the buffer while on this list.
-+               */
-+              struct list_head active_list;
-+
-+              /**
-+               * List of objects which are not in the ringbuffer but which
-+               * still have a write_domain which needs to be flushed before
-+               * unbinding.
-+               *
-+               * A reference is held on the buffer while on this list.
-+               */
-+              struct list_head flushing_list;
-+
-+              /**
-+               * LRU list of objects which are not in the ringbuffer and
-+               * are ready to unbind, but are still in the GTT.
-+               *
-+               * A reference is not held on the buffer while on this list,
-+               * as merely being GTT-bound shouldn't prevent its being
-+               * freed, and we'll pull it off the list in the free path.
-+               */
-+              struct list_head inactive_list;
-+
-+              /**
-+               * List of breadcrumbs associated with GPU requests currently
-+               * outstanding.
-+               */
-+              struct list_head request_list;
-+
-+              /**
-+               * We leave the user IRQ off as much as possible,
-+               * but this means that requests will finish and never
-+               * be retired once the system goes idle. Set a timer to
-+               * fire periodically while the ring is running. When it
-+               * fires, go retire requests.
-+               */
-+              struct delayed_work retire_work;
-+
-+              uint32_t next_gem_seqno;
-+
-+              /**
-+               * Waiting sequence number, if any
-+               */
-+              uint32_t waiting_gem_seqno;
-+
-+              /**
-+               * Last seq seen at irq time
-+               */
-+              uint32_t irq_gem_seqno;
-+
-+              /**
-+               * Flag if the X Server, and thus DRM, is not currently in
-+               * control of the device.
-+               *
-+               * This is set between LeaveVT and EnterVT.  It needs to be
-+               * replaced with a semaphore.  It also needs to be
-+               * transitioned away from for kernel modesetting.
-+               */
-+              int suspended;
-+
-+              /**
-+               * Flag if the hardware appears to be wedged.
-+               *
-+               * This is set when attempts to idle the device timeout.
-+               * It prevents command submission from occuring and makes
-+               * every pending request fail
-+               */
-+              int wedged;
-+
-+              /** Bit 6 swizzling required for X tiling */
-+              uint32_t bit_6_swizzle_x;
-+              /** Bit 6 swizzling required for Y tiling */
-+              uint32_t bit_6_swizzle_y;
-+      } mm;
- } drm_i915_private_t;
-+/** driver private structure attached to each drm_gem_object */
-+struct drm_i915_gem_object {
-+      struct drm_gem_object *obj;
-+
-+      /** Current space allocated to this object in the GTT, if any. */
-+      struct drm_mm_node *gtt_space;
-+
-+      /** This object's place on the active/flushing/inactive lists */
-+      struct list_head list;
-+
-+      /**
-+       * This is set if the object is on the active or flushing lists
-+       * (has pending rendering), and is not set if it's on inactive (ready
-+       * to be unbound).
-+       */
-+      int active;
-+
-+      /**
-+       * This is set if the object has been written to since last bound
-+       * to the GTT
-+       */
-+      int dirty;
-+
-+      /** AGP memory structure for our GTT binding. */
-+      DRM_AGP_MEM *agp_mem;
-+
-+      struct page **page_list;
-+
-+      /**
-+       * Current offset of the object in GTT space.
-+       *
-+       * This is the same as gtt_space->start
-+       */
-+      uint32_t gtt_offset;
-+
-+      /** Boolean whether this object has a valid gtt offset. */
-+      int gtt_bound;
-+
-+      /** How many users have pinned this object in GTT space */
-+      int pin_count;
-+
-+      /** Breadcrumb of last rendering to the buffer. */
-+      uint32_t last_rendering_seqno;
-+
-+      /** Current tiling mode for the object. */
-+      uint32_t tiling_mode;
-+
-+      /**
-+       * Flagging of which individual pages are valid in GEM_DOMAIN_CPU when
-+       * GEM_DOMAIN_CPU is not in the object's read domain.
-+       */
-+      uint8_t *page_cpu_valid;
-+};
-+
-+/**
-+ * Request queue structure.
-+ *
-+ * The request queue allows us to note sequence numbers that have been emitted
-+ * and may be associated with active buffers to be retired.
-+ *
-+ * By keeping this list, we can avoid having to do questionable
-+ * sequence-number comparisons on buffer last_rendering_seqnos, and associate
-+ * an emission time with seqnos for tracking how far ahead of the GPU we are.
-+ */
-+struct drm_i915_gem_request {
-+      /** GEM sequence number associated with this request. */
-+      uint32_t seqno;
-+
-+      /** Time at which this request was emitted, in jiffies. */
-+      unsigned long emitted_jiffies;
-+
-+      /** Cache domains that were flushed at the start of the request. */
-+      uint32_t flush_domains;
-+
-+      struct list_head list;
-+};
-+
-+struct drm_i915_file_private {
-+      struct {
-+              uint32_t last_gem_seqno;
-+              uint32_t last_gem_throttle_seqno;
-+      } mm;
-+};
-+
- extern struct drm_ioctl_desc i915_ioctls[];
- extern int i915_max_ioctl;
-@@ -239,18 +414,26 @@ extern int i915_max_ioctl;
- extern void i915_kernel_lost_context(struct drm_device * dev);
- extern int i915_driver_load(struct drm_device *, unsigned long flags);
- extern int i915_driver_unload(struct drm_device *);
-+extern int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv);
- extern void i915_driver_lastclose(struct drm_device * dev);
- extern void i915_driver_preclose(struct drm_device *dev,
-                                struct drm_file *file_priv);
-+extern void i915_driver_postclose(struct drm_device *dev,
-+                                struct drm_file *file_priv);
- extern int i915_driver_device_is_agp(struct drm_device * dev);
- extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
-                             unsigned long arg);
-+extern int i915_emit_box(struct drm_device *dev,
-+                       struct drm_clip_rect __user *boxes,
-+                       int i, int DR1, int DR4);
- /* i915_irq.c */
- extern int i915_irq_emit(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
- extern int i915_irq_wait(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-+void i915_user_irq_get(struct drm_device *dev);
-+void i915_user_irq_put(struct drm_device *dev);
- extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
- extern void i915_driver_irq_preinstall(struct drm_device * dev);
-@@ -279,6 +462,67 @@ extern int i915_mem_destroy_heap(struct drm_device *dev, void *data,
- extern void i915_mem_takedown(struct mem_block **heap);
- extern void i915_mem_release(struct drm_device * dev,
-                            struct drm_file *file_priv, struct mem_block *heap);
-+/* i915_gem.c */
-+int i915_gem_init_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_create_ioctl(struct drm_device *dev, void *data,
-+                        struct drm_file *file_priv);
-+int i915_gem_pread_ioctl(struct drm_device *dev, void *data,
-+                       struct drm_file *file_priv);
-+int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
-+                        struct drm_file *file_priv);
-+int i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
-+                            struct drm_file *file_priv);
-+int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
-+                           struct drm_file *file_priv);
-+int i915_gem_execbuffer(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_pin_ioctl(struct drm_device *dev, void *data,
-+                     struct drm_file *file_priv);
-+int i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
-+                       struct drm_file *file_priv);
-+int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
-+                          struct drm_file *file_priv);
-+int i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
-+                         struct drm_file *file_priv);
-+int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
-+                         struct drm_file *file_priv);
-+int i915_gem_set_tiling(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int i915_gem_get_tiling(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+void i915_gem_load(struct drm_device *dev);
-+int i915_gem_proc_init(struct drm_minor *minor);
-+void i915_gem_proc_cleanup(struct drm_minor *minor);
-+int i915_gem_init_object(struct drm_gem_object *obj);
-+void i915_gem_free_object(struct drm_gem_object *obj);
-+int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
-+void i915_gem_object_unpin(struct drm_gem_object *obj);
-+void i915_gem_lastclose(struct drm_device *dev);
-+uint32_t i915_get_gem_seqno(struct drm_device *dev);
-+void i915_gem_retire_requests(struct drm_device *dev);
-+void i915_gem_retire_work_handler(struct work_struct *work);
-+void i915_gem_clflush_object(struct drm_gem_object *obj);
-+
-+/* i915_gem_tiling.c */
-+void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
-+
-+/* i915_gem_debug.c */
-+void i915_gem_dump_object(struct drm_gem_object *obj, int len,
-+                        const char *where, uint32_t mark);
-+#if WATCH_INACTIVE
-+void i915_verify_inactive(struct drm_device *dev, char *file, int line);
-+#else
-+#define i915_verify_inactive(dev, file, line)
-+#endif
-+void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle);
-+void i915_gem_dump_object(struct drm_gem_object *obj, int len,
-+                        const char *where, uint32_t mark);
-+void i915_dump_lru(struct drm_device *dev, const char *where);
- /* i915_suspend.c */
- extern int i915_save_state(struct drm_device *dev);
-@@ -347,6 +591,7 @@ extern void opregion_enable_asle(struct drm_device *dev);
-  */
- #define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
- #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, 5)
-+#define I915_GEM_HWS_INDEX            0x10
- extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-new file mode 100644
-index 0000000..90ae8a0
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -0,0 +1,2497 @@
-+/*
-+ * Copyright Â© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Eric Anholt <eric@anholt.net>
-+ *
-+ */
-+
-+#include "drmP.h"
-+#include "drm.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+#include <linux/swap.h>
-+
-+static int
-+i915_gem_object_set_domain(struct drm_gem_object *obj,
-+                          uint32_t read_domains,
-+                          uint32_t write_domain);
-+static int
-+i915_gem_object_set_domain_range(struct drm_gem_object *obj,
-+                               uint64_t offset,
-+                               uint64_t size,
-+                               uint32_t read_domains,
-+                               uint32_t write_domain);
-+static int
-+i915_gem_set_domain(struct drm_gem_object *obj,
-+                  struct drm_file *file_priv,
-+                  uint32_t read_domains,
-+                  uint32_t write_domain);
-+static int i915_gem_object_get_page_list(struct drm_gem_object *obj);
-+static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
-+static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
-+
-+int
-+i915_gem_init_ioctl(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_init *args = data;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      if (args->gtt_start >= args->gtt_end ||
-+          (args->gtt_start & (PAGE_SIZE - 1)) != 0 ||
-+          (args->gtt_end & (PAGE_SIZE - 1)) != 0) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EINVAL;
-+      }
-+
-+      drm_mm_init(&dev_priv->mm.gtt_space, args->gtt_start,
-+          args->gtt_end - args->gtt_start);
-+
-+      dev->gtt_total = (uint32_t) (args->gtt_end - args->gtt_start);
-+
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+
-+/**
-+ * Creates a new mm object and returns a handle to it.
-+ */
-+int
-+i915_gem_create_ioctl(struct drm_device *dev, void *data,
-+                    struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_create *args = data;
-+      struct drm_gem_object *obj;
-+      int handle, ret;
-+
-+      args->size = roundup(args->size, PAGE_SIZE);
-+
-+      /* Allocate the new object */
-+      obj = drm_gem_object_alloc(dev, args->size);
-+      if (obj == NULL)
-+              return -ENOMEM;
-+
-+      ret = drm_gem_handle_create(file_priv, obj, &handle);
-+      mutex_lock(&dev->struct_mutex);
-+      drm_gem_object_handle_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      if (ret)
-+              return ret;
-+
-+      args->handle = handle;
-+
-+      return 0;
-+}
-+
-+/**
-+ * Reads data from the object referenced by handle.
-+ *
-+ * On error, the contents of *data are undefined.
-+ */
-+int
-+i915_gem_pread_ioctl(struct drm_device *dev, void *data,
-+                   struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_pread *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      ssize_t read;
-+      loff_t offset;
-+      int ret;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EBADF;
-+      obj_priv = obj->driver_private;
-+
-+      /* Bounds check source.
-+       *
-+       * XXX: This could use review for overflow issues...
-+       */
-+      if (args->offset > obj->size || args->size > obj->size ||
-+          args->offset + args->size > obj->size) {
-+              drm_gem_object_unreference(obj);
-+              return -EINVAL;
-+      }
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      ret = i915_gem_object_set_domain_range(obj, args->offset, args->size,
-+                                             I915_GEM_DOMAIN_CPU, 0);
-+      if (ret != 0) {
-+              drm_gem_object_unreference(obj);
-+              mutex_unlock(&dev->struct_mutex);
-+      }
-+
-+      offset = args->offset;
-+
-+      read = vfs_read(obj->filp, (char __user *)(uintptr_t)args->data_ptr,
-+                      args->size, &offset);
-+      if (read != args->size) {
-+              drm_gem_object_unreference(obj);
-+              mutex_unlock(&dev->struct_mutex);
-+              if (read < 0)
-+                      return read;
-+              else
-+                      return -EINVAL;
-+      }
-+
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+static int
-+i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-+                  struct drm_i915_gem_pwrite *args,
-+                  struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      ssize_t remain;
-+      loff_t offset;
-+      char __user *user_data;
-+      char *vaddr;
-+      int i, o, l;
-+      int ret = 0;
-+      unsigned long pfn;
-+      unsigned long unwritten;
-+
-+      user_data = (char __user *) (uintptr_t) args->data_ptr;
-+      remain = args->size;
-+      if (!access_ok(VERIFY_READ, user_data, remain))
-+              return -EFAULT;
-+
-+
-+      mutex_lock(&dev->struct_mutex);
-+      ret = i915_gem_object_pin(obj, 0);
-+      if (ret) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return ret;
-+      }
-+      ret = i915_gem_set_domain(obj, file_priv,
-+                                I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
-+      if (ret)
-+              goto fail;
-+
-+      obj_priv = obj->driver_private;
-+      offset = obj_priv->gtt_offset + args->offset;
-+      obj_priv->dirty = 1;
-+
-+      while (remain > 0) {
-+              /* Operation in this page
-+               *
-+               * i = page number
-+               * o = offset within page
-+               * l = bytes to copy
-+               */
-+              i = offset >> PAGE_SHIFT;
-+              o = offset & (PAGE_SIZE-1);
-+              l = remain;
-+              if ((o + l) > PAGE_SIZE)
-+                      l = PAGE_SIZE - o;
-+
-+              pfn = (dev->agp->base >> PAGE_SHIFT) + i;
-+
-+#ifdef CONFIG_HIGHMEM
-+              /* kmap_atomic can't map IO pages on non-HIGHMEM kernels
-+               */
-+              vaddr = kmap_atomic_pfn(pfn, KM_USER0);
-+#if WATCH_PWRITE
-+              DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n",
-+                       i, o, l, pfn, vaddr);
-+#endif
-+              unwritten = __copy_from_user_inatomic_nocache(vaddr + o,
-+                                                            user_data, l);
-+              kunmap_atomic(vaddr, KM_USER0);
-+
-+              if (unwritten)
-+#endif /* CONFIG_HIGHMEM */
-+              {
-+                      vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
-+#if WATCH_PWRITE
-+                      DRM_INFO("pwrite slow i %d o %d l %d "
-+                               "pfn %ld vaddr %p\n",
-+                               i, o, l, pfn, vaddr);
-+#endif
-+                      if (vaddr == NULL) {
-+                              ret = -EFAULT;
-+                              goto fail;
-+                      }
-+                      unwritten = __copy_from_user(vaddr + o, user_data, l);
-+#if WATCH_PWRITE
-+                      DRM_INFO("unwritten %ld\n", unwritten);
-+#endif
-+                      iounmap(vaddr);
-+                      if (unwritten) {
-+                              ret = -EFAULT;
-+                              goto fail;
-+                      }
-+              }
-+
-+              remain -= l;
-+              user_data += l;
-+              offset += l;
-+      }
-+#if WATCH_PWRITE && 1
-+      i915_gem_clflush_object(obj);
-+      i915_gem_dump_object(obj, args->offset + args->size, __func__, ~0);
-+      i915_gem_clflush_object(obj);
-+#endif
-+
-+fail:
-+      i915_gem_object_unpin(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return ret;
-+}
-+
-+int
-+i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-+                    struct drm_i915_gem_pwrite *args,
-+                    struct drm_file *file_priv)
-+{
-+      int ret;
-+      loff_t offset;
-+      ssize_t written;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      ret = i915_gem_set_domain(obj, file_priv,
-+                                I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
-+      if (ret) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return ret;
-+      }
-+
-+      offset = args->offset;
-+
-+      written = vfs_write(obj->filp,
-+                          (char __user *)(uintptr_t) args->data_ptr,
-+                          args->size, &offset);
-+      if (written != args->size) {
-+              mutex_unlock(&dev->struct_mutex);
-+              if (written < 0)
-+                      return written;
-+              else
-+                      return -EINVAL;
-+      }
-+
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+/**
-+ * Writes data to the object referenced by handle.
-+ *
-+ * On error, the contents of the buffer that were to be modified are undefined.
-+ */
-+int
-+i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
-+                    struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_pwrite *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret = 0;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EBADF;
-+      obj_priv = obj->driver_private;
-+
-+      /* Bounds check destination.
-+       *
-+       * XXX: This could use review for overflow issues...
-+       */
-+      if (args->offset > obj->size || args->size > obj->size ||
-+          args->offset + args->size > obj->size) {
-+              drm_gem_object_unreference(obj);
-+              return -EINVAL;
-+      }
-+
-+      /* We can only do the GTT pwrite on untiled buffers, as otherwise
-+       * it would end up going through the fenced access, and we'll get
-+       * different detiling behavior between reading and writing.
-+       * pread/pwrite currently are reading and writing from the CPU
-+       * perspective, requiring manual detiling by the client.
-+       */
-+      if (obj_priv->tiling_mode == I915_TILING_NONE &&
-+          dev->gtt_total != 0)
-+              ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv);
-+      else
-+              ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv);
-+
-+#if WATCH_PWRITE
-+      if (ret)
-+              DRM_INFO("pwrite failed %d\n", ret);
-+#endif
-+
-+      drm_gem_object_unreference(obj);
-+
-+      return ret;
-+}
-+
-+/**
-+ * Called when user space prepares to use an object
-+ */
-+int
-+i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
-+                        struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_set_domain *args = data;
-+      struct drm_gem_object *obj;
-+      int ret;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EBADF;
-+
-+      mutex_lock(&dev->struct_mutex);
-+#if WATCH_BUF
-+      DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n",
-+               obj, obj->size, args->read_domains, args->write_domain);
-+#endif
-+      ret = i915_gem_set_domain(obj, file_priv,
-+                                args->read_domains, args->write_domain);
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      return ret;
-+}
-+
-+/**
-+ * Called when user space has done writes to this buffer
-+ */
-+int
-+i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
-+                    struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_sw_finish *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret = 0;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBADF;
-+      }
-+
-+#if WATCH_BUF
-+      DRM_INFO("%s: sw_finish %d (%p %d)\n",
-+               __func__, args->handle, obj, obj->size);
-+#endif
-+      obj_priv = obj->driver_private;
-+
-+      /* Pinned buffers may be scanout, so flush the cache */
-+      if ((obj->write_domain & I915_GEM_DOMAIN_CPU) && obj_priv->pin_count) {
-+              i915_gem_clflush_object(obj);
-+              drm_agp_chipset_flush(dev);
-+      }
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      return ret;
-+}
-+
-+/**
-+ * Maps the contents of an object, returning the address it is mapped
-+ * into.
-+ *
-+ * While the mapping holds a reference on the contents of the object, it doesn't
-+ * imply a ref on the object itself.
-+ */
-+int
-+i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_mmap *args = data;
-+      struct drm_gem_object *obj;
-+      loff_t offset;
-+      unsigned long addr;
-+
-+      if (!(dev->driver->driver_features & DRIVER_GEM))
-+              return -ENODEV;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EBADF;
-+
-+      offset = args->offset;
-+
-+      down_write(&current->mm->mmap_sem);
-+      addr = do_mmap(obj->filp, 0, args->size,
-+                     PROT_READ | PROT_WRITE, MAP_SHARED,
-+                     args->offset);
-+      up_write(&current->mm->mmap_sem);
-+      mutex_lock(&dev->struct_mutex);
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      if (IS_ERR((void *)addr))
-+              return addr;
-+
-+      args->addr_ptr = (uint64_t) addr;
-+
-+      return 0;
-+}
-+
-+static void
-+i915_gem_object_free_page_list(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int page_count = obj->size / PAGE_SIZE;
-+      int i;
-+
-+      if (obj_priv->page_list == NULL)
-+              return;
-+
-+
-+      for (i = 0; i < page_count; i++)
-+              if (obj_priv->page_list[i] != NULL) {
-+                      if (obj_priv->dirty)
-+                              set_page_dirty(obj_priv->page_list[i]);
-+                      mark_page_accessed(obj_priv->page_list[i]);
-+                      page_cache_release(obj_priv->page_list[i]);
-+              }
-+      obj_priv->dirty = 0;
-+
-+      drm_free(obj_priv->page_list,
-+               page_count * sizeof(struct page *),
-+               DRM_MEM_DRIVER);
-+      obj_priv->page_list = NULL;
-+}
-+
-+static void
-+i915_gem_object_move_to_active(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+      /* Add a reference if we're newly entering the active list. */
-+      if (!obj_priv->active) {
-+              drm_gem_object_reference(obj);
-+              obj_priv->active = 1;
-+      }
-+      /* Move from whatever list we were on to the tail of execution. */
-+      list_move_tail(&obj_priv->list,
-+                     &dev_priv->mm.active_list);
-+}
-+
-+
-+static void
-+i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+      if (obj_priv->pin_count != 0)
-+              list_del_init(&obj_priv->list);
-+      else
-+              list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
-+
-+      if (obj_priv->active) {
-+              obj_priv->active = 0;
-+              drm_gem_object_unreference(obj);
-+      }
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+}
-+
-+/**
-+ * Creates a new sequence number, emitting a write of it to the status page
-+ * plus an interrupt, which will trigger i915_user_interrupt_handler.
-+ *
-+ * Must be called with struct_lock held.
-+ *
-+ * Returned sequence numbers are nonzero on success.
-+ */
-+static uint32_t
-+i915_add_request(struct drm_device *dev, uint32_t flush_domains)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_request *request;
-+      uint32_t seqno;
-+      int was_empty;
-+      RING_LOCALS;
-+
-+      request = drm_calloc(1, sizeof(*request), DRM_MEM_DRIVER);
-+      if (request == NULL)
-+              return 0;
-+
-+      /* Grab the seqno we're going to make this request be, and bump the
-+       * next (skipping 0 so it can be the reserved no-seqno value).
-+       */
-+      seqno = dev_priv->mm.next_gem_seqno;
-+      dev_priv->mm.next_gem_seqno++;
-+      if (dev_priv->mm.next_gem_seqno == 0)
-+              dev_priv->mm.next_gem_seqno++;
-+
-+      BEGIN_LP_RING(4);
-+      OUT_RING(MI_STORE_DWORD_INDEX);
-+      OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-+      OUT_RING(seqno);
-+
-+      OUT_RING(MI_USER_INTERRUPT);
-+      ADVANCE_LP_RING();
-+
-+      DRM_DEBUG("%d\n", seqno);
-+
-+      request->seqno = seqno;
-+      request->emitted_jiffies = jiffies;
-+      request->flush_domains = flush_domains;
-+      was_empty = list_empty(&dev_priv->mm.request_list);
-+      list_add_tail(&request->list, &dev_priv->mm.request_list);
-+
-+      if (was_empty)
-+              schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
-+      return seqno;
-+}
-+
-+/**
-+ * Command execution barrier
-+ *
-+ * Ensures that all commands in the ring are finished
-+ * before signalling the CPU
-+ */
-+uint32_t
-+i915_retire_commands(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
-+      uint32_t flush_domains = 0;
-+      RING_LOCALS;
-+
-+      /* The sampler always gets flushed on i965 (sigh) */
-+      if (IS_I965G(dev))
-+              flush_domains |= I915_GEM_DOMAIN_SAMPLER;
-+      BEGIN_LP_RING(2);
-+      OUT_RING(cmd);
-+      OUT_RING(0); /* noop */
-+      ADVANCE_LP_RING();
-+      return flush_domains;
-+}
-+
-+/**
-+ * Moves buffers associated only with the given active seqno from the active
-+ * to inactive list, potentially freeing them.
-+ */
-+static void
-+i915_gem_retire_request(struct drm_device *dev,
-+                      struct drm_i915_gem_request *request)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      /* Move any buffers on the active list that are no longer referenced
-+       * by the ringbuffer to the flushing/inactive lists as appropriate.
-+       */
-+      while (!list_empty(&dev_priv->mm.active_list)) {
-+              struct drm_gem_object *obj;
-+              struct drm_i915_gem_object *obj_priv;
-+
-+              obj_priv = list_first_entry(&dev_priv->mm.active_list,
-+                                          struct drm_i915_gem_object,
-+                                          list);
-+              obj = obj_priv->obj;
-+
-+              /* If the seqno being retired doesn't match the oldest in the
-+               * list, then the oldest in the list must still be newer than
-+               * this seqno.
-+               */
-+              if (obj_priv->last_rendering_seqno != request->seqno)
-+                      return;
-+#if WATCH_LRU
-+              DRM_INFO("%s: retire %d moves to inactive list %p\n",
-+                       __func__, request->seqno, obj);
-+#endif
-+
-+              if (obj->write_domain != 0) {
-+                      list_move_tail(&obj_priv->list,
-+                                     &dev_priv->mm.flushing_list);
-+              } else {
-+                      i915_gem_object_move_to_inactive(obj);
-+              }
-+      }
-+
-+      if (request->flush_domains != 0) {
-+              struct drm_i915_gem_object *obj_priv, *next;
-+
-+              /* Clear the write domain and activity from any buffers
-+               * that are just waiting for a flush matching the one retired.
-+               */
-+              list_for_each_entry_safe(obj_priv, next,
-+                                       &dev_priv->mm.flushing_list, list) {
-+                      struct drm_gem_object *obj = obj_priv->obj;
-+
-+                      if (obj->write_domain & request->flush_domains) {
-+                              obj->write_domain = 0;
-+                              i915_gem_object_move_to_inactive(obj);
-+                      }
-+              }
-+
-+      }
-+}
-+
-+/**
-+ * Returns true if seq1 is later than seq2.
-+ */
-+static int
-+i915_seqno_passed(uint32_t seq1, uint32_t seq2)
-+{
-+      return (int32_t)(seq1 - seq2) >= 0;
-+}
-+
-+uint32_t
-+i915_get_gem_seqno(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
-+}
-+
-+/**
-+ * This function clears the request list as sequence numbers are passed.
-+ */
-+void
-+i915_gem_retire_requests(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      uint32_t seqno;
-+
-+      seqno = i915_get_gem_seqno(dev);
-+
-+      while (!list_empty(&dev_priv->mm.request_list)) {
-+              struct drm_i915_gem_request *request;
-+              uint32_t retiring_seqno;
-+
-+              request = list_first_entry(&dev_priv->mm.request_list,
-+                                         struct drm_i915_gem_request,
-+                                         list);
-+              retiring_seqno = request->seqno;
-+
-+              if (i915_seqno_passed(seqno, retiring_seqno) ||
-+                  dev_priv->mm.wedged) {
-+                      i915_gem_retire_request(dev, request);
-+
-+                      list_del(&request->list);
-+                      drm_free(request, sizeof(*request), DRM_MEM_DRIVER);
-+              } else
-+                      break;
-+      }
-+}
-+
-+void
-+i915_gem_retire_work_handler(struct work_struct *work)
-+{
-+      drm_i915_private_t *dev_priv;
-+      struct drm_device *dev;
-+
-+      dev_priv = container_of(work, drm_i915_private_t,
-+                              mm.retire_work.work);
-+      dev = dev_priv->dev;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      i915_gem_retire_requests(dev);
-+      if (!list_empty(&dev_priv->mm.request_list))
-+              schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
-+      mutex_unlock(&dev->struct_mutex);
-+}
-+
-+/**
-+ * Waits for a sequence number to be signaled, and cleans up the
-+ * request and object lists appropriately for that event.
-+ */
-+int
-+i915_wait_request(struct drm_device *dev, uint32_t seqno)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      int ret = 0;
-+
-+      BUG_ON(seqno == 0);
-+
-+      if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
-+              dev_priv->mm.waiting_gem_seqno = seqno;
-+              i915_user_irq_get(dev);
-+              ret = wait_event_interruptible(dev_priv->irq_queue,
-+                                             i915_seqno_passed(i915_get_gem_seqno(dev),
-+                                                               seqno) ||
-+                                             dev_priv->mm.wedged);
-+              i915_user_irq_put(dev);
-+              dev_priv->mm.waiting_gem_seqno = 0;
-+      }
-+      if (dev_priv->mm.wedged)
-+              ret = -EIO;
-+
-+      if (ret && ret != -ERESTARTSYS)
-+              DRM_ERROR("%s returns %d (awaiting %d at %d)\n",
-+                        __func__, ret, seqno, i915_get_gem_seqno(dev));
-+
-+      /* Directly dispatch request retiring.  While we have the work queue
-+       * to handle this, the waiter on a request often wants an associated
-+       * buffer to have made it to the inactive list, and we would need
-+       * a separate wait queue to handle that.
-+       */
-+      if (ret == 0)
-+              i915_gem_retire_requests(dev);
-+
-+      return ret;
-+}
-+
-+static void
-+i915_gem_flush(struct drm_device *dev,
-+             uint32_t invalidate_domains,
-+             uint32_t flush_domains)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      uint32_t cmd;
-+      RING_LOCALS;
-+
-+#if WATCH_EXEC
-+      DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
-+                invalidate_domains, flush_domains);
-+#endif
-+
-+      if (flush_domains & I915_GEM_DOMAIN_CPU)
-+              drm_agp_chipset_flush(dev);
-+
-+      if ((invalidate_domains | flush_domains) & ~(I915_GEM_DOMAIN_CPU |
-+                                                   I915_GEM_DOMAIN_GTT)) {
-+              /*
-+               * read/write caches:
-+               *
-+               * I915_GEM_DOMAIN_RENDER is always invalidated, but is
-+               * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
-+               * also flushed at 2d versus 3d pipeline switches.
-+               *
-+               * read-only caches:
-+               *
-+               * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
-+               * MI_READ_FLUSH is set, and is always flushed on 965.
-+               *
-+               * I915_GEM_DOMAIN_COMMAND may not exist?
-+               *
-+               * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
-+               * invalidated when MI_EXE_FLUSH is set.
-+               *
-+               * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
-+               * invalidated with every MI_FLUSH.
-+               *
-+               * TLBs:
-+               *
-+               * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
-+               * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
-+               * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
-+               * are flushed at any MI_FLUSH.
-+               */
-+
-+              cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
-+              if ((invalidate_domains|flush_domains) &
-+                  I915_GEM_DOMAIN_RENDER)
-+                      cmd &= ~MI_NO_WRITE_FLUSH;
-+              if (!IS_I965G(dev)) {
-+                      /*
-+                       * On the 965, the sampler cache always gets flushed
-+                       * and this bit is reserved.
-+                       */
-+                      if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
-+                              cmd |= MI_READ_FLUSH;
-+              }
-+              if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
-+                      cmd |= MI_EXE_FLUSH;
-+
-+#if WATCH_EXEC
-+              DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
-+#endif
-+              BEGIN_LP_RING(2);
-+              OUT_RING(cmd);
-+              OUT_RING(0); /* noop */
-+              ADVANCE_LP_RING();
-+      }
-+}
-+
-+/**
-+ * Ensures that all rendering to the object has completed and the object is
-+ * safe to unbind from the GTT or access from the CPU.
-+ */
-+static int
-+i915_gem_object_wait_rendering(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int ret;
-+
-+      /* If there are writes queued to the buffer, flush and
-+       * create a new seqno to wait for.
-+       */
-+      if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) {
-+              uint32_t write_domain = obj->write_domain;
-+#if WATCH_BUF
-+              DRM_INFO("%s: flushing object %p from write domain %08x\n",
-+                        __func__, obj, write_domain);
-+#endif
-+              i915_gem_flush(dev, 0, write_domain);
-+
-+              i915_gem_object_move_to_active(obj);
-+              obj_priv->last_rendering_seqno = i915_add_request(dev,
-+                                                                write_domain);
-+              BUG_ON(obj_priv->last_rendering_seqno == 0);
-+#if WATCH_LRU
-+              DRM_INFO("%s: flush moves to exec list %p\n", __func__, obj);
-+#endif
-+      }
-+
-+      /* If there is rendering queued on the buffer being evicted, wait for
-+       * it.
-+       */
-+      if (obj_priv->active) {
-+#if WATCH_BUF
-+              DRM_INFO("%s: object %p wait for seqno %08x\n",
-+                        __func__, obj, obj_priv->last_rendering_seqno);
-+#endif
-+              ret = i915_wait_request(dev, obj_priv->last_rendering_seqno);
-+              if (ret != 0)
-+                      return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-+ * Unbinds an object from the GTT aperture.
-+ */
-+static int
-+i915_gem_object_unbind(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int ret = 0;
-+
-+#if WATCH_BUF
-+      DRM_INFO("%s:%d %p\n", __func__, __LINE__, obj);
-+      DRM_INFO("gtt_space %p\n", obj_priv->gtt_space);
-+#endif
-+      if (obj_priv->gtt_space == NULL)
-+              return 0;
-+
-+      if (obj_priv->pin_count != 0) {
-+              DRM_ERROR("Attempting to unbind pinned buffer\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Wait for any rendering to complete
-+       */
-+      ret = i915_gem_object_wait_rendering(obj);
-+      if (ret) {
-+              DRM_ERROR("wait_rendering failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* Move the object to the CPU domain to ensure that
-+       * any possible CPU writes while it's not in the GTT
-+       * are flushed when we go to remap it. This will
-+       * also ensure that all pending GPU writes are finished
-+       * before we unbind.
-+       */
-+      ret = i915_gem_object_set_domain(obj, I915_GEM_DOMAIN_CPU,
-+                                       I915_GEM_DOMAIN_CPU);
-+      if (ret) {
-+              DRM_ERROR("set_domain failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      if (obj_priv->agp_mem != NULL) {
-+              drm_unbind_agp(obj_priv->agp_mem);
-+              drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE);
-+              obj_priv->agp_mem = NULL;
-+      }
-+
-+      BUG_ON(obj_priv->active);
-+
-+      i915_gem_object_free_page_list(obj);
-+
-+      if (obj_priv->gtt_space) {
-+              atomic_dec(&dev->gtt_count);
-+              atomic_sub(obj->size, &dev->gtt_memory);
-+
-+              drm_mm_put_block(obj_priv->gtt_space);
-+              obj_priv->gtt_space = NULL;
-+      }
-+
-+      /* Remove ourselves from the LRU list if present. */
-+      if (!list_empty(&obj_priv->list))
-+              list_del_init(&obj_priv->list);
-+
-+      return 0;
-+}
-+
-+static int
-+i915_gem_evict_something(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret = 0;
-+
-+      for (;;) {
-+              /* If there's an inactive buffer available now, grab it
-+               * and be done.
-+               */
-+              if (!list_empty(&dev_priv->mm.inactive_list)) {
-+                      obj_priv = list_first_entry(&dev_priv->mm.inactive_list,
-+                                                  struct drm_i915_gem_object,
-+                                                  list);
-+                      obj = obj_priv->obj;
-+                      BUG_ON(obj_priv->pin_count != 0);
-+#if WATCH_LRU
-+                      DRM_INFO("%s: evicting %p\n", __func__, obj);
-+#endif
-+                      BUG_ON(obj_priv->active);
-+
-+                      /* Wait on the rendering and unbind the buffer. */
-+                      ret = i915_gem_object_unbind(obj);
-+                      break;
-+              }
-+
-+              /* If we didn't get anything, but the ring is still processing
-+               * things, wait for one of those things to finish and hopefully
-+               * leave us a buffer to evict.
-+               */
-+              if (!list_empty(&dev_priv->mm.request_list)) {
-+                      struct drm_i915_gem_request *request;
-+
-+                      request = list_first_entry(&dev_priv->mm.request_list,
-+                                                 struct drm_i915_gem_request,
-+                                                 list);
-+
-+                      ret = i915_wait_request(dev, request->seqno);
-+                      if (ret)
-+                              break;
-+
-+                      /* if waiting caused an object to become inactive,
-+                       * then loop around and wait for it. Otherwise, we
-+                       * assume that waiting freed and unbound something,
-+                       * so there should now be some space in the GTT
-+                       */
-+                      if (!list_empty(&dev_priv->mm.inactive_list))
-+                              continue;
-+                      break;
-+              }
-+
-+              /* If we didn't have anything on the request list but there
-+               * are buffers awaiting a flush, emit one and try again.
-+               * When we wait on it, those buffers waiting for that flush
-+               * will get moved to inactive.
-+               */
-+              if (!list_empty(&dev_priv->mm.flushing_list)) {
-+                      obj_priv = list_first_entry(&dev_priv->mm.flushing_list,
-+                                                  struct drm_i915_gem_object,
-+                                                  list);
-+                      obj = obj_priv->obj;
-+
-+                      i915_gem_flush(dev,
-+                                     obj->write_domain,
-+                                     obj->write_domain);
-+                      i915_add_request(dev, obj->write_domain);
-+
-+                      obj = NULL;
-+                      continue;
-+              }
-+
-+              DRM_ERROR("inactive empty %d request empty %d "
-+                        "flushing empty %d\n",
-+                        list_empty(&dev_priv->mm.inactive_list),
-+                        list_empty(&dev_priv->mm.request_list),
-+                        list_empty(&dev_priv->mm.flushing_list));
-+              /* If we didn't do any of the above, there's nothing to be done
-+               * and we just can't fit it in.
-+               */
-+              return -ENOMEM;
-+      }
-+      return ret;
-+}
-+
-+static int
-+i915_gem_object_get_page_list(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int page_count, i;
-+      struct address_space *mapping;
-+      struct inode *inode;
-+      struct page *page;
-+      int ret;
-+
-+      if (obj_priv->page_list)
-+              return 0;
-+
-+      /* Get the list of pages out of our struct file.  They'll be pinned
-+       * at this point until we release them.
-+       */
-+      page_count = obj->size / PAGE_SIZE;
-+      BUG_ON(obj_priv->page_list != NULL);
-+      obj_priv->page_list = drm_calloc(page_count, sizeof(struct page *),
-+                                       DRM_MEM_DRIVER);
-+      if (obj_priv->page_list == NULL) {
-+              DRM_ERROR("Faled to allocate page list\n");
-+              return -ENOMEM;
-+      }
-+
-+      inode = obj->filp->f_path.dentry->d_inode;
-+      mapping = inode->i_mapping;
-+      for (i = 0; i < page_count; i++) {
-+              page = read_mapping_page(mapping, i, NULL);
-+              if (IS_ERR(page)) {
-+                      ret = PTR_ERR(page);
-+                      DRM_ERROR("read_mapping_page failed: %d\n", ret);
-+                      i915_gem_object_free_page_list(obj);
-+                      return ret;
-+              }
-+              obj_priv->page_list[i] = page;
-+      }
-+      return 0;
-+}
-+
-+/**
-+ * Finds free space in the GTT aperture and binds the object there.
-+ */
-+static int
-+i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
-+{
-+      struct drm_device *dev = obj->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      struct drm_mm_node *free_space;
-+      int page_count, ret;
-+
-+      if (alignment == 0)
-+              alignment = PAGE_SIZE;
-+      if (alignment & (PAGE_SIZE - 1)) {
-+              DRM_ERROR("Invalid object alignment requested %u\n", alignment);
-+              return -EINVAL;
-+      }
-+
-+ search_free:
-+      free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
-+                                      obj->size, alignment, 0);
-+      if (free_space != NULL) {
-+              obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
-+                                                     alignment);
-+              if (obj_priv->gtt_space != NULL) {
-+                      obj_priv->gtt_space->private = obj;
-+                      obj_priv->gtt_offset = obj_priv->gtt_space->start;
-+              }
-+      }
-+      if (obj_priv->gtt_space == NULL) {
-+              /* If the gtt is empty and we're still having trouble
-+               * fitting our object in, we're out of memory.
-+               */
-+#if WATCH_LRU
-+              DRM_INFO("%s: GTT full, evicting something\n", __func__);
-+#endif
-+              if (list_empty(&dev_priv->mm.inactive_list) &&
-+                  list_empty(&dev_priv->mm.flushing_list) &&
-+                  list_empty(&dev_priv->mm.active_list)) {
-+                      DRM_ERROR("GTT full, but LRU list empty\n");
-+                      return -ENOMEM;
-+              }
-+
-+              ret = i915_gem_evict_something(dev);
-+              if (ret != 0) {
-+                      DRM_ERROR("Failed to evict a buffer %d\n", ret);
-+                      return ret;
-+              }
-+              goto search_free;
-+      }
-+
-+#if WATCH_BUF
-+      DRM_INFO("Binding object of size %d at 0x%08x\n",
-+               obj->size, obj_priv->gtt_offset);
-+#endif
-+      ret = i915_gem_object_get_page_list(obj);
-+      if (ret) {
-+              drm_mm_put_block(obj_priv->gtt_space);
-+              obj_priv->gtt_space = NULL;
-+              return ret;
-+      }
-+
-+      page_count = obj->size / PAGE_SIZE;
-+      /* Create an AGP memory structure pointing at our pages, and bind it
-+       * into the GTT.
-+       */
-+      obj_priv->agp_mem = drm_agp_bind_pages(dev,
-+                                             obj_priv->page_list,
-+                                             page_count,
-+                                             obj_priv->gtt_offset);
-+      if (obj_priv->agp_mem == NULL) {
-+              i915_gem_object_free_page_list(obj);
-+              drm_mm_put_block(obj_priv->gtt_space);
-+              obj_priv->gtt_space = NULL;
-+              return -ENOMEM;
-+      }
-+      atomic_inc(&dev->gtt_count);
-+      atomic_add(obj->size, &dev->gtt_memory);
-+
-+      /* Assert that the object is not currently in any GPU domain. As it
-+       * wasn't in the GTT, there shouldn't be any way it could have been in
-+       * a GPU cache
-+       */
-+      BUG_ON(obj->read_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
-+      BUG_ON(obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
-+
-+      return 0;
-+}
-+
-+void
-+i915_gem_clflush_object(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object      *obj_priv = obj->driver_private;
-+
-+      /* If we don't have a page list set up, then we're not pinned
-+       * to GPU, and we can ignore the cache flush because it'll happen
-+       * again at bind time.
-+       */
-+      if (obj_priv->page_list == NULL)
-+              return;
-+
-+      drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE);
-+}
-+
-+/*
-+ * Set the next domain for the specified object. This
-+ * may not actually perform the necessary flushing/invaliding though,
-+ * as that may want to be batched with other set_domain operations
-+ *
-+ * This is (we hope) the only really tricky part of gem. The goal
-+ * is fairly simple -- track which caches hold bits of the object
-+ * and make sure they remain coherent. A few concrete examples may
-+ * help to explain how it works. For shorthand, we use the notation
-+ * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the
-+ * a pair of read and write domain masks.
-+ *
-+ * Case 1: the batch buffer
-+ *
-+ *    1. Allocated
-+ *    2. Written by CPU
-+ *    3. Mapped to GTT
-+ *    4. Read by GPU
-+ *    5. Unmapped from GTT
-+ *    6. Freed
-+ *
-+ *    Let's take these a step at a time
-+ *
-+ *    1. Allocated
-+ *            Pages allocated from the kernel may still have
-+ *            cache contents, so we set them to (CPU, CPU) always.
-+ *    2. Written by CPU (using pwrite)
-+ *            The pwrite function calls set_domain (CPU, CPU) and
-+ *            this function does nothing (as nothing changes)
-+ *    3. Mapped by GTT
-+ *            This function asserts that the object is not
-+ *            currently in any GPU-based read or write domains
-+ *    4. Read by GPU
-+ *            i915_gem_execbuffer calls set_domain (COMMAND, 0).
-+ *            As write_domain is zero, this function adds in the
-+ *            current read domains (CPU+COMMAND, 0).
-+ *            flush_domains is set to CPU.
-+ *            invalidate_domains is set to COMMAND
-+ *            clflush is run to get data out of the CPU caches
-+ *            then i915_dev_set_domain calls i915_gem_flush to
-+ *            emit an MI_FLUSH and drm_agp_chipset_flush
-+ *    5. Unmapped from GTT
-+ *            i915_gem_object_unbind calls set_domain (CPU, CPU)
-+ *            flush_domains and invalidate_domains end up both zero
-+ *            so no flushing/invalidating happens
-+ *    6. Freed
-+ *            yay, done
-+ *
-+ * Case 2: The shared render buffer
-+ *
-+ *    1. Allocated
-+ *    2. Mapped to GTT
-+ *    3. Read/written by GPU
-+ *    4. set_domain to (CPU,CPU)
-+ *    5. Read/written by CPU
-+ *    6. Read/written by GPU
-+ *
-+ *    1. Allocated
-+ *            Same as last example, (CPU, CPU)
-+ *    2. Mapped to GTT
-+ *            Nothing changes (assertions find that it is not in the GPU)
-+ *    3. Read/written by GPU
-+ *            execbuffer calls set_domain (RENDER, RENDER)
-+ *            flush_domains gets CPU
-+ *            invalidate_domains gets GPU
-+ *            clflush (obj)
-+ *            MI_FLUSH and drm_agp_chipset_flush
-+ *    4. set_domain (CPU, CPU)
-+ *            flush_domains gets GPU
-+ *            invalidate_domains gets CPU
-+ *            wait_rendering (obj) to make sure all drawing is complete.
-+ *            This will include an MI_FLUSH to get the data from GPU
-+ *            to memory
-+ *            clflush (obj) to invalidate the CPU cache
-+ *            Another MI_FLUSH in i915_gem_flush (eliminate this somehow?)
-+ *    5. Read/written by CPU
-+ *            cache lines are loaded and dirtied
-+ *    6. Read written by GPU
-+ *            Same as last GPU access
-+ *
-+ * Case 3: The constant buffer
-+ *
-+ *    1. Allocated
-+ *    2. Written by CPU
-+ *    3. Read by GPU
-+ *    4. Updated (written) by CPU again
-+ *    5. Read by GPU
-+ *
-+ *    1. Allocated
-+ *            (CPU, CPU)
-+ *    2. Written by CPU
-+ *            (CPU, CPU)
-+ *    3. Read by GPU
-+ *            (CPU+RENDER, 0)
-+ *            flush_domains = CPU
-+ *            invalidate_domains = RENDER
-+ *            clflush (obj)
-+ *            MI_FLUSH
-+ *            drm_agp_chipset_flush
-+ *    4. Updated (written) by CPU again
-+ *            (CPU, CPU)
-+ *            flush_domains = 0 (no previous write domain)
-+ *            invalidate_domains = 0 (no new read domains)
-+ *    5. Read by GPU
-+ *            (CPU+RENDER, 0)
-+ *            flush_domains = CPU
-+ *            invalidate_domains = RENDER
-+ *            clflush (obj)
-+ *            MI_FLUSH
-+ *            drm_agp_chipset_flush
-+ */
-+static int
-+i915_gem_object_set_domain(struct drm_gem_object *obj,
-+                          uint32_t read_domains,
-+                          uint32_t write_domain)
-+{
-+      struct drm_device               *dev = obj->dev;
-+      struct drm_i915_gem_object      *obj_priv = obj->driver_private;
-+      uint32_t                        invalidate_domains = 0;
-+      uint32_t                        flush_domains = 0;
-+      int                             ret;
-+
-+#if WATCH_BUF
-+      DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
-+               __func__, obj,
-+               obj->read_domains, read_domains,
-+               obj->write_domain, write_domain);
-+#endif
-+      /*
-+       * If the object isn't moving to a new write domain,
-+       * let the object stay in multiple read domains
-+       */
-+      if (write_domain == 0)
-+              read_domains |= obj->read_domains;
-+      else
-+              obj_priv->dirty = 1;
-+
-+      /*
-+       * Flush the current write domain if
-+       * the new read domains don't match. Invalidate
-+       * any read domains which differ from the old
-+       * write domain
-+       */
-+      if (obj->write_domain && obj->write_domain != read_domains) {
-+              flush_domains |= obj->write_domain;
-+              invalidate_domains |= read_domains & ~obj->write_domain;
-+      }
-+      /*
-+       * Invalidate any read caches which may have
-+       * stale data. That is, any new read domains.
-+       */
-+      invalidate_domains |= read_domains & ~obj->read_domains;
-+      if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) {
-+#if WATCH_BUF
-+              DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n",
-+                       __func__, flush_domains, invalidate_domains);
-+#endif
-+              /*
-+               * If we're invaliding the CPU cache and flushing a GPU cache,
-+               * then pause for rendering so that the GPU caches will be
-+               * flushed before the cpu cache is invalidated
-+               */
-+              if ((invalidate_domains & I915_GEM_DOMAIN_CPU) &&
-+                  (flush_domains & ~(I915_GEM_DOMAIN_CPU |
-+                                     I915_GEM_DOMAIN_GTT))) {
-+                      ret = i915_gem_object_wait_rendering(obj);
-+                      if (ret)
-+                              return ret;
-+              }
-+              i915_gem_clflush_object(obj);
-+      }
-+
-+      if ((write_domain | flush_domains) != 0)
-+              obj->write_domain = write_domain;
-+
-+      /* If we're invalidating the CPU domain, clear the per-page CPU
-+       * domain list as well.
-+       */
-+      if (obj_priv->page_cpu_valid != NULL &&
-+          (write_domain != 0 ||
-+           read_domains & I915_GEM_DOMAIN_CPU)) {
-+              drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE,
-+                       DRM_MEM_DRIVER);
-+              obj_priv->page_cpu_valid = NULL;
-+      }
-+      obj->read_domains = read_domains;
-+
-+      dev->invalidate_domains |= invalidate_domains;
-+      dev->flush_domains |= flush_domains;
-+#if WATCH_BUF
-+      DRM_INFO("%s: read %08x write %08x invalidate %08x flush %08x\n",
-+               __func__,
-+               obj->read_domains, obj->write_domain,
-+               dev->invalidate_domains, dev->flush_domains);
-+#endif
-+      return 0;
-+}
-+
-+/**
-+ * Set the read/write domain on a range of the object.
-+ *
-+ * Currently only implemented for CPU reads, otherwise drops to normal
-+ * i915_gem_object_set_domain().
-+ */
-+static int
-+i915_gem_object_set_domain_range(struct drm_gem_object *obj,
-+                               uint64_t offset,
-+                               uint64_t size,
-+                               uint32_t read_domains,
-+                               uint32_t write_domain)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int ret, i;
-+
-+      if (obj->read_domains & I915_GEM_DOMAIN_CPU)
-+              return 0;
-+
-+      if (read_domains != I915_GEM_DOMAIN_CPU ||
-+          write_domain != 0)
-+              return i915_gem_object_set_domain(obj,
-+                                                read_domains, write_domain);
-+
-+      /* Wait on any GPU rendering to the object to be flushed. */
-+      if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) {
-+              ret = i915_gem_object_wait_rendering(obj);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      if (obj_priv->page_cpu_valid == NULL) {
-+              obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE,
-+                                                    DRM_MEM_DRIVER);
-+      }
-+
-+      /* Flush the cache on any pages that are still invalid from the CPU's
-+       * perspective.
-+       */
-+      for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE; i++) {
-+              if (obj_priv->page_cpu_valid[i])
-+                      continue;
-+
-+              drm_clflush_pages(obj_priv->page_list + i, 1);
-+
-+              obj_priv->page_cpu_valid[i] = 1;
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-+ * Once all of the objects have been set in the proper domain,
-+ * perform the necessary flush and invalidate operations.
-+ *
-+ * Returns the write domains flushed, for use in flush tracking.
-+ */
-+static uint32_t
-+i915_gem_dev_set_domain(struct drm_device *dev)
-+{
-+      uint32_t flush_domains = dev->flush_domains;
-+
-+      /*
-+       * Now that all the buffers are synced to the proper domains,
-+       * flush and invalidate the collected domains
-+       */
-+      if (dev->invalidate_domains | dev->flush_domains) {
-+#if WATCH_EXEC
-+              DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
-+                        __func__,
-+                       dev->invalidate_domains,
-+                       dev->flush_domains);
-+#endif
-+              i915_gem_flush(dev,
-+                             dev->invalidate_domains,
-+                             dev->flush_domains);
-+              dev->invalidate_domains = 0;
-+              dev->flush_domains = 0;
-+      }
-+
-+      return flush_domains;
-+}
-+
-+/**
-+ * Pin an object to the GTT and evaluate the relocations landing in it.
-+ */
-+static int
-+i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
-+                               struct drm_file *file_priv,
-+                               struct drm_i915_gem_exec_object *entry)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_relocation_entry reloc;
-+      struct drm_i915_gem_relocation_entry __user *relocs;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int i, ret;
-+      uint32_t last_reloc_offset = -1;
-+      void *reloc_page = NULL;
-+
-+      /* Choose the GTT offset for our buffer and put it there. */
-+      ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
-+      if (ret)
-+              return ret;
-+
-+      entry->offset = obj_priv->gtt_offset;
-+
-+      relocs = (struct drm_i915_gem_relocation_entry __user *)
-+               (uintptr_t) entry->relocs_ptr;
-+      /* Apply the relocations, using the GTT aperture to avoid cache
-+       * flushing requirements.
-+       */
-+      for (i = 0; i < entry->relocation_count; i++) {
-+              struct drm_gem_object *target_obj;
-+              struct drm_i915_gem_object *target_obj_priv;
-+              uint32_t reloc_val, reloc_offset, *reloc_entry;
-+              int ret;
-+
-+              ret = copy_from_user(&reloc, relocs + i, sizeof(reloc));
-+              if (ret != 0) {
-+                      i915_gem_object_unpin(obj);
-+                      return ret;
-+              }
-+
-+              target_obj = drm_gem_object_lookup(obj->dev, file_priv,
-+                                                 reloc.target_handle);
-+              if (target_obj == NULL) {
-+                      i915_gem_object_unpin(obj);
-+                      return -EBADF;
-+              }
-+              target_obj_priv = target_obj->driver_private;
-+
-+              /* The target buffer should have appeared before us in the
-+               * exec_object list, so it should have a GTT space bound by now.
-+               */
-+              if (target_obj_priv->gtt_space == NULL) {
-+                      DRM_ERROR("No GTT space found for object %d\n",
-+                                reloc.target_handle);
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return -EINVAL;
-+              }
-+
-+              if (reloc.offset > obj->size - 4) {
-+                      DRM_ERROR("Relocation beyond object bounds: "
-+                                "obj %p target %d offset %d size %d.\n",
-+                                obj, reloc.target_handle,
-+                                (int) reloc.offset, (int) obj->size);
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return -EINVAL;
-+              }
-+              if (reloc.offset & 3) {
-+                      DRM_ERROR("Relocation not 4-byte aligned: "
-+                                "obj %p target %d offset %d.\n",
-+                                obj, reloc.target_handle,
-+                                (int) reloc.offset);
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return -EINVAL;
-+              }
-+
-+              if (reloc.write_domain && target_obj->pending_write_domain &&
-+                  reloc.write_domain != target_obj->pending_write_domain) {
-+                      DRM_ERROR("Write domain conflict: "
-+                                "obj %p target %d offset %d "
-+                                "new %08x old %08x\n",
-+                                obj, reloc.target_handle,
-+                                (int) reloc.offset,
-+                                reloc.write_domain,
-+                                target_obj->pending_write_domain);
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return -EINVAL;
-+              }
-+
-+#if WATCH_RELOC
-+              DRM_INFO("%s: obj %p offset %08x target %d "
-+                       "read %08x write %08x gtt %08x "
-+                       "presumed %08x delta %08x\n",
-+                       __func__,
-+                       obj,
-+                       (int) reloc.offset,
-+                       (int) reloc.target_handle,
-+                       (int) reloc.read_domains,
-+                       (int) reloc.write_domain,
-+                       (int) target_obj_priv->gtt_offset,
-+                       (int) reloc.presumed_offset,
-+                       reloc.delta);
-+#endif
-+
-+              target_obj->pending_read_domains |= reloc.read_domains;
-+              target_obj->pending_write_domain |= reloc.write_domain;
-+
-+              /* If the relocation already has the right value in it, no
-+               * more work needs to be done.
-+               */
-+              if (target_obj_priv->gtt_offset == reloc.presumed_offset) {
-+                      drm_gem_object_unreference(target_obj);
-+                      continue;
-+              }
-+
-+              /* Now that we're going to actually write some data in,
-+               * make sure that any rendering using this buffer's contents
-+               * is completed.
-+               */
-+              i915_gem_object_wait_rendering(obj);
-+
-+              /* As we're writing through the gtt, flush
-+               * any CPU writes before we write the relocations
-+               */
-+              if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
-+                      i915_gem_clflush_object(obj);
-+                      drm_agp_chipset_flush(dev);
-+                      obj->write_domain = 0;
-+              }
-+
-+              /* Map the page containing the relocation we're going to
-+               * perform.
-+               */
-+              reloc_offset = obj_priv->gtt_offset + reloc.offset;
-+              if (reloc_page == NULL ||
-+                  (last_reloc_offset & ~(PAGE_SIZE - 1)) !=
-+                  (reloc_offset & ~(PAGE_SIZE - 1))) {
-+                      if (reloc_page != NULL)
-+                              iounmap(reloc_page);
-+
-+                      reloc_page = ioremap(dev->agp->base +
-+                                           (reloc_offset & ~(PAGE_SIZE - 1)),
-+                                           PAGE_SIZE);
-+                      last_reloc_offset = reloc_offset;
-+                      if (reloc_page == NULL) {
-+                              drm_gem_object_unreference(target_obj);
-+                              i915_gem_object_unpin(obj);
-+                              return -ENOMEM;
-+                      }
-+              }
-+
-+              reloc_entry = (uint32_t *)((char *)reloc_page +
-+                                         (reloc_offset & (PAGE_SIZE - 1)));
-+              reloc_val = target_obj_priv->gtt_offset + reloc.delta;
-+
-+#if WATCH_BUF
-+              DRM_INFO("Applied relocation: %p@0x%08x %08x -> %08x\n",
-+                        obj, (unsigned int) reloc.offset,
-+                        readl(reloc_entry), reloc_val);
-+#endif
-+              writel(reloc_val, reloc_entry);
-+
-+              /* Write the updated presumed offset for this entry back out
-+               * to the user.
-+               */
-+              reloc.presumed_offset = target_obj_priv->gtt_offset;
-+              ret = copy_to_user(relocs + i, &reloc, sizeof(reloc));
-+              if (ret != 0) {
-+                      drm_gem_object_unreference(target_obj);
-+                      i915_gem_object_unpin(obj);
-+                      return ret;
-+              }
-+
-+              drm_gem_object_unreference(target_obj);
-+      }
-+
-+      if (reloc_page != NULL)
-+              iounmap(reloc_page);
-+
-+#if WATCH_BUF
-+      if (0)
-+              i915_gem_dump_object(obj, 128, __func__, ~0);
-+#endif
-+      return 0;
-+}
-+
-+/** Dispatch a batchbuffer to the ring
-+ */
-+static int
-+i915_dispatch_gem_execbuffer(struct drm_device *dev,
-+                            struct drm_i915_gem_execbuffer *exec,
-+                            uint64_t exec_offset)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_clip_rect __user *boxes = (struct drm_clip_rect __user *)
-+                                           (uintptr_t) exec->cliprects_ptr;
-+      int nbox = exec->num_cliprects;
-+      int i = 0, count;
-+      uint32_t        exec_start, exec_len;
-+      RING_LOCALS;
-+
-+      exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
-+      exec_len = (uint32_t) exec->batch_len;
-+
-+      if ((exec_start | exec_len) & 0x7) {
-+              DRM_ERROR("alignment\n");
-+              return -EINVAL;
-+      }
-+
-+      if (!exec_start)
-+              return -EINVAL;
-+
-+      count = nbox ? nbox : 1;
-+
-+      for (i = 0; i < count; i++) {
-+              if (i < nbox) {
-+                      int ret = i915_emit_box(dev, boxes, i,
-+                                              exec->DR1, exec->DR4);
-+                      if (ret)
-+                              return ret;
-+              }
-+
-+              if (IS_I830(dev) || IS_845G(dev)) {
-+                      BEGIN_LP_RING(4);
-+                      OUT_RING(MI_BATCH_BUFFER);
-+                      OUT_RING(exec_start | MI_BATCH_NON_SECURE);
-+                      OUT_RING(exec_start + exec_len - 4);
-+                      OUT_RING(0);
-+                      ADVANCE_LP_RING();
-+              } else {
-+                      BEGIN_LP_RING(2);
-+                      if (IS_I965G(dev)) {
-+                              OUT_RING(MI_BATCH_BUFFER_START |
-+                                       (2 << 6) |
-+                                       MI_BATCH_NON_SECURE_I965);
-+                              OUT_RING(exec_start);
-+                      } else {
-+                              OUT_RING(MI_BATCH_BUFFER_START |
-+                                       (2 << 6));
-+                              OUT_RING(exec_start | MI_BATCH_NON_SECURE);
-+                      }
-+                      ADVANCE_LP_RING();
-+              }
-+      }
-+
-+      /* XXX breadcrumb */
-+      return 0;
-+}
-+
-+/* Throttle our rendering by waiting until the ring has completed our requests
-+ * emitted over 20 msec ago.
-+ *
-+ * This should get us reasonable parallelism between CPU and GPU but also
-+ * relatively low latency when blocking on a particular request to finish.
-+ */
-+static int
-+i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
-+{
-+      struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
-+      int ret = 0;
-+      uint32_t seqno;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      seqno = i915_file_priv->mm.last_gem_throttle_seqno;
-+      i915_file_priv->mm.last_gem_throttle_seqno =
-+              i915_file_priv->mm.last_gem_seqno;
-+      if (seqno)
-+              ret = i915_wait_request(dev, seqno);
-+      mutex_unlock(&dev->struct_mutex);
-+      return ret;
-+}
-+
-+int
-+i915_gem_execbuffer(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
-+      struct drm_i915_gem_execbuffer *args = data;
-+      struct drm_i915_gem_exec_object *exec_list = NULL;
-+      struct drm_gem_object **object_list = NULL;
-+      struct drm_gem_object *batch_obj;
-+      int ret, i, pinned = 0;
-+      uint64_t exec_offset;
-+      uint32_t seqno, flush_domains;
-+
-+#if WATCH_EXEC
-+      DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-+                (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-+#endif
-+
-+      /* Copy in the exec list from userland */
-+      exec_list = drm_calloc(sizeof(*exec_list), args->buffer_count,
-+                             DRM_MEM_DRIVER);
-+      object_list = drm_calloc(sizeof(*object_list), args->buffer_count,
-+                               DRM_MEM_DRIVER);
-+      if (exec_list == NULL || object_list == NULL) {
-+              DRM_ERROR("Failed to allocate exec or object list "
-+                        "for %d buffers\n",
-+                        args->buffer_count);
-+              ret = -ENOMEM;
-+              goto pre_mutex_err;
-+      }
-+      ret = copy_from_user(exec_list,
-+                           (struct drm_i915_relocation_entry __user *)
-+                           (uintptr_t) args->buffers_ptr,
-+                           sizeof(*exec_list) * args->buffer_count);
-+      if (ret != 0) {
-+              DRM_ERROR("copy %d exec entries failed %d\n",
-+                        args->buffer_count, ret);
-+              goto pre_mutex_err;
-+      }
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      if (dev_priv->mm.wedged) {
-+              DRM_ERROR("Execbuf while wedged\n");
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EIO;
-+      }
-+
-+      if (dev_priv->mm.suspended) {
-+              DRM_ERROR("Execbuf while VT-switched.\n");
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBUSY;
-+      }
-+
-+      /* Zero the gloabl flush/invalidate flags. These
-+       * will be modified as each object is bound to the
-+       * gtt
-+       */
-+      dev->invalidate_domains = 0;
-+      dev->flush_domains = 0;
-+
-+      /* Look up object handles and perform the relocations */
-+      for (i = 0; i < args->buffer_count; i++) {
-+              object_list[i] = drm_gem_object_lookup(dev, file_priv,
-+                                                     exec_list[i].handle);
-+              if (object_list[i] == NULL) {
-+                      DRM_ERROR("Invalid object handle %d at index %d\n",
-+                                 exec_list[i].handle, i);
-+                      ret = -EBADF;
-+                      goto err;
-+              }
-+
-+              object_list[i]->pending_read_domains = 0;
-+              object_list[i]->pending_write_domain = 0;
-+              ret = i915_gem_object_pin_and_relocate(object_list[i],
-+                                                     file_priv,
-+                                                     &exec_list[i]);
-+              if (ret) {
-+                      DRM_ERROR("object bind and relocate failed %d\n", ret);
-+                      goto err;
-+              }
-+              pinned = i + 1;
-+      }
-+
-+      /* Set the pending read domains for the batch buffer to COMMAND */
-+      batch_obj = object_list[args->buffer_count-1];
-+      batch_obj->pending_read_domains = I915_GEM_DOMAIN_COMMAND;
-+      batch_obj->pending_write_domain = 0;
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      for (i = 0; i < args->buffer_count; i++) {
-+              struct drm_gem_object *obj = object_list[i];
-+              struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+              if (obj_priv->gtt_space == NULL) {
-+                      /* We evicted the buffer in the process of validating
-+                       * our set of buffers in.  We could try to recover by
-+                       * kicking them everything out and trying again from
-+                       * the start.
-+                       */
-+                      ret = -ENOMEM;
-+                      goto err;
-+              }
-+
-+              /* make sure all previous memory operations have passed */
-+              ret = i915_gem_object_set_domain(obj,
-+                                               obj->pending_read_domains,
-+                                               obj->pending_write_domain);
-+              if (ret)
-+                      goto err;
-+      }
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      /* Flush/invalidate caches and chipset buffer */
-+      flush_domains = i915_gem_dev_set_domain(dev);
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+#if WATCH_COHERENCY
-+      for (i = 0; i < args->buffer_count; i++) {
-+              i915_gem_object_check_coherency(object_list[i],
-+                                              exec_list[i].handle);
-+      }
-+#endif
-+
-+      exec_offset = exec_list[args->buffer_count - 1].offset;
-+
-+#if WATCH_EXEC
-+      i915_gem_dump_object(object_list[args->buffer_count - 1],
-+                            args->batch_len,
-+                            __func__,
-+                            ~0);
-+#endif
-+
-+      (void)i915_add_request(dev, flush_domains);
-+
-+      /* Exec the batchbuffer */
-+      ret = i915_dispatch_gem_execbuffer(dev, args, exec_offset);
-+      if (ret) {
-+              DRM_ERROR("dispatch failed %d\n", ret);
-+              goto err;
-+      }
-+
-+      /*
-+       * Ensure that the commands in the batch buffer are
-+       * finished before the interrupt fires
-+       */
-+      flush_domains = i915_retire_commands(dev);
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      /*
-+       * Get a seqno representing the execution of the current buffer,
-+       * which we can wait on.  We would like to mitigate these interrupts,
-+       * likely by only creating seqnos occasionally (so that we have
-+       * *some* interrupts representing completion of buffers that we can
-+       * wait on when trying to clear up gtt space).
-+       */
-+      seqno = i915_add_request(dev, flush_domains);
-+      BUG_ON(seqno == 0);
-+      i915_file_priv->mm.last_gem_seqno = seqno;
-+      for (i = 0; i < args->buffer_count; i++) {
-+              struct drm_gem_object *obj = object_list[i];
-+              struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+              i915_gem_object_move_to_active(obj);
-+              obj_priv->last_rendering_seqno = seqno;
-+#if WATCH_LRU
-+              DRM_INFO("%s: move to exec list %p\n", __func__, obj);
-+#endif
-+      }
-+#if WATCH_LRU
-+      i915_dump_lru(dev, __func__);
-+#endif
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      /* Copy the new buffer offsets back to the user's exec list. */
-+      ret = copy_to_user((struct drm_i915_relocation_entry __user *)
-+                         (uintptr_t) args->buffers_ptr,
-+                         exec_list,
-+                         sizeof(*exec_list) * args->buffer_count);
-+      if (ret)
-+              DRM_ERROR("failed to copy %d exec entries "
-+                        "back to user (%d)\n",
-+                         args->buffer_count, ret);
-+err:
-+      if (object_list != NULL) {
-+              for (i = 0; i < pinned; i++)
-+                      i915_gem_object_unpin(object_list[i]);
-+
-+              for (i = 0; i < args->buffer_count; i++)
-+                      drm_gem_object_unreference(object_list[i]);
-+      }
-+      mutex_unlock(&dev->struct_mutex);
-+
-+pre_mutex_err:
-+      drm_free(object_list, sizeof(*object_list) * args->buffer_count,
-+               DRM_MEM_DRIVER);
-+      drm_free(exec_list, sizeof(*exec_list) * args->buffer_count,
-+               DRM_MEM_DRIVER);
-+
-+      return ret;
-+}
-+
-+int
-+i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int ret;
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+      if (obj_priv->gtt_space == NULL) {
-+              ret = i915_gem_object_bind_to_gtt(obj, alignment);
-+              if (ret != 0) {
-+                      DRM_ERROR("Failure to bind: %d", ret);
-+                      return ret;
-+              }
-+      }
-+      obj_priv->pin_count++;
-+
-+      /* If the object is not active and not pending a flush,
-+       * remove it from the inactive list
-+       */
-+      if (obj_priv->pin_count == 1) {
-+              atomic_inc(&dev->pin_count);
-+              atomic_add(obj->size, &dev->pin_memory);
-+              if (!obj_priv->active &&
-+                  (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
-+                                         I915_GEM_DOMAIN_GTT)) == 0 &&
-+                  !list_empty(&obj_priv->list))
-+                      list_del_init(&obj_priv->list);
-+      }
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+
-+      return 0;
-+}
-+
-+void
-+i915_gem_object_unpin(struct drm_gem_object *obj)
-+{
-+      struct drm_device *dev = obj->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+      obj_priv->pin_count--;
-+      BUG_ON(obj_priv->pin_count < 0);
-+      BUG_ON(obj_priv->gtt_space == NULL);
-+
-+      /* If the object is no longer pinned, and is
-+       * neither active nor being flushed, then stick it on
-+       * the inactive list
-+       */
-+      if (obj_priv->pin_count == 0) {
-+              if (!obj_priv->active &&
-+                  (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
-+                                         I915_GEM_DOMAIN_GTT)) == 0)
-+                      list_move_tail(&obj_priv->list,
-+                                     &dev_priv->mm.inactive_list);
-+              atomic_dec(&dev->pin_count);
-+              atomic_sub(obj->size, &dev->pin_memory);
-+      }
-+      i915_verify_inactive(dev, __FILE__, __LINE__);
-+}
-+
-+int
-+i915_gem_pin_ioctl(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_pin *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL) {
-+              DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n",
-+                        args->handle);
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBADF;
-+      }
-+      obj_priv = obj->driver_private;
-+
-+      ret = i915_gem_object_pin(obj, args->alignment);
-+      if (ret != 0) {
-+              drm_gem_object_unreference(obj);
-+              mutex_unlock(&dev->struct_mutex);
-+              return ret;
-+      }
-+
-+      /* XXX - flush the CPU caches for pinned objects
-+       * as the X server doesn't manage domains yet
-+       */
-+      if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
-+              i915_gem_clflush_object(obj);
-+              drm_agp_chipset_flush(dev);
-+              obj->write_domain = 0;
-+      }
-+      args->offset = obj_priv->gtt_offset;
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+int
-+i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
-+                   struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_pin *args = data;
-+      struct drm_gem_object *obj;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL) {
-+              DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n",
-+                        args->handle);
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBADF;
-+      }
-+
-+      i915_gem_object_unpin(obj);
-+
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      return 0;
-+}
-+
-+int
-+i915_gem_busy_ioctl(struct drm_device *dev, void *data,
-+                  struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_busy *args = data;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL) {
-+              DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n",
-+                        args->handle);
-+              mutex_unlock(&dev->struct_mutex);
-+              return -EBADF;
-+      }
-+
-+      obj_priv = obj->driver_private;
-+      args->busy = obj_priv->active;
-+
-+      drm_gem_object_unreference(obj);
-+      mutex_unlock(&dev->struct_mutex);
-+      return 0;
-+}
-+
-+int
-+i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv)
-+{
-+    return i915_gem_ring_throttle(dev, file_priv);
-+}
-+
-+int i915_gem_init_object(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER);
-+      if (obj_priv == NULL)
-+              return -ENOMEM;
-+
-+      /*
-+       * We've just allocated pages from the kernel,
-+       * so they've just been written by the CPU with
-+       * zeros. They'll need to be clflushed before we
-+       * use them with the GPU.
-+       */
-+      obj->write_domain = I915_GEM_DOMAIN_CPU;
-+      obj->read_domains = I915_GEM_DOMAIN_CPU;
-+
-+      obj->driver_private = obj_priv;
-+      obj_priv->obj = obj;
-+      INIT_LIST_HEAD(&obj_priv->list);
-+      return 0;
-+}
-+
-+void i915_gem_free_object(struct drm_gem_object *obj)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+
-+      while (obj_priv->pin_count > 0)
-+              i915_gem_object_unpin(obj);
-+
-+      i915_gem_object_unbind(obj);
-+
-+      drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
-+      drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
-+}
-+
-+static int
-+i915_gem_set_domain(struct drm_gem_object *obj,
-+                  struct drm_file *file_priv,
-+                  uint32_t read_domains,
-+                  uint32_t write_domain)
-+{
-+      struct drm_device *dev = obj->dev;
-+      int ret;
-+      uint32_t flush_domains;
-+
-+      BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-+
-+      ret = i915_gem_object_set_domain(obj, read_domains, write_domain);
-+      if (ret)
-+              return ret;
-+      flush_domains = i915_gem_dev_set_domain(obj->dev);
-+
-+      if (flush_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT))
-+              (void) i915_add_request(dev, flush_domains);
-+
-+      return 0;
-+}
-+
-+/** Unbinds all objects that are on the given buffer list. */
-+static int
-+i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
-+{
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret;
-+
-+      while (!list_empty(head)) {
-+              obj_priv = list_first_entry(head,
-+                                          struct drm_i915_gem_object,
-+                                          list);
-+              obj = obj_priv->obj;
-+
-+              if (obj_priv->pin_count != 0) {
-+                      DRM_ERROR("Pinned object in unbind list\n");
-+                      mutex_unlock(&dev->struct_mutex);
-+                      return -EINVAL;
-+              }
-+
-+              ret = i915_gem_object_unbind(obj);
-+              if (ret != 0) {
-+                      DRM_ERROR("Error unbinding object in LeaveVT: %d\n",
-+                                ret);
-+                      mutex_unlock(&dev->struct_mutex);
-+                      return ret;
-+              }
-+      }
-+
-+
-+      return 0;
-+}
-+
-+static int
-+i915_gem_idle(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      uint32_t seqno, cur_seqno, last_seqno;
-+      int stuck, ret;
-+
-+      if (dev_priv->mm.suspended)
-+              return 0;
-+
-+      /* Hack!  Don't let anybody do execbuf while we don't control the chip.
-+       * We need to replace this with a semaphore, or something.
-+       */
-+      dev_priv->mm.suspended = 1;
-+
-+      i915_kernel_lost_context(dev);
-+
-+      /* Flush the GPU along with all non-CPU write domains
-+       */
-+      i915_gem_flush(dev, ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT),
-+                     ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
-+      seqno = i915_add_request(dev, ~(I915_GEM_DOMAIN_CPU |
-+                                      I915_GEM_DOMAIN_GTT));
-+
-+      if (seqno == 0) {
-+              mutex_unlock(&dev->struct_mutex);
-+              return -ENOMEM;
-+      }
-+
-+      dev_priv->mm.waiting_gem_seqno = seqno;
-+      last_seqno = 0;
-+      stuck = 0;
-+      for (;;) {
-+              cur_seqno = i915_get_gem_seqno(dev);
-+              if (i915_seqno_passed(cur_seqno, seqno))
-+                      break;
-+              if (last_seqno == cur_seqno) {
-+                      if (stuck++ > 100) {
-+                              DRM_ERROR("hardware wedged\n");
-+                              dev_priv->mm.wedged = 1;
-+                              DRM_WAKEUP(&dev_priv->irq_queue);
-+                              break;
-+                      }
-+              }
-+              msleep(10);
-+              last_seqno = cur_seqno;
-+      }
-+      dev_priv->mm.waiting_gem_seqno = 0;
-+
-+      i915_gem_retire_requests(dev);
-+
-+      /* Active and flushing should now be empty as we've
-+       * waited for a sequence higher than any pending execbuffer
-+       */
-+      BUG_ON(!list_empty(&dev_priv->mm.active_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
-+
-+      /* Request should now be empty as we've also waited
-+       * for the last request in the list
-+       */
-+      BUG_ON(!list_empty(&dev_priv->mm.request_list));
-+
-+      /* Move all buffers out of the GTT. */
-+      ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
-+      if (ret)
-+              return ret;
-+
-+      BUG_ON(!list_empty(&dev_priv->mm.active_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.request_list));
-+      return 0;
-+}
-+
-+static int
-+i915_gem_init_hws(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret;
-+
-+      /* If we need a physical address for the status page, it's already
-+       * initialized at driver load time.
-+       */
-+      if (!I915_NEED_GFX_HWS(dev))
-+              return 0;
-+
-+      obj = drm_gem_object_alloc(dev, 4096);
-+      if (obj == NULL) {
-+              DRM_ERROR("Failed to allocate status page\n");
-+              return -ENOMEM;
-+      }
-+      obj_priv = obj->driver_private;
-+
-+      ret = i915_gem_object_pin(obj, 4096);
-+      if (ret != 0) {
-+              drm_gem_object_unreference(obj);
-+              return ret;
-+      }
-+
-+      dev_priv->status_gfx_addr = obj_priv->gtt_offset;
-+      dev_priv->hws_map.offset = dev->agp->base + obj_priv->gtt_offset;
-+      dev_priv->hws_map.size = 4096;
-+      dev_priv->hws_map.type = 0;
-+      dev_priv->hws_map.flags = 0;
-+      dev_priv->hws_map.mtrr = 0;
-+
-+      drm_core_ioremap(&dev_priv->hws_map, dev);
-+      if (dev_priv->hws_map.handle == NULL) {
-+              DRM_ERROR("Failed to map status page.\n");
-+              memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-+              drm_gem_object_unreference(obj);
-+              return -EINVAL;
-+      }
-+      dev_priv->hws_obj = obj;
-+      dev_priv->hw_status_page = dev_priv->hws_map.handle;
-+      memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-+      I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-+      DRM_DEBUG("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
-+
-+      return 0;
-+}
-+
-+static int
-+i915_gem_init_ringbuffer(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+      int ret;
-+
-+      ret = i915_gem_init_hws(dev);
-+      if (ret != 0)
-+              return ret;
-+
-+      obj = drm_gem_object_alloc(dev, 128 * 1024);
-+      if (obj == NULL) {
-+              DRM_ERROR("Failed to allocate ringbuffer\n");
-+              return -ENOMEM;
-+      }
-+      obj_priv = obj->driver_private;
-+
-+      ret = i915_gem_object_pin(obj, 4096);
-+      if (ret != 0) {
-+              drm_gem_object_unreference(obj);
-+              return ret;
-+      }
-+
-+      /* Set up the kernel mapping for the ring. */
-+      dev_priv->ring.Size = obj->size;
-+      dev_priv->ring.tail_mask = obj->size - 1;
-+
-+      dev_priv->ring.map.offset = dev->agp->base + obj_priv->gtt_offset;
-+      dev_priv->ring.map.size = obj->size;
-+      dev_priv->ring.map.type = 0;
-+      dev_priv->ring.map.flags = 0;
-+      dev_priv->ring.map.mtrr = 0;
-+
-+      drm_core_ioremap(&dev_priv->ring.map, dev);
-+      if (dev_priv->ring.map.handle == NULL) {
-+              DRM_ERROR("Failed to map ringbuffer.\n");
-+              memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
-+              drm_gem_object_unreference(obj);
-+              return -EINVAL;
-+      }
-+      dev_priv->ring.ring_obj = obj;
-+      dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-+
-+      /* Stop the ring if it's running. */
-+      I915_WRITE(PRB0_CTL, 0);
-+      I915_WRITE(PRB0_HEAD, 0);
-+      I915_WRITE(PRB0_TAIL, 0);
-+      I915_WRITE(PRB0_START, 0);
-+
-+      /* Initialize the ring. */
-+      I915_WRITE(PRB0_START, obj_priv->gtt_offset);
-+      I915_WRITE(PRB0_CTL,
-+                 ((obj->size - 4096) & RING_NR_PAGES) |
-+                 RING_NO_REPORT |
-+                 RING_VALID);
-+
-+      /* Update our cache of the ring state */
-+      i915_kernel_lost_context(dev);
-+
-+      return 0;
-+}
-+
-+static void
-+i915_gem_cleanup_ringbuffer(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      if (dev_priv->ring.ring_obj == NULL)
-+              return;
-+
-+      drm_core_ioremapfree(&dev_priv->ring.map, dev);
-+
-+      i915_gem_object_unpin(dev_priv->ring.ring_obj);
-+      drm_gem_object_unreference(dev_priv->ring.ring_obj);
-+      dev_priv->ring.ring_obj = NULL;
-+      memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
-+
-+      if (dev_priv->hws_obj != NULL) {
-+              i915_gem_object_unpin(dev_priv->hws_obj);
-+              drm_gem_object_unreference(dev_priv->hws_obj);
-+              dev_priv->hws_obj = NULL;
-+              memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-+
-+              /* Write high address into HWS_PGA when disabling. */
-+              I915_WRITE(HWS_PGA, 0x1ffff000);
-+      }
-+}
-+
-+int
-+i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
-+                     struct drm_file *file_priv)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      int ret;
-+
-+      if (dev_priv->mm.wedged) {
-+              DRM_ERROR("Reenabling wedged hardware, good luck\n");
-+              dev_priv->mm.wedged = 0;
-+      }
-+
-+      ret = i915_gem_init_ringbuffer(dev);
-+      if (ret != 0)
-+              return ret;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      BUG_ON(!list_empty(&dev_priv->mm.active_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
-+      BUG_ON(!list_empty(&dev_priv->mm.request_list));
-+      dev_priv->mm.suspended = 0;
-+      mutex_unlock(&dev->struct_mutex);
-+      return 0;
-+}
-+
-+int
-+i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
-+                     struct drm_file *file_priv)
-+{
-+      int ret;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      ret = i915_gem_idle(dev);
-+      if (ret == 0)
-+              i915_gem_cleanup_ringbuffer(dev);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return 0;
-+}
-+
-+void
-+i915_gem_lastclose(struct drm_device *dev)
-+{
-+      int ret;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      if (dev_priv->ring.ring_obj != NULL) {
-+              ret = i915_gem_idle(dev);
-+              if (ret)
-+                      DRM_ERROR("failed to idle hardware: %d\n", ret);
-+
-+              i915_gem_cleanup_ringbuffer(dev);
-+      }
-+
-+      mutex_unlock(&dev->struct_mutex);
-+}
-+
-+void
-+i915_gem_load(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+
-+      INIT_LIST_HEAD(&dev_priv->mm.active_list);
-+      INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
-+      INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
-+      INIT_LIST_HEAD(&dev_priv->mm.request_list);
-+      INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
-+                        i915_gem_retire_work_handler);
-+      dev_priv->mm.next_gem_seqno = 1;
-+
-+      i915_gem_detect_bit_6_swizzle(dev);
-+}
-diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c
-new file mode 100644
-index 0000000..131c088
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
-@@ -0,0 +1,201 @@
-+/*
-+ * Copyright Â© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Keith Packard <keithp@keithp.com>
-+ *
-+ */
-+
-+#include "drmP.h"
-+#include "drm.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+
-+#if WATCH_INACTIVE
-+void
-+i915_verify_inactive(struct drm_device *dev, char *file, int line)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
-+              obj = obj_priv->obj;
-+              if (obj_priv->pin_count || obj_priv->active ||
-+                  (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
-+                                         I915_GEM_DOMAIN_GTT)))
-+                      DRM_ERROR("inactive %p (p %d a %d w %x)  %s:%d\n",
-+                                obj,
-+                                obj_priv->pin_count, obj_priv->active,
-+                                obj->write_domain, file, line);
-+      }
-+}
-+#endif /* WATCH_INACTIVE */
-+
-+
-+#if WATCH_BUF | WATCH_EXEC | WATCH_PWRITE
-+static void
-+i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end,
-+                 uint32_t bias, uint32_t mark)
-+{
-+      uint32_t *mem = kmap_atomic(page, KM_USER0);
-+      int i;
-+      for (i = start; i < end; i += 4)
-+              DRM_INFO("%08x: %08x%s\n",
-+                        (int) (bias + i), mem[i / 4],
-+                        (bias + i == mark) ? " ********" : "");
-+      kunmap_atomic(mem, KM_USER0);
-+      /* give syslog time to catch up */
-+      msleep(1);
-+}
-+
-+void
-+i915_gem_dump_object(struct drm_gem_object *obj, int len,
-+                   const char *where, uint32_t mark)
-+{
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int page;
-+
-+      DRM_INFO("%s: object at offset %08x\n", where, obj_priv->gtt_offset);
-+      for (page = 0; page < (len + PAGE_SIZE-1) / PAGE_SIZE; page++) {
-+              int page_len, chunk, chunk_len;
-+
-+              page_len = len - page * PAGE_SIZE;
-+              if (page_len > PAGE_SIZE)
-+                      page_len = PAGE_SIZE;
-+
-+              for (chunk = 0; chunk < page_len; chunk += 128) {
-+                      chunk_len = page_len - chunk;
-+                      if (chunk_len > 128)
-+                              chunk_len = 128;
-+                      i915_gem_dump_page(obj_priv->page_list[page],
-+                                         chunk, chunk + chunk_len,
-+                                         obj_priv->gtt_offset +
-+                                         page * PAGE_SIZE,
-+                                         mark);
-+              }
-+      }
-+}
-+#endif
-+
-+#if WATCH_LRU
-+void
-+i915_dump_lru(struct drm_device *dev, const char *where)
-+{
-+      drm_i915_private_t              *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object      *obj_priv;
-+
-+      DRM_INFO("active list %s {\n", where);
-+      list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
-+                          list)
-+      {
-+              DRM_INFO("    %p: %08x\n", obj_priv,
-+                       obj_priv->last_rendering_seqno);
-+      }
-+      DRM_INFO("}\n");
-+      DRM_INFO("flushing list %s {\n", where);
-+      list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
-+                          list)
-+      {
-+              DRM_INFO("    %p: %08x\n", obj_priv,
-+                       obj_priv->last_rendering_seqno);
-+      }
-+      DRM_INFO("}\n");
-+      DRM_INFO("inactive %s {\n", where);
-+      list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
-+              DRM_INFO("    %p: %08x\n", obj_priv,
-+                       obj_priv->last_rendering_seqno);
-+      }
-+      DRM_INFO("}\n");
-+}
-+#endif
-+
-+
-+#if WATCH_COHERENCY
-+void
-+i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
-+{
-+      struct drm_device *dev = obj->dev;
-+      struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+      int page;
-+      uint32_t *gtt_mapping;
-+      uint32_t *backing_map = NULL;
-+      int bad_count = 0;
-+
-+      DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n",
-+               __func__, obj, obj_priv->gtt_offset, handle,
-+               obj->size / 1024);
-+
-+      gtt_mapping = ioremap(dev->agp->base + obj_priv->gtt_offset,
-+                            obj->size);
-+      if (gtt_mapping == NULL) {
-+              DRM_ERROR("failed to map GTT space\n");
-+              return;
-+      }
-+
-+      for (page = 0; page < obj->size / PAGE_SIZE; page++) {
-+              int i;
-+
-+              backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0);
-+
-+              if (backing_map == NULL) {
-+                      DRM_ERROR("failed to map backing page\n");
-+                      goto out;
-+              }
-+
-+              for (i = 0; i < PAGE_SIZE / 4; i++) {
-+                      uint32_t cpuval = backing_map[i];
-+                      uint32_t gttval = readl(gtt_mapping +
-+                                              page * 1024 + i);
-+
-+                      if (cpuval != gttval) {
-+                              DRM_INFO("incoherent CPU vs GPU at 0x%08x: "
-+                                       "0x%08x vs 0x%08x\n",
-+                                       (int)(obj_priv->gtt_offset +
-+                                             page * PAGE_SIZE + i * 4),
-+                                       cpuval, gttval);
-+                              if (bad_count++ >= 8) {
-+                                      DRM_INFO("...\n");
-+                                      goto out;
-+                              }
-+                      }
-+              }
-+              kunmap_atomic(backing_map, KM_USER0);
-+              backing_map = NULL;
-+      }
-+
-+ out:
-+      if (backing_map != NULL)
-+              kunmap_atomic(backing_map, KM_USER0);
-+      iounmap(gtt_mapping);
-+
-+      /* give syslog time to catch up */
-+      msleep(1);
-+
-+      /* Directly flush the object, since we just loaded values with the CPU
-+       * from the backing pages and we don't want to disturb the cache
-+       * management that we're trying to observe.
-+       */
-+
-+      i915_gem_clflush_object(obj);
-+}
-+#endif
-diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c
-new file mode 100644
-index 0000000..15d4160
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_gem_proc.c
-@@ -0,0 +1,292 @@
-+/*
-+ * Copyright Â© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Eric Anholt <eric@anholt.net>
-+ *    Keith Packard <keithp@keithp.com>
-+ *
-+ */
-+
-+#include "drmP.h"
-+#include "drm.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+
-+static int i915_gem_active_info(char *buf, char **start, off_t offset,
-+                              int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Active:\n");
-+      list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
-+                          list)
-+      {
-+              struct drm_gem_object *obj = obj_priv->obj;
-+              if (obj->name) {
-+                      DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
-+                                     obj, obj->name,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              } else {
-+                      DRM_PROC_PRINT("       %p: %08x %08x %d\n",
-+                                     obj,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              }
-+      }
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static int i915_gem_flushing_info(char *buf, char **start, off_t offset,
-+                                int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Flushing:\n");
-+      list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
-+                          list)
-+      {
-+              struct drm_gem_object *obj = obj_priv->obj;
-+              if (obj->name) {
-+                      DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
-+                                     obj, obj->name,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              } else {
-+                      DRM_PROC_PRINT("       %p: %08x %08x %d\n", obj,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              }
-+      }
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static int i915_gem_inactive_info(char *buf, char **start, off_t offset,
-+                                int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_object *obj_priv;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Inactive:\n");
-+      list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list,
-+                          list)
-+      {
-+              struct drm_gem_object *obj = obj_priv->obj;
-+              if (obj->name) {
-+                      DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
-+                                     obj, obj->name,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              } else {
-+                      DRM_PROC_PRINT("       %p: %08x %08x %d\n", obj,
-+                                     obj->read_domains, obj->write_domain,
-+                                     obj_priv->last_rendering_seqno);
-+              }
-+      }
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static int i915_gem_request_info(char *buf, char **start, off_t offset,
-+                               int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_i915_gem_request *gem_request;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Request:\n");
-+      list_for_each_entry(gem_request, &dev_priv->mm.request_list,
-+                          list)
-+      {
-+              DRM_PROC_PRINT("    %d @ %d %08x\n",
-+                             gem_request->seqno,
-+                             (int) (jiffies - gem_request->emitted_jiffies),
-+                             gem_request->flush_domains);
-+      }
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static int i915_gem_seqno_info(char *buf, char **start, off_t offset,
-+                             int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Current sequence: %d\n", i915_get_gem_seqno(dev));
-+      DRM_PROC_PRINT("Waiter sequence:  %d\n",
-+                     dev_priv->mm.waiting_gem_seqno);
-+      DRM_PROC_PRINT("IRQ sequence:     %d\n", dev_priv->mm.irq_gem_seqno);
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+
-+static int i915_interrupt_info(char *buf, char **start, off_t offset,
-+                             int request, int *eof, void *data)
-+{
-+      struct drm_minor *minor = (struct drm_minor *) data;
-+      struct drm_device *dev = minor->dev;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      int len = 0;
-+
-+      if (offset > DRM_PROC_LIMIT) {
-+              *eof = 1;
-+              return 0;
-+      }
-+
-+      *start = &buf[offset];
-+      *eof = 0;
-+      DRM_PROC_PRINT("Interrupt enable:    %08x\n",
-+                     I915_READ(IER));
-+      DRM_PROC_PRINT("Interrupt identity:  %08x\n",
-+                     I915_READ(IIR));
-+      DRM_PROC_PRINT("Interrupt mask:      %08x\n",
-+                     I915_READ(IMR));
-+      DRM_PROC_PRINT("Pipe A stat:         %08x\n",
-+                     I915_READ(PIPEASTAT));
-+      DRM_PROC_PRINT("Pipe B stat:         %08x\n",
-+                     I915_READ(PIPEBSTAT));
-+      DRM_PROC_PRINT("Interrupts received: %d\n",
-+                     atomic_read(&dev_priv->irq_received));
-+      DRM_PROC_PRINT("Current sequence:    %d\n",
-+                     i915_get_gem_seqno(dev));
-+      DRM_PROC_PRINT("Waiter sequence:     %d\n",
-+                     dev_priv->mm.waiting_gem_seqno);
-+      DRM_PROC_PRINT("IRQ sequence:        %d\n",
-+                     dev_priv->mm.irq_gem_seqno);
-+      if (len > request + offset)
-+              return request;
-+      *eof = 1;
-+      return len - offset;
-+}
-+
-+static struct drm_proc_list {
-+      /** file name */
-+      const char *name;
-+      /** proc callback*/
-+      int (*f) (char *, char **, off_t, int, int *, void *);
-+} i915_gem_proc_list[] = {
-+      {"i915_gem_active", i915_gem_active_info},
-+      {"i915_gem_flushing", i915_gem_flushing_info},
-+      {"i915_gem_inactive", i915_gem_inactive_info},
-+      {"i915_gem_request", i915_gem_request_info},
-+      {"i915_gem_seqno", i915_gem_seqno_info},
-+      {"i915_gem_interrupt", i915_interrupt_info},
-+};
-+
-+#define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list)
-+
-+int i915_gem_proc_init(struct drm_minor *minor)
-+{
-+      struct proc_dir_entry *ent;
-+      int i, j;
-+
-+      for (i = 0; i < I915_GEM_PROC_ENTRIES; i++) {
-+              ent = create_proc_entry(i915_gem_proc_list[i].name,
-+                                      S_IFREG | S_IRUGO, minor->dev_root);
-+              if (!ent) {
-+                      DRM_ERROR("Cannot create /proc/dri/.../%s\n",
-+                                i915_gem_proc_list[i].name);
-+                      for (j = 0; j < i; j++)
-+                              remove_proc_entry(i915_gem_proc_list[i].name,
-+                                                minor->dev_root);
-+                      return -1;
-+              }
-+              ent->read_proc = i915_gem_proc_list[i].f;
-+              ent->data = minor;
-+      }
-+      return 0;
-+}
-+
-+void i915_gem_proc_cleanup(struct drm_minor *minor)
-+{
-+      int i;
-+
-+      if (!minor->dev_root)
-+              return;
-+
-+      for (i = 0; i < I915_GEM_PROC_ENTRIES; i++)
-+              remove_proc_entry(i915_gem_proc_list[i].name, minor->dev_root);
-+}
-diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
-new file mode 100644
-index 0000000..0c1b3a0
---- /dev/null
-+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
-@@ -0,0 +1,256 @@
-+/*
-+ * Copyright Â© 2008 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ * Authors:
-+ *    Eric Anholt <eric@anholt.net>
-+ *
-+ */
-+
-+#include "drmP.h"
-+#include "drm.h"
-+#include "i915_drm.h"
-+#include "i915_drv.h"
-+
-+/** @file i915_gem_tiling.c
-+ *
-+ * Support for managing tiling state of buffer objects.
-+ *
-+ * The idea behind tiling is to increase cache hit rates by rearranging
-+ * pixel data so that a group of pixel accesses are in the same cacheline.
-+ * Performance improvement from doing this on the back/depth buffer are on
-+ * the order of 30%.
-+ *
-+ * Intel architectures make this somewhat more complicated, though, by
-+ * adjustments made to addressing of data when the memory is in interleaved
-+ * mode (matched pairs of DIMMS) to improve memory bandwidth.
-+ * For interleaved memory, the CPU sends every sequential 64 bytes
-+ * to an alternate memory channel so it can get the bandwidth from both.
-+ *
-+ * The GPU also rearranges its accesses for increased bandwidth to interleaved
-+ * memory, and it matches what the CPU does for non-tiled.  However, when tiled
-+ * it does it a little differently, since one walks addresses not just in the
-+ * X direction but also Y.  So, along with alternating channels when bit
-+ * 6 of the address flips, it also alternates when other bits flip --  Bits 9
-+ * (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines)
-+ * are common to both the 915 and 965-class hardware.
-+ *
-+ * The CPU also sometimes XORs in higher bits as well, to improve
-+ * bandwidth doing strided access like we do so frequently in graphics.  This
-+ * is called "Channel XOR Randomization" in the MCH documentation.  The result
-+ * is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address
-+ * decode.
-+ *
-+ * All of this bit 6 XORing has an effect on our memory management,
-+ * as we need to make sure that the 3d driver can correctly address object
-+ * contents.
-+ *
-+ * If we don't have interleaved memory, all tiling is safe and no swizzling is
-+ * required.
-+ *
-+ * When bit 17 is XORed in, we simply refuse to tile at all.  Bit
-+ * 17 is not just a page offset, so as we page an objet out and back in,
-+ * individual pages in it will have different bit 17 addresses, resulting in
-+ * each 64 bytes being swapped with its neighbor!
-+ *
-+ * Otherwise, if interleaved, we have to tell the 3d driver what the address
-+ * swizzling it needs to do is, since it's writing with the CPU to the pages
-+ * (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the
-+ * pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling
-+ * required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order
-+ * to match what the GPU expects.
-+ */
-+
-+/**
-+ * Detects bit 6 swizzling of address lookup between IGD access and CPU
-+ * access through main memory.
-+ */
-+void
-+i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
-+{
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-+      uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-+
-+      if (!IS_I9XX(dev)) {
-+              /* As far as we know, the 865 doesn't have these bit 6
-+               * swizzling issues.
-+               */
-+              swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-+              swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-+      } else if (!IS_I965G(dev) || IS_I965GM(dev)) {
-+              uint32_t dcc;
-+
-+              /* On 915-945 and GM965, channel interleave by the CPU is
-+               * determined by DCC.  The CPU will alternate based on bit 6
-+               * in interleaved mode, and the GPU will then also alternate
-+               * on bit 6, 9, and 10 for X, but the CPU may also optionally
-+               * alternate based on bit 17 (XOR not disabled and XOR
-+               * bit == 17).
-+               */
-+              dcc = I915_READ(DCC);
-+              switch (dcc & DCC_ADDRESSING_MODE_MASK) {
-+              case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
-+              case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
-+                      swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-+                      swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-+                      break;
-+              case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
-+                      if (IS_I915G(dev) || IS_I915GM(dev) ||
-+                          dcc & DCC_CHANNEL_XOR_DISABLE) {
-+                              swizzle_x = I915_BIT_6_SWIZZLE_9_10;
-+                              swizzle_y = I915_BIT_6_SWIZZLE_9;
-+                      } else if (IS_I965GM(dev)) {
-+                              /* GM965 only does bit 11-based channel
-+                               * randomization
-+                               */
-+                              swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
-+                              swizzle_y = I915_BIT_6_SWIZZLE_9_11;
-+                      } else {
-+                              /* Bit 17 or perhaps other swizzling */
-+                              swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-+                              swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-+                      }
-+                      break;
-+              }
-+              if (dcc == 0xffffffff) {
-+                      DRM_ERROR("Couldn't read from MCHBAR.  "
-+                                "Disabling tiling.\n");
-+                      swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-+                      swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-+              }
-+      } else {
-+              /* The 965, G33, and newer, have a very flexible memory
-+               * configuration.  It will enable dual-channel mode
-+               * (interleaving) on as much memory as it can, and the GPU
-+               * will additionally sometimes enable different bit 6
-+               * swizzling for tiled objects from the CPU.
-+               *
-+               * Here's what I found on the G965:
-+               *    slot fill         memory size  swizzling
-+               * 0A   0B   1A   1B    1-ch   2-ch
-+               * 512  0    0    0     512    0     O
-+               * 512  0    512  0     16     1008  X
-+               * 512  0    0    512   16     1008  X
-+               * 0    512  0    512   16     1008  X
-+               * 1024 1024 1024 0     2048   1024  O
-+               *
-+               * We could probably detect this based on either the DRB
-+               * matching, which was the case for the swizzling required in
-+               * the table above, or from the 1-ch value being less than
-+               * the minimum size of a rank.
-+               */
-+              if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) {
-+                      swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-+                      swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-+              } else {
-+                      swizzle_x = I915_BIT_6_SWIZZLE_9_10;
-+                      swizzle_y = I915_BIT_6_SWIZZLE_9;
-+              }
-+      }
-+
-+      dev_priv->mm.bit_6_swizzle_x = swizzle_x;
-+      dev_priv->mm.bit_6_swizzle_y = swizzle_y;
-+}
-+
-+/**
-+ * Sets the tiling mode of an object, returning the required swizzling of
-+ * bit 6 of addresses in the object.
-+ */
-+int
-+i915_gem_set_tiling(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_set_tiling *args = data;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EINVAL;
-+      obj_priv = obj->driver_private;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      if (args->tiling_mode == I915_TILING_NONE) {
-+              obj_priv->tiling_mode = I915_TILING_NONE;
-+              args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
-+      } else {
-+              if (args->tiling_mode == I915_TILING_X)
-+                      args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
-+              else
-+                      args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
-+              /* If we can't handle the swizzling, make it untiled. */
-+              if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
-+                      args->tiling_mode = I915_TILING_NONE;
-+                      args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
-+              }
-+      }
-+      obj_priv->tiling_mode = args->tiling_mode;
-+
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      drm_gem_object_unreference(obj);
-+
-+      return 0;
-+}
-+
-+/**
-+ * Returns the current tiling mode and required bit 6 swizzling for the object.
-+ */
-+int
-+i915_gem_get_tiling(struct drm_device *dev, void *data,
-+                 struct drm_file *file_priv)
-+{
-+      struct drm_i915_gem_get_tiling *args = data;
-+      drm_i915_private_t *dev_priv = dev->dev_private;
-+      struct drm_gem_object *obj;
-+      struct drm_i915_gem_object *obj_priv;
-+
-+      obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-+      if (obj == NULL)
-+              return -EINVAL;
-+      obj_priv = obj->driver_private;
-+
-+      mutex_lock(&dev->struct_mutex);
-+
-+      args->tiling_mode = obj_priv->tiling_mode;
-+      switch (obj_priv->tiling_mode) {
-+      case I915_TILING_X:
-+              args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
-+              break;
-+      case I915_TILING_Y:
-+              args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
-+              break;
-+      case I915_TILING_NONE:
-+              args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
-+              break;
-+      default:
-+              DRM_ERROR("unknown tiling mode\n");
-+      }
-+
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      drm_gem_object_unreference(obj);
-+
-+      return 0;
-+}
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index f875959..f295bdf 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -407,15 +407,20 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-               I915_WRITE(PIPEBSTAT, pipeb_stats);
-       }
--      if (iir & I915_ASLE_INTERRUPT)
--              opregion_asle_intr(dev);
-+      I915_WRITE(IIR, iir);
-+      if (dev->pdev->msi_enabled)
-+              I915_WRITE(IMR, dev_priv->irq_mask_reg);
-+      (void) I915_READ(IIR); /* Flush posted writes */
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
--      if (dev->pdev->msi_enabled)
--              I915_WRITE(IMR, dev_priv->irq_mask_reg);
--      I915_WRITE(IIR, iir);
--      (void) I915_READ(IIR);
-+      if (iir & I915_USER_INTERRUPT) {
-+              dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
-+              DRM_WAKEUP(&dev_priv->irq_queue);
-+      }
-+
-+      if (iir & I915_ASLE_INTERRUPT)
-+              opregion_asle_intr(dev);
-       if (vblank && dev_priv->swaps_pending > 0)
-               drm_locked_tasklet(dev, i915_vblank_tasklet);
-@@ -449,7 +454,7 @@ static int i915_emit_irq(struct drm_device * dev)
-       return dev_priv->counter;
- }
--static void i915_user_irq_get(struct drm_device *dev)
-+void i915_user_irq_get(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
-index 43ad2cb..5c2d9f2 100644
---- a/drivers/gpu/drm/i915/i915_reg.h
-+++ b/drivers/gpu/drm/i915/i915_reg.h
-@@ -25,19 +25,6 @@
- #ifndef _I915_REG_H_
- #define _I915_REG_H_
--/* MCH MMIO space */
--/** 915-945 and GM965 MCH register controlling DRAM channel access */
--#define DCC           0x200
--#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL            (0 << 0)
--#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC   (1 << 0)
--#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED  (2 << 0)
--#define DCC_ADDRESSING_MODE_MASK                      (3 << 0)
--#define DCC_CHANNEL_XOR_DISABLE                               (1 << 10)
--
--/** 965 MCH register controlling DRAM channel configuration */
--#define CHDECMISC             0x111
--#define CHDECMISC_FLEXMEMORY          (1 << 1)
--
- /*
-  * The Bridge device's PCI config space has information about the
-  * fb aperture size and the amount of pre-reserved memory.
-@@ -516,6 +503,30 @@
- #define PALETTE_A             0x0a000
- #define PALETTE_B             0x0a800
-+/* MCH MMIO space */
-+
-+/*
-+ * MCHBAR mirror.
-+ *
-+ * This mirrors the MCHBAR MMIO space whose location is determined by
-+ * device 0 function 0's pci config register 0x44 or 0x48 and matches it in
-+ * every way.  It is not accessible from the CP register read instructions.
-+ *
-+ */
-+#define MCHBAR_MIRROR_BASE    0x10000
-+
-+/** 915-945 and GM965 MCH register controlling DRAM channel access */
-+#define DCC                   0x10200
-+#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL            (0 << 0)
-+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC   (1 << 0)
-+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED  (2 << 0)
-+#define DCC_ADDRESSING_MODE_MASK                      (3 << 0)
-+#define DCC_CHANNEL_XOR_DISABLE                               (1 << 10)
-+
-+/** 965 MCH register controlling DRAM channel configuration */
-+#define C0DRB3                        0x10206
-+#define C1DRB3                        0x10606
-+
- /*
-  * Overlay regs
-  */
-diff --git a/include/drm/drm.h b/include/drm/drm.h
-index 15e5503..f46ba4b 100644
---- a/include/drm/drm.h
-+++ b/include/drm/drm.h
-@@ -570,6 +570,34 @@ struct drm_set_version {
-       int drm_dd_minor;
- };
-+/** DRM_IOCTL_GEM_CLOSE ioctl argument type */
-+struct drm_gem_close {
-+      /** Handle of the object to be closed. */
-+      uint32_t handle;
-+      uint32_t pad;
-+};
-+
-+/** DRM_IOCTL_GEM_FLINK ioctl argument type */
-+struct drm_gem_flink {
-+      /** Handle for the object being named */
-+      uint32_t handle;
-+
-+      /** Returned global name */
-+      uint32_t name;
-+};
-+
-+/** DRM_IOCTL_GEM_OPEN ioctl argument type */
-+struct drm_gem_open {
-+      /** Name of object being opened */
-+      uint32_t name;
-+
-+      /** Returned handle for the object */
-+      uint32_t handle;
-+
-+      /** Returned size of the object */
-+      uint64_t size;
-+};
-+
- #define DRM_IOCTL_BASE                        'd'
- #define DRM_IO(nr)                    _IO(DRM_IOCTL_BASE,nr)
- #define DRM_IOR(nr,type)              _IOR(DRM_IOCTL_BASE,nr,type)
-@@ -585,6 +613,9 @@ struct drm_set_version {
- #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
- #define DRM_IOCTL_SET_VERSION         DRM_IOWR(0x07, struct drm_set_version)
- #define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08, struct drm_modeset_ctl)
-+#define DRM_IOCTL_GEM_CLOSE           DRM_IOW (0x09, struct drm_gem_close)
-+#define DRM_IOCTL_GEM_FLINK           DRM_IOWR(0x0a, struct drm_gem_flink)
-+#define DRM_IOCTL_GEM_OPEN            DRM_IOWR(0x0b, struct drm_gem_open)
- #define DRM_IOCTL_SET_UNIQUE          DRM_IOW( 0x10, struct drm_unique)
- #define DRM_IOCTL_AUTH_MAGIC          DRM_IOW( 0x11, struct drm_auth)
-diff --git a/include/drm/drmP.h b/include/drm/drmP.h
-index e79ce07..1469a1b 100644
---- a/include/drm/drmP.h
-+++ b/include/drm/drmP.h
-@@ -104,6 +104,7 @@ struct drm_device;
- #define DRIVER_DMA_QUEUE   0x200
- #define DRIVER_FB_DMA      0x400
- #define DRIVER_IRQ_VBL2    0x800
-+#define DRIVER_GEM         0x1000
- /***********************************************************************/
- /** \name Begin the DRM... */
-@@ -387,6 +388,10 @@ struct drm_file {
-       struct drm_minor *minor;
-       int remove_auth_on_close;
-       unsigned long lock_count;
-+      /** Mapping of mm object handles to object pointers. */
-+      struct idr object_idr;
-+      /** Lock for synchronization of access to object_idr. */
-+      spinlock_t table_lock;
-       struct file *filp;
-       void *driver_priv;
- };
-@@ -558,6 +563,56 @@ struct drm_ati_pcigart_info {
- };
- /**
-+ * This structure defines the drm_mm memory object, which will be used by the
-+ * DRM for its buffer objects.
-+ */
-+struct drm_gem_object {
-+      /** Reference count of this object */
-+      struct kref refcount;
-+
-+      /** Handle count of this object. Each handle also holds a reference */
-+      struct kref handlecount;
-+
-+      /** Related drm device */
-+      struct drm_device *dev;
-+
-+      /** File representing the shmem storage */
-+      struct file *filp;
-+
-+      /**
-+       * Size of the object, in bytes.  Immutable over the object's
-+       * lifetime.
-+       */
-+      size_t size;
-+
-+      /**
-+       * Global name for this object, starts at 1. 0 means unnamed.
-+       * Access is covered by the object_name_lock in the related drm_device
-+       */
-+      int name;
-+
-+      /**
-+       * Memory domains. These monitor which caches contain read/write data
-+       * related to the object. When transitioning from one set of domains
-+       * to another, the driver is called to ensure that caches are suitably
-+       * flushed and invalidated
-+       */
-+      uint32_t read_domains;
-+      uint32_t write_domain;
-+
-+      /**
-+       * While validating an exec operation, the
-+       * new read/write domain values are computed here.
-+       * They will be transferred to the above values
-+       * at the point that any cache flushing occurs
-+       */
-+      uint32_t pending_read_domains;
-+      uint32_t pending_write_domain;
-+
-+      void *driver_private;
-+};
-+
-+/**
-  * DRM driver structure. This structure represent the common code for
-  * a family of cards. There will one drm_device for each card present
-  * in this family
-@@ -657,6 +712,18 @@ struct drm_driver {
-       void (*set_version) (struct drm_device *dev,
-                            struct drm_set_version *sv);
-+      int (*proc_init)(struct drm_minor *minor);
-+      void (*proc_cleanup)(struct drm_minor *minor);
-+
-+      /**
-+       * Driver-specific constructor for drm_gem_objects, to set up
-+       * obj->driver_private.
-+       *
-+       * Returns 0 on success.
-+       */
-+      int (*gem_init_object) (struct drm_gem_object *obj);
-+      void (*gem_free_object) (struct drm_gem_object *obj);
-+
-       int major;
-       int minor;
-       int patchlevel;
-@@ -830,6 +897,22 @@ struct drm_device {
-       spinlock_t drw_lock;
-       struct idr drw_idr;
-       /*@} */
-+
-+      /** \name GEM information */
-+      /*@{ */
-+      spinlock_t object_name_lock;
-+      struct idr object_name_idr;
-+      atomic_t object_count;
-+      atomic_t object_memory;
-+      atomic_t pin_count;
-+      atomic_t pin_memory;
-+      atomic_t gtt_count;
-+      atomic_t gtt_memory;
-+      uint32_t gtt_total;
-+      uint32_t invalidate_domains;    /* domains pending invalidation */
-+      uint32_t flush_domains;         /* domains pending flush */
-+      /*@} */
-+
- };
- static __inline__ int drm_core_check_feature(struct drm_device *dev,
-@@ -926,6 +1009,10 @@ extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
- extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
- extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
- extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
-+extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
-+                                     struct page **pages,
-+                                     unsigned long num_pages,
-+                                     uint32_t gtt_offset);
- extern int drm_unbind_agp(DRM_AGP_MEM * handle);
-                               /* Misc. IOCTL support (drm_ioctl.h) */
-@@ -988,6 +1075,9 @@ extern int drm_getmagic(struct drm_device *dev, void *data,
- extern int drm_authmagic(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-+/* Cache management (drm_cache.c) */
-+void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
-+
-                               /* Locking IOCTL support (drm_lock.h) */
- extern int drm_lock(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv);
-@@ -1094,6 +1184,7 @@ extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size
- extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
- extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
- extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
-+extern void drm_agp_chipset_flush(struct drm_device *dev);
-                               /* Stub support (drm_stub.h) */
- extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
-@@ -1156,6 +1247,66 @@ extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
- extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
- extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
-+/* Graphics Execution Manager library functions (drm_gem.c) */
-+int drm_gem_init(struct drm_device *dev);
-+void drm_gem_object_free(struct kref *kref);
-+struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
-+                                          size_t size);
-+void drm_gem_object_handle_free(struct kref *kref);
-+
-+static inline void
-+drm_gem_object_reference(struct drm_gem_object *obj)
-+{
-+      kref_get(&obj->refcount);
-+}
-+
-+static inline void
-+drm_gem_object_unreference(struct drm_gem_object *obj)
-+{
-+      if (obj == NULL)
-+              return;
-+
-+      kref_put(&obj->refcount, drm_gem_object_free);
-+}
-+
-+int drm_gem_handle_create(struct drm_file *file_priv,
-+                        struct drm_gem_object *obj,
-+                        int *handlep);
-+
-+static inline void
-+drm_gem_object_handle_reference(struct drm_gem_object *obj)
-+{
-+      drm_gem_object_reference(obj);
-+      kref_get(&obj->handlecount);
-+}
-+
-+static inline void
-+drm_gem_object_handle_unreference(struct drm_gem_object *obj)
-+{
-+      if (obj == NULL)
-+              return;
-+
-+      /*
-+       * Must bump handle count first as this may be the last
-+       * ref, in which case the object would disappear before we
-+       * checked for a name
-+       */
-+      kref_put(&obj->handlecount, drm_gem_object_handle_free);
-+      drm_gem_object_unreference(obj);
-+}
-+
-+struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
-+                                           struct drm_file *filp,
-+                                           int handle);
-+int drm_gem_close_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int drm_gem_flink_ioctl(struct drm_device *dev, void *data,
-+                      struct drm_file *file_priv);
-+int drm_gem_open_ioctl(struct drm_device *dev, void *data,
-+                     struct drm_file *file_priv);
-+void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
-+void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
-+
- extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
- extern void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev);
- extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
-diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
-index 05c66cf..59d08fc 100644
---- a/include/drm/i915_drm.h
-+++ b/include/drm/i915_drm.h
-@@ -143,6 +143,22 @@ typedef struct _drm_i915_sarea {
- #define DRM_I915_GET_VBLANK_PIPE      0x0e
- #define DRM_I915_VBLANK_SWAP  0x0f
- #define DRM_I915_HWS_ADDR     0x11
-+#define DRM_I915_GEM_INIT     0x13
-+#define DRM_I915_GEM_EXECBUFFER       0x14
-+#define DRM_I915_GEM_PIN      0x15
-+#define DRM_I915_GEM_UNPIN    0x16
-+#define DRM_I915_GEM_BUSY     0x17
-+#define DRM_I915_GEM_THROTTLE 0x18
-+#define DRM_I915_GEM_ENTERVT  0x19
-+#define DRM_I915_GEM_LEAVEVT  0x1a
-+#define DRM_I915_GEM_CREATE   0x1b
-+#define DRM_I915_GEM_PREAD    0x1c
-+#define DRM_I915_GEM_PWRITE   0x1d
-+#define DRM_I915_GEM_MMAP     0x1e
-+#define DRM_I915_GEM_SET_DOMAIN       0x1f
-+#define DRM_I915_GEM_SW_FINISH        0x20
-+#define DRM_I915_GEM_SET_TILING       0x21
-+#define DRM_I915_GEM_GET_TILING       0x22
- #define DRM_IOCTL_I915_INIT           DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
- #define DRM_IOCTL_I915_FLUSH          DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
-@@ -160,6 +176,20 @@ typedef struct _drm_i915_sarea {
- #define DRM_IOCTL_I915_SET_VBLANK_PIPE        DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
- #define DRM_IOCTL_I915_GET_VBLANK_PIPE        DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
- #define DRM_IOCTL_I915_VBLANK_SWAP    DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
-+#define DRM_IOCTL_I915_GEM_PIN                DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
-+#define DRM_IOCTL_I915_GEM_UNPIN      DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
-+#define DRM_IOCTL_I915_GEM_BUSY               DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
-+#define DRM_IOCTL_I915_GEM_THROTTLE   DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
-+#define DRM_IOCTL_I915_GEM_ENTERVT    DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
-+#define DRM_IOCTL_I915_GEM_LEAVEVT    DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
-+#define DRM_IOCTL_I915_GEM_CREATE     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create)
-+#define DRM_IOCTL_I915_GEM_PREAD      DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread)
-+#define DRM_IOCTL_I915_GEM_PWRITE     DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
-+#define DRM_IOCTL_I915_GEM_MMAP               DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
-+#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
-+#define DRM_IOCTL_I915_GEM_SW_FINISH  DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
-+#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
-+#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
- /* Allow drivers to submit batchbuffers directly to hardware, relying
-  * on the security mechanisms provided by hardware.
-@@ -200,6 +230,7 @@ typedef struct drm_i915_irq_wait {
- #define I915_PARAM_IRQ_ACTIVE            1
- #define I915_PARAM_ALLOW_BATCHBUFFER     2
- #define I915_PARAM_LAST_DISPATCH         3
-+#define I915_PARAM_HAS_GEM               5
- typedef struct drm_i915_getparam {
-       int param;
-@@ -267,4 +298,305 @@ typedef struct drm_i915_hws_addr {
-       uint64_t addr;
- } drm_i915_hws_addr_t;
-+struct drm_i915_gem_init {
-+      /**
-+       * Beginning offset in the GTT to be managed by the DRM memory
-+       * manager.
-+       */
-+      uint64_t gtt_start;
-+      /**
-+       * Ending offset in the GTT to be managed by the DRM memory
-+       * manager.
-+       */
-+      uint64_t gtt_end;
-+};
-+
-+struct drm_i915_gem_create {
-+      /**
-+       * Requested size for the object.
-+       *
-+       * The (page-aligned) allocated size for the object will be returned.
-+       */
-+      uint64_t size;
-+      /**
-+       * Returned handle for the object.
-+       *
-+       * Object handles are nonzero.
-+       */
-+      uint32_t handle;
-+      uint32_t pad;
-+};
-+
-+struct drm_i915_gem_pread {
-+      /** Handle for the object being read. */
-+      uint32_t handle;
-+      uint32_t pad;
-+      /** Offset into the object to read from */
-+      uint64_t offset;
-+      /** Length of data to read */
-+      uint64_t size;
-+      /**
-+       * Pointer to write the data into.
-+       *
-+       * This is a fixed-size type for 32/64 compatibility.
-+       */
-+      uint64_t data_ptr;
-+};
-+
-+struct drm_i915_gem_pwrite {
-+      /** Handle for the object being written to. */
-+      uint32_t handle;
-+      uint32_t pad;
-+      /** Offset into the object to write to */
-+      uint64_t offset;
-+      /** Length of data to write */
-+      uint64_t size;
-+      /**
-+       * Pointer to read the data from.
-+       *
-+       * This is a fixed-size type for 32/64 compatibility.
-+       */
-+      uint64_t data_ptr;
-+};
-+
-+struct drm_i915_gem_mmap {
-+      /** Handle for the object being mapped. */
-+      uint32_t handle;
-+      uint32_t pad;
-+      /** Offset in the object to map. */
-+      uint64_t offset;
-+      /**
-+       * Length of data to map.
-+       *
-+       * The value will be page-aligned.
-+       */
-+      uint64_t size;
-+      /**
-+       * Returned pointer the data was mapped at.
-+       *
-+       * This is a fixed-size type for 32/64 compatibility.
-+       */
-+      uint64_t addr_ptr;
-+};
-+
-+struct drm_i915_gem_set_domain {
-+      /** Handle for the object */
-+      uint32_t handle;
-+
-+      /** New read domains */
-+      uint32_t read_domains;
-+
-+      /** New write domain */
-+      uint32_t write_domain;
-+};
-+
-+struct drm_i915_gem_sw_finish {
-+      /** Handle for the object */
-+      uint32_t handle;
-+};
-+
-+struct drm_i915_gem_relocation_entry {
-+      /**
-+       * Handle of the buffer being pointed to by this relocation entry.
-+       *
-+       * It's appealing to make this be an index into the mm_validate_entry
-+       * list to refer to the buffer, but this allows the driver to create
-+       * a relocation list for state buffers and not re-write it per
-+       * exec using the buffer.
-+       */
-+      uint32_t target_handle;
-+
-+      /**
-+       * Value to be added to the offset of the target buffer to make up
-+       * the relocation entry.
-+       */
-+      uint32_t delta;
-+
-+      /** Offset in the buffer the relocation entry will be written into */
-+      uint64_t offset;
-+
-+      /**
-+       * Offset value of the target buffer that the relocation entry was last
-+       * written as.
-+       *
-+       * If the buffer has the same offset as last time, we can skip syncing
-+       * and writing the relocation.  This value is written back out by
-+       * the execbuffer ioctl when the relocation is written.
-+       */
-+      uint64_t presumed_offset;
-+
-+      /**
-+       * Target memory domains read by this operation.
-+       */
-+      uint32_t read_domains;
-+
-+      /**
-+       * Target memory domains written by this operation.
-+       *
-+       * Note that only one domain may be written by the whole
-+       * execbuffer operation, so that where there are conflicts,
-+       * the application will get -EINVAL back.
-+       */
-+      uint32_t write_domain;
-+};
-+
-+/** @{
-+ * Intel memory domains
-+ *
-+ * Most of these just align with the various caches in
-+ * the system and are used to flush and invalidate as
-+ * objects end up cached in different domains.
-+ */
-+/** CPU cache */
-+#define I915_GEM_DOMAIN_CPU           0x00000001
-+/** Render cache, used by 2D and 3D drawing */
-+#define I915_GEM_DOMAIN_RENDER                0x00000002
-+/** Sampler cache, used by texture engine */
-+#define I915_GEM_DOMAIN_SAMPLER               0x00000004
-+/** Command queue, used to load batch buffers */
-+#define I915_GEM_DOMAIN_COMMAND               0x00000008
-+/** Instruction cache, used by shader programs */
-+#define I915_GEM_DOMAIN_INSTRUCTION   0x00000010
-+/** Vertex address cache */
-+#define I915_GEM_DOMAIN_VERTEX                0x00000020
-+/** GTT domain - aperture and scanout */
-+#define I915_GEM_DOMAIN_GTT           0x00000040
-+/** @} */
-+
-+struct drm_i915_gem_exec_object {
-+      /**
-+       * User's handle for a buffer to be bound into the GTT for this
-+       * operation.
-+       */
-+      uint32_t handle;
-+
-+      /** Number of relocations to be performed on this buffer */
-+      uint32_t relocation_count;
-+      /**
-+       * Pointer to array of struct drm_i915_gem_relocation_entry containing
-+       * the relocations to be performed in this buffer.
-+       */
-+      uint64_t relocs_ptr;
-+
-+      /** Required alignment in graphics aperture */
-+      uint64_t alignment;
-+
-+      /**
-+       * Returned value of the updated offset of the object, for future
-+       * presumed_offset writes.
-+       */
-+      uint64_t offset;
-+};
-+
-+struct drm_i915_gem_execbuffer {
-+      /**
-+       * List of buffers to be validated with their relocations to be
-+       * performend on them.
-+       *
-+       * This is a pointer to an array of struct drm_i915_gem_validate_entry.
-+       *
-+       * These buffers must be listed in an order such that all relocations
-+       * a buffer is performing refer to buffers that have already appeared
-+       * in the validate list.
-+       */
-+      uint64_t buffers_ptr;
-+      uint32_t buffer_count;
-+
-+      /** Offset in the batchbuffer to start execution from. */
-+      uint32_t batch_start_offset;
-+      /** Bytes used in batchbuffer from batch_start_offset */
-+      uint32_t batch_len;
-+      uint32_t DR1;
-+      uint32_t DR4;
-+      uint32_t num_cliprects;
-+      /** This is a struct drm_clip_rect *cliprects */
-+      uint64_t cliprects_ptr;
-+};
-+
-+struct drm_i915_gem_pin {
-+      /** Handle of the buffer to be pinned. */
-+      uint32_t handle;
-+      uint32_t pad;
-+
-+      /** alignment required within the aperture */
-+      uint64_t alignment;
-+
-+      /** Returned GTT offset of the buffer. */
-+      uint64_t offset;
-+};
-+
-+struct drm_i915_gem_unpin {
-+      /** Handle of the buffer to be unpinned. */
-+      uint32_t handle;
-+      uint32_t pad;
-+};
-+
-+struct drm_i915_gem_busy {
-+      /** Handle of the buffer to check for busy */
-+      uint32_t handle;
-+
-+      /** Return busy status (1 if busy, 0 if idle) */
-+      uint32_t busy;
-+};
-+
-+#define I915_TILING_NONE      0
-+#define I915_TILING_X         1
-+#define I915_TILING_Y         2
-+
-+#define I915_BIT_6_SWIZZLE_NONE               0
-+#define I915_BIT_6_SWIZZLE_9          1
-+#define I915_BIT_6_SWIZZLE_9_10               2
-+#define I915_BIT_6_SWIZZLE_9_11               3
-+#define I915_BIT_6_SWIZZLE_9_10_11    4
-+/* Not seen by userland */
-+#define I915_BIT_6_SWIZZLE_UNKNOWN    5
-+
-+struct drm_i915_gem_set_tiling {
-+      /** Handle of the buffer to have its tiling state updated */
-+      uint32_t handle;
-+
-+      /**
-+       * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
-+       * I915_TILING_Y).
-+       *
-+       * This value is to be set on request, and will be updated by the
-+       * kernel on successful return with the actual chosen tiling layout.
-+       *
-+       * The tiling mode may be demoted to I915_TILING_NONE when the system
-+       * has bit 6 swizzling that can't be managed correctly by GEM.
-+       *
-+       * Buffer contents become undefined when changing tiling_mode.
-+       */
-+      uint32_t tiling_mode;
-+
-+      /**
-+       * Stride in bytes for the object when in I915_TILING_X or
-+       * I915_TILING_Y.
-+       */
-+      uint32_t stride;
-+
-+      /**
-+       * Returned address bit 6 swizzling required for CPU access through
-+       * mmap mapping.
-+       */
-+      uint32_t swizzle_mode;
-+};
-+
-+struct drm_i915_gem_get_tiling {
-+      /** Handle of the buffer to get tiling state for. */
-+      uint32_t handle;
-+
-+      /**
-+       * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
-+       * I915_TILING_Y).
-+       */
-+      uint32_t tiling_mode;
-+
-+      /**
-+       * Returned address bit 6 swizzling required for CPU access through
-+       * mmap mapping.
-+       */
-+      uint32_t swizzle_mode;
-+};
-+
- #endif                                /* _I915_DRM_H_ */
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0015-i915-Add-chip-set-ID-param.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0015-i915-Add-chip-set-ID-param.patch
deleted file mode 100644 (file)
index c3bf8eb..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-commit 26ead293ddf664f33dc0ba12b726887c40ce3957
-Author: Kristian Høgsberg <krh@redhat.com>
-Date:   Wed Aug 20 11:08:52 2008 -0400
-
-    i915: Add chip set ID param.
-    
-    Signed-off-by: Kristian Høgsberg <krh@redhat.com>
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 3b5aa74..205d21e 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -689,6 +689,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
-       case I915_PARAM_LAST_DISPATCH:
-               value = READ_BREADCRUMB(dev_priv);
-               break;
-+      case I915_PARAM_CHIPSET_ID:
-+              value = dev->pci_device;
-+              break;
-       case I915_PARAM_HAS_GEM:
-               value = 1;
-               break;
-diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
-index 59d08fc..eb4b350 100644
---- a/include/drm/i915_drm.h
-+++ b/include/drm/i915_drm.h
-@@ -230,6 +230,7 @@ typedef struct drm_i915_irq_wait {
- #define I915_PARAM_IRQ_ACTIVE            1
- #define I915_PARAM_ALLOW_BATCHBUFFER     2
- #define I915_PARAM_LAST_DISPATCH         3
-+#define I915_PARAM_CHIPSET_ID            4
- #define I915_PARAM_HAS_GEM               5
- typedef struct drm_i915_getparam {
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch
deleted file mode 100644 (file)
index 910f37e..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-commit 8a524209fce67d3b6d2e831b5dad4eced796ce98
-Author: Eric Anholt <eric@anholt.net>
-Date:   Mon Sep 1 16:45:29 2008 -0700
-
-    i915: Use struct_mutex to protect ring in GEM mode.
-    
-    In the conversion for GEM, we had stopped using the hardware lock to protect
-    ring usage, since it was all internal to the DRM now.  However, some paths
-    weren't converted to using struct_mutex to prevent multiple threads from
-    concurrently working on the ring, in particular between the vblank swap handler
-    and ioctls.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 205d21e..25f59c1 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -588,9 +588,15 @@ static int i915_quiescent(struct drm_device * dev)
- static int i915_flush_ioctl(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv)
- {
--      LOCK_TEST_WITH_RETURN(dev, file_priv);
-+      int ret;
-+
-+      RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
--      return i915_quiescent(dev);
-+      mutex_lock(&dev->struct_mutex);
-+      ret = i915_quiescent(dev);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return ret;
- }
- static int i915_batchbuffer(struct drm_device *dev, void *data,
-@@ -611,14 +617,16 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
-       DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
-                 batch->start, batch->used, batch->num_cliprects);
--      LOCK_TEST_WITH_RETURN(dev, file_priv);
-+      RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-       if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
-                                                      batch->num_cliprects *
-                                                      sizeof(struct drm_clip_rect)))
-               return -EFAULT;
-+      mutex_lock(&dev->struct_mutex);
-       ret = i915_dispatch_batchbuffer(dev, batch);
-+      mutex_unlock(&dev->struct_mutex);
-       sarea_priv->last_dispatch = (int)hw_status[5];
-       return ret;
-@@ -637,7 +645,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
-       DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
-                 cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
--      LOCK_TEST_WITH_RETURN(dev, file_priv);
-+      RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-       if (cmdbuf->num_cliprects &&
-           DRM_VERIFYAREA_READ(cmdbuf->cliprects,
-@@ -647,7 +655,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
-               return -EFAULT;
-       }
-+      mutex_lock(&dev->struct_mutex);
-       ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
-+      mutex_unlock(&dev->struct_mutex);
-       if (ret) {
-               DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
-               return ret;
-@@ -660,11 +670,17 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
- static int i915_flip_bufs(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
- {
-+      int ret;
-+
-       DRM_DEBUG("%s\n", __FUNCTION__);
--      LOCK_TEST_WITH_RETURN(dev, file_priv);
-+      RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
--      return i915_dispatch_flip(dev);
-+      mutex_lock(&dev->struct_mutex);
-+      ret = i915_dispatch_flip(dev);
-+      mutex_unlock(&dev->struct_mutex);
-+
-+      return ret;
- }
- static int i915_getparam(struct drm_device *dev, void *data,
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index 87b071a..8547f0a 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -285,6 +285,9 @@ typedef struct drm_i915_private {
-                */
-               struct delayed_work retire_work;
-+              /** Work task for vblank-related ring access */
-+              struct work_struct vblank_work;
-+
-               uint32_t next_gem_seqno;
-               /**
-@@ -435,6 +438,7 @@ extern int i915_irq_wait(struct drm_device *dev, void *data,
- void i915_user_irq_get(struct drm_device *dev);
- void i915_user_irq_put(struct drm_device *dev);
-+extern void i915_gem_vblank_work_handler(struct work_struct *work);
- extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
- extern void i915_driver_irq_preinstall(struct drm_device * dev);
- extern int i915_driver_irq_postinstall(struct drm_device *dev);
-@@ -538,6 +542,17 @@ extern void intel_opregion_free(struct drm_device *dev);
- extern void opregion_asle_intr(struct drm_device *dev);
- extern void opregion_enable_asle(struct drm_device *dev);
-+/**
-+ * Lock test for when it's just for synchronization of ring access.
-+ *
-+ * In that case, we don't need to do it when GEM is initialized as nobody else
-+ * has access to the ring.
-+ */
-+#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do {                       \
-+      if (((drm_i915_private_t *)dev->dev_private)->ring.ring_obj == NULL) \
-+              LOCK_TEST_WITH_RETURN(dev, file_priv);                  \
-+} while (0)
-+
- #define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
- #define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
- #define I915_READ16(reg)      DRM_READ16(dev_priv->mmio_map, (reg))
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 90ae8a0..bb6e5a3 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -2491,6 +2491,8 @@ i915_gem_load(struct drm_device *dev)
-       INIT_LIST_HEAD(&dev_priv->mm.request_list);
-       INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
-                         i915_gem_retire_work_handler);
-+      INIT_WORK(&dev_priv->mm.vblank_work,
-+                i915_gem_vblank_work_handler);
-       dev_priv->mm.next_gem_seqno = 1;
-       i915_gem_detect_bit_6_swizzle(dev);
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index f295bdf..d04c526 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -349,6 +349,21 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
-       return count;
- }
-+void
-+i915_gem_vblank_work_handler(struct work_struct *work)
-+{
-+      drm_i915_private_t *dev_priv;
-+      struct drm_device *dev;
-+
-+      dev_priv = container_of(work, drm_i915_private_t,
-+                              mm.vblank_work);
-+      dev = dev_priv->dev;
-+
-+      mutex_lock(&dev->struct_mutex);
-+      i915_vblank_tasklet(dev);
-+      mutex_unlock(&dev->struct_mutex);
-+}
-+
- irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
- {
-       struct drm_device *dev = (struct drm_device *) arg;
-@@ -422,8 +437,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-       if (iir & I915_ASLE_INTERRUPT)
-               opregion_asle_intr(dev);
--      if (vblank && dev_priv->swaps_pending > 0)
--              drm_locked_tasklet(dev, i915_vblank_tasklet);
-+      if (vblank && dev_priv->swaps_pending > 0) {
-+              if (dev_priv->ring.ring_obj == NULL)
-+                      drm_locked_tasklet(dev, i915_vblank_tasklet);
-+              else
-+                      schedule_work(&dev_priv->mm.vblank_work);
-+      }
-       return IRQ_HANDLED;
- }
-@@ -514,14 +533,15 @@ int i915_irq_emit(struct drm_device *dev, void *data,
-       drm_i915_irq_emit_t *emit = data;
-       int result;
--      LOCK_TEST_WITH_RETURN(dev, file_priv);
-+      RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
--
-+      mutex_lock(&dev->struct_mutex);
-       result = i915_emit_irq(dev);
-+      mutex_unlock(&dev->struct_mutex);
-       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0017-i915-Make-use-of-sarea_priv-conditional.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0017-i915-Make-use-of-sarea_priv-conditional.patch
deleted file mode 100644 (file)
index 542b69d..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-commit 69749cf99189a8a78de201ac24990c91ee111469
-Author: Kristian Høgsberg <krh@redhat.com>
-Date:   Wed Aug 20 11:20:13 2008 -0400
-
-    i915: Make use of sarea_priv conditional.
-    
-    We fail ioctls that depend on the sarea_priv with EINVAL.
-    
-    Signed-off-by: Kristian Høgsberg <krh@redhat.com>
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 25f59c1..dbd3f49 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -55,7 +55,8 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
-               if (ring->space >= n)
-                       return 0;
--              dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-+              if (dev_priv->sarea_priv)
-+                      dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-               if (ring->head != last_head)
-                       i = 0;
-@@ -128,7 +129,7 @@ void i915_kernel_lost_context(struct drm_device * dev)
-       if (ring->space < 0)
-               ring->space += ring->Size;
--      if (ring->head == ring->tail)
-+      if (ring->head == ring->tail && dev_priv->sarea_priv)
-               dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
- }
-@@ -433,10 +434,11 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
--      dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
--
-+      dev_priv->counter++;
-       if (dev_priv->counter > 0x7FFFFFFFUL)
--              dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
-+              dev_priv->counter = 0;
-+      if (dev_priv->sarea_priv)
-+              dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
-       BEGIN_LP_RING(4);
-       OUT_RING(MI_STORE_DWORD_INDEX);
-@@ -534,6 +536,9 @@ static int i915_dispatch_flip(struct drm_device * dev)
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-+      if (!dev_priv->sarea_priv)
-+              return -EINVAL;
-+
-       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-                 __FUNCTION__,
-                 dev_priv->current_page,
-@@ -628,7 +633,8 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
-       ret = i915_dispatch_batchbuffer(dev, batch);
-       mutex_unlock(&dev->struct_mutex);
--      sarea_priv->last_dispatch = (int)hw_status[5];
-+      if (sarea_priv)
-+              sarea_priv->last_dispatch = (int)hw_status[5];
-       return ret;
- }
-@@ -663,7 +669,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
-               return ret;
-       }
--      sarea_priv->last_dispatch = (int)hw_status[5];
-+      if (sarea_priv)
-+              sarea_priv->last_dispatch = (int)hw_status[5];
-       return 0;
- }
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index d04c526..ef03a59 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -427,7 +427,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-               I915_WRITE(IMR, dev_priv->irq_mask_reg);
-       (void) I915_READ(IIR); /* Flush posted writes */
--      dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-+      if (dev_priv->sarea_priv)
-+              dev_priv->sarea_priv->last_dispatch =
-+                      READ_BREADCRUMB(dev_priv);
-       if (iir & I915_USER_INTERRUPT) {
-               dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
-@@ -456,10 +458,11 @@ static int i915_emit_irq(struct drm_device * dev)
-       DRM_DEBUG("\n");
--      dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
--
-+      dev_priv->counter++;
-       if (dev_priv->counter > 0x7FFFFFFFUL)
--              dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
-+              dev_priv->counter = 1;
-+      if (dev_priv->sarea_priv)
-+              dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
-       BEGIN_LP_RING(6);
-       OUT_RING(MI_STORE_DWORD_INDEX);
-@@ -503,11 +506,15 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
-                 READ_BREADCRUMB(dev_priv));
-       if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
--              dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-+              if (dev_priv->sarea_priv) {
-+                      dev_priv->sarea_priv->last_dispatch =
-+                              READ_BREADCRUMB(dev_priv);
-+              }
-               return 0;
-       }
--      dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-+      if (dev_priv->sarea_priv)
-+              dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-       i915_user_irq_get(dev);
-       DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
-@@ -519,7 +526,9 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
-                         READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
-       }
--      dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-+      if (dev_priv->sarea_priv)
-+              dev_priv->sarea_priv->last_dispatch =
-+                      READ_BREADCRUMB(dev_priv);
-       return ret;
- }
-@@ -682,7 +691,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
-       struct list_head *list;
-       int ret;
--      if (!dev_priv) {
-+      if (!dev_priv || !dev_priv->sarea_priv) {
-               DRM_ERROR("%s called with no initialization\n", __func__);
-               return -EINVAL;
-       }
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0018-i915-gem-install-and-uninstall-irq-handler-in-enter.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0018-i915-gem-install-and-uninstall-irq-handler-in-enter.patch
deleted file mode 100644 (file)
index 3593fa5..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-commit 7ad6d5861b04bbb2cdc36d1dcf8989e16f86e659
-Author: Kristian Høgsberg <krh@redhat.com>
-Date:   Wed Aug 20 11:04:27 2008 -0400
-
-    i915 gem: install and uninstall irq handler in entervt and leavevt ioctls.
-    
-    Signed-off-by: Kristian Høgsberg <krh@redhat.com>
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index bb6e5a3..5fe5034 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -2443,6 +2443,9 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
-       BUG_ON(!list_empty(&dev_priv->mm.request_list));
-       dev_priv->mm.suspended = 0;
-       mutex_unlock(&dev->struct_mutex);
-+
-+      drm_irq_install(dev);
-+
-       return 0;
- }
-@@ -2458,6 +2461,8 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
-               i915_gem_cleanup_ringbuffer(dev);
-       mutex_unlock(&dev->struct_mutex);
-+      drm_irq_uninstall(dev);
-+
-       return 0;
- }
-diff --git a/include/drm/drmP.h b/include/drm/drmP.h
-index 1469a1b..51ee72c 100644
---- a/include/drm/drmP.h
-+++ b/include/drm/drmP.h
-@@ -1134,6 +1134,7 @@ extern void drm_core_reclaim_buffers(struct drm_device *dev,
- extern int drm_control(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv);
- extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
-+extern int drm_irq_install(struct drm_device *dev);
- extern int drm_irq_uninstall(struct drm_device *dev);
- extern void drm_driver_irq_preinstall(struct drm_device *dev);
- extern void drm_driver_irq_postinstall(struct drm_device *dev);
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0019-DRM-Return-EBADF-on-bad-object-in-flink-and-retur.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0019-DRM-Return-EBADF-on-bad-object-in-flink-and-retur.patch
deleted file mode 100644 (file)
index 6de4514..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-commit c3de45b0488762a9161e9b9e8bf419f63c100c47
-Author: Eric Anholt <eric@anholt.net>
-Date:   Tue Sep 9 11:40:34 2008 -0700
-
-    DRM: Return -EBADF on bad object in flink, and return curent name if it exists.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
-index 434155b..ccd1afd 100644
---- a/drivers/gpu/drm/drm_gem.c
-+++ b/drivers/gpu/drm/drm_gem.c
-@@ -251,7 +251,7 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
-       obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-       if (obj == NULL)
--              return -EINVAL;
-+              return -EBADF;
- again:
-       if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
-@@ -259,8 +259,9 @@ again:
-       spin_lock(&dev->object_name_lock);
-       if (obj->name) {
-+              args->name = obj->name;
-               spin_unlock(&dev->object_name_lock);
--              return -EEXIST;
-+              return 0;
-       }
-       ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
-                                &obj->name);
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0020-drm-Avoid-oops-in-GEM-execbuffers-with-bad-argument.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0020-drm-Avoid-oops-in-GEM-execbuffers-with-bad-argument.patch
deleted file mode 100644 (file)
index 7080907..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-commit 880db7a8dbed226d638b3a48aa1a3996f8624911
-Author: Eric Anholt <eric@anholt.net>
-Date:   Wed Sep 10 14:22:49 2008 -0700
-
-    drm: Avoid oops in GEM execbuffers with bad arguments.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 5fe5034..29d9d21 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -1763,6 +1763,10 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
-                 (int) args->buffers_ptr, args->buffer_count, args->batch_len);
- #endif
-+      if (args->buffer_count < 1) {
-+              DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
-+              return -EINVAL;
-+      }
-       /* Copy in the exec list from userland */
-       exec_list = drm_calloc(sizeof(*exec_list), args->buffer_count,
-                              DRM_MEM_DRIVER);
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0021-drm-G33-class-hardware-has-a-newer-965-style-MCH-n.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0021-drm-G33-class-hardware-has-a-newer-965-style-MCH-n.patch
deleted file mode 100644 (file)
index f5481d7..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-commit 930469634910fa87c21f0a7423c98b270d35d8c6
-Author: Eric Anholt <eric@anholt.net>
-Date:   Mon Sep 15 13:13:34 2008 -0700
-
-    drm: G33-class hardware has a newer 965-style MCH (no DCC register).
-    
-    Fixes bad software fallback rendering in Mesa in dual-channel configurations.
-    
-    d9a2470012588dc5313a5ac8bb2f03575af00e99
-
-diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
-index 0c1b3a0..6b3f1e4 100644
---- a/drivers/gpu/drm/i915/i915_gem_tiling.c
-+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
-@@ -96,7 +96,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
-                */
-               swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-               swizzle_y = I915_BIT_6_SWIZZLE_NONE;
--      } else if (!IS_I965G(dev) || IS_I965GM(dev)) {
-+      } else if ((!IS_I965G(dev) && !IS_G33(dev)) || IS_I965GM(dev)) {
-               uint32_t dcc;
-               /* On 915-945 and GM965, channel interleave by the CPU is
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0022-drm-use-ioremap_wc-in-i915-instead-of-ioremap.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0022-drm-use-ioremap_wc-in-i915-instead-of-ioremap.patch
deleted file mode 100644 (file)
index 8e6cbe9..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-commit d9f2382adde582f8792ad96e9570716bcbea21a0
-Author: Eric Anholt <eric@anholt.net>
-Date:   Tue Sep 23 14:50:57 2008 -0700
-
-    drm: Use ioremap_wc in i915_driver instead of ioremap, since we always want WC.
-    
-    Fixes failure to map the ringbuffer when PAT tells us we don't get to do
-    uncached on something that's already mapped WC, or something along those lines.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 29d9d21..6ecfd10 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -233,7 +233,7 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-               if (unwritten)
- #endif /* CONFIG_HIGHMEM */
-               {
--                      vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
-+                      vaddr = ioremap_wc(pfn << PAGE_SHIFT, PAGE_SIZE);
- #if WATCH_PWRITE
-                       DRM_INFO("pwrite slow i %d o %d l %d "
-                                "pfn %ld vaddr %p\n",
-@@ -1612,9 +1612,10 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
-                       if (reloc_page != NULL)
-                               iounmap(reloc_page);
--                      reloc_page = ioremap(dev->agp->base +
--                                           (reloc_offset & ~(PAGE_SIZE - 1)),
--                                           PAGE_SIZE);
-+                      reloc_page = ioremap_wc(dev->agp->base +
-+                                              (reloc_offset &
-+                                               ~(PAGE_SIZE - 1)),
-+                                              PAGE_SIZE);
-                       last_reloc_offset = reloc_offset;
-                       if (reloc_page == NULL) {
-                               drm_gem_object_unreference(target_obj);
-@@ -2318,7 +2319,9 @@ i915_gem_init_hws(struct drm_device *dev)
-       dev_priv->hws_map.flags = 0;
-       dev_priv->hws_map.mtrr = 0;
--      drm_core_ioremap(&dev_priv->hws_map, dev);
-+      /* Ioremapping here is the wrong thing to do.  We want cached access.
-+       */
-+      drm_core_ioremap_wc(&dev_priv->hws_map, dev);
-       if (dev_priv->hws_map.handle == NULL) {
-               DRM_ERROR("Failed to map status page.\n");
-               memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-@@ -2369,7 +2372,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
-       dev_priv->ring.map.flags = 0;
-       dev_priv->ring.map.mtrr = 0;
--      drm_core_ioremap(&dev_priv->ring.map, dev);
-+      drm_core_ioremap_wc(&dev_priv->ring.map, dev);
-       if (dev_priv->ring.map.handle == NULL) {
-               DRM_ERROR("Failed to map ringbuffer.\n");
-               memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0023-drm-clean-up-many-sparse-warnings-in-i915.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0023-drm-clean-up-many-sparse-warnings-in-i915.patch
deleted file mode 100644 (file)
index 236b161..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-commit 034994cfffbb2371b720e3f49378031ebc12645e
-Author: Eric Anholt <eric@anholt.net>
-Date:   Thu Oct 2 12:24:47 2008 -0700
-
-    drm: Clean up many sparse warnings in i915.
-    
-    Signed-off-by: Eric Anholt <eric@anholt.net>
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index dbd3f49..814cc12 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -76,7 +76,7 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
-  * Sets up the hardware status page for devices that need a physical address
-  * in the register.
-  */
--int i915_init_phys_hws(struct drm_device *dev)
-+static int i915_init_phys_hws(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       /* Program Hardware Status Page */
-@@ -101,7 +101,7 @@ int i915_init_phys_hws(struct drm_device *dev)
-  * Frees the hardware status page, whether it's a physical address or a virtual
-  * address set up by the X Server.
-  */
--void i915_free_hws(struct drm_device *dev)
-+static void i915_free_hws(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       if (dev_priv->status_page_dmah) {
-@@ -145,8 +145,8 @@ static int i915_dma_cleanup(struct drm_device * dev)
-       if (dev_priv->ring.virtual_start) {
-               drm_core_ioremapfree(&dev_priv->ring.map, dev);
--              dev_priv->ring.virtual_start = 0;
--              dev_priv->ring.map.handle = 0;
-+              dev_priv->ring.virtual_start = NULL;
-+              dev_priv->ring.map.handle = NULL;
-               dev_priv->ring.map.size = 0;
-       }
-@@ -827,9 +827,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
-       base = drm_get_resource_start(dev, mmio_bar);
-       size = drm_get_resource_len(dev, mmio_bar);
--      ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
--                       _DRM_KERNEL | _DRM_DRIVER,
--                       &dev_priv->mmio_map);
-+      dev_priv->regs = ioremap(base, size);
-       i915_gem_load(dev);
-@@ -867,8 +865,8 @@ int i915_driver_unload(struct drm_device *dev)
-       i915_free_hws(dev);
--      if (dev_priv->mmio_map)
--              drm_rmmap(dev, dev_priv->mmio_map);
-+      if (dev_priv->regs != NULL)
-+              iounmap(dev_priv->regs);
-       intel_opregion_free(dev);
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index 8547f0a..b184d54 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -110,8 +110,8 @@ struct intel_opregion {
- typedef struct drm_i915_private {
-       struct drm_device *dev;
-+      void __iomem *regs;
-       drm_local_map_t *sarea;
--      drm_local_map_t *mmio_map;
-       drm_i915_sarea_t *sarea_priv;
-       drm_i915_ring_buffer_t ring;
-@@ -553,12 +553,12 @@ extern void opregion_enable_asle(struct drm_device *dev);
-               LOCK_TEST_WITH_RETURN(dev, file_priv);                  \
- } while (0)
--#define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
--#define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
--#define I915_READ16(reg)      DRM_READ16(dev_priv->mmio_map, (reg))
--#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
--#define I915_READ8(reg)               DRM_READ8(dev_priv->mmio_map, (reg))
--#define I915_WRITE8(reg,val)  DRM_WRITE8(dev_priv->mmio_map, (reg), (val))
-+#define I915_READ(reg)          readl(dev_priv->regs + (reg))
-+#define I915_WRITE(reg,val)     writel(val, dev_priv->regs + (reg))
-+#define I915_READ16(reg)      readw(dev_priv->regs + (reg))
-+#define I915_WRITE16(reg,val) writel(val, dev_priv->regs + (reg))
-+#define I915_READ8(reg)               readb(dev_priv->regs + (reg))
-+#define I915_WRITE8(reg,val)  writeb(val, dev_priv->regs + (reg))
- #define I915_VERBOSE 0
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 6ecfd10..6a89449 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -176,7 +176,8 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-       ssize_t remain;
-       loff_t offset;
-       char __user *user_data;
--      char *vaddr;
-+      char __iomem *vaddr;
-+      char *vaddr_atomic;
-       int i, o, l;
-       int ret = 0;
-       unsigned long pfn;
-@@ -219,16 +220,20 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-               pfn = (dev->agp->base >> PAGE_SHIFT) + i;
- #ifdef CONFIG_HIGHMEM
--              /* kmap_atomic can't map IO pages on non-HIGHMEM kernels
-+              /* This is a workaround for the low performance of iounmap
-+               * (approximate 10% cpu cost on normal 3D workloads).
-+               * kmap_atomic on HIGHMEM kernels happens to let us map card
-+               * memory without taking IPIs.  When the vmap rework lands
-+               * we should be able to dump this hack.
-                */
--              vaddr = kmap_atomic_pfn(pfn, KM_USER0);
-+              vaddr_atomic = kmap_atomic_pfn(pfn, KM_USER0);
- #if WATCH_PWRITE
-               DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n",
--                       i, o, l, pfn, vaddr);
-+                       i, o, l, pfn, vaddr_atomic);
- #endif
--              unwritten = __copy_from_user_inatomic_nocache(vaddr + o,
-+              unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + o,
-                                                             user_data, l);
--              kunmap_atomic(vaddr, KM_USER0);
-+              kunmap_atomic(vaddr_atomic, KM_USER0);
-               if (unwritten)
- #endif /* CONFIG_HIGHMEM */
-@@ -271,7 +276,7 @@ fail:
-       return ret;
- }
--int
-+static int
- i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-                     struct drm_i915_gem_pwrite *args,
-                     struct drm_file *file_priv)
-@@ -587,7 +592,7 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains)
-  * Ensures that all commands in the ring are finished
-  * before signalling the CPU
-  */
--uint32_t
-+static uint32_t
- i915_retire_commands(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-@@ -734,7 +739,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
-  * Waits for a sequence number to be signaled, and cleans up the
-  * request and object lists appropriately for that event.
-  */
--int
-+static int
- i915_wait_request(struct drm_device *dev, uint32_t seqno)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-@@ -1483,7 +1488,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
-       struct drm_i915_gem_object *obj_priv = obj->driver_private;
-       int i, ret;
-       uint32_t last_reloc_offset = -1;
--      void *reloc_page = NULL;
-+      void __iomem *reloc_page = NULL;
-       /* Choose the GTT offset for our buffer and put it there. */
-       ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
-@@ -1500,8 +1505,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
-       for (i = 0; i < entry->relocation_count; i++) {
-               struct drm_gem_object *target_obj;
-               struct drm_i915_gem_object *target_obj_priv;
--              uint32_t reloc_val, reloc_offset, *reloc_entry;
--              int ret;
-+              uint32_t reloc_val, reloc_offset;
-+              uint32_t __iomem *reloc_entry;
-               ret = copy_from_user(&reloc, relocs + i, sizeof(reloc));
-               if (ret != 0) {
-@@ -1624,7 +1629,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
-                       }
-               }
--              reloc_entry = (uint32_t *)((char *)reloc_page +
-+              reloc_entry = (uint32_t __iomem *)(reloc_page +
-                                          (reloc_offset & (PAGE_SIZE - 1)));
-               reloc_val = target_obj_priv->gtt_offset + reloc.delta;
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0024-fastboot-create-a-asynchronous-initlevel.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0024-fastboot-create-a-asynchronous-initlevel.patch
deleted file mode 100644 (file)
index 7c19053..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-From ac9103dd8e4dc65c110d6cba9a3380c6c617ffa7 Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Fri, 18 Jul 2008 15:16:08 -0700
-Subject: [PATCH] fastboot: create a "asynchronous" initlevel
-
-This patch creates an asynchronous initlevel (6a) which is at the same
-level as the normal device initcalls, but with the difference that they
-are run asynchronous from all the other initcalls. The purpose of this
-*selective* level is that we can move long waiting inits that are not
-boot-critical to this level one at a time.
-
-To keep things not totally insane, the asynchronous initcalls are async
-to the other initcalls, but are still ordered to themselves; think of it
-as "bottom-half-not-softirq". This has the benefit that async drivers
-still have stable device ordering between them.
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- include/asm-generic/vmlinux.lds.h |    3 +++
- include/linux/init.h              |    6 ++++++
- init/main.c                       |   36 +++++++++++++++++++++++++++++++++---
- 3 files changed, 42 insertions(+), 3 deletions(-)
-
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index 729f6b0..39c1afc 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -372,6 +372,9 @@
-       *(.initcall5.init)                                              \
-       *(.initcall5s.init)                                             \
-       *(.initcallrootfs.init)                                         \
-+      __async_initcall_start = .;                                     \
-+      *(.initcall6a.init)                                             \
-+      __async_initcall_end = .;                                       \
-       *(.initcall6.init)                                              \
-       *(.initcall6s.init)                                             \
-       *(.initcall7.init)                                              \
-diff --git a/include/linux/init.h b/include/linux/init.h
-index 21d658c..75db909 100644
---- a/include/linux/init.h
-+++ b/include/linux/init.h
-@@ -197,11 +197,13 @@
- #define fs_initcall_sync(fn)          __define_initcall("5s",fn,5s)
- #define rootfs_initcall(fn)           __define_initcall("rootfs",fn,rootfs)
- #define device_initcall(fn)           __define_initcall("6",fn,6)
-+#define device_initcall_async(fn)     __define_initcall("6a", fn, 6a)
- #define device_initcall_sync(fn)      __define_initcall("6s",fn,6s)
- #define late_initcall(fn)             __define_initcall("7",fn,7)
- #define late_initcall_sync(fn)                __define_initcall("7s",fn,7s)
- #define __initcall(fn) device_initcall(fn)
-+#define __initcall_async(fn) device_initcall_async(fn)
- #define __exitcall(fn) \
-       static exitcall_t __exitcall_##fn __exit_call = fn
-@@ -257,6 +259,7 @@
-  * be one per module.
-  */
- #define module_init(x)        __initcall(x);
-+#define module_init_async(x)  __initcall_async(x);
- /**
-  * module_exit() - driver exit entry point
-@@ -279,10 +282,13 @@
- #define subsys_initcall(fn)           module_init(fn)
- #define fs_initcall(fn)                       module_init(fn)
- #define device_initcall(fn)           module_init(fn)
-+#define device_initcall_async(fn)     module_init(fn)
- #define late_initcall(fn)             module_init(fn)
- #define security_initcall(fn)         module_init(fn)
-+#define module_init_async(fn)         module_init(fn)
-+
- /* Each module must use one module_init(). */
- #define module_init(initfn)                                   \
-       static inline initcall_t __inittest(void)               \
-diff --git a/init/main.c b/init/main.c
-index edeace0..6961de2 100644
---- a/init/main.c
-+++ b/init/main.c
-@@ -746,18 +746,47 @@
- extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
-+extern initcall_t __async_initcall_start[], __async_initcall_end[];
--static void __init do_initcalls(void)
-+static void __init do_async_initcalls(struct work_struct *dummy)
- {
-       initcall_t *call;
--      for (call = __early_initcall_end; call < __initcall_end; call++)
-+      for (call = __async_initcall_start; call < __async_initcall_end; call++)
-               do_one_initcall(*call);
-+}
-+
-+static struct workqueue_struct *async_init_wq;
-+
-+static void __init do_initcalls(void)
-+{
-+      initcall_t *call;
-+      static DECLARE_WORK(async_work, do_async_initcalls);
-+      int phase = 0; /* 0 = levels 0 - 6, 1 = level 6a, 2 = after level 6a */
-+
-+      async_init_wq = create_singlethread_workqueue("kasyncinit");
-+
-+      for (call = __early_initcall_end; call < __initcall_end; call++) {
-+              if (phase == 0 && call >= __async_initcall_start) {
-+                      phase = 1;
-+                      queue_work(async_init_wq, &async_work);
-+              }
-+              if (phase == 1 && call >= __async_initcall_end)
-+                      phase = 2;
-+              if (phase != 1)
-+                      do_one_initcall(*call);
-+      }
--      /* Make sure there is no pending stuff from the initcall sequence */
-+      /*
-+      * Make sure there is no pending stuff from the initcall sequence,
-+      * including the async initcalls
-+      */
-       flush_scheduled_work();
-+      flush_workqueue(async_init_wq);
-+      destroy_workqueue(async_init_wq);
- }
-+
- /*
-  * Ok, the machine is now initialized. None of the devices
-  * have been touched yet, but the CPU subsystem is up and
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0025-fastboot-turn-the-USB-hostcontroller-initcalls-into.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0025-fastboot-turn-the-USB-hostcontroller-initcalls-into.patch
deleted file mode 100644 (file)
index 75d4151..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-From d1a26186ee222329a797bb0b2c8e2b5bc7d94d42 Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Fri, 18 Jul 2008 15:16:53 -0700
-Subject: [PATCH] fastboot: turn the USB hostcontroller initcalls into async initcalls
-
-the USB host controller init calls take a long time, mostly due to a
-"minimally 100 msec" delay *per port* during initialization.
-These are prime candidates for going in parallel to everything else.
-
-The USB device ordering is not affected by this due to the
-serialized-within-eachother property of async initcalls.
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- drivers/usb/host/ehci-hcd.c |    2 +-
- drivers/usb/host/ohci-hcd.c |    2 +-
- drivers/usb/host/uhci-hcd.c |    2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
-index 369a8a5..8f84b17 100644
---- a/drivers/usb/host/ehci-hcd.c
-+++ b/drivers/usb/host/ehci-hcd.c
-@@ -1101,7 +1101,7 @@ clean0:
- #endif
-       return retval;
- }
--module_init(ehci_hcd_init);
-+module_init_async(ehci_hcd_init);
- static void __exit ehci_hcd_cleanup(void)
- {
-diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
-index a8160d6..e060ed1 100644
---- a/drivers/usb/host/ohci-hcd.c
-+++ b/drivers/usb/host/ohci-hcd.c
-@@ -1165,7 +1165,7 @@ static int __init ohci_hcd_mod_init(void)
-       return retval;
- }
--module_init(ohci_hcd_mod_init);
-+module_init_async(ohci_hcd_mod_init);
- static void __exit ohci_hcd_mod_exit(void)
- {
-diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
-index 3a7bfe7..f2a05ac 100644
---- a/drivers/usb/host/uhci-hcd.c
-+++ b/drivers/usb/host/uhci-hcd.c
-@@ -999,7 +999,7 @@ static void __exit uhci_hcd_cleanup(void)
-       kfree(errbuf);
- }
--module_init(uhci_hcd_init);
-+module_init_async(uhci_hcd_init);
- module_exit(uhci_hcd_cleanup);
- MODULE_AUTHOR(DRIVER_AUTHOR);
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0026-fastboot-convert-a-few-non-critical-ACPI-drivers-to.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0026-fastboot-convert-a-few-non-critical-ACPI-drivers-to.patch
deleted file mode 100644 (file)
index efd8ca9..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-From 60ddc2e5c44b4b9f5fcb440065469eacbeabf5eb Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Fri, 18 Jul 2008 15:17:35 -0700
-Subject: [PATCH] fastboot: convert a few non-critical ACPI drivers to async initcalls
-
-This patch converts a few non-critical ACPI drivers to async initcalls;
-these initcalls (battery, button and thermal) tend to take quite a bit of
-time (100's of milliseconds) due to the hardware they need to talk to,
-but are otherwise clearly non-essential for the boot process.
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- drivers/acpi/battery.c |    2 +-
- drivers/acpi/button.c  |    2 +-
- drivers/acpi/thermal.c |    2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
-index b1c723f..d5d30ca 100644
---- a/drivers/acpi/battery.c
-+++ b/drivers/acpi/battery.c
-@@ -904,5 +904,5 @@ static void __exit acpi_battery_exit(void)
- #endif
- }
--module_init(acpi_battery_init);
-+module_init_async(acpi_battery_init);
- module_exit(acpi_battery_exit);
-diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
-index 1dfec41..46b3805 100644
---- a/drivers/acpi/button.c
-+++ b/drivers/acpi/button.c
-@@ -545,5 +545,5 @@ static void __exit acpi_button_exit(void)
-       remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
- }
--module_init(acpi_button_init);
-+module_init_async(acpi_button_init);
- module_exit(acpi_button_exit);
-diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
-index 84c795f..1f529af 100644
---- a/drivers/acpi/thermal.c
-+++ b/drivers/acpi/thermal.c
-@@ -1833,5 +1833,5 @@ static void __exit acpi_thermal_exit(void)
-       return;
- }
--module_init(acpi_thermal_init);
-+module_init_async(acpi_thermal_init);
- module_exit(acpi_thermal_exit);
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0027-fastboot-hold-the-BKL-over-the-async-init-call-sequ.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0027-fastboot-hold-the-BKL-over-the-async-init-call-sequ.patch
deleted file mode 100644 (file)
index 129823b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From 3e6558b693dd1e69e3177bc248977f067a769f14 Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Sun, 20 Jul 2008 08:59:24 -0700
-Subject: [PATCH] fastboot: hold the BKL over the async init call sequence
-
-Regular init calls are called with the BKL held; make sure
-the async init calls are also called with the BKL held.
-While this reduces parallelism a little, it does provide
-lock-for-lock compatibility. The hit to prallelism isn't too
-bad, most of the init calls are done immediately or actually
-block for their delays.
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- init/main.c |    6 ++++++
- 1 files changed, 6 insertions(+), 0 deletions(-)
-
-diff --git a/init/main.c b/init/main.c
-index 6961de2..9e2aee8 100644
---- a/init/main.c
-+++ b/init/main.c
-@@ -744,8 +744,14 @@ static void __init do_async_initcalls(struct work_struct *dummy)
- {
-       initcall_t *call;
-+      /*
-+       * For compatibility with normal init calls... take the BKL
-+       * not pretty, not desirable, but compatibility first
-+       */
-+      lock_kernel();
-       for (call = __async_initcall_start; call < __async_initcall_end; call++)
-               do_one_initcall(*call);
-+      unlock_kernel();
- }
- static struct workqueue_struct *async_init_wq;
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0028-fastboot-sync-the-async-execution-before-late_initc.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0028-fastboot-sync-the-async-execution-before-late_initc.patch
deleted file mode 100644 (file)
index 0700fb3..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-From 660625fb93f2fc0e633da9cb71d13d895b385f64 Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Sun, 20 Jul 2008 09:00:41 -0700
-Subject: [PATCH] fastboot: sync the async execution before late_initcall and move level 6s (sync) first
-
-Rene Herman points out several cases where it's basically needed to have
-all level 6/6a/6s calls done before the level 7 (late_initcall) code
-runs. This patch adds a sync point in the transition from the 6's to the
-7's.
-
-Second, this patch makes sure that level 6s (sync) happens before the
-async code starts, and puts a user in driver/pci in this category that
-needs to happen before device init.
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- drivers/pci/pci.c                 |    2 +-
- include/asm-generic/vmlinux.lds.h |    3 ++-
- init/main.c                       |   14 +++++++++++++-
- 3 files changed, 16 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index 44a46c9..d75295d 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -1889,7 +1889,7 @@ static int __devinit pci_setup(char *str)
- }
- early_param("pci", pci_setup);
--device_initcall(pci_init);
-+device_initcall_sync(pci_init);
- EXPORT_SYMBOL(pci_reenable_device);
- EXPORT_SYMBOL(pci_enable_device_io);
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index 39c1afc..020c641 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -372,11 +372,12 @@
-       *(.initcall5.init)                                              \
-       *(.initcall5s.init)                                             \
-       *(.initcallrootfs.init)                                         \
-+      *(.initcall6s.init)                                             \
-       __async_initcall_start = .;                                     \
-       *(.initcall6a.init)                                             \
-       __async_initcall_end = .;                                       \
-       *(.initcall6.init)                                              \
--      *(.initcall6s.init)                                             \
-+      __device_initcall_end = .;                                      \
-       *(.initcall7.init)                                              \
-       *(.initcall7s.init)
-diff --git a/init/main.c b/init/main.c
-index 9e2aee8..6be1756 100644
---- a/init/main.c
-+++ b/init/main.c
-@@ -739,6 +739,7 @@ static void __init do_one_initcall(initcall_t fn)
- extern initcall_t __initcall_start[], __initcall_end[];
- extern initcall_t __async_initcall_start[], __async_initcall_end[];
-+extern initcall_t __device_initcall_end[];
- static void __init do_async_initcalls(struct work_struct *dummy)
- {
-@@ -762,7 +763,13 @@ static void __init do_initcalls(void)
- {
-       initcall_t *call;
-       static DECLARE_WORK(async_work, do_async_initcalls);
--      int phase = 0; /* 0 = levels 0 - 6, 1 = level 6a, 2 = after level 6a */
-+      /*
-+       * 0 = levels 0 - 6,
-+       * 1 = level 6a,
-+       * 2 = after level 6a,
-+       * 3 = after level 6
-+       */
-+      int phase = 0;
-       async_init_wq = create_singlethread_workqueue("kasyncinit");
-@@ -773,6 +780,11 @@ static void __init do_initcalls(void)
-               }
-               if (phase == 1 && call >= __async_initcall_end)
-                       phase = 2;
-+              if (phase == 2 && call >= __device_initcall_end) {
-+                      phase = 3;
-+                      /* make sure all async work is done before level 7 */
-+                      flush_workqueue(async_init_wq);
-+              }
-               if (phase != 1)
-                       do_one_initcall(*call);
-       }
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0029-fastboot-make-fastboot-a-config-option.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0029-fastboot-make-fastboot-a-config-option.patch
deleted file mode 100644 (file)
index faf9622..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 50b6962016b824dfac254b8f36fc6cac301c8a8d Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Sun, 20 Jul 2008 10:20:49 -0700
-Subject: [PATCH] fastboot: make fastboot a config option
-
-to mitigate the risks of async bootup, make fastboot a configuration
-option...
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- init/Kconfig |   11 +++++++++++
- init/main.c  |    4 ++++
- 2 files changed, 15 insertions(+), 0 deletions(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 6199d11..7545c8b 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -524,6 +524,17 @@ config CC_OPTIMIZE_FOR_SIZE
-         If unsure, say N.
-+config FASTBOOT
-+      bool "Fast boot support"
-+      help
-+        The fastboot option will cause the kernel to try to optimize
-+        for faster boot. 
-+
-+        This includes doing some of the device initialization asynchronous
-+        as well as opportunistically trying to mount the root fs early.
-+
-+        If unsure, say N.
-+
- config SYSCTL
-       bool
-diff --git a/init/main.c b/init/main.c
-index 6be1756..bb97add 100644
---- a/init/main.c
-+++ b/init/main.c
-@@ -776,7 +776,11 @@ static void __init do_initcalls(void)
-       for (call = __initcall_start; call < __initcall_end; call++) {
-               if (phase == 0 && call >= __async_initcall_start) {
-                       phase = 1;
-+#ifdef CONFIG_FASTBOOT
-                       queue_work(async_init_wq, &async_work);
-+#else
-+                      do_async_initcalls(NULL);
-+#endif
-               }
-               if (phase == 1 && call >= __async_initcall_end)
-                       phase = 2;
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0030-fastboot-retry-mounting-the-root-fs-if-we-can-t-fin.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0030-fastboot-retry-mounting-the-root-fs-if-we-can-t-fin.patch
deleted file mode 100644 (file)
index e2c3737..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From db62cd29f9b9142c19c574ca00916f66ff22ed4a Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Sun, 20 Jul 2008 13:01:28 -0700
-Subject: [PATCH] fastboot: retry mounting the root fs if we can't find init
-
-currently we wait until all device init is done before trying to mount
-the root fs, and to consequently execute init.
-
-In preparation for relaxing the first delay, this patch adds a retry
-attempt in case /sbin/init is not found. Before retrying, the code
-will wait for all device init to complete.
-
-While this patch by itself doesn't gain boot time yet (it needs follow on
-patches), the alternative already is to panic()...
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
----
- init/main.c |   19 +++++++++++++++++++
- 1 files changed, 19 insertions(+), 0 deletions(-)
-
-diff --git a/init/main.c b/init/main.c
-index 3575b84..73785a4 100644
---- a/init/main.c
-+++ b/init/main.c
-@@ -853,6 +853,7 @@ static void run_init_process(char *init_filename)
-  */
- static int noinline init_post(void)
- {
-+      int retry_count = 1;
-       free_initmem();
-       unlock_kernel();
-       mark_rodata_ro();
-@@ -873,6 +874,7 @@ static int noinline init_post(void)
-                               ramdisk_execute_command);
-       }
-+retry:
-       /*
-        * We try each of these until one succeeds.
-        *
-@@ -885,6 +887,23 @@ static int noinline init_post(void)
-                                       "defaults...\n", execute_command);
-       }
-       run_init_process("/sbin/init");
-+
-+      if (retry_count > 0) {
-+              retry_count--;
-+              /* 
-+               * We haven't found init yet... potentially because the device
-+               * is still being probed. We need to
-+               * - flush keventd and friends
-+               * - wait for the known devices to complete their probing
-+               * - try to mount the root fs again
-+               */
-+              flush_scheduled_work();
-+              while (driver_probe_done() != 0)
-+                      msleep(100);
-+              prepare_namespace();
-+              goto retry;
-+      }
-+      
-       run_init_process("/etc/init");
-       run_init_process("/bin/init");
-       run_init_process("/bin/sh");
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0031-fastboot-make-the-raid-autodetect-code-wait-for-all.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0031-fastboot-make-the-raid-autodetect-code-wait-for-all.patch
deleted file mode 100644 (file)
index 03b3b82..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-From b52c36a95ed8026b6925fe8595ebcab6921ae62d Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Sun, 20 Jul 2008 13:07:09 -0700
-Subject: [PATCH] fastboot: make the raid autodetect code wait for all devices to init
-
-The raid autodetect code really needs to have all devices probed before
-it can detect raid arrays; not doing so would give rather messy situations
-where arrays would get detected as degraded while they shouldn't be etc.
-
-This is in preparation of removing the "wait for everything to init"
-code that makes everyone pay, not just raid users.
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
----
- init/do_mounts_md.c |    7 +++++++
- 1 files changed, 7 insertions(+), 0 deletions(-)
-
-diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c
-index 693d246..c0412a9 100644
---- a/init/do_mounts_md.c
-+++ b/init/do_mounts_md.c
-@@ -267,9 +267,16 @@ __setup("md=", md_setup);
- void __init md_run_setup(void)
- {
-       create_dev("/dev/md0", MKDEV(MD_MAJOR, 0));
-+
-       if (raid_noautodetect)
-               printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n");
-       else {
-+              /* 
-+               * Since we don't want to detect and use half a raid array, we need to
-+               * wait for the known devices to complete their probing
-+               */
-+              while (driver_probe_done() != 0)
-+                      msleep(100);
-               int fd = sys_open("/dev/md0", 0, 0);
-               if (fd >= 0) {
-                       sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0032-fastboot-remove-wait-for-all-devices-before-mounti.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0032-fastboot-remove-wait-for-all-devices-before-mounti.patch
deleted file mode 100644 (file)
index 4e9be15..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 1b5a2bd0602010398cb473d1b821a9f1c1399caf Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Sun, 20 Jul 2008 13:12:16 -0700
-Subject: [PATCH] fastboot: remove "wait for all devices before mounting root" delay
-
-In the non-initrd case, we wait for all devices to finish their
-probing before we try to mount the rootfs.
-In practice, this means that we end up waiting 2 extra seconds for
-the PS/2 mouse probing even though the root holding device has been
-ready since a long time.
-
-The previous two patches in this series made the RAID autodetect code
-do it's own "wait for probing to be done" code, and added
-"wait and retry" functionality in case the root device isn't actually
-available.
-
-These two changes should make it safe to remove the delay itself,
-and this patch does this. On my test laptop, this reduces the boot time
-by 2 seconds (kernel time goes from 3.9 to 1.9 seconds).
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
----
- init/do_mounts.c |    2 ++
- 1 files changed, 2 insertions(+), 0 deletions(-)
-
-diff --git a/init/do_mounts.c b/init/do_mounts.c
-index a1de1bf..c984fab 100644
---- a/init/do_mounts.c
-+++ b/init/do_mounts.c
-@@ -364,9 +364,11 @@ void __init prepare_namespace(void)
-               ssleep(root_delay);
-       }
-+#ifndef CONFIG_FASTBOOT
-       /* wait for the known devices to complete their probing */
-       while (driver_probe_done() != 0)
-               msleep(100);
-+#endif
-       md_run_setup();
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0033-fastboot-make-the-RAID-autostart-code-print-a-messa.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0033-fastboot-make-the-RAID-autostart-code-print-a-messa.patch
deleted file mode 100644 (file)
index 55c6c1a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-From 799d0da9e645258b9d1ae11d4aac73c9474906e3 Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Sun, 20 Jul 2008 16:30:29 -0700
-Subject: [PATCH] fastboot: make the RAID autostart code print a message just before waiting
-
-As requested/suggested by Neil Brown: make the raid code print that it's
-about to wait for probing to be done as well as give a suggestion on how
-to disable the probing if the user doesn't use raid.
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com
----
- init/do_mounts_md.c |    4 +++-
- 1 files changed, 3 insertions(+), 1 deletions(-)
-
-diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c
-index c0412a9..1ec5c41 100644
---- a/init/do_mounts_md.c
-+++ b/init/do_mounts_md.c
-@@ -275,7 +275,9 @@ void __init md_run_setup(void)
-                * Since we don't want to detect and use half a raid array, we need to
-                * wait for the known devices to complete their probing
-                */
--              while (driver_probe_done() != 0)
-+              printk(KERN_INFO "md: Waiting for all devices to be available before autodetect\n");
-+              printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
-+              while (driver_probe_done() < 0)
-                       msleep(100);
-               int fd = sys_open("/dev/md0", 0, 0);
-               if (fd >= 0) {
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0034-fastboot-fix-typo-in-init-Kconfig-text.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0034-fastboot-fix-typo-in-init-Kconfig-text.patch
deleted file mode 100644 (file)
index 7426293..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From 1a23ed42e1baf0481cc70c2f71d97b0bf0f1be70 Mon Sep 17 00:00:00 2001
-From: Ingo Molnar <mingo@elte.hu>
-Date: Thu, 31 Jul 2008 12:52:29 +0200
-Subject: [PATCH] fastboot: fix typo in init/Kconfig text
-
-noticed by Randy Dunlap.
-
-Reported-by: Randy Dunlap <randy.dunlap@oracle.com>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- init/Kconfig |    2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 4f73780..6b4de4d 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -530,7 +530,7 @@ config FASTBOOT
-         The fastboot option will cause the kernel to try to optimize
-         for faster boot. 
--        This includes doing some of the device initialization asynchronous
-+        This includes doing some of the device initialization asynchronously
-         as well as opportunistically trying to mount the root fs early.
-         If unsure, say N.
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0035-fastboot-remove-duplicate-unpack_to_rootfs.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0035-fastboot-remove-duplicate-unpack_to_rootfs.patch
deleted file mode 100644 (file)
index b8af74e..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-From 8929dda869d51b953c8f300864da62297db8a74e Mon Sep 17 00:00:00 2001
-From: Li, Shaohua <shaohua.li@intel.com>
-Date: Wed, 13 Aug 2008 17:26:01 +0800
-Subject: [PATCH] fastboot: remove duplicate unpack_to_rootfs()
-
-we check if initrd is initramfs first and then do real unpack. The
-check isn't required, we can directly do unpack. If initrd isn't
-initramfs, we can remove garbage. In my laptop, this saves 0.1s boot
-time. This penalizes non-initramfs case, but now initramfs is mostly
-widely used.
-
-Signed-off-by: Shaohua Li <shaohua.li@intel.com>
-Acked-by: Arjan van de Ven <arjan@infradead.org>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- init/initramfs.c |   71 ++++++++++++++++++++++++++++++++++++++++++-----------
- 1 files changed, 56 insertions(+), 15 deletions(-)
-
-diff --git a/init/initramfs.c b/init/initramfs.c
-index 644fc01..da8d030 100644
---- a/init/initramfs.c
-+++ b/init/initramfs.c
-@@ -5,6 +5,7 @@
- #include <linux/fcntl.h>
- #include <linux/delay.h>
- #include <linux/string.h>
-+#include <linux/dirent.h>
- #include <linux/syscalls.h>
- static __initdata char *message;
-@@ -121,8 +122,6 @@ static __initdata char *victim;
- static __initdata unsigned count;
- static __initdata loff_t this_header, next_header;
--static __initdata int dry_run;
--
- static inline void __init eat(unsigned n)
- {
-       victim += n;
-@@ -183,10 +182,6 @@ static int __init do_header(void)
-       parse_header(collected);
-       next_header = this_header + N_ALIGN(name_len) + body_len;
-       next_header = (next_header + 3) & ~3;
--      if (dry_run) {
--              read_into(name_buf, N_ALIGN(name_len), GotName);
--              return 0;
--      }
-       state = SkipIt;
-       if (name_len <= 0 || name_len > PATH_MAX)
-               return 0;
-@@ -257,8 +252,6 @@ static int __init do_name(void)
-               free_hash();
-               return 0;
-       }
--      if (dry_run)
--              return 0;
-       clean_path(collected, mode);
-       if (S_ISREG(mode)) {
-               int ml = maybe_link();
-@@ -423,10 +416,9 @@ static void __init flush_window(void)
-       outcnt = 0;
- }
--static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
-+static char * __init unpack_to_rootfs(char *buf, unsigned len)
- {
-       int written;
--      dry_run = check_only;
-       header_buf = kmalloc(110, GFP_KERNEL);
-       symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
-       name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
-@@ -520,10 +512,57 @@ skip:
-       initrd_end = 0;
- }
-+#define BUF_SIZE 1024
-+static void __init clean_rootfs(void)
-+{
-+      int fd;
-+      void *buf;
-+      struct linux_dirent64 *dirp;
-+      int count;
-+
-+      fd = sys_open("/", O_RDONLY, 0);
-+      WARN_ON(fd < 0);
-+      if (fd < 0)
-+              return;
-+      buf = kzalloc(BUF_SIZE, GFP_KERNEL);
-+      WARN_ON(!buf);
-+      if (!buf) {
-+              sys_close(fd);
-+              return;
-+      }
-+
-+      dirp = buf;
-+      count = sys_getdents64(fd, dirp, BUF_SIZE);
-+      while (count > 0) {
-+              while (count > 0) {
-+                      struct stat st;
-+                      int ret;
-+
-+                      ret = sys_newlstat(dirp->d_name, &st);
-+                      WARN_ON_ONCE(ret);
-+                      if (!ret) {
-+                              if (S_ISDIR(st.st_mode))
-+                                      sys_rmdir(dirp->d_name);
-+                              else
-+                                      sys_unlink(dirp->d_name);
-+                      }
-+
-+                      count -= dirp->d_reclen;
-+                      dirp = (void *)dirp + dirp->d_reclen;
-+              }
-+              dirp = buf;
-+              memset(buf, 0, BUF_SIZE);
-+              count = sys_getdents64(fd, dirp, BUF_SIZE);
-+      }
-+
-+      sys_close(fd);
-+      kfree(buf);
-+}
-+
- static int __init populate_rootfs(void)
- {
-       char *err = unpack_to_rootfs(__initramfs_start,
--                       __initramfs_end - __initramfs_start, 0);
-+                       __initramfs_end - __initramfs_start);
-       if (err)
-               panic(err);
-       if (initrd_start) {
-@@ -531,13 +570,15 @@ static int __init populate_rootfs(void)
-               int fd;
-               printk(KERN_INFO "checking if image is initramfs...");
-               err = unpack_to_rootfs((char *)initrd_start,
--                      initrd_end - initrd_start, 1);
-+                      initrd_end - initrd_start);
-               if (!err) {
-                       printk(" it is\n");
--                      unpack_to_rootfs((char *)initrd_start,
--                              initrd_end - initrd_start, 0);
-                       free_initrd();
-                       return 0;
-+              } else {
-+                      clean_rootfs();
-+                      unpack_to_rootfs(__initramfs_start,
-+                               __initramfs_end - __initramfs_start);
-               }
-               printk("it isn't (%s); looks like an initrd\n", err);
-               fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
-@@ -550,7 +591,7 @@ static int __init populate_rootfs(void)
- #else
-               printk(KERN_INFO "Unpacking initramfs...");
-               err = unpack_to_rootfs((char *)initrd_start,
--                      initrd_end - initrd_start, 0);
-+                      initrd_end - initrd_start);
-               if (err)
-                       panic(err);
-               printk(" done\n");
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0036-warning-fix-init-do_mounts_md-c.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0036-warning-fix-init-do_mounts_md-c.patch
deleted file mode 100644 (file)
index 9ba44a8..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-From fa3038625d7df2a1244c5b753069e7fdf99af3b5 Mon Sep 17 00:00:00 2001
-From: Ingo Molnar <mingo@elte.hu>
-Date: Mon, 18 Aug 2008 12:54:00 +0200
-Subject: [PATCH] warning: fix init do_mounts_md c
-MIME-Version: 1.0
-Content-Type: text/plain; charset=utf-8
-Content-Transfer-Encoding: 8bit
-
-fix warning:
-
-  init/do_mounts_md.c: In function â€˜md_run_setup’:
-  init/do_mounts_md.c:282: warning: ISO C90 forbids mixed declarations and code
-
-also, use the opportunity to put the RAID autodetection code
-into a separate function - this also solves a checkpatch style warning.
-
-No code changed:
-
-md5:
-   aa36a35faef371b05f1974ad583bdbbd  do_mounts_md.o.before.asm
-   aa36a35faef371b05f1974ad583bdbbd  do_mounts_md.o.after.asm
-
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- init/do_mounts_md.c |   36 +++++++++++++++++++++---------------
- 1 files changed, 21 insertions(+), 15 deletions(-)
-
-diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c
-index 1ec5c41..c0dfd3c 100644
---- a/init/do_mounts_md.c
-+++ b/init/do_mounts_md.c
-@@ -264,26 +264,32 @@ static int __init raid_setup(char *str)
- __setup("raid=", raid_setup);
- __setup("md=", md_setup);
-+static void autodetect_raid(void)
-+{
-+      int fd;
-+
-+      /*
-+       * Since we don't want to detect and use half a raid array, we need to
-+       * wait for the known devices to complete their probing
-+       */
-+      printk(KERN_INFO "md: Waiting for all devices to be available before autodetect\n");
-+      printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
-+      while (driver_probe_done() < 0)
-+              msleep(100);
-+      fd = sys_open("/dev/md0", 0, 0);
-+      if (fd >= 0) {
-+              sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
-+              sys_close(fd);
-+      }
-+}
-+
- void __init md_run_setup(void)
- {
-       create_dev("/dev/md0", MKDEV(MD_MAJOR, 0));
-       if (raid_noautodetect)
-               printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n");
--      else {
--              /* 
--               * Since we don't want to detect and use half a raid array, we need to
--               * wait for the known devices to complete their probing
--               */
--              printk(KERN_INFO "md: Waiting for all devices to be available before autodetect\n");
--              printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
--              while (driver_probe_done() < 0)
--                      msleep(100);
--              int fd = sys_open("/dev/md0", 0, 0);
--              if (fd >= 0) {
--                      sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
--                      sys_close(fd);
--              }
--      }
-+      else
-+              autodetect_raid();
-       md_setup_drive();
- }
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0037-init-initramfs.c-unused-function-when-compiling-wit.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0037-init-initramfs.c-unused-function-when-compiling-wit.patch
deleted file mode 100644 (file)
index 159f988..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From b4931e6c151acad06b4c12dc7cdb634366d7d27a Mon Sep 17 00:00:00 2001
-From: Steven Noonan <steven@uplinklabs.net>
-Date: Mon, 8 Sep 2008 16:19:10 -0700
-Subject: [PATCH] init/initramfs.c: unused function when compiling without CONFIG_BLK_DEV_RAM
-
-Fixing compiler warning when the kernel isn't compiled with support
-for RAM block devices enabled.
-
-Signed-off-by: Steven Noonan <steven@uplinklabs.net>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- init/initramfs.c |    2 ++
- 1 files changed, 2 insertions(+), 0 deletions(-)
-
-diff --git a/init/initramfs.c b/init/initramfs.c
-index da8d030..2f056e2 100644
---- a/init/initramfs.c
-+++ b/init/initramfs.c
-@@ -512,6 +512,7 @@ skip:
-       initrd_end = 0;
- }
-+#ifdef CONFIG_BLK_DEV_RAM
- #define BUF_SIZE 1024
- static void __init clean_rootfs(void)
- {
-@@ -558,6 +559,7 @@ static void __init clean_rootfs(void)
-       sys_close(fd);
-       kfree(buf);
- }
-+#endif
- static int __init populate_rootfs(void)
- {
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0038-fastboot-fix-blackfin-breakage-due-to-vmlinux.lds-c.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0038-fastboot-fix-blackfin-breakage-due-to-vmlinux.lds-c.patch
deleted file mode 100644 (file)
index 8d1e3f2..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 5e4f25d1f43991324794657655bbbc43983522a2 Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@infradead.org>
-Date: Wed, 10 Sep 2008 08:25:34 -0700
-Subject: [PATCH] fastboot: fix blackfin breakage due to vmlinux.lds change
-
-As reported by Mike Frysinger, the vmlinux.lds changes should
-have used VMLINUX_SYMBOL()...
-
-Reported-by: Mike Frysinger <vapier.adi@gmail.com>
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
-Acked-by: Bryan Wu <cooloney@kernel.org>
-Signed-off-by: Ingo Molnar <mingo@elte.hu>
----
- include/asm-generic/vmlinux.lds.h |    6 +++---
- 1 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index b9be858..ccabc4e 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -377,11 +377,11 @@
-       *(.initcall5s.init)                                             \
-       *(.initcallrootfs.init)                                         \
-       *(.initcall6s.init)                                             \
--      __async_initcall_start = .;                                     \
-+      VMLINUX_SYMBOL(__async_initcall_start) = .;                     \
-       *(.initcall6a.init)                                             \
--      __async_initcall_end = .;                                       \
-+      VMLINUX_SYMBOL(__async_initcall_end) = .;                       \
-       *(.initcall6.init)                                              \
--      __device_initcall_end = .;                                      \
-+      VMLINUX_SYMBOL(__device_initcall_end) = .;                      \
-       *(.initcall7.init)                                              \
-       *(.initcall7s.init)
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0039-Add-a-script-to-visualize-the-kernel-boot-process.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0039-Add-a-script-to-visualize-the-kernel-boot-process.patch
deleted file mode 100644 (file)
index da72d3b..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-From 77e9695b9d5c9ce761dedc193045d9cb64b8e245 Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Sat, 13 Sep 2008 09:36:06 -0700
-Subject: [PATCH] Add a script to visualize the kernel boot process / time
-
-When optimizing the kernel boot time, it's very valuable to visualize
-what is going on at which time. In addition, with the fastboot asynchronous
-initcall level, it's very valuable to see which initcall gets run where
-and when.
-
-This patch adds a script to turn a dmesg into a SVG graph (that can be
-shown with tools such as InkScape, Gimp or Firefox) and a small change
-to the initcall code to print the PID of the thread calling the initcall
-(so that the script can work out the parallelism).
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
----
- init/main.c          |    3 +-
- scripts/bootgraph.pl |  138 ++++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 140 insertions(+), 1 deletions(-)
- create mode 100644 scripts/bootgraph.pl
-
-diff --git a/init/main.c b/init/main.c
-index a1b95f3..14f2609 100644
---- a/init/main.c
-+++ b/init/main.c
-@@ -708,7 +708,8 @@ int do_one_initcall(initcall_t fn)
-       int result;
-       if (initcall_debug) {
--              print_fn_descriptor_symbol("calling  %s\n", fn);
-+              print_fn_descriptor_symbol("calling  %s", fn);
-+              printk(" @ %i\n",  task_pid_nr(current));
-               t0 = ktime_get();
-       }
-diff --git a/scripts/bootgraph.pl b/scripts/bootgraph.pl
-new file mode 100644
-index 0000000..d459b8b
---- /dev/null
-+++ b/scripts/bootgraph.pl
-@@ -0,0 +1,138 @@
-+#!/usr/bin/perl
-+
-+# Copyright 2008, Intel Corporation
-+#
-+# This file is part of the Linux kernel
-+#
-+# This program file is free software; you can redistribute it and/or modify it
-+# under the terms of the GNU General Public License as published by the
-+# Free Software Foundation; version 2 of the License.
-+#
-+# This program is distributed in the hope that it will be useful, but WITHOUT
-+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-+# for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program in a file named COPYING; if not, write to the
-+# Free Software Foundation, Inc.,
-+# 51 Franklin Street, Fifth Floor,
-+# Boston, MA 02110-1301 USA
-+#
-+# Authors:
-+#     Arjan van de Ven <arjan@linux.intel.com>
-+
-+
-+#
-+# This script turns a dmesg output into a SVG graphic that shows which
-+# functions take how much time. You can view SVG graphics with various
-+# programs, including Inkscape, The Gimp and Firefox.
-+#
-+#
-+# For this script to work, the kernel needs to be compiled with the
-+# CONFIG_PRINTK_TIME configuration option enabled, and with
-+# "initcall_debug" passed on the kernel command line.
-+#
-+# usage:
-+#     dmesg | perl scripts/bootgraph.pl > output.svg
-+#
-+
-+my @rows;
-+my %start, %end, %row;
-+my $done = 0;
-+my $rowcount = 0;
-+my $maxtime = 0;
-+my $count = 0;
-+while (<>) {
-+      my $line = $_;
-+      if ($line =~ /([0-9\.]+)\] calling  ([a-zA-Z\_]+)\+/) {
-+              my $func = $2;
-+              if ($done == 0) {
-+                      $start{$func} = $1;
-+              }
-+              $row{$func} = 1;
-+              if ($line =~ /\@ ([0-9]+)/) {
-+                      my $pid = $1;
-+                      if (!defined($rows[$pid])) {
-+                              $rowcount = $rowcount + 1;
-+                              $rows[$pid] = $rowcount;
-+                      }
-+                      $row{$func} = $rows[$pid];
-+              }
-+              $count = $count + 1;
-+      }
-+
-+      if ($line =~ /([0-9\.]+)\] initcall ([a-zA-Z\_]+)\+.*returned/) {
-+              if ($done == 0) {
-+                      $end{$2} = $1;
-+                      $maxtime = $1;
-+              }
-+      }
-+      if ($line =~ /Write protecting the/) {
-+              $done = 1;
-+      }
-+}
-+
-+if ($count == 0) {
-+      print "No data found in the dmesg. Make sure CONFIG_PRINTK_TIME is enabled and\n";
-+      print "that initcall_debug is passed on the kernel command line.\n\n";
-+      print "Usage: \n";
-+      print "      dmesg | perl scripts/bootgraph.pl > output.svg\n\n";
-+      exit;
-+}
-+
-+print "<?xml version=\"1.0\" standalone=\"no\"?> \n";
-+print "<svg width=\"1000\" height=\"100%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n";
-+
-+my @styles;
-+
-+$styles[0] = "fill:rgb(0,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[1] = "fill:rgb(0,255,0);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[2] = "fill:rgb(255,0,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[3] = "fill:rgb(255,255,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[4] = "fill:rgb(255,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[5] = "fill:rgb(0,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[6] = "fill:rgb(0,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[7] = "fill:rgb(0,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[8] = "fill:rgb(255,0,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[9] = "fill:rgb(255,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[10] = "fill:rgb(255,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+$styles[11] = "fill:rgb(128,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
-+
-+my $mult = 950.0 / $maxtime;
-+my $threshold = 0.0500 / $maxtime;
-+my $stylecounter = 0;
-+while (($key,$value) = each %start) {
-+      my $duration = $end{$key} - $start{$key};
-+
-+      if ($duration >= $threshold) {
-+              my $s, $s2, $e, $y;
-+              $s = $value * $mult;
-+              $s2 = $s + 6;
-+              $e = $end{$key} * $mult;
-+              $w = $e - $s;
-+
-+              $y = $row{$key} * 150;
-+              $y2 = $y + 4;
-+
-+              $style = $styles[$stylecounter];
-+              $stylecounter = $stylecounter + 1;
-+              if ($stylecounter > 11) {
-+                      $stylecounter = 0;
-+              };
-+
-+              print "<rect x=\"$s\" width=\"$w\" y=\"$y\" height=\"145\" style=\"$style\"/>\n";
-+              print "<text transform=\"translate($s2,$y2) rotate(90)\">$key</text>\n";
-+      }
-+}
-+
-+
-+# print the time line on top
-+my $time = 0.0;
-+while ($time < $maxtime) {
-+      my $s2 = $time * $mult;
-+      print "<text transform=\"translate($s2,89) rotate(90)\">$time</text>\n";
-+      $time = $time + 0.1;
-+}
-+
-+print "</svg>\n";
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0040-fastboot-fix-issues-and-improve-output-of-bootgraph.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0040-fastboot-fix-issues-and-improve-output-of-bootgraph.patch
deleted file mode 100644 (file)
index 0daba9d..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-From 5470e09b98074974316bbf98c8b8da01d670c2a4 Mon Sep 17 00:00:00 2001
-From: Arjan van de Ven <arjan@linux.intel.com>
-Date: Sun, 14 Sep 2008 15:30:52 -0700
-Subject: [PATCH] fastboot: fix issues and improve output of bootgraph.pl
-
-David Sanders reported some issues with bootgraph.pl's display
-of his sytems bootup; this commit fixes these by scaling the graph
-not from 0 - end time but from the first initcall to the end time;
-the minimum display size etc also now need to scale with this, as does
-the axis display.
-
-Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
----
- scripts/bootgraph.pl |   25 +++++++++++++++++--------
- 1 files changed, 17 insertions(+), 8 deletions(-)
-
-diff --git a/scripts/bootgraph.pl b/scripts/bootgraph.pl
-index d459b8b..4e5f4ab 100644
---- a/scripts/bootgraph.pl
-+++ b/scripts/bootgraph.pl
-@@ -42,6 +42,7 @@ my %start, %end, %row;
- my $done = 0;
- my $rowcount = 0;
- my $maxtime = 0;
-+my $firsttime = 100;
- my $count = 0;
- while (<>) {
-       my $line = $_;
-@@ -49,6 +50,9 @@ while (<>) {
-               my $func = $2;
-               if ($done == 0) {
-                       $start{$func} = $1;
-+                      if ($1 < $firsttime) {
-+                              $firsttime = $1;
-+                      }
-               }
-               $row{$func} = 1;
-               if ($line =~ /\@ ([0-9]+)/) {
-@@ -71,6 +75,9 @@ while (<>) {
-       if ($line =~ /Write protecting the/) {
-               $done = 1;
-       }
-+      if ($line =~ /Freeing unused kernel memory/) {
-+              $done = 1;
-+      }
- }
- if ($count == 0) {
-@@ -99,17 +106,17 @@ $styles[9] = "fill:rgb(255,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0
- $styles[10] = "fill:rgb(255,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
- $styles[11] = "fill:rgb(128,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
--my $mult = 950.0 / $maxtime;
--my $threshold = 0.0500 / $maxtime;
-+my $mult = 950.0 / ($maxtime - $firsttime);
-+my $threshold = ($maxtime - $firsttime) / 60.0;
- my $stylecounter = 0;
- while (($key,$value) = each %start) {
-       my $duration = $end{$key} - $start{$key};
-       if ($duration >= $threshold) {
-               my $s, $s2, $e, $y;
--              $s = $value * $mult;
-+              $s = ($value - $firsttime) * $mult;
-               $s2 = $s + 6;
--              $e = $end{$key} * $mult;
-+              $e = ($end{$key} - $firsttime) * $mult;
-               $w = $e - $s;
-               $y = $row{$key} * 150;
-@@ -128,11 +135,13 @@ while (($key,$value) = each %start) {
- # print the time line on top
--my $time = 0.0;
-+my $time = $firsttime;
-+my $step = ($maxtime - $firsttime) / 15;
- while ($time < $maxtime) {
--      my $s2 = $time * $mult;
--      print "<text transform=\"translate($s2,89) rotate(90)\">$time</text>\n";
--      $time = $time + 0.1;
-+      my $s2 = ($time - $firsttime) * $mult;
-+      my $tm = int($time * 100) / 100.0;
-+      print "<text transform=\"translate($s2,89) rotate(90)\">$tm</text>\n";
-+      $time = $time + $step;
- }
- print "</svg>\n";
--- 
-1.5.4.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0041-r8169-8101e.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0041-r8169-8101e.patch
deleted file mode 100644 (file)
index 781c9a1..0000000
+++ /dev/null
@@ -1,940 +0,0 @@
-From 771c0d99c0ab3ca7f1a9bc400e8259171b518d5f Mon Sep 17 00:00:00 2001
-From: Francois Romieu <romieu@fr.zoreil.com>
-Date: Thu, 21 Aug 2008 23:20:40 +0200
-Subject: [PATCH] r8169: fix RxMissed register access
-
-- the register location is defined for the 8169 chipset only and
-  there is no 8169 beyond RTL_GIGA_MAC_VER_06
-- only the lower 3 bytes of the register are valid
-
-Fixes:
-1. http://bugzilla.kernel.org/show_bug.cgi?id=10180
-2. http://bugzilla.kernel.org/show_bug.cgi?id=11062 (bits of)
-
-Tested by Hermann Gausterer and Adam Huffman.
-
-Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
-Cc: Edward Hsu <edward_hsu@realtek.com.tw>
----
- drivers/net/r8169.c |   25 ++++++++++++++-----------
- 1 files changed, 14 insertions(+), 11 deletions(-)
-
-diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
-index 0f6f974..4190ee7 100644
---- a/drivers/net/r8169.c
-+++ b/drivers/net/r8169.c
-@@ -2099,8 +2099,6 @@ static void rtl_hw_start_8168(struct net_device *dev)
-       RTL_R8(IntrMask);
--      RTL_W32(RxMissed, 0);
--
-       rtl_set_rx_mode(dev);
-       RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
-@@ -2143,8 +2141,6 @@ static void rtl_hw_start_8101(struct net_device *dev)
-       RTL_R8(IntrMask);
--      RTL_W32(RxMissed, 0);
--
-       rtl_set_rx_mode(dev);
-       RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
-@@ -2922,6 +2918,17 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
-       return work_done;
- }
-+static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
-+{
-+      struct rtl8169_private *tp = netdev_priv(dev);
-+
-+      if (tp->mac_version > RTL_GIGA_MAC_VER_06)
-+              return;
-+
-+      dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
-+      RTL_W32(RxMissed, 0);
-+}
-+
- static void rtl8169_down(struct net_device *dev)
- {
-       struct rtl8169_private *tp = netdev_priv(dev);
-@@ -2939,9 +2946,7 @@ core_down:
-       rtl8169_asic_down(ioaddr);
--      /* Update the error counts. */
--      dev->stats.rx_missed_errors += RTL_R32(RxMissed);
--      RTL_W32(RxMissed, 0);
-+      rtl8169_rx_missed(dev, ioaddr);
-       spin_unlock_irq(&tp->lock);
-@@ -3063,8 +3068,7 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
-       if (netif_running(dev)) {
-               spin_lock_irqsave(&tp->lock, flags);
--              dev->stats.rx_missed_errors += RTL_R32(RxMissed);
--              RTL_W32(RxMissed, 0);
-+              rtl8169_rx_missed(dev, ioaddr);
-               spin_unlock_irqrestore(&tp->lock, flags);
-       }
-@@ -3089,8 +3093,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
-       rtl8169_asic_down(ioaddr);
--      dev->stats.rx_missed_errors += RTL_R32(RxMissed);
--      RTL_W32(RxMissed, 0);
-+      rtl8169_rx_missed(dev, ioaddr);
-       spin_unlock_irq(&tp->lock);
--- 
-1.5.3.3
-
-From 6ee4bc96d446a9c466a18b715c7ab2d662c03ebd Mon Sep 17 00:00:00 2001
-From: Francois Romieu <romieu@fr.zoreil.com>
-Date: Sat, 26 Jul 2008 14:26:06 +0200
-Subject: [PATCH] r8169: get ethtool settings through the generic mii helper
-
-It avoids to report unsupported link capabilities with
-the fast-ethernet only 8101/8102.
-
-Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
-Tested-by: Martin Capitanio <martin@capitanio.org>
-Fixed-by: Ivan Vecera <ivecera@redhat.com>
-Cc: Edward Hsu <edward_hsu@realtek.com.tw>
----
- drivers/net/r8169.c |   99 +++++++++++++++++++++++---------------------------
- 1 files changed, 46 insertions(+), 53 deletions(-)
-
-diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
-index 4190ee7..7e026a6 100644
---- a/drivers/net/r8169.c
-+++ b/drivers/net/r8169.c
-@@ -370,8 +370,9 @@ struct ring_info {
- };
- enum features {
--      RTL_FEATURE_WOL = (1 << 0),
--      RTL_FEATURE_MSI = (1 << 1),
-+      RTL_FEATURE_WOL         = (1 << 0),
-+      RTL_FEATURE_MSI         = (1 << 1),
-+      RTL_FEATURE_GMII        = (1 << 2),
- };
- struct rtl8169_private {
-@@ -406,13 +407,15 @@ struct rtl8169_private {
-       struct vlan_group *vlgrp;
- #endif
-       int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
--      void (*get_settings)(struct net_device *, struct ethtool_cmd *);
-+      int (*get_settings)(struct net_device *, struct ethtool_cmd *);
-       void (*phy_reset_enable)(void __iomem *);
-       void (*hw_start)(struct net_device *);
-       unsigned int (*phy_reset_pending)(void __iomem *);
-       unsigned int (*link_ok)(void __iomem *);
-       struct delayed_work task;
-       unsigned features;
-+
-+      struct mii_if_info mii;
- };
- MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
-@@ -482,6 +485,23 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
-       return value;
- }
-+static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
-+                         int val)
-+{
-+      struct rtl8169_private *tp = netdev_priv(dev);
-+      void __iomem *ioaddr = tp->mmio_addr;
-+
-+      mdio_write(ioaddr, location, val);
-+}
-+
-+static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
-+{
-+      struct rtl8169_private *tp = netdev_priv(dev);
-+      void __iomem *ioaddr = tp->mmio_addr;
-+
-+      return mdio_read(ioaddr, location);
-+}
-+
- static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
- {
-       RTL_W16(IntrMask, 0x0000);
-@@ -850,7 +870,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
- #endif
--static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
-+static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
- {
-       struct rtl8169_private *tp = netdev_priv(dev);
-       void __iomem *ioaddr = tp->mmio_addr;
-@@ -867,65 +887,29 @@ static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
-       cmd->speed = SPEED_1000;
-       cmd->duplex = DUPLEX_FULL; /* Always set */
-+
-+      return 0;
- }
--static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
-+static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
- {
-       struct rtl8169_private *tp = netdev_priv(dev);
--      void __iomem *ioaddr = tp->mmio_addr;
--      u8 status;
--
--      cmd->supported = SUPPORTED_10baseT_Half |
--                       SUPPORTED_10baseT_Full |
--                       SUPPORTED_100baseT_Half |
--                       SUPPORTED_100baseT_Full |
--                       SUPPORTED_1000baseT_Full |
--                       SUPPORTED_Autoneg |
--                       SUPPORTED_TP;
--
--      cmd->autoneg = 1;
--      cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
--
--      if (tp->phy_auto_nego_reg & ADVERTISE_10HALF)
--              cmd->advertising |= ADVERTISED_10baseT_Half;
--      if (tp->phy_auto_nego_reg & ADVERTISE_10FULL)
--              cmd->advertising |= ADVERTISED_10baseT_Full;
--      if (tp->phy_auto_nego_reg & ADVERTISE_100HALF)
--              cmd->advertising |= ADVERTISED_100baseT_Half;
--      if (tp->phy_auto_nego_reg & ADVERTISE_100FULL)
--              cmd->advertising |= ADVERTISED_100baseT_Full;
--      if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)
--              cmd->advertising |= ADVERTISED_1000baseT_Full;
--
--      status = RTL_R8(PHYstatus);
--
--      if (status & _1000bpsF)
--              cmd->speed = SPEED_1000;
--      else if (status & _100bps)
--              cmd->speed = SPEED_100;
--      else if (status & _10bps)
--              cmd->speed = SPEED_10;
--
--      if (status & TxFlowCtrl)
--              cmd->advertising |= ADVERTISED_Asym_Pause;
--      if (status & RxFlowCtrl)
--              cmd->advertising |= ADVERTISED_Pause;
--
--      cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ?
--                    DUPLEX_FULL : DUPLEX_HALF;
-+
-+      return mii_ethtool_gset(&tp->mii, cmd);
- }
- static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
- {
-       struct rtl8169_private *tp = netdev_priv(dev);
-       unsigned long flags;
-+      int rc;
-       spin_lock_irqsave(&tp->lock, flags);
--      tp->get_settings(dev, cmd);
-+      rc = tp->get_settings(dev, cmd);
-       spin_unlock_irqrestore(&tp->lock, flags);
--      return 0;
-+      return rc;
- }
- static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
-@@ -1513,7 +1497,7 @@ static const struct rtl_cfg_info {
-       unsigned int align;
-       u16 intr_event;
-       u16 napi_event;
--      unsigned msi;
-+      unsigned features;
- } rtl_cfg_infos [] = {
-       [RTL_CFG_0] = {
-               .hw_start       = rtl_hw_start_8169,
-@@ -1522,7 +1506,7 @@ static const struct rtl_cfg_info {
-               .intr_event     = SYSErr | LinkChg | RxOverflow |
-                                 RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
-               .napi_event     = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
--              .msi            = 0
-+              .features       = RTL_FEATURE_GMII
-       },
-       [RTL_CFG_1] = {
-               .hw_start       = rtl_hw_start_8168,
-@@ -1531,7 +1515,7 @@ static const struct rtl_cfg_info {
-               .intr_event     = SYSErr | LinkChg | RxOverflow |
-                                 TxErr | TxOK | RxOK | RxErr,
-               .napi_event     = TxErr | TxOK | RxOK | RxOverflow,
--              .msi            = RTL_FEATURE_MSI
-+              .features       = RTL_FEATURE_GMII | RTL_FEATURE_MSI
-       },
-       [RTL_CFG_2] = {
-               .hw_start       = rtl_hw_start_8101,
-@@ -1540,7 +1524,7 @@ static const struct rtl_cfg_info {
-               .intr_event     = SYSErr | LinkChg | RxOverflow | PCSTimeout |
-                                 RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
-               .napi_event     = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
--              .msi            = RTL_FEATURE_MSI
-+              .features       = RTL_FEATURE_MSI
-       }
- };
-@@ -1552,7 +1536,7 @@ static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr,
-       u8 cfg2;
-       cfg2 = RTL_R8(Config2) & ~MSIEnable;
--      if (cfg->msi) {
-+      if (cfg->features & RTL_FEATURE_MSI) {
-               if (pci_enable_msi(pdev)) {
-                       dev_info(&pdev->dev, "no MSI. Back to INTx.\n");
-               } else {
-@@ -1578,6 +1562,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-       const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
-       const unsigned int region = cfg->region;
-       struct rtl8169_private *tp;
-+      struct mii_if_info *mii;
-       struct net_device *dev;
-       void __iomem *ioaddr;
-       unsigned int i;
-@@ -1602,6 +1587,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-       tp->pci_dev = pdev;
-       tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
-+      mii = &tp->mii;
-+      mii->dev = dev;
-+      mii->mdio_read = rtl_mdio_read;
-+      mii->mdio_write = rtl_mdio_write;
-+      mii->phy_id_mask = 0x1f;
-+      mii->reg_num_mask = 0x1f;
-+      mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
-+
-       /* enable device (incl. PCI PM wakeup and hotplug setup) */
-       rc = pci_enable_device(pdev);
-       if (rc < 0) {
--- 
-1.5.3.3
-
-From ef60b2a38e223a331e13ef503aee7cd5d4d5c12c Mon Sep 17 00:00:00 2001
-From: Hugh Dickins <hugh@veritas.com>
-Date: Mon, 8 Sep 2008 21:49:01 +0100
-Subject: [PATCH] r8169: select MII in Kconfig
-
-drivers/built-in.o: In function `rtl8169_gset_xmii':
-r8169.c:(.text+0x82259): undefined reference to `mii_ethtool_gset'
-suggests that the r8169 driver now needs to select MII.
-
-Signed-off-by: Hugh Dickins <hugh@veritas.com>
-Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
-Cc: Edward Hsu <edward_hsu@realtek.com.tw>
----
- drivers/net/Kconfig |    1 +
- 1 files changed, 1 insertions(+), 0 deletions(-)
-
-diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
-index 4a11296..60a0453 100644
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -2046,6 +2046,7 @@ config R8169
-       tristate "Realtek 8169 gigabit ethernet support"
-       depends on PCI
-       select CRC32
-+      select MII
-       ---help---
-         Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
--- 
-1.5.3.3
-
-From bca31864fca6004c4a4a9bd549e95c93b3c3bb10 Mon Sep 17 00:00:00 2001
-From: Francois Romieu <romieu@fr.zoreil.com>
-Date: Sat, 2 Aug 2008 15:50:02 +0200
-Subject: [PATCH] r8169: Tx performance tweak helper
-
-Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
-Cc: Edward Hsu <edward_hsu@realtek.com.tw>
----
- drivers/net/r8169.c |   15 ++++++++++-----
- 1 files changed, 10 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
-index 7e026a6..eea96fb 100644
---- a/drivers/net/r8169.c
-+++ b/drivers/net/r8169.c
-@@ -2054,12 +2054,20 @@ static void rtl_hw_start_8169(struct net_device *dev)
-       RTL_W16(IntrMask, tp->intr_event);
- }
-+static void rtl_tx_performance_tweak(struct pci_dev *pdev, u8 force)
-+{
-+      u8 ctl;
-+
-+      pci_read_config_byte(pdev, 0x69, &ctl);
-+      ctl = (ctl & ~0x70) | force;
-+      pci_write_config_byte(pdev, 0x69, ctl);
-+}
-+
- static void rtl_hw_start_8168(struct net_device *dev)
- {
-       struct rtl8169_private *tp = netdev_priv(dev);
-       void __iomem *ioaddr = tp->mmio_addr;
-       struct pci_dev *pdev = tp->pci_dev;
--      u8 ctl;
-       RTL_W8(Cfg9346, Cfg9346_Unlock);
-@@ -2073,10 +2081,7 @@ static void rtl_hw_start_8168(struct net_device *dev)
-       RTL_W16(CPlusCmd, tp->cp_cmd);
--      /* Tx performance tweak. */
--      pci_read_config_byte(pdev, 0x69, &ctl);
--      ctl = (ctl & ~0x70) | 0x50;
--      pci_write_config_byte(pdev, 0x69, ctl);
-+      rtl_tx_performance_tweak(pdev, 0x50);
-       RTL_W16(IntrMitigate, 0x5151);
--- 
-1.5.3.3
-
-From 7a929ae7d5a3618f56bf1ccaf8c62df628e820aa Mon Sep 17 00:00:00 2001
-From: Francois Romieu <romieu@fr.zoreil.com>
-Date: Sat, 5 Jul 2008 00:21:15 +0200
-Subject: [PATCH] r8169: use pci_find_capability for the PCI-E features
-
-Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
-Cc: Edward Hsu <edward_hsu@realtek.com.tw>
----
- drivers/net/r8169.c |   32 ++++++++++++++++++++++++--------
- 1 files changed, 24 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
-index eea96fb..5c00522 100644
---- a/drivers/net/r8169.c
-+++ b/drivers/net/r8169.c
-@@ -61,6 +61,7 @@ static const int multicast_filter_limit = 32;
- /* MAC address length */
- #define MAC_ADDR_LEN  6
-+#define MAX_READ_REQUEST_SHIFT        12
- #define RX_FIFO_THRESH        7       /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
- #define RX_DMA_BURST  6       /* Maximum PCI burst, '6' is 1024 */
- #define TX_DMA_BURST  6       /* Maximum PCI burst, '6' is 1024 */
-@@ -412,6 +413,7 @@ struct rtl8169_private {
-       void (*hw_start)(struct net_device *);
-       unsigned int (*phy_reset_pending)(void __iomem *);
-       unsigned int (*link_ok)(void __iomem *);
-+      int pcie_cap;
-       struct delayed_work task;
-       unsigned features;
-@@ -1663,6 +1665,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-               goto err_out_free_res_4;
-       }
-+      tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-+      if (!tp->pcie_cap && netif_msg_probe(tp))
-+              dev_info(&pdev->dev, "no PCI Express capability\n");
-+
-       /* Unneeded ? Don't mess with Mrs. Murphy. */
-       rtl8169_irq_mask_and_ack(ioaddr);
-@@ -2054,13 +2060,19 @@ static void rtl_hw_start_8169(struct net_device *dev)
-       RTL_W16(IntrMask, tp->intr_event);
- }
--static void rtl_tx_performance_tweak(struct pci_dev *pdev, u8 force)
-+static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
- {
--      u8 ctl;
-+      struct net_device *dev = pci_get_drvdata(pdev);
-+      struct rtl8169_private *tp = netdev_priv(dev);
-+      int cap = tp->pcie_cap;
-+
-+      if (cap) {
-+              u16 ctl;
--      pci_read_config_byte(pdev, 0x69, &ctl);
--      ctl = (ctl & ~0x70) | force;
--      pci_write_config_byte(pdev, 0x69, ctl);
-+              pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
-+              ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
-+              pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
-+      }
- }
- static void rtl_hw_start_8168(struct net_device *dev)
-@@ -2081,7 +2093,7 @@ static void rtl_hw_start_8168(struct net_device *dev)
-       RTL_W16(CPlusCmd, tp->cp_cmd);
--      rtl_tx_performance_tweak(pdev, 0x50);
-+      rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
-       RTL_W16(IntrMitigate, 0x5151);
-@@ -2114,8 +2126,12 @@ static void rtl_hw_start_8101(struct net_device *dev)
-       if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
-           (tp->mac_version == RTL_GIGA_MAC_VER_16)) {
--              pci_write_config_word(pdev, 0x68, 0x00);
--              pci_write_config_word(pdev, 0x69, 0x08);
-+              int cap = tp->pcie_cap;
-+
-+              if (cap) {
-+                      pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL,
-+                                            PCI_EXP_DEVCTL_NOSNOOP_EN);
-+              }
-       }
-       RTL_W8(Cfg9346, Cfg9346_Unlock);
--- 
-1.5.3.3
-
-From ba648bdcbca93084360d348eb43dde4b19b2489e Mon Sep 17 00:00:00 2001
-From: Francois Romieu <romieu@fr.zoreil.com>
-Date: Sun, 1 Jun 2008 22:37:49 +0200
-Subject: [PATCH] r8169: add 8168/8101 registers description
-
-Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
-Cc: Edward Hsu <edward_hsu@realtek.com.tw>
----
- drivers/net/r8169.c |   47 +++++++++++++++++++++++++++++++++++++++++++----
- 1 files changed, 43 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
-index 5c00522..0b8db03 100644
---- a/drivers/net/r8169.c
-+++ b/drivers/net/r8169.c
-@@ -197,9 +197,6 @@ enum rtl_registers {
-       Config5         = 0x56,
-       MultiIntr       = 0x5c,
-       PHYAR           = 0x60,
--      TBICSR          = 0x64,
--      TBI_ANAR        = 0x68,
--      TBI_LPAR        = 0x6a,
-       PHYstatus       = 0x6c,
-       RxMaxSize       = 0xda,
-       CPlusCmd        = 0xe0,
-@@ -213,6 +210,32 @@ enum rtl_registers {
-       FuncForceEvent  = 0xfc,
- };
-+enum rtl8110_registers {
-+      TBICSR                  = 0x64,
-+      TBI_ANAR                = 0x68,
-+      TBI_LPAR                = 0x6a,
-+};
-+
-+enum rtl8168_8101_registers {
-+      CSIDR                   = 0x64,
-+      CSIAR                   = 0x68,
-+#define       CSIAR_FLAG                      0x80000000
-+#define       CSIAR_WRITE_CMD                 0x80000000
-+#define       CSIAR_BYTE_ENABLE               0x0f
-+#define       CSIAR_BYTE_ENABLE_SHIFT         12
-+#define       CSIAR_ADDR_MASK                 0x0fff
-+
-+      EPHYAR                  = 0x80,
-+#define       EPHYAR_FLAG                     0x80000000
-+#define       EPHYAR_WRITE_CMD                0x80000000
-+#define       EPHYAR_REG_MASK                 0x1f
-+#define       EPHYAR_REG_SHIFT                16
-+#define       EPHYAR_DATA_MASK                0xffff
-+      DBG_REG                 = 0xd1,
-+#define       FIX_NAK_1                       (1 << 4)
-+#define       FIX_NAK_2                       (1 << 3)
-+};
-+
- enum rtl_register_content {
-       /* InterruptStatusBits */
-       SYSErr          = 0x8000,
-@@ -266,7 +289,13 @@ enum rtl_register_content {
-       TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
-       /* Config1 register p.24 */
-+      LEDS1           = (1 << 7),
-+      LEDS0           = (1 << 6),
-       MSIEnable       = (1 << 5),     /* Enable Message Signaled Interrupt */
-+      Speed_down      = (1 << 4),
-+      MEMMAP          = (1 << 3),
-+      IOMAP           = (1 << 2),
-+      VPD             = (1 << 1),
-       PMEnable        = (1 << 0),     /* Power Management Enable */
-       /* Config2 register p. 25 */
-@@ -276,6 +305,7 @@ enum rtl_register_content {
-       /* Config3 register p.25 */
-       MagicPacket     = (1 << 5),     /* Wake up when receives a Magic Packet */
-       LinkUp          = (1 << 4),     /* Wake up when the cable connection is re-established */
-+      Beacon_en       = (1 << 0),     /* 8168 only. Reserved in the 8168b */
-       /* Config5 register p.27 */
-       BWF             = (1 << 6),     /* Accept Broadcast wakeup frame */
-@@ -293,7 +323,16 @@ enum rtl_register_content {
-       TBINwComplete   = 0x01000000,
-       /* CPlusCmd p.31 */
--      PktCntrDisable  = (1 << 7),     // 8168
-+      EnableBist      = (1 << 15),    // 8168 8101
-+      Mac_dbgo_oe     = (1 << 14),    // 8168 8101
-+      Normal_mode     = (1 << 13),    // unused
-+      Force_half_dup  = (1 << 12),    // 8168 8101
-+      Force_rxflow_en = (1 << 11),    // 8168 8101
-+      Force_txflow_en = (1 << 10),    // 8168 8101
-+      Cxpl_dbg_sel    = (1 << 9),     // 8168 8101
-+      ASF             = (1 << 8),     // 8168 8101
-+      PktCntrDisable  = (1 << 7),     // 8168 8101
-+      Mac_dbgo_sel    = 0x001c,       // 8168
-       RxVlan          = (1 << 6),
-       RxChkSum        = (1 << 5),
-       PCIDAC          = (1 << 4),
--- 
-1.5.3.3
-
-From 61650c9e3d637b0990d9f26b1421ac4b55f5c744 Mon Sep 17 00:00:00 2001
-From: Francois Romieu <romieu@fr.zoreil.com>
-Date: Sat, 2 Aug 2008 20:44:13 +0200
-Subject: [PATCH] r8169: add hw start helpers for the 8168 and the 8101
-
-This commit triggers three 'defined but not used' warnings but
-I prefer avoiding to tie these helpers to a specific change in
-the hw start sequences of the 8168 or of the 8101.
-
-Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
-Cc: Edward Hsu <edward_hsu@realtek.com.tw>
----
- drivers/net/r8169.c |   96 +++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 files changed, 96 insertions(+), 0 deletions(-)
-
-diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
-index 0b8db03..52eba5c 100644
---- a/drivers/net/r8169.c
-+++ b/drivers/net/r8169.c
-@@ -526,6 +526,11 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
-       return value;
- }
-+static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value)
-+{
-+      mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value);
-+}
-+
- static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
-                          int val)
- {
-@@ -543,6 +548,72 @@ static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
-       return mdio_read(ioaddr, location);
- }
-+static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value)
-+{
-+      unsigned int i;
-+
-+      RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
-+              (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
-+
-+      for (i = 0; i < 100; i++) {
-+              if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG))
-+                      break;
-+              udelay(10);
-+      }
-+}
-+
-+static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr)
-+{
-+      u16 value = 0xffff;
-+      unsigned int i;
-+
-+      RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
-+
-+      for (i = 0; i < 100; i++) {
-+              if (RTL_R32(EPHYAR) & EPHYAR_FLAG) {
-+                      value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK;
-+                      break;
-+              }
-+              udelay(10);
-+      }
-+
-+      return value;
-+}
-+
-+static void rtl_csi_write(void __iomem *ioaddr, int addr, int value)
-+{
-+      unsigned int i;
-+
-+      RTL_W32(CSIDR, value);
-+      RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
-+              CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
-+
-+      for (i = 0; i < 100; i++) {
-+              if (!(RTL_R32(CSIAR) & CSIAR_FLAG))
-+                      break;
-+              udelay(10);
-+      }
-+}
-+
-+static u32 rtl_csi_read(void __iomem *ioaddr, int addr)
-+{
-+      u32 value = ~0x00;
-+      unsigned int i;
-+
-+      RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
-+              CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
-+
-+      for (i = 0; i < 100; i++) {
-+              if (RTL_R32(CSIAR) & CSIAR_FLAG) {
-+                      value = RTL_R32(CSIDR);
-+                      break;
-+              }
-+              udelay(10);
-+      }
-+
-+      return value;
-+}
-+
- static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
- {
-       RTL_W16(IntrMask, 0x0000);
-@@ -2114,6 +2185,31 @@ static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
-       }
- }
-+static void rtl_csi_access_enable(void __iomem *ioaddr)
-+{
-+      u32 csi;
-+
-+      csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff;
-+      rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000);
-+}
-+
-+struct ephy_info {
-+      unsigned int offset;
-+      u16 mask;
-+      u16 bits;
-+};
-+
-+static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len)
-+{
-+      u16 w;
-+
-+      while (len-- > 0) {
-+              w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits;
-+              rtl_ephy_write(ioaddr, e->offset, w);
-+              e++;
-+      }
-+}
-+
- static void rtl_hw_start_8168(struct net_device *dev)
- {
-       struct rtl8169_private *tp = netdev_priv(dev);
--- 
-1.5.3.3
-
-From 81fbfc404f2a13646bee46fa98545c0023e3a67a Mon Sep 17 00:00:00 2001
-From: Francois Romieu <romieu@fr.zoreil.com>
-Date: Sat, 2 Aug 2008 21:08:49 +0200
-Subject: [PATCH] r8169: additional 8101 and 8102 support
-
-Signed-off-by: Ivan Vecera <ivecera@redhat.com>
-Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
-Cc: Edward Hsu <edward_hsu@realtek.com.tw>
----
- drivers/net/r8169.c |  124 ++++++++++++++++++++++++++++++++++++++++++++++++++-
- 1 files changed, 122 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
-index 52eba5c..f28c202 100644
---- a/drivers/net/r8169.c
-+++ b/drivers/net/r8169.c
-@@ -96,6 +96,10 @@ enum mac_version {
-       RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB
-       RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
-       RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
-+      RTL_GIGA_MAC_VER_07 = 0x07, // 8102e
-+      RTL_GIGA_MAC_VER_08 = 0x08, // 8102e
-+      RTL_GIGA_MAC_VER_09 = 0x09, // 8102e
-+      RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e
-       RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
-       RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be
-       RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb
-@@ -122,6 +126,10 @@ static const struct {
-       _R("RTL8169sb/8110sb",  RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB
-       _R("RTL8169sc/8110sc",  RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd
-       _R("RTL8169sc/8110sc",  RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe
-+      _R("RTL8102e",          RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E
-+      _R("RTL8102e",          RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E
-+      _R("RTL8102e",          RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E
-+      _R("RTL8101e",          RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E
-       _R("RTL8168b/8111b",    RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
-       _R("RTL8168b/8111b",    RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
-       _R("RTL8101e",          RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
-@@ -837,8 +845,12 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
-               }
-       }
--      /* The 8100e/8101e do Fast Ethernet only. */
--      if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
-+      /* The 8100e/8101e/8102e do Fast Ethernet only. */
-+      if ((tp->mac_version == RTL_GIGA_MAC_VER_07) ||
-+          (tp->mac_version == RTL_GIGA_MAC_VER_08) ||
-+          (tp->mac_version == RTL_GIGA_MAC_VER_09) ||
-+          (tp->mac_version == RTL_GIGA_MAC_VER_10) ||
-+          (tp->mac_version == RTL_GIGA_MAC_VER_13) ||
-           (tp->mac_version == RTL_GIGA_MAC_VER_14) ||
-           (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
-           (tp->mac_version == RTL_GIGA_MAC_VER_16)) {
-@@ -1212,8 +1224,17 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
-               { 0x7c800000, 0x30000000,       RTL_GIGA_MAC_VER_11 },
-               /* 8101 family. */
-+              { 0x7cf00000, 0x34a00000,       RTL_GIGA_MAC_VER_09 },
-+              { 0x7cf00000, 0x24a00000,       RTL_GIGA_MAC_VER_09 },
-+              { 0x7cf00000, 0x34900000,       RTL_GIGA_MAC_VER_08 },
-+              { 0x7cf00000, 0x24900000,       RTL_GIGA_MAC_VER_08 },
-+              { 0x7cf00000, 0x34800000,       RTL_GIGA_MAC_VER_07 },
-+              { 0x7cf00000, 0x24800000,       RTL_GIGA_MAC_VER_07 },
-               { 0x7cf00000, 0x34000000,       RTL_GIGA_MAC_VER_13 },
-+              { 0x7cf00000, 0x34300000,       RTL_GIGA_MAC_VER_10 },
-               { 0x7cf00000, 0x34200000,       RTL_GIGA_MAC_VER_16 },
-+              { 0x7c800000, 0x34800000,       RTL_GIGA_MAC_VER_09 },
-+              { 0x7c800000, 0x24800000,       RTL_GIGA_MAC_VER_09 },
-               { 0x7c800000, 0x34000000,       RTL_GIGA_MAC_VER_16 },
-               /* FIXME: where did these entries come from ? -- FR */
-               { 0xfc800000, 0x38800000,       RTL_GIGA_MAC_VER_15 },
-@@ -1375,6 +1396,22 @@ static void rtl8168cx_hw_phy_config(void __iomem *ioaddr)
-       rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
- }
-+static void rtl8102e_hw_phy_config(void __iomem *ioaddr)
-+{
-+      struct phy_reg phy_reg_init[] = {
-+              { 0x1f, 0x0003 },
-+              { 0x08, 0x441d },
-+              { 0x01, 0x9100 },
-+              { 0x1f, 0x0000 }
-+      };
-+
-+      mdio_write(ioaddr, 0x1f, 0x0000);
-+      mdio_patch(ioaddr, 0x11, 1 << 12);
-+      mdio_patch(ioaddr, 0x19, 1 << 13);
-+
-+      rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
-+}
-+
- static void rtl_hw_phy_config(struct net_device *dev)
- {
-       struct rtl8169_private *tp = netdev_priv(dev);
-@@ -1392,6 +1429,11 @@ static void rtl_hw_phy_config(struct net_device *dev)
-       case RTL_GIGA_MAC_VER_04:
-               rtl8169sb_hw_phy_config(ioaddr);
-               break;
-+      case RTL_GIGA_MAC_VER_07:
-+      case RTL_GIGA_MAC_VER_08:
-+      case RTL_GIGA_MAC_VER_09:
-+              rtl8102e_hw_phy_config(ioaddr);
-+              break;
-       case RTL_GIGA_MAC_VER_18:
-               rtl8168cp_hw_phy_config(ioaddr);
-               break;
-@@ -2253,6 +2295,70 @@ static void rtl_hw_start_8168(struct net_device *dev)
-       RTL_W16(IntrMask, tp->intr_event);
- }
-+#define R810X_CPCMD_QUIRK_MASK (\
-+      EnableBist | \
-+      Mac_dbgo_oe | \
-+      Force_half_dup | \
-+      Force_half_dup | \
-+      Force_txflow_en | \
-+      Cxpl_dbg_sel | \
-+      ASF | \
-+      PktCntrDisable | \
-+      PCIDAC | \
-+      PCIMulRW)
-+
-+static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev)
-+{
-+      static struct ephy_info e_info_8102e_1[] = {
-+              { 0x01, 0, 0x6e65 },
-+              { 0x02, 0, 0x091f },
-+              { 0x03, 0, 0xc2f9 },
-+              { 0x06, 0, 0xafb5 },
-+              { 0x07, 0, 0x0e00 },
-+              { 0x19, 0, 0xec80 },
-+              { 0x01, 0, 0x2e65 },
-+              { 0x01, 0, 0x6e65 }
-+      };
-+      u8 cfg1;
-+
-+      rtl_csi_access_enable(ioaddr);
-+
-+      RTL_W8(DBG_REG, FIX_NAK_1);
-+
-+      rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
-+
-+      RTL_W8(Config1,
-+             LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
-+      RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
-+
-+      cfg1 = RTL_R8(Config1);
-+      if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
-+              RTL_W8(Config1, cfg1 & ~LEDS0);
-+
-+      RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
-+
-+      rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
-+}
-+
-+static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev)
-+{
-+      rtl_csi_access_enable(ioaddr);
-+
-+      rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
-+
-+      RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
-+      RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
-+
-+      RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
-+}
-+
-+static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev)
-+{
-+      rtl_hw_start_8102e_2(ioaddr, pdev);
-+
-+      rtl_ephy_write(ioaddr, 0x03, 0xc2f9);
-+}
-+
- static void rtl_hw_start_8101(struct net_device *dev)
- {
-       struct rtl8169_private *tp = netdev_priv(dev);
-@@ -2269,6 +2375,20 @@ static void rtl_hw_start_8101(struct net_device *dev)
-               }
-       }
-+      switch (tp->mac_version) {
-+      case RTL_GIGA_MAC_VER_07:
-+              rtl_hw_start_8102e_1(ioaddr, pdev);
-+              break;
-+
-+      case RTL_GIGA_MAC_VER_08:
-+              rtl_hw_start_8102e_3(ioaddr, pdev);
-+              break;
-+
-+      case RTL_GIGA_MAC_VER_09:
-+              rtl_hw_start_8102e_2(ioaddr, pdev);
-+              break;
-+      }
-+
-       RTL_W8(Cfg9346, Cfg9346_Unlock);
-       RTL_W8(EarlyTxThres, EarlyTxThld);
--- 
-1.5.3.3
-
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0042-intelfb-945gme.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0042-intelfb-945gme.patch
deleted file mode 100644 (file)
index 15ebe56..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-The following patch adds support for Intel's 945GME graphics chip to
-the intelfb driver.  I have assumed that the 945GME is identical to the
-already-supported 945GM apart from its PCI IDs; this is based on a quick
-look at the X driver for these chips which seems to treat them
-identically.
-
-Signed-off-by: Phil Endecott <spam_from_intelfb@chezphil.org>
-
----
-
-The 945GME is used in the ASUS Eee 901, and I coded this in the hope that 
-I'd be able to use it to get a console at the native 1024x600 resolution 
-which is not known to the BIOS.  I realised too late that the intelfb 
-driver does not support mode changing on laptops, so it won't be any 
-use for me.  But rather than throw it away I will post it here as 
-essentially "untested"; maybe someone who knows more about this driver, 
-and with more useful hardware to test on, can pick it up.
-
-diff --git a/Documentation/fb/intelfb.txt b/Documentation/fb/intelfb.txt
-index 27a3160..dd9e944 100644
---- a/Documentation/fb/intelfb.txt
-+++ b/Documentation/fb/intelfb.txt
-@@ -14,6 +14,7 @@ graphics devices.  These would include:
-       Intel 915GM
-       Intel 945G
-       Intel 945GM
-+      Intel 945GME
-       Intel 965G
-       Intel 965GM
-diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
-index 3325fbd..a50bea6 100644
---- a/drivers/video/intelfb/intelfb.h
-+++ b/drivers/video/intelfb/intelfb.h
-@@ -12,9 +12,9 @@
- #endif
- /*** Version/name ***/
--#define INTELFB_VERSION                       "0.9.5"
-+#define INTELFB_VERSION                       "0.9.6"
- #define INTELFB_MODULE_NAME           "intelfb"
--#define SUPPORTED_CHIPSETS            "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM"
-+#define SUPPORTED_CHIPSETS            "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM"
- /*** Debug/feature defines ***/
-@@ -58,6 +58,7 @@
- #define PCI_DEVICE_ID_INTEL_915GM     0x2592
- #define PCI_DEVICE_ID_INTEL_945G      0x2772
- #define PCI_DEVICE_ID_INTEL_945GM     0x27A2
-+#define PCI_DEVICE_ID_INTEL_945GME    0x27AE
- #define PCI_DEVICE_ID_INTEL_965G      0x29A2
- #define PCI_DEVICE_ID_INTEL_965GM     0x2A02
-@@ -160,6 +161,7 @@ enum intel_chips {
-       INTEL_915GM,
-       INTEL_945G,
-       INTEL_945GM,
-+      INTEL_945GME,
-       INTEL_965G,
-       INTEL_965GM,
- };
-@@ -363,6 +365,7 @@ struct intelfb_info {
-                       ((dinfo)->chipset == INTEL_915GM) ||    \
-                       ((dinfo)->chipset == INTEL_945G) ||     \
-                       ((dinfo)->chipset == INTEL_945GM) ||    \
-+                      ((dinfo)->chipset == INTEL_945GME) ||   \
-                       ((dinfo)->chipset == INTEL_965G) ||     \
-                       ((dinfo)->chipset == INTEL_965GM))
-diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
-index fcf9fad..5d896b8 100644
---- a/drivers/video/intelfb/intelfb_i2c.c
-+++ b/drivers/video/intelfb/intelfb_i2c.c
-@@ -171,6 +171,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
-               /* has some LVDS + tv-out */
-       case INTEL_945G:
-       case INTEL_945GM:
-+      case INTEL_945GME:
-       case INTEL_965G:
-       case INTEL_965GM:
-               /* SDVO ports have a single control bus - 2 devices */
-diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
-index e44303f..a09e236 100644
---- a/drivers/video/intelfb/intelfbdrv.c
-+++ b/drivers/video/intelfb/intelfbdrv.c
-@@ -2,7 +2,7 @@
-  * intelfb
-  *
-  * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
-- * 945G/945GM/965G/965GM integrated graphics chips.
-+ * 945G/945GM/945GME/965G/965GM integrated graphics chips.
-  *
-  * Copyright Â© 2002, 2003 David Dawes <dawes@xfree86.org>
-  *                   2004 Sylvain Meyer
-@@ -102,6 +102,9 @@
-  *
-  *    04/2008 - Version 0.9.5
-  *              Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>)
-+ *
-+ *    08/2008 - Version 0.9.6
-+ *              Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
-  */
- #include <linux/module.h>
-@@ -183,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
-+      { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
-       { 0, }
-@@ -555,6 +559,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
-           (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
-           (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||
-           (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
-+          (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
-           (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
-           (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
-diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
-index 8e6d6a4..8b26b27 100644
---- a/drivers/video/intelfb/intelfbhw.c
-+++ b/drivers/video/intelfb/intelfbhw.c
-@@ -143,6 +143,12 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
-               dinfo->mobile = 1;
-               dinfo->pll_index = PLLS_I9xx;
-               return 0;
-+      case PCI_DEVICE_ID_INTEL_945GME:
-+              dinfo->name = "Intel(R) 945GME";
-+              dinfo->chipset = INTEL_945GME;
-+              dinfo->mobile = 1;
-+              dinfo->pll_index = PLLS_I9xx;
-+              return 0;
-       case PCI_DEVICE_ID_INTEL_965G:
-               dinfo->name = "Intel(R) 965G";
-               dinfo->chipset = INTEL_965G;
-@@ -186,6 +192,7 @@ int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
-       case PCI_DEVICE_ID_INTEL_915GM:
-       case PCI_DEVICE_ID_INTEL_945G:
-       case PCI_DEVICE_ID_INTEL_945GM:
-+      case PCI_DEVICE_ID_INTEL_945GME:
-       case PCI_DEVICE_ID_INTEL_965G:
-       case PCI_DEVICE_ID_INTEL_965GM:
-               /* 915, 945 and 965 chipsets support a 256MB aperture.
-
-
---
-To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at  http://vger.kernel.org/majordomo-info.html
-Please read the FAQ at  http://www.tux.org/lkml/
\ No newline at end of file
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/defconfig-netbook b/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/defconfig-netbook
deleted file mode 100644 (file)
index ad9729e..0000000
+++ /dev/null
@@ -1,2424 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Thu Oct  9 20:10:11 2008
-#
-# CONFIG_64BIT is not set
-CONFIG_X86_32=y
-# CONFIG_X86_64 is not set
-CONFIG_X86=y
-CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
-# CONFIG_GENERIC_LOCKBREAK is not set
-CONFIG_GENERIC_TIME=y
-CONFIG_GENERIC_CMOS_UPDATE=y
-CONFIG_CLOCKSOURCE_WATCHDOG=y
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_FAST_CMPXCHG_LOCAL=y
-CONFIG_MMU=y
-CONFIG_ZONE_DMA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_GENERIC_IOMAP=y
-CONFIG_GENERIC_BUG=y
-CONFIG_GENERIC_HWEIGHT=y
-# CONFIG_GENERIC_GPIO is not set
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_GENERIC_TIME_VSYSCALL is not set
-CONFIG_ARCH_HAS_CPU_RELAX=y
-CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
-CONFIG_HAVE_SETUP_PER_CPU_AREA=y
-# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set
-CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_ZONE_DMA32 is not set
-CONFIG_ARCH_POPULATES_NODE_MAP=y
-# CONFIG_AUDIT_ARCH is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_PENDING_IRQ=y
-CONFIG_X86_SMP=y
-CONFIG_X86_32_SMP=y
-CONFIG_X86_HT=y
-CONFIG_X86_BIOS_REBOOT=y
-CONFIG_X86_TRAMPOLINE=y
-CONFIG_KTIME_SCALAR=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_LOCALVERSION="-netbook"
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_TASKSTATS=y
-CONFIG_TASK_DELAY_ACCT=y
-CONFIG_TASK_XACCT=y
-CONFIG_TASK_IO_ACCOUNTING=y
-CONFIG_AUDIT=y
-CONFIG_AUDITSYSCALL=y
-CONFIG_AUDIT_TREE=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_CGROUPS is not set
-CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
-# CONFIG_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED_V2 is not set
-CONFIG_RELAY=y
-CONFIG_NAMESPACES=y
-# CONFIG_UTS_NS is not set
-# CONFIG_IPC_NS is not set
-CONFIG_USER_NS=y
-# CONFIG_PID_NS is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_FASTBOOT=y
-CONFIG_SYSCTL=y
-# CONFIG_EMBEDDED is not set
-CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_PCSPKR_PLATFORM=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-CONFIG_PROFILING=y
-# CONFIG_MARKERS is not set
-# CONFIG_OPROFILE is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_USE_GENERIC_SMP_HELPERS=y
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-CONFIG_BLK_DEV_IO_TRACE=y
-# CONFIG_LSF is not set
-CONFIG_BLK_DEV_BSG=y
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-
-#
-# Processor type and features
-#
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_SMP=y
-CONFIG_X86_FIND_SMP_CONFIG=y
-CONFIG_X86_MPPARSE=y
-CONFIG_X86_PC=y
-# CONFIG_X86_ELAN is not set
-# CONFIG_X86_VOYAGER is not set
-# CONFIG_X86_GENERICARCH is not set
-# CONFIG_X86_VSMP is not set
-# CONFIG_X86_RDC321X is not set
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_PARAVIRT_GUEST is not set
-# CONFIG_MEMTEST is not set
-# CONFIG_M386 is not set
-# CONFIG_M486 is not set
-# CONFIG_M586 is not set
-# CONFIG_M586TSC is not set
-# CONFIG_M586MMX is not set
-CONFIG_M686=y
-# CONFIG_MPENTIUMII is not set
-# CONFIG_MPENTIUMIII is not set
-# CONFIG_MPENTIUMM is not set
-# CONFIG_MPENTIUM4 is not set
-# CONFIG_MK6 is not set
-# CONFIG_MK7 is not set
-# CONFIG_MK8 is not set
-# CONFIG_MCRUSOE is not set
-# CONFIG_MEFFICEON is not set
-# CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
-# CONFIG_MWINCHIP3D is not set
-# CONFIG_MGEODEGX1 is not set
-# CONFIG_MGEODE_LX is not set
-# CONFIG_MCYRIXIII is not set
-# CONFIG_MVIAC3_2 is not set
-# CONFIG_MVIAC7 is not set
-# CONFIG_MPSC is not set
-# CONFIG_MCORE2 is not set
-# CONFIG_GENERIC_CPU is not set
-# CONFIG_X86_GENERIC is not set
-CONFIG_X86_CPU=y
-CONFIG_X86_CMPXCHG=y
-CONFIG_X86_L1_CACHE_SHIFT=5
-CONFIG_X86_XADD=y
-# CONFIG_X86_PPRO_FENCE is not set
-CONFIG_X86_WP_WORKS_OK=y
-CONFIG_X86_INVLPG=y
-CONFIG_X86_BSWAP=y
-CONFIG_X86_POPAD_OK=y
-CONFIG_X86_USE_PPRO_CHECKSUM=y
-CONFIG_X86_TSC=y
-CONFIG_X86_CMOV=y
-CONFIG_X86_MINIMUM_CPU_FAMILY=4
-CONFIG_X86_DEBUGCTLMSR=y
-CONFIG_HPET_TIMER=y
-CONFIG_HPET_EMULATE_RTC=y
-CONFIG_DMI=y
-# CONFIG_IOMMU_HELPER is not set
-CONFIG_NR_CPUS=2
-CONFIG_SCHED_SMT=y
-CONFIG_SCHED_MC=y
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
-# CONFIG_PREEMPT is not set
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_MCE=y
-# CONFIG_X86_MCE_NONFATAL is not set
-# CONFIG_X86_MCE_P4THERMAL is not set
-CONFIG_VM86=y
-# CONFIG_TOSHIBA is not set
-# CONFIG_I8K is not set
-# CONFIG_X86_REBOOTFIXUPS is not set
-CONFIG_MICROCODE=y
-CONFIG_MICROCODE_OLD_INTERFACE=y
-CONFIG_X86_MSR=y
-CONFIG_X86_CPUID=y
-# CONFIG_NOHIGHMEM is not set
-CONFIG_HIGHMEM4G=y
-# CONFIG_HIGHMEM64G is not set
-CONFIG_PAGE_OFFSET=0xC0000000
-CONFIG_HIGHMEM=y
-CONFIG_NEED_NODE_MEMMAP_SIZE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_SELECT_MEMORY_MODEL=y
-CONFIG_SELECT_MEMORY_MODEL=y
-# CONFIG_FLATMEM_MANUAL is not set
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-CONFIG_SPARSEMEM_MANUAL=y
-CONFIG_SPARSEMEM=y
-CONFIG_HAVE_MEMORY_PRESENT=y
-CONFIG_SPARSEMEM_STATIC=y
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
-
-#
-# Memory hotplug is currently incompatible with Software Suspend
-#
-CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-# CONFIG_HIGHPTE is not set
-# CONFIG_MATH_EMULATION is not set
-CONFIG_MTRR=y
-# CONFIG_MTRR_SANITIZER is not set
-# CONFIG_X86_PAT is not set
-# CONFIG_EFI is not set
-# CONFIG_IRQBALANCE is not set
-# CONFIG_SECCOMP is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_300 is not set
-CONFIG_HZ_1000=y
-CONFIG_HZ=1000
-CONFIG_SCHED_HRTICK=y
-CONFIG_KEXEC=y
-CONFIG_CRASH_DUMP=y
-# CONFIG_KEXEC_JUMP is not set
-CONFIG_PHYSICAL_START=0x400000
-CONFIG_RELOCATABLE=y
-CONFIG_PHYSICAL_ALIGN=0x200000
-CONFIG_HOTPLUG_CPU=y
-CONFIG_COMPAT_VDSO=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-# CONFIG_PM_VERBOSE is not set
-CONFIG_CAN_PM_TRACE=y
-CONFIG_PM_TRACE=y
-CONFIG_PM_TRACE_RTC=y
-CONFIG_PM_SLEEP_SMP=y
-CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND=y
-# CONFIG_PM_TEST_SUSPEND is not set
-CONFIG_SUSPEND_FREEZER=y
-CONFIG_HIBERNATION=y
-CONFIG_PM_STD_PARTITION=""
-CONFIG_ACPI=y
-CONFIG_ACPI_SLEEP=y
-CONFIG_ACPI_PROCFS=y
-CONFIG_ACPI_PROCFS_POWER=y
-CONFIG_ACPI_SYSFS_POWER=y
-CONFIG_ACPI_PROC_EVENT=y
-CONFIG_ACPI_AC=y
-CONFIG_ACPI_BATTERY=m
-CONFIG_ACPI_BUTTON=y
-CONFIG_ACPI_VIDEO=y
-CONFIG_ACPI_FAN=y
-CONFIG_ACPI_DOCK=y
-# CONFIG_ACPI_BAY is not set
-CONFIG_ACPI_PROCESSOR=y
-CONFIG_ACPI_HOTPLUG_CPU=y
-CONFIG_ACPI_THERMAL=y
-CONFIG_ACPI_WMI=m
-CONFIG_ACPI_ASUS=y
-# CONFIG_ACPI_TOSHIBA is not set
-# CONFIG_ACPI_CUSTOM_DSDT is not set
-CONFIG_ACPI_BLACKLIST_YEAR=0
-# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_EC=y
-# CONFIG_ACPI_PCI_SLOT is not set
-CONFIG_ACPI_POWER=y
-CONFIG_ACPI_SYSTEM=y
-CONFIG_X86_PM_TIMER=y
-CONFIG_ACPI_CONTAINER=y
-CONFIG_ACPI_SBS=m
-# CONFIG_APM is not set
-
-#
-# CPU Frequency scaling
-#
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-CONFIG_CPU_FREQ_DEBUG=y
-CONFIG_CPU_FREQ_STAT=m
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
-
-#
-# CPUFreq processor drivers
-#
-CONFIG_X86_ACPI_CPUFREQ=y
-# CONFIG_X86_POWERNOW_K6 is not set
-# CONFIG_X86_POWERNOW_K7 is not set
-# CONFIG_X86_POWERNOW_K8 is not set
-# CONFIG_X86_GX_SUSPMOD is not set
-# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
-# CONFIG_X86_SPEEDSTEP_ICH is not set
-# CONFIG_X86_SPEEDSTEP_SMI is not set
-# CONFIG_X86_P4_CLOCKMOD is not set
-# CONFIG_X86_CPUFREQ_NFORCE2 is not set
-# CONFIG_X86_LONGRUN is not set
-# CONFIG_X86_LONGHAUL is not set
-# CONFIG_X86_E_POWERSAVER is not set
-
-#
-# shared options
-#
-# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
-# CONFIG_X86_SPEEDSTEP_LIB is not set
-CONFIG_CPU_IDLE=y
-CONFIG_CPU_IDLE_GOV_LADDER=y
-CONFIG_CPU_IDLE_GOV_MENU=y
-
-#
-# Bus options (PCI etc.)
-#
-CONFIG_PCI=y
-# CONFIG_PCI_GOBIOS is not set
-# CONFIG_PCI_GOMMCONFIG is not set
-# CONFIG_PCI_GODIRECT is not set
-# CONFIG_PCI_GOOLPC is not set
-CONFIG_PCI_GOANY=y
-CONFIG_PCI_BIOS=y
-CONFIG_PCI_DIRECT=y
-CONFIG_PCI_MMCONFIG=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_PCIEAER=y
-CONFIG_PCIEASPM=y
-# CONFIG_PCIEASPM_DEBUG is not set
-CONFIG_ARCH_SUPPORTS_MSI=y
-CONFIG_PCI_MSI=y
-CONFIG_PCI_LEGACY=y
-# CONFIG_PCI_DEBUG is not set
-CONFIG_HT_IRQ=y
-CONFIG_ISA_DMA_API=y
-# CONFIG_ISA is not set
-# CONFIG_MCA is not set
-# CONFIG_SCx200 is not set
-# CONFIG_OLPC is not set
-CONFIG_K8_NB=y
-# CONFIG_PCCARD is not set
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats / Emulations
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_AOUT is not set
-CONFIG_BINFMT_MISC=y
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-CONFIG_XFRM_SUB_POLICY=y
-CONFIG_XFRM_MIGRATE=y
-CONFIG_XFRM_STATISTICS=y
-CONFIG_XFRM_IPCOMP=m
-CONFIG_NET_KEY=m
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_TUNNEL=m
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_LRO=y
-CONFIG_INET_DIAG=m
-CONFIG_INET_TCP_DIAG=m
-CONFIG_TCP_CONG_ADVANCED=y
-CONFIG_TCP_CONG_BIC=m
-CONFIG_TCP_CONG_CUBIC=y
-# CONFIG_TCP_CONG_WESTWOOD is not set
-# CONFIG_TCP_CONG_HTCP is not set
-# CONFIG_TCP_CONG_HSTCP is not set
-# CONFIG_TCP_CONG_HYBLA is not set
-# CONFIG_TCP_CONG_VEGAS is not set
-# CONFIG_TCP_CONG_SCALABLE is not set
-# CONFIG_TCP_CONG_LP is not set
-# CONFIG_TCP_CONG_VENO is not set
-# CONFIG_TCP_CONG_YEAH is not set
-# CONFIG_TCP_CONG_ILLINOIS is not set
-# CONFIG_DEFAULT_BIC is not set
-CONFIG_DEFAULT_CUBIC=y
-# CONFIG_DEFAULT_HTCP is not set
-# CONFIG_DEFAULT_VEGAS is not set
-# CONFIG_DEFAULT_WESTWOOD is not set
-# CONFIG_DEFAULT_RENO is not set
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-CONFIG_IPV6_OPTIMISTIC_DAD=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_TUNNEL=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-CONFIG_IPV6_NDISC_NODETYPE=y
-CONFIG_IPV6_TUNNEL=m
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-# CONFIG_IPV6_MROUTE is not set
-CONFIG_NETLABEL=y
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_NETFILTER_ADVANCED=y
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK=y
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-# CONFIG_NF_CT_PROTO_DCCP is not set
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-CONFIG_NF_CONNTRACK_NETBIOS_NS=m
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=y
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
-CONFIG_NETFILTER_XT_TARGET_DSCP=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
-CONFIG_NETFILTER_XT_TARGET_RATEEST=m
-CONFIG_NETFILTER_XT_TARGET_TRACE=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_OWNER=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_RATEEST=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_TIME=m
-CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV4=y
-# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_AH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
-CONFIG_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_NF_NAT_SNMP_BASIC=m
-CONFIG_NF_NAT_PROTO_GRE=m
-CONFIG_NF_NAT_PROTO_UDPLITE=m
-CONFIG_NF_NAT_PROTO_SCTP=m
-CONFIG_NF_NAT_FTP=m
-CONFIG_NF_NAT_IRC=m
-CONFIG_NF_NAT_TFTP=m
-CONFIG_NF_NAT_AMANDA=m
-CONFIG_NF_NAT_PPTP=m
-CONFIG_NF_NAT_H323=m
-CONFIG_NF_NAT_SIP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-# CONFIG_IP_NF_SECURITY is not set
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV6=y
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
-CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=y
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_TARGET_REJECT=y
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_RAW=m
-# CONFIG_IP6_NF_SECURITY is not set
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
-# CONFIG_BT_BNEP_MC_FILTER is not set
-# CONFIG_BT_BNEP_PROTO_FILTER is not set
-# CONFIG_BT_HIDP is not set
-
-#
-# Bluetooth device drivers
-#
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
-# CONFIG_BT_HCIBTUSB is not set
-CONFIG_BT_HCIBTSDIO=m
-CONFIG_BT_HCIUART=m
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIUART_BCSP=y
-CONFIG_BT_HCIUART_LL=y
-CONFIG_BT_HCIBCM203X=m
-CONFIG_BT_HCIBPA10X=m
-CONFIG_BT_HCIBFUSB=m
-CONFIG_BT_HCIVHCI=m
-# CONFIG_AF_RXRPC is not set
-CONFIG_FIB_RULES=y
-
-#
-# Wireless
-#
-CONFIG_CFG80211=m
-CONFIG_NL80211=y
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-CONFIG_MAC80211=m
-
-#
-# Rate control algorithm selection
-#
-CONFIG_MAC80211_RC_PID=y
-CONFIG_MAC80211_RC_DEFAULT_PID=y
-CONFIG_MAC80211_RC_DEFAULT="pid"
-CONFIG_MAC80211_MESH=y
-CONFIG_MAC80211_LEDS=y
-CONFIG_MAC80211_DEBUGFS=y
-# CONFIG_MAC80211_DEBUG_MENU is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_RFKILL=m
-CONFIG_RFKILL_INPUT=m
-CONFIG_RFKILL_LEDS=y
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_DEBUG_DRIVER is not set
-CONFIG_DEBUG_DEVRES=y
-# CONFIG_SYS_HYPERVISOR is not set
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
-# CONFIG_PARPORT is not set
-CONFIG_PNP=y
-# CONFIG_PNP_DEBUG is not set
-
-#
-# Protocols
-#
-CONFIG_PNPACPI=y
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=262144
-# CONFIG_BLK_DEV_XIP is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_IBM_ASM is not set
-# CONFIG_PHANTOM is not set
-CONFIG_EEPROM_93CX6=m
-# CONFIG_SGI_IOC4 is not set
-CONFIG_TIFM_CORE=m
-CONFIG_TIFM_7XX1=m
-# CONFIG_ACER_WMI is not set
-# CONFIG_FUJITSU_LAPTOP is not set
-# CONFIG_TC1100_WMI is not set
-# CONFIG_HP_WMI is not set
-# CONFIG_MSI_LAPTOP is not set
-# CONFIG_COMPAL_LAPTOP is not set
-# CONFIG_SONY_LAPTOP is not set
-# CONFIG_THINKPAD_ACPI is not set
-# CONFIG_INTEL_MENLOW is not set
-CONFIG_EEEPC_LAPTOP=y
-# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HP_ILO is not set
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=y
-CONFIG_SCSI_DMA=y
-# CONFIG_SCSI_TGT is not set
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
-CONFIG_CHR_DEV_SCH=m
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_SCSI_WAIT_SCAN=m
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
-# CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_SRP is not set
-# CONFIG_SCSI_DH is not set
-CONFIG_ATA=y
-# CONFIG_ATA_NONSTANDARD is not set
-CONFIG_ATA_ACPI=y
-# CONFIG_SATA_PMP is not set
-CONFIG_SATA_AHCI=y
-# CONFIG_SATA_SIL24 is not set
-CONFIG_ATA_SFF=y
-# CONFIG_SATA_SVW is not set
-CONFIG_ATA_PIIX=y
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_PDC_ADMA is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
-# CONFIG_SATA_INIC162X is not set
-# CONFIG_PATA_ACPI is not set
-# CONFIG_PATA_ALI is not set
-# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
-# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_CMD640_PCI is not set
-# CONFIG_PATA_CMD64X is not set
-# CONFIG_PATA_CS5520 is not set
-# CONFIG_PATA_CS5530 is not set
-# CONFIG_PATA_CS5535 is not set
-# CONFIG_PATA_CS5536 is not set
-# CONFIG_PATA_CYPRESS is not set
-# CONFIG_PATA_EFAR is not set
-# CONFIG_ATA_GENERIC is not set
-# CONFIG_PATA_HPT366 is not set
-# CONFIG_PATA_HPT37X is not set
-# CONFIG_PATA_HPT3X2N is not set
-# CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_TRIFLEX is not set
-# CONFIG_PATA_MARVELL is not set
-# CONFIG_PATA_MPIIX is not set
-# CONFIG_PATA_OLDPIIX is not set
-# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NINJA32 is not set
-# CONFIG_PATA_NS87410 is not set
-# CONFIG_PATA_NS87415 is not set
-# CONFIG_PATA_OPTI is not set
-# CONFIG_PATA_OPTIDMA is not set
-# CONFIG_PATA_PDC_OLD is not set
-# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RZ1000 is not set
-# CONFIG_PATA_SC1200 is not set
-# CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
-# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
-CONFIG_PATA_SCH=y
-# CONFIG_MD is not set
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# Enable only one of the two stacks, unless you know what you are doing
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
-# CONFIG_I2O is not set
-# CONFIG_MACINTOSH_DRIVERS is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-CONFIG_MACVLAN=m
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_VETH is not set
-# CONFIG_NET_SB1000 is not set
-# CONFIG_ARCNET is not set
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-CONFIG_BROADCOM_PHY=m
-CONFIG_ICPLUS_PHY=m
-CONFIG_REALTEK_PHY=m
-CONFIG_MDIO_BITBANG=m
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_HAPPYMEAL=m
-CONFIG_SUNGEM=m
-CONFIG_CASSINI=m
-CONFIG_NET_VENDOR_3COM=y
-# CONFIG_VORTEX is not set
-# CONFIG_TYPHOON is not set
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_IBM_NEW_EMAC_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_E1000E is not set
-# CONFIG_IP1000 is not set
-# CONFIG_IGB is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_QLA3XXX is not set
-CONFIG_ATL1=y
-CONFIG_ATL1E=y
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
-CONFIG_WLAN_PRE80211=y
-# CONFIG_STRIP is not set
-CONFIG_WLAN_80211=y
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 is not set
-# CONFIG_LIBERTAS is not set
-# CONFIG_AIRO is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-# CONFIG_PRISM54 is not set
-CONFIG_USB_ZD1201=m
-CONFIG_USB_NET_RNDIS_WLAN=m
-CONFIG_RTL8180=m
-CONFIG_RTL8187=m
-# CONFIG_ADM8211 is not set
-# CONFIG_MAC80211_HWSIM is not set
-# CONFIG_P54_COMMON is not set
-CONFIG_ATH5K=m
-# CONFIG_ATH5K_DEBUG is not set
-# CONFIG_ATH9K is not set
-CONFIG_IWLWIFI=m
-CONFIG_IWLCORE=m
-# CONFIG_IWLWIFI_LEDS is not set
-CONFIG_IWLWIFI_RFKILL=y
-# CONFIG_IWLWIFI_DEBUG is not set
-# CONFIG_IWLAGN is not set
-CONFIG_IWL3945=m
-CONFIG_IWL3945_RFKILL=y
-# CONFIG_IWL3945_SPECTRUM_MEASUREMENT is not set
-# CONFIG_IWL3945_LEDS is not set
-# CONFIG_IWL3945_DEBUG is not set
-# CONFIG_HOSTAP is not set
-# CONFIG_B43 is not set
-# CONFIG_B43LEGACY is not set
-# CONFIG_ZD1211RW is not set
-CONFIG_RT2X00=m
-CONFIG_RT2X00_LIB=m
-CONFIG_RT2X00_LIB_PCI=m
-CONFIG_RT2X00_LIB_USB=m
-CONFIG_RT2X00_LIB_FIRMWARE=y
-CONFIG_RT2X00_LIB_RFKILL=y
-CONFIG_RT2X00_LIB_LEDS=y
-CONFIG_RT2400PCI=m
-CONFIG_RT2400PCI_RFKILL=y
-CONFIG_RT2400PCI_LEDS=y
-CONFIG_RT2500PCI=m
-CONFIG_RT2500PCI_RFKILL=y
-CONFIG_RT2500PCI_LEDS=y
-CONFIG_RT61PCI=m
-CONFIG_RT61PCI_RFKILL=y
-CONFIG_RT61PCI_LEDS=y
-CONFIG_RT2500USB=m
-CONFIG_RT2500USB_LEDS=y
-CONFIG_RT73USB=m
-CONFIG_RT73USB_LEDS=y
-CONFIG_RT2X00_LIB_DEBUGFS=y
-# CONFIG_RT2X00_DEBUG is not set
-
-#
-# USB Network Adapters
-#
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_NET_AX8817X=m
-CONFIG_USB_NET_CDCETHER=m
-CONFIG_USB_NET_DM9601=m
-CONFIG_USB_NET_GL620A=m
-CONFIG_USB_NET_NET1080=m
-CONFIG_USB_NET_PLUSB=m
-CONFIG_USB_NET_MCS7830=m
-CONFIG_USB_NET_RNDIS_HOST=m
-CONFIG_USB_NET_CDC_SUBSET=m
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_BELKIN=y
-CONFIG_USB_ARMLINUX=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_KC2190=y
-CONFIG_USB_NET_ZAURUS=m
-# CONFIG_USB_HSO is not set
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_PPPOL2TP=m
-# CONFIG_SLIP is not set
-CONFIG_SLHC=m
-CONFIG_NET_FC=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_FF_MEMLESS=y
-CONFIG_INPUT_POLLDEV=m
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=m
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-CONFIG_MOUSE_PS2_ALPS=y
-CONFIG_MOUSE_PS2_LOGIPS2PP=y
-CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
-CONFIG_MOUSE_PS2_TRACKPOINT=y
-# CONFIG_MOUSE_PS2_TOUCHKIT is not set
-CONFIG_MOUSE_SERIAL=m
-# CONFIG_MOUSE_APPLETOUCH is not set
-# CONFIG_MOUSE_BCM5974 is not set
-CONFIG_MOUSE_VSXXXAA=m
-CONFIG_INPUT_JOYSTICK=y
-# CONFIG_JOYSTICK_ANALOG is not set
-# CONFIG_JOYSTICK_A3D is not set
-# CONFIG_JOYSTICK_ADI is not set
-# CONFIG_JOYSTICK_COBRA is not set
-# CONFIG_JOYSTICK_GF2K is not set
-# CONFIG_JOYSTICK_GRIP is not set
-# CONFIG_JOYSTICK_GRIP_MP is not set
-# CONFIG_JOYSTICK_GUILLEMOT is not set
-# CONFIG_JOYSTICK_INTERACT is not set
-# CONFIG_JOYSTICK_SIDEWINDER is not set
-# CONFIG_JOYSTICK_TMDC is not set
-# CONFIG_JOYSTICK_IFORCE is not set
-# CONFIG_JOYSTICK_WARRIOR is not set
-# CONFIG_JOYSTICK_MAGELLAN is not set
-# CONFIG_JOYSTICK_SPACEORB is not set
-# CONFIG_JOYSTICK_SPACEBALL is not set
-# CONFIG_JOYSTICK_STINGER is not set
-# CONFIG_JOYSTICK_TWIDJOY is not set
-# CONFIG_JOYSTICK_ZHENHUA is not set
-# CONFIG_JOYSTICK_JOYDUMP is not set
-# CONFIG_JOYSTICK_XPAD is not set
-# CONFIG_INPUT_TABLET is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_FUJITSU=m
-CONFIG_TOUCHSCREEN_GUNZE=m
-CONFIG_TOUCHSCREEN_ELO=m
-CONFIG_TOUCHSCREEN_MTOUCH=m
-CONFIG_TOUCHSCREEN_INEXIO=m
-CONFIG_TOUCHSCREEN_MK712=m
-CONFIG_TOUCHSCREEN_PENMOUNT=m
-CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
-CONFIG_TOUCHSCREEN_TOUCHWIN=m
-CONFIG_TOUCHSCREEN_UCB1400=m
-# CONFIG_TOUCHSCREEN_WM97XX is not set
-CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
-CONFIG_TOUCHSCREEN_USB_EGALAX=y
-CONFIG_TOUCHSCREEN_USB_PANJIT=y
-CONFIG_TOUCHSCREEN_USB_3M=y
-CONFIG_TOUCHSCREEN_USB_ITM=y
-CONFIG_TOUCHSCREEN_USB_ETURBO=y
-CONFIG_TOUCHSCREEN_USB_GUNZE=y
-CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
-CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
-CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
-CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
-CONFIG_TOUCHSCREEN_USB_GOTOP=y
-CONFIG_TOUCHSCREEN_TOUCHIT213=m
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_PCSPKR is not set
-# CONFIG_INPUT_APANEL is not set
-# CONFIG_INPUT_WISTRON_BTNS is not set
-CONFIG_INPUT_ATLAS_BTNS=m
-CONFIG_INPUT_ATI_REMOTE=m
-CONFIG_INPUT_ATI_REMOTE2=m
-CONFIG_INPUT_KEYSPAN_REMOTE=m
-CONFIG_INPUT_POWERMATE=m
-CONFIG_INPUT_YEALINK=m
-CONFIG_INPUT_UINPUT=m
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_DEVKMEM is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-CONFIG_FIX_EARLYCON_MEM=y
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_SONYPI is not set
-# CONFIG_MWAVE is not set
-# CONFIG_PC8736x_GPIO is not set
-# CONFIG_NSC_GPIO is not set
-# CONFIG_CS5535_GPIO is not set
-# CONFIG_RAW_DRIVER is not set
-CONFIG_HPET=y
-# CONFIG_HPET_MMAP is not set
-# CONFIG_HANGCHECK_TIMER is not set
-# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_CHARDEV is not set
-CONFIG_I2C_HELPER_AUTO=y
-CONFIG_I2C_ALGOBIT=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
-
-#
-# External I2C/SMBus adapter drivers
-#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_TINY_USB is not set
-
-#
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Other I2C/SMBus bus drivers
-#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_SCx200_ACB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
-# CONFIG_W1 is not set
-CONFIG_POWER_SUPPLY=y
-# CONFIG_POWER_SUPPLY_DEBUG is not set
-# CONFIG_PDA_POWER is not set
-# CONFIG_BATTERY_DS2760 is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
-# CONFIG_SENSORS_AD7414 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7473 is not set
-# CONFIG_SENSORS_K8TEMP is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_I5K_AMB is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_FSCHMD is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_CORETEMP is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_VT8231 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_SENSORS_HDAPS is not set
-# CONFIG_SENSORS_APPLESMC is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-CONFIG_THERMAL=y
-# CONFIG_THERMAL_HWMON is not set
-# CONFIG_WATCHDOG is not set
-
-#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_MFD_TMIO is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
-CONFIG_VIDEO_V4L1_COMPAT=y
-CONFIG_DVB_CORE=y
-CONFIG_VIDEO_MEDIA=y
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=y
-# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=y
-CONFIG_MEDIA_TUNER_TDA8290=y
-CONFIG_MEDIA_TUNER_TDA9887=y
-CONFIG_MEDIA_TUNER_TEA5761=y
-CONFIG_MEDIA_TUNER_TEA5767=y
-CONFIG_MEDIA_TUNER_MT20XX=y
-CONFIG_MEDIA_TUNER_XC2028=y
-CONFIG_MEDIA_TUNER_XC5000=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_BT848 is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_VIDEO_SAA7134 is not set
-# CONFIG_VIDEO_HEXIUM_ORION is not set
-# CONFIG_VIDEO_HEXIUM_GEMINI is not set
-# CONFIG_VIDEO_CX88 is not set
-# CONFIG_VIDEO_CX23885 is not set
-# CONFIG_VIDEO_AU0828 is not set
-# CONFIG_VIDEO_CX18 is not set
-# CONFIG_VIDEO_CAFE_CCIC is not set
-CONFIG_V4L_USB_DRIVERS=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
-# CONFIG_USB_GSPCA is not set
-# CONFIG_VIDEO_PVRUSB2 is not set
-# CONFIG_VIDEO_EM28XX is not set
-# CONFIG_VIDEO_USBVISION is not set
-# CONFIG_USB_ET61X251 is not set
-# CONFIG_USB_SN9C102 is not set
-# CONFIG_USB_ZC0301 is not set
-# CONFIG_USB_ZR364XX is not set
-# CONFIG_USB_STKWEBCAM is not set
-# CONFIG_USB_S2255 is not set
-# CONFIG_SOC_CAMERA is not set
-# CONFIG_VIDEO_SH_MOBILE_CEU is not set
-# CONFIG_RADIO_ADAPTERS is not set
-# CONFIG_DVB_CAPTURE_DRIVERS is not set
-# CONFIG_DAB is not set
-
-#
-# Graphics support
-#
-CONFIG_AGP=y
-# CONFIG_AGP_ALI is not set
-# CONFIG_AGP_ATI is not set
-# CONFIG_AGP_AMD is not set
-CONFIG_AGP_AMD64=y
-CONFIG_AGP_INTEL=y
-# CONFIG_AGP_NVIDIA is not set
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_SWORKS is not set
-# CONFIG_AGP_VIA is not set
-# CONFIG_AGP_EFFICEON is not set
-CONFIG_DRM=y
-# CONFIG_DRM_TDFX is not set
-# CONFIG_DRM_R128 is not set
-# CONFIG_DRM_RADEON is not set
-CONFIG_DRM_I810=y
-# CONFIG_DRM_I830 is not set
-CONFIG_DRM_I915=y
-# CONFIG_DRM_MGA is not set
-# CONFIG_DRM_SIS is not set
-# CONFIG_DRM_VIA is not set
-# CONFIG_DRM_SAVAGE is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-CONFIG_FB_DDC=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
-# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-
-#
-# Frame buffer hardware drivers
-#
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ARC is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_UVESA is not set
-# CONFIG_FB_VESA is not set
-# CONFIG_FB_EFI is not set
-# CONFIG_FB_N411 is not set
-# CONFIG_FB_HGA is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_I810 is not set
-# CONFIG_FB_LE80578 is not set
-CONFIG_FB_INTEL=y
-CONFIG_FB_INTEL_DEBUG=y
-CONFIG_FB_INTEL_I2C=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_VT8623 is not set
-# CONFIG_FB_CYBLA is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_ARK is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_CARMINE is not set
-# CONFIG_FB_GEODE is not set
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-# CONFIG_LCD_ILI9320 is not set
-CONFIG_LCD_PLATFORM=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_CORGI is not set
-# CONFIG_BACKLIGHT_PROGEAR is not set
-CONFIG_BACKLIGHT_MBP_NVIDIA=y
-
-#
-# Display device support
-#
-CONFIG_DISPLAY_SUPPORT=y
-
-#
-# Display hardware drivers
-#
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_VGACON_SOFT_SCROLLBACK=y
-CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
-CONFIG_VIDEO_SELECT=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-# CONFIG_LOGO is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-CONFIG_SND_HWDEP=y
-CONFIG_SND_RAWMIDI=m
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_SEQ_DUMMY=y
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
-# CONFIG_SND_SEQUENCER_OSS is not set
-CONFIG_SND_DYNAMIC_MINORS=y
-# CONFIG_SND_SUPPORT_OLD_API is not set
-CONFIG_SND_VERBOSE_PROCFS=y
-CONFIG_SND_VERBOSE_PRINTK=y
-CONFIG_SND_DEBUG=y
-# CONFIG_SND_DEBUG_VERBOSE is not set
-CONFIG_SND_PCM_XRUN_DEBUG=y
-CONFIG_SND_VMASTER=y
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_DRIVERS=y
-# CONFIG_SND_PCSP is not set
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-CONFIG_SND_AC97_POWER_SAVE=y
-CONFIG_SND_AC97_POWER_SAVE_DEFAULT=5
-CONFIG_SND_PCI=y
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS300 is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_ATIIXP_MODEM is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AW2 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_OXYGEN is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS5530 is not set
-# CONFIG_SND_CS5535AUDIO is not set
-# CONFIG_SND_DARLA20 is not set
-# CONFIG_SND_GINA20 is not set
-# CONFIG_SND_LAYLA20 is not set
-# CONFIG_SND_DARLA24 is not set
-# CONFIG_SND_GINA24 is not set
-# CONFIG_SND_LAYLA24 is not set
-# CONFIG_SND_MONA is not set
-# CONFIG_SND_MIA is not set
-# CONFIG_SND_ECHO3G is not set
-# CONFIG_SND_INDIGO is not set
-# CONFIG_SND_INDIGOIO is not set
-# CONFIG_SND_INDIGODJ is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_FM801 is not set
-CONFIG_SND_HDA_INTEL=y
-CONFIG_SND_HDA_HWDEP=y
-CONFIG_SND_HDA_CODEC_REALTEK=y
-CONFIG_SND_HDA_CODEC_ANALOG=y
-CONFIG_SND_HDA_CODEC_SIGMATEL=y
-CONFIG_SND_HDA_CODEC_VIA=y
-CONFIG_SND_HDA_CODEC_ATIHDMI=y
-CONFIG_SND_HDA_CODEC_CONEXANT=y
-CONFIG_SND_HDA_CODEC_CMEDIA=y
-CONFIG_SND_HDA_CODEC_SI3054=y
-CONFIG_SND_HDA_GENERIC=y
-CONFIG_SND_HDA_POWER_SAVE=y
-CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_HIFIER is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-CONFIG_SND_INTEL8X0=y
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_PCXHR is not set
-# CONFIG_SND_RIPTIDE is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_SIS7019 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VIRTUOSO is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_USB=y
-CONFIG_SND_USB_AUDIO=m
-CONFIG_SND_USB_USX2Y=m
-CONFIG_SND_USB_CAIAQ=m
-CONFIG_SND_USB_CAIAQ_INPUT=y
-# CONFIG_SND_SOC is not set
-# CONFIG_SOUND_PRIME is not set
-CONFIG_AC97_BUS=y
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-CONFIG_HID_DEBUG=y
-CONFIG_HIDRAW=y
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT_POWERBOOK=y
-CONFIG_HID_FF=y
-CONFIG_HID_PID=y
-CONFIG_LOGITECH_FF=y
-# CONFIG_LOGIRUMBLEPAD2_FF is not set
-CONFIG_PANTHERLORD_FF=y
-CONFIG_THRUSTMASTER_FF=y
-CONFIG_ZEROPLUS_FF=y
-CONFIG_USB_HIDDEV=y
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-CONFIG_USB_SUSPEND=y
-# CONFIG_USB_OTG is not set
-CONFIG_USB_MON=y
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_C67X00_HCD is not set
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
-CONFIG_USB_ISP116X_HCD=m
-# CONFIG_USB_ISP1760_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
-# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_U132_HCD=m
-CONFIG_USB_SL811_HCD=m
-# CONFIG_USB_R8A66597_HCD is not set
-
-#
-# USB Device Class drivers
-#
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-# CONFIG_USB_WDM is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# may also be needed; see USB_STORAGE Help for more information
-#
-CONFIG_USB_STORAGE=y
-# CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_DPCM=y
-CONFIG_USB_STORAGE_USBAT=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_STORAGE_ALAUDA=y
-# CONFIG_USB_STORAGE_ONETOUCH is not set
-CONFIG_USB_STORAGE_KARMA=y
-# CONFIG_USB_STORAGE_SIERRA is not set
-# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Imaging devices
-#
-CONFIG_USB_MDC800=m
-CONFIG_USB_MICROTEK=m
-
-#
-# USB port drivers
-#
-CONFIG_USB_SERIAL=m
-CONFIG_USB_EZUSB=y
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_AIRCABLE=m
-CONFIG_USB_SERIAL_ARK3116=m
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_CH341=m
-CONFIG_USB_SERIAL_WHITEHEAT=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_CP2101=m
-CONFIG_USB_SERIAL_CYPRESS_M8=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_FUNSOFT=m
-CONFIG_USB_SERIAL_VISOR=m
-CONFIG_USB_SERIAL_IPAQ=m
-CONFIG_USB_SERIAL_IR=m
-CONFIG_USB_SERIAL_EDGEPORT=m
-CONFIG_USB_SERIAL_EDGEPORT_TI=m
-CONFIG_USB_SERIAL_GARMIN=m
-CONFIG_USB_SERIAL_IPW=m
-CONFIG_USB_SERIAL_IUU=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19=y
-CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-CONFIG_USB_SERIAL_KLSI=m
-CONFIG_USB_SERIAL_KOBIL_SCT=m
-CONFIG_USB_SERIAL_MCT_U232=m
-CONFIG_USB_SERIAL_MOS7720=m
-CONFIG_USB_SERIAL_MOS7840=m
-# CONFIG_USB_SERIAL_MOTOROLA is not set
-CONFIG_USB_SERIAL_NAVMAN=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_OTI6858=m
-# CONFIG_USB_SERIAL_SPCP8X5 is not set
-CONFIG_USB_SERIAL_HP4X=m
-CONFIG_USB_SERIAL_SAFE=m
-CONFIG_USB_SERIAL_SAFE_PADDED=y
-CONFIG_USB_SERIAL_SIERRAWIRELESS=m
-CONFIG_USB_SERIAL_TI=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_OPTION=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_SERIAL_DEBUG=m
-
-#
-# USB Miscellaneous drivers
-#
-CONFIG_USB_EMI62=m
-CONFIG_USB_EMI26=m
-CONFIG_USB_ADUTUX=m
-# CONFIG_USB_RIO500 is not set
-CONFIG_USB_LEGOTOWER=m
-CONFIG_USB_LCD=m
-CONFIG_USB_BERRY_CHARGE=m
-CONFIG_USB_LED=m
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-CONFIG_USB_PHIDGET=m
-CONFIG_USB_PHIDGETKIT=m
-CONFIG_USB_PHIDGETMOTORCONTROL=m
-CONFIG_USB_PHIDGETSERVO=m
-CONFIG_USB_IDMOUSE=m
-CONFIG_USB_FTDI_ELAN=m
-CONFIG_USB_APPLEDISPLAY=m
-CONFIG_USB_SISUSBVGA=m
-CONFIG_USB_SISUSBVGA_CON=y
-CONFIG_USB_LD=m
-CONFIG_USB_TRANCEVIBRATOR=m
-CONFIG_USB_IOWARRIOR=m
-# CONFIG_USB_TEST is not set
-# CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_GADGET is not set
-CONFIG_MMC=m
-# CONFIG_MMC_DEBUG is not set
-# CONFIG_MMC_UNSAFE_RESUME is not set
-
-#
-# MMC/SD Card Drivers
-#
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_BLOCK_BOUNCE=y
-CONFIG_SDIO_UART=m
-# CONFIG_MMC_TEST is not set
-
-#
-# MMC/SD Host Controller Drivers
-#
-CONFIG_MMC_SDHCI=m
-# CONFIG_MMC_SDHCI_PCI is not set
-CONFIG_MMC_WBSD=m
-CONFIG_MMC_TIFM_SD=m
-CONFIG_MEMSTICK=m
-CONFIG_MEMSTICK_DEBUG=y
-
-#
-# MemoryStick drivers
-#
-# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
-CONFIG_MSPRO_BLOCK=m
-
-#
-# MemoryStick Host Controller Drivers
-#
-# CONFIG_MEMSTICK_TIFM_MS is not set
-# CONFIG_MEMSTICK_JMICRON_38X is not set
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=m
-
-#
-# LED drivers
-#
-# CONFIG_LEDS_PCA9532 is not set
-# CONFIG_LEDS_CLEVO_MAIL is not set
-# CONFIG_LEDS_PCA955X is not set
-
-#
-# LED Triggers
-#
-CONFIG_LEDS_TRIGGERS=y
-# CONFIG_LEDS_TRIGGER_TIMER is not set
-# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
-# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
-# CONFIG_ACCESSIBILITY is not set
-# CONFIG_INFINIBAND is not set
-# CONFIG_EDAC is not set
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_HCTOSYS is not set
-# CONFIG_RTC_DEBUG is not set
-
-#
-# RTC interfaces
-#
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
-# CONFIG_RTC_DRV_TEST is not set
-
-#
-# I2C RTC drivers
-#
-# CONFIG_RTC_DRV_DS1307 is not set
-# CONFIG_RTC_DRV_DS1374 is not set
-# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_MAX6900 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
-# CONFIG_RTC_DRV_X1205 is not set
-# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
-# CONFIG_RTC_DRV_M41T80 is not set
-# CONFIG_RTC_DRV_S35390A is not set
-# CONFIG_RTC_DRV_FM3130 is not set
-
-#
-# SPI RTC drivers
-#
-
-#
-# Platform RTC drivers
-#
-CONFIG_RTC_DRV_CMOS=y
-# CONFIG_RTC_DRV_DS1511 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-
-#
-# on-CPU RTC drivers
-#
-# CONFIG_DMADEVICES is not set
-# CONFIG_UIO is not set
-
-#
-# Firmware Drivers
-#
-# CONFIG_EDD is not set
-CONFIG_FIRMWARE_MEMMAP=y
-# CONFIG_DELL_RBU is not set
-# CONFIG_DCDBAS is not set
-# CONFIG_DMIID is not set
-# CONFIG_ISCSI_IBFT_FIND is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-CONFIG_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-# CONFIG_PRINT_QUOTA_WARNING is not set
-# CONFIG_QFMT_V1 is not set
-CONFIG_QFMT_V2=y
-CONFIG_QUOTACTL=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_VMCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_HUGETLBFS=y
-CONFIG_HUGETLB_PAGE=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-CONFIG_AMIGA_PARTITION=y
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-CONFIG_KARMA_PARTITION=y
-CONFIG_EFI_PARTITION=y
-# CONFIG_SYSV68_PARTITION is not set
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="utf8"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-# CONFIG_DLM is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-CONFIG_PRINTK_TIME=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_UNUSED_SYMBOLS=y
-CONFIG_DEBUG_FS=y
-# CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SHIRQ=y
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_LOCK_ALLOC is not set
-# CONFIG_PROVE_LOCKING is not set
-# CONFIG_LOCK_STAT is not set
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-CONFIG_STACKTRACE=y
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_HIGHMEM is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
-CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_DEBUG_LIST=y
-# CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
-CONFIG_BOOT_PRINTK_DELAY=y
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_FAULT_INJECTION is not set
-CONFIG_LATENCYTOP=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_TRACING=y
-# CONFIG_FTRACE is not set
-# CONFIG_IRQSOFF_TRACER is not set
-CONFIG_SYSPROF_TRACER=y
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
-# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-# CONFIG_STRICT_DEVMEM is not set
-CONFIG_X86_VERBOSE_BOOTUP=y
-CONFIG_EARLY_PRINTK=y
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUG_PER_CPU_MAPS is not set
-CONFIG_X86_PTDUMP=y
-CONFIG_DEBUG_RODATA=y
-# CONFIG_DEBUG_RODATA_TEST is not set
-# CONFIG_DEBUG_NX_TEST is not set
-# CONFIG_4KSTACKS is not set
-CONFIG_DOUBLEFAULT=y
-# CONFIG_MMIOTRACE is not set
-CONFIG_IO_DELAY_TYPE_0X80=0
-CONFIG_IO_DELAY_TYPE_0XED=1
-CONFIG_IO_DELAY_TYPE_UDELAY=2
-CONFIG_IO_DELAY_TYPE_NONE=3
-CONFIG_IO_DELAY_0X80=y
-# CONFIG_IO_DELAY_0XED is not set
-# CONFIG_IO_DELAY_UDELAY is not set
-# CONFIG_IO_DELAY_NONE is not set
-CONFIG_DEFAULT_IO_DELAY_TYPE=0
-CONFIG_DEBUG_BOOT_PARAMS=y
-# CONFIG_CPA_DEBUG is not set
-# CONFIG_OPTIMIZE_INLINING is not set
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
-CONFIG_SECURITY_NETWORK_XFRM=y
-CONFIG_SECURITY_FILE_CAPABILITIES=y
-# CONFIG_SECURITY_ROOTPLUG is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=65536
-# CONFIG_SECURITY_SELINUX is not set
-# CONFIG_SECURITY_SMACK is not set
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_NULL=m
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_AUTHENC=m
-CONFIG_CRYPTO_TEST=m
-
-#
-# Authenticated Encryption with Associated Data
-#
-CONFIG_CRYPTO_CCM=m
-CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_SEQIV=m
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_CTR=m
-# CONFIG_CRYPTO_CTS is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-
-#
-# Hash modes
-#
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-
-#
-# Digest
-#
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-
-#
-# Ciphers
-#
-CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_AES_586 is not set
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
-# CONFIG_CRYPTO_SALSA20_586 is not set
-CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-# CONFIG_CRYPTO_TWOFISH_586 is not set
-
-#
-# Compression
-#
-CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_LZO is not set
-CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_PADLOCK is not set
-# CONFIG_CRYPTO_DEV_GEODE is not set
-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-CONFIG_HAVE_KVM=y
-# CONFIG_VIRTUALIZATION is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_GENERIC_FIND_FIRST_BIT=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=m
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-CONFIG_LIBCRC32C=m
-CONFIG_AUDIT_GENERIC=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
diff --git a/meta-moblin/packages/linux/linux-moblin_2.6.27-rc1.bb b/meta-moblin/packages/linux/linux-moblin_2.6.27-rc1.bb
deleted file mode 100644 (file)
index dd46944..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-require linux-moblin.inc
-
-PR = "r5"
-
-SRC_URI = "${KERNELORG_MIRROR}pub/linux/kernel/v2.6/linux-2.6.26.tar.bz2 \
-               ${KERNELORG_MIRROR}pub/linux/kernel/v2.6/testing/patch-2.6.27-rc1.bz2;patch=1 \
-               file://0001_Export_shmem_file_setup_for_DRM-GEM.patch;patch=1 \
-               file://0002_i915.Use_more_consistent_names_for_regs.patch;patch=1 \
-               file://0003_i915.Add_support_for_MSI_and_interrupt_mitigation.patch;patch=1 \
-               file://0004_i915.Track_progress_inside_of_batchbuffers_for_determining_wedgedness.patch;patch=1 \
-               file://0005_i915.remove_settable_use_mi_batchbuffer_start.patch;patch=1 \
-               file://0006_i915.Ignore_X_server_provided_mmio_address.patch;patch=1 \
-               file://0007_i915.Initialize_hardware_status_page_at_device_load_when_possible.patch;patch=1 \
-               file://0008_drm.Add_GEM_graphics_execution_manager_to_i915_driver.patch;patch=1 \
-               file://0009-squashfs3.3-2.6.27.patch;patch=1 \
-               file://0010_unionfs-2.4_for_2.6.27-rc1.patch;patch=1 \
-               file://0011_workaround_unidef_step.patch;patch=1 \
-               file://0012_intelfb_945gme.patch;patch=1 \
-               file://defconfig-netbook"
-
-S = "${WORKDIR}/linux-2.6.26"
diff --git a/meta-moblin/packages/linux/linux-moblin_2.6.27-rc6.bb b/meta-moblin/packages/linux/linux-moblin_2.6.27-rc6.bb
deleted file mode 100644 (file)
index e638291..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-require linux-moblin.inc
-
-PR = "r5"
-
-DEFAULT_PREFERENCE = "-1"
-
-SRC_URI = "${KERNELORG_MIRROR}pub/linux/kernel/v2.6/linux-2.6.26.tar.bz2 \
-               ${KERNELORG_MIRROR}pub/linux/kernel/v2.6/testing/v2.6.27/patch-2.6.27-rc6.bz2;patch=1 \
-               file://0001-drm-remove-define-for-non-linux-systems.patch;patch=1 \
-               file://0002-i915-remove-settable-use_mi_batchbuffer_start.patch;patch=1 \
-               file://0003-i915-Ignore-X-server-provided-mmio-address.patch;patch=1 \
-               file://0004-i915-Use-more-consistent-names-for-regs-and-store.patch;patch=1 \
-               file://0005-i915-Add-support-for-MSI-and-interrupt-mitigation.patch;patch=1 \
-               file://0006-i915-Track-progress-inside-of-batchbuffers-for-dete.patch;patch=1 \
-               file://0007-i915-Initialize-hardware-status-page-at-device-load.patch;patch=1 \
-               file://0008-Add-Intel-ACPI-IGD-OpRegion-support.patch;patch=1 \
-               file://0009-drm-fix-sysfs-error-path.patch;patch=1 \
-               file://0010-i915-separate-suspend-resume-functions.patch;patch=1 \
-               file://0011-drm-vblank-rework.patch;patch=1 \
-               file://0012-Export-shmem_file_setup-for-DRM-GEM.patch;patch=1 \
-               file://0013-Export-kmap_atomic_pfn-for-DRM-GEM.patch;patch=1 \
-               file://0014-drm-Add-GEM-graphics-execution-manager-to-i915.patch;patch=1 \
-               file://0015-i915-Add-chip-set-ID-param.patch;patch=1 \
-               file://0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch;patch=1 \
-               file://0017-i915-Make-use-of-sarea_priv-conditional.patch;patch=1 \
-               file://0018-i915-gem-install-and-uninstall-irq-handler-in-enter.patch;patch=1 \
-               file://0019-DRM-Return-EBADF-on-bad-object-in-flink-and-retur.patch;patch=1 \
-               file://0020-drm-Avoid-oops-in-GEM-execbuffers-with-bad-argument.patch;patch=1 \
-               file://0021-drm-G33-class-hardware-has-a-newer-965-style-MCH-n.patch;patch=1 \
-               file://0022-drm-use-ioremap_wc-in-i915-instead-of-ioremap.patch;patch=1 \
-               file://0023-drm-clean-up-many-sparse-warnings-in-i915.patch;patch=1 \
-               file://0024-fastboot-create-a-asynchronous-initlevel.patch;patch=1 \
-               file://0025-fastboot-turn-the-USB-hostcontroller-initcalls-into.patch;patch=1 \
-               file://0026-fastboot-convert-a-few-non-critical-ACPI-drivers-to.patch;patch=1 \
-               file://0027-fastboot-hold-the-BKL-over-the-async-init-call-sequ.patch;patch=1 \
-               file://0028-fastboot-sync-the-async-execution-before-late_initc.patch;patch=1 \
-               file://0029-fastboot-make-fastboot-a-config-option.patch;patch=1 \
-               file://0030-fastboot-retry-mounting-the-root-fs-if-we-can-t-fin.patch;patch=1 \
-               file://0031-fastboot-make-the-raid-autodetect-code-wait-for-all.patch;patch=1 \
-               file://0032-fastboot-remove-wait-for-all-devices-before-mounti.patch;patch=1 \
-               file://0033-fastboot-make-the-RAID-autostart-code-print-a-messa.patch;patch=1 \
-               file://0034-fastboot-fix-typo-in-init-Kconfig-text.patch;patch=1 \
-               file://0035-fastboot-remove-duplicate-unpack_to_rootfs.patch;patch=1 \
-               file://0036-warning-fix-init-do_mounts_md-c.patch;patch=1 \
-               file://0037-init-initramfs.c-unused-function-when-compiling-wit.patch;patch=1 \
-               file://0038-fastboot-fix-blackfin-breakage-due-to-vmlinux.lds-c.patch;patch=1 \
-               file://0039-Add-a-script-to-visualize-the-kernel-boot-process.patch;patch=1 \
-               file://0040-fastboot-fix-issues-and-improve-output-of-bootgraph.patch;patch=1 \
-               file://0041-r8169-8101e.patch;patch=1 \
-               file://0042-intelfb-945gme.patch;patch=1 \
-               file://defconfig-netbook"
-
-S = "${WORKDIR}/linux-2.6.26"