summaryrefslogtreecommitdiff
path: root/meta-moblin/packages/linux
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2009-01-12 17:41:01 +0000
committerRichard Purdie <rpurdie@linux.intel.com>2009-01-12 17:41:01 +0000
commit0acce24b3c9caf80bad270dd1a4994f1486c266d (patch)
tree2614caadc3dc22f339035c770dd05ef8dc712f0e /meta-moblin/packages/linux
parentf51973f5afb4775252bdf26827ba44663e1dda2d (diff)
downloadopenembedded-core-0acce24b3c9caf80bad270dd1a4994f1486c266d.tar.gz
openembedded-core-0acce24b3c9caf80bad270dd1a4994f1486c266d.tar.bz2
openembedded-core-0acce24b3c9caf80bad270dd1a4994f1486c266d.tar.xz
openembedded-core-0acce24b3c9caf80bad270dd1a4994f1486c266d.zip
Drop linux-moblin obsolete kernels
Diffstat (limited to 'meta-moblin/packages/linux')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0001_Export_shmem_file_setup_for_DRM-GEM.patch27
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0002_i915.Use_more_consistent_names_for_regs.patch2739
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0003_i915.Add_support_for_MSI_and_interrupt_mitigation.patch421
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0004_i915.Track_progress_inside_of_batchbuffers_for_determining_wedgedness.patch47
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0005_i915.remove_settable_use_mi_batchbuffer_start.patch59
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0006_i915.Ignore_X_server_provided_mmio_address.patch42
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0007_i915.Initialize_hardware_status_page_at_device_load_when_possible.patch138
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0008_drm.Add_GEM_graphics_execution_manager_to_i915_driver.patch5453
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch6727
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0010_unionfs-2.4_for_2.6.27-rc1.patch11320
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0011_workaround_unidef_step.patch10
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0012_intelfb_945gme.patch153
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/defconfig-netbook2419
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0001-drm-remove-define-for-non-linux-systems.patch48
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0002-i915-remove-settable-use_mi_batchbuffer_start.patch60
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0003-i915-Ignore-X-server-provided-mmio-address.patch41
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0004-i915-Use-more-consistent-names-for-regs-and-store.patch2746
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0005-i915-Add-support-for-MSI-and-interrupt-mitigation.patch424
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0006-i915-Track-progress-inside-of-batchbuffers-for-dete.patch46
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0007-i915-Initialize-hardware-status-page-at-device-load.patch137
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0008-Add-Intel-ACPI-IGD-OpRegion-support.patch572
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0009-drm-fix-sysfs-error-path.patch23
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0010-i915-separate-suspend-resume-functions.patch1079
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0011-drm-vblank-rework.patch1534
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0012-Export-shmem_file_setup-for-DRM-GEM.patch25
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0013-Export-kmap_atomic_pfn-for-DRM-GEM.patch24
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0014-drm-Add-GEM-graphics-execution-manager-to-i915.patch5483
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0015-i915-Add-chip-set-ID-param.patch35
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch205
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0017-i915-Make-use-of-sarea_priv-conditional.patch147
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0018-i915-gem-install-and-uninstall-irq-handler-in-enter.patch44
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0019-DRM-Return-EBADF-on-bad-object-in-flink-and-retur.patch32
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0020-drm-Avoid-oops-in-GEM-execbuffers-with-bad-argument.patch23
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0021-drm-G33-class-hardware-has-a-newer-965-style-MCH-n.patch23
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0022-drm-use-ioremap_wc-in-i915-instead-of-ioremap.patch58
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0023-drm-clean-up-many-sparse-warnings-in-i915.patch192
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0024-fastboot-create-a-asynchronous-initlevel.patch136
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0025-fastboot-turn-the-USB-hostcontroller-initcalls-into.patch62
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0026-fastboot-convert-a-few-non-critical-ACPI-drivers-to.patch54
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0027-fastboot-hold-the-BKL-over-the-async-init-call-sequ.patch40
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0028-fastboot-sync-the-async-execution-before-late_initc.patch95
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0029-fastboot-make-fastboot-a-config-option.patch56
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0030-fastboot-retry-mounting-the-root-fs-if-we-can-t-fin.patch67
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0031-fastboot-make-the-raid-autodetect-code-wait-for-all.patch41
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0032-fastboot-remove-wait-for-all-devices-before-mounti.patch44
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0033-fastboot-make-the-RAID-autostart-code-print-a-messa.patch32
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0034-fastboot-fix-typo-in-init-Kconfig-text.patch29
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0035-fastboot-remove-duplicate-unpack_to_rootfs.patch161
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0036-warning-fix-init-do_mounts_md-c.patch82
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0037-init-initramfs.c-unused-function-when-compiling-wit.patch37
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0038-fastboot-fix-blackfin-breakage-due-to-vmlinux.lds-c.patch38
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0039-Add-a-script-to-visualize-the-kernel-boot-process.patch183
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0040-fastboot-fix-issues-and-improve-output-of-bootgraph.patch91
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0041-r8169-8101e.patch940
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0042-intelfb-945gme.patch153
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/defconfig-netbook2424
-rw-r--r--meta-moblin/packages/linux/linux-moblin_2.6.27-rc1.bb21
-rw-r--r--meta-moblin/packages/linux/linux-moblin_2.6.27-rc6.bb53
58 files changed, 0 insertions, 47395 deletions
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
index 9589838af..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0001_Export_shmem_file_setup_for_DRM-GEM.patch
+++ /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
index 9a035b544..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0002_i915.Use_more_consistent_names_for_regs.patch
+++ /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
index 70f91194e..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0003_i915.Add_support_for_MSI_and_interrupt_mitigation.patch
+++ /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
index c391d16b7..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0004_i915.Track_progress_inside_of_batchbuffers_for_determining_wedgedness.patch
+++ /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
index 12362fef5..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0005_i915.remove_settable_use_mi_batchbuffer_start.patch
+++ /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
index 397f683af..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0006_i915.Ignore_X_server_provided_mmio_address.patch
+++ /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
index cf646f01c..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0007_i915.Initialize_hardware_status_page_at_device_load_when_possible.patch
+++ /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
index e7ae851c4..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0008_drm.Add_GEM_graphics_execution_manager_to_i915_driver.patch
+++ /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
index 4de9839c7..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch
+++ /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
index 8a2e83aa6..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0010_unionfs-2.4_for_2.6.27-rc1.patch
+++ /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
index a77ff3c62..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0011_workaround_unidef_step.patch
+++ /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
index 15ebe5632..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/0012_intelfb_945gme.patch
+++ /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
index 666a14c7d..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc1/defconfig-netbook
+++ /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
index 588c1af70..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0001-drm-remove-define-for-non-linux-systems.patch
+++ /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
index f3c41f7cb..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0002-i915-remove-settable-use_mi_batchbuffer_start.patch
+++ /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
index 9f7e0b4bc..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0003-i915-Ignore-X-server-provided-mmio-address.patch
+++ /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
index f7a310ea6..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0004-i915-Use-more-consistent-names-for-regs-and-store.patch
+++ /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
index 9337475c3..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0005-i915-Add-support-for-MSI-and-interrupt-mitigation.patch
+++ /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
index 8736250f0..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0006-i915-Track-progress-inside-of-batchbuffers-for-dete.patch
+++ /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
index 79f068f42..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0007-i915-Initialize-hardware-status-page-at-device-load.patch
+++ /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
index afa6f9634..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0008-Add-Intel-ACPI-IGD-OpRegion-support.patch
+++ /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
index 8dea82480..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0009-drm-fix-sysfs-error-path.patch
+++ /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
index 897d50c39..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0010-i915-separate-suspend-resume-functions.patch
+++ /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
index 6161a71f0..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0011-drm-vblank-rework.patch
+++ /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
index 642d89ba7..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0012-Export-shmem_file_setup-for-DRM-GEM.patch
+++ /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
index cc90d4626..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0013-Export-kmap_atomic_pfn-for-DRM-GEM.patch
+++ /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
index 95cca5d0c..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0014-drm-Add-GEM-graphics-execution-manager-to-i915.patch
+++ /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
index c3bf8ebd1..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0015-i915-Add-chip-set-ID-param.patch
+++ /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
index 910f37e9c..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch
+++ /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
index 542b69dd5..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0017-i915-Make-use-of-sarea_priv-conditional.patch
+++ /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
index 3593fa582..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0018-i915-gem-install-and-uninstall-irq-handler-in-enter.patch
+++ /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
index 6de4514e2..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0019-DRM-Return-EBADF-on-bad-object-in-flink-and-retur.patch
+++ /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
index 7080907cd..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0020-drm-Avoid-oops-in-GEM-execbuffers-with-bad-argument.patch
+++ /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
index f5481d7d8..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0021-drm-G33-class-hardware-has-a-newer-965-style-MCH-n.patch
+++ /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
index 8e6cbe95a..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0022-drm-use-ioremap_wc-in-i915-instead-of-ioremap.patch
+++ /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
index 236b16158..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0023-drm-clean-up-many-sparse-warnings-in-i915.patch
+++ /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
index 7c19053b0..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0024-fastboot-create-a-asynchronous-initlevel.patch
+++ /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
index 75d4151b3..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0025-fastboot-turn-the-USB-hostcontroller-initcalls-into.patch
+++ /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
index efd8ca9c9..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0026-fastboot-convert-a-few-non-critical-ACPI-drivers-to.patch
+++ /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
index 129823b6c..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0027-fastboot-hold-the-BKL-over-the-async-init-call-sequ.patch
+++ /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
index 0700fb318..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0028-fastboot-sync-the-async-execution-before-late_initc.patch
+++ /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
index faf962209..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0029-fastboot-make-fastboot-a-config-option.patch
+++ /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
index e2c373793..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0030-fastboot-retry-mounting-the-root-fs-if-we-can-t-fin.patch
+++ /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
index 03b3b8220..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0031-fastboot-make-the-raid-autodetect-code-wait-for-all.patch
+++ /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
index 4e9be15e1..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0032-fastboot-remove-wait-for-all-devices-before-mounti.patch
+++ /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
index 55c6c1ada..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0033-fastboot-make-the-RAID-autostart-code-print-a-messa.patch
+++ /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
index 742629354..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0034-fastboot-fix-typo-in-init-Kconfig-text.patch
+++ /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
index b8af74eaf..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0035-fastboot-remove-duplicate-unpack_to_rootfs.patch
+++ /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
index 9ba44a892..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0036-warning-fix-init-do_mounts_md-c.patch
+++ /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
index 159f98867..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0037-init-initramfs.c-unused-function-when-compiling-wit.patch
+++ /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
index 8d1e3f22f..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0038-fastboot-fix-blackfin-breakage-due-to-vmlinux.lds-c.patch
+++ /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
index da72d3bb7..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0039-Add-a-script-to-visualize-the-kernel-boot-process.patch
+++ /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
index 0daba9d2c..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0040-fastboot-fix-issues-and-improve-output-of-bootgraph.patch
+++ /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
index 781c9a127..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0041-r8169-8101e.patch
+++ /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
index 15ebe5632..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/0042-intelfb-945gme.patch
+++ /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
index ad9729e88..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.27-rc6/defconfig-netbook
+++ /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
index dd4694400..000000000
--- a/meta-moblin/packages/linux/linux-moblin_2.6.27-rc1.bb
+++ /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
index e638291f5..000000000
--- a/meta-moblin/packages/linux/linux-moblin_2.6.27-rc6.bb
+++ /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"