--- /dev/null
+From sconklin@canonical.com Fri Jan 29 11:11:00 2010
+From: Steve Conklin <sconklin@canonical.com>
+Date: Fri, 29 Jan 2010 12:55:46 -0600
+Subject: drm/i915: Add ACPI OpRegion support for Ironlake
+To: stable@kernel.org
+Cc: Zhao Yakui <yakui.zhao@intel.com>, Eric Anholt <eric@anholt.net>, Steve Conklin <sconklin@canonical.com>, Zhenyu Wang <zhenyuw@linux.intel.com>
+Message-ID: <1264791346-8113-1-git-send-email-sconklin@canonical.com>
+
+
+commit 01c66889c14aa163c49355b3be2ccfb214500599 upstream
+
+Add the support of ACPI opregion on Ironlake so that the backlight
+brightness can be adjusted by using ACPI interface
+ >/sys/class/backlight/acpi_video0/brightness
+
+Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Steve Conklin <sconklin@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/gpu/drm/i915/i915_dma.c | 7 ---
+ drivers/gpu/drm/i915/i915_drv.h | 3 +
+ drivers/gpu/drm/i915/i915_irq.c | 19 ++++++++
+ drivers/gpu/drm/i915/i915_opregion.c | 74 ++++++++++++++++++++++++++++++++++-
+ 4 files changed, 95 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_dma.c
++++ b/drivers/gpu/drm/i915/i915_dma.c
+@@ -1490,9 +1490,7 @@ int i915_driver_load(struct drm_device *
+ }
+
+ /* Must be done after probing outputs */
+- /* FIXME: verify on IGDNG */
+- if (!IS_IGDNG(dev))
+- intel_opregion_init(dev, 0);
++ intel_opregion_init(dev, 0);
+
+ setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
+ (unsigned long) dev);
+@@ -1536,8 +1534,7 @@ int i915_driver_unload(struct drm_device
+ if (dev_priv->regs != NULL)
+ iounmap(dev_priv->regs);
+
+- if (!IS_IGDNG(dev))
+- intel_opregion_free(dev, 0);
++ intel_opregion_free(dev, 0);
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ intel_modeset_cleanup(dev);
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -739,6 +739,7 @@ i915_enable_pipestat(drm_i915_private_t
+ void
+ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
+
++void intel_enable_asle (struct drm_device *dev);
+
+ /* i915_mem.c */
+ extern int i915_mem_alloc(struct drm_device *dev, void *data,
+@@ -864,11 +865,13 @@ extern int i915_restore_state(struct drm
+ extern int intel_opregion_init(struct drm_device *dev, int resume);
+ extern void intel_opregion_free(struct drm_device *dev, int suspend);
+ extern void opregion_asle_intr(struct drm_device *dev);
++extern void ironlake_opregion_gse_intr(struct drm_device *dev);
+ extern void opregion_enable_asle(struct drm_device *dev);
+ #else
+ static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
+ static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; }
+ static inline void opregion_asle_intr(struct drm_device *dev) { return; }
++static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; }
+ static inline void opregion_enable_asle(struct drm_device *dev) { return; }
+ #endif
+
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -157,6 +157,20 @@ i915_disable_pipestat(drm_i915_private_t
+ }
+
+ /**
++ * intel_enable_asle - enable ASLE interrupt for OpRegion
++ */
++void intel_enable_asle (struct drm_device *dev)
++{
++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++
++ if (IS_IGDNG(dev))
++ igdng_enable_display_irq(dev_priv, DE_GSE);
++ else
++ i915_enable_pipestat(dev_priv, 1,
++ I915_LEGACY_BLC_EVENT_ENABLE);
++}
++
++/**
+ * i915_pipe_enabled - check if a pipe is enabled
+ * @dev: DRM device
+ * @pipe: pipe to check
+@@ -286,6 +300,9 @@ irqreturn_t igdng_irq_handler(struct drm
+ mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
+ }
+
++ if (de_iir & DE_GSE)
++ ironlake_opregion_gse_intr(dev);
++
+ I915_WRITE(GTIIR, gt_iir);
+ I915_WRITE(DEIIR, de_iir);
+
+@@ -993,7 +1010,7 @@ static int igdng_irq_postinstall(struct
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ /* enable kind of interrupts always enabled */
+- u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */;
++ u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE /*| DE_PCH_EVENT */;
+ u32 render_mask = GT_USER_INTERRUPT;
+
+ dev_priv->irq_mask_reg = ~display_mask;
+--- a/drivers/gpu/drm/i915/i915_opregion.c
++++ b/drivers/gpu/drm/i915/i915_opregion.c
+@@ -118,6 +118,10 @@ struct opregion_asle {
+ #define ASLE_BACKLIGHT_FAIL (2<<12)
+ #define ASLE_PFIT_FAIL (2<<14)
+ #define ASLE_PWM_FREQ_FAIL (2<<16)
++#define ASLE_ALS_ILLUM_FAILED (1<<10)
++#define ASLE_BACKLIGHT_FAILED (1<<12)
++#define ASLE_PFIT_FAILED (1<<14)
++#define ASLE_PWM_FREQ_FAILED (1<<16)
+
+ /* ASLE backlight brightness to set */
+ #define ASLE_BCLP_VALID (1<<31)
+@@ -243,6 +247,73 @@ void opregion_asle_intr(struct drm_devic
+ asle->aslc = asle_stat;
+ }
+
++static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp)
++{
++ struct drm_i915_private *dev_priv = dev->dev_private;
++ struct opregion_asle *asle = dev_priv->opregion.asle;
++ u32 cpu_pwm_ctl, pch_pwm_ctl2;
++ u32 max_backlight, level;
++
++ if (!(bclp & ASLE_BCLP_VALID))
++ return ASLE_BACKLIGHT_FAILED;
++
++ bclp &= ASLE_BCLP_MSK;
++ if (bclp < 0 || bclp > 255)
++ return ASLE_BACKLIGHT_FAILED;
++
++ cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL);
++ pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
++ /* get the max PWM frequency */
++ max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK;
++ /* calculate the expected PMW frequency */
++ level = (bclp * max_backlight) / 255;
++ /* reserve the high 16 bits */
++ cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK);
++ /* write the updated PWM frequency */
++ I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level);
++
++ asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
++
++ return 0;
++}
++
++void ironlake_opregion_gse_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_DRIVER("non asle set request??\n");
++ return;
++ }
++
++ if (asle_req & ASLE_SET_ALS_ILLUM) {
++ DRM_DEBUG_DRIVER("Illum is not supported\n");
++ asle_stat |= ASLE_ALS_ILLUM_FAILED;
++ }
++
++ if (asle_req & ASLE_SET_BACKLIGHT)
++ asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp);
++
++ if (asle_req & ASLE_SET_PFIT) {
++ DRM_DEBUG_DRIVER("Pfit is not supported\n");
++ asle_stat |= ASLE_PFIT_FAILED;
++ }
++
++ if (asle_req & ASLE_SET_PWM_FREQ) {
++ DRM_DEBUG_DRIVER("PWM freq is not supported\n");
++ asle_stat |= ASLE_PWM_FREQ_FAILED;
++ }
++
++ asle->aslc = asle_stat;
++}
+ #define ASLE_ALS_EN (1<<0)
+ #define ASLE_BLC_EN (1<<1)
+ #define ASLE_PFIT_EN (1<<2)
+@@ -258,8 +329,7 @@ void opregion_enable_asle(struct drm_dev
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+- i915_enable_pipestat(dev_priv, 1,
+- I915_LEGACY_BLC_EVENT_ENABLE);
++ intel_enable_asle(dev);
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock,
+ irqflags);
+ }
--- /dev/null
+From sconklin@canonical.com Fri Jan 29 11:32:08 2010
+From: Steve Conklin <sconklin@canonical.com>
+Date: Fri, 29 Jan 2010 12:56:45 -0600
+Subject: drm/i915: Add display hotplug event on Ironlake
+To: stable@kernel.org
+Cc: Steve Conklin <sconklin@canonical.com>, Eric Anholt <eric@anholt.net>, Zhenyu Wang <zhenyuw@linux.intel.com>
+Message-ID: <1264791405-8169-1-git-send-email-sconklin@canonical.com>
+
+
+commit c650156af34bffa3d3a62c9fe26eee595aab3fd1 upstream
+
+Enable display hotplug irqs from Ibex Peak (PCH).
+
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Steve Conklin <sconklin@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_drv.h | 2 ++
+ drivers/gpu/drm/i915/i915_irq.c | 30 +++++++++++++++++++++++++++---
+ drivers/gpu/drm/i915/i915_reg.h | 1 +
+ 3 files changed, 30 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -211,6 +211,8 @@ typedef struct drm_i915_private {
+ u32 gt_irq_mask_reg;
+ u32 gt_irq_enable_reg;
+ u32 de_irq_enable_reg;
++ u32 pch_irq_mask_reg;
++ u32 pch_irq_enable_reg;
+
+ u32 hotplug_supported_mask;
+ struct work_struct hotplug_work;
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -268,7 +268,7 @@ irqreturn_t igdng_irq_handler(struct drm
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ int ret = IRQ_NONE;
+- u32 de_iir, gt_iir, de_ier;
++ u32 de_iir, gt_iir, de_ier, pch_iir;
+ struct drm_i915_master_private *master_priv;
+
+ /* disable master interrupt before clearing iir */
+@@ -278,8 +278,9 @@ irqreturn_t igdng_irq_handler(struct drm
+
+ de_iir = I915_READ(DEIIR);
+ gt_iir = I915_READ(GTIIR);
++ pch_iir = I915_READ(SDEIIR);
+
+- if (de_iir == 0 && gt_iir == 0)
++ if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
+ goto done;
+
+ ret = IRQ_HANDLED;
+@@ -303,6 +304,14 @@ irqreturn_t igdng_irq_handler(struct drm
+ if (de_iir & DE_GSE)
+ ironlake_opregion_gse_intr(dev);
+
++ /* check event from PCH */
++ if ((de_iir & DE_PCH_EVENT) &&
++ (pch_iir & SDE_HOTPLUG_MASK)) {
++ queue_work(dev_priv->wq, &dev_priv->hotplug_work);
++ }
++
++ /* should clear PCH hotplug event before clear CPU irq */
++ I915_WRITE(SDEIIR, pch_iir);
+ I915_WRITE(GTIIR, gt_iir);
+ I915_WRITE(DEIIR, de_iir);
+
+@@ -1004,14 +1013,21 @@ static void igdng_irq_preinstall(struct
+ I915_WRITE(GTIMR, 0xffffffff);
+ I915_WRITE(GTIER, 0x0);
+ (void) I915_READ(GTIER);
++
++ /* south display irq */
++ I915_WRITE(SDEIMR, 0xffffffff);
++ I915_WRITE(SDEIER, 0x0);
++ (void) I915_READ(SDEIER);
+ }
+
+ static int igdng_irq_postinstall(struct drm_device *dev)
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ /* enable kind of interrupts always enabled */
+- u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE /*| DE_PCH_EVENT */;
++ u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT;
+ u32 render_mask = GT_USER_INTERRUPT;
++ u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
++ SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
+
+ dev_priv->irq_mask_reg = ~display_mask;
+ dev_priv->de_irq_enable_reg = display_mask;
+@@ -1031,6 +1047,14 @@ static int igdng_irq_postinstall(struct
+ I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
+ (void) I915_READ(GTIER);
+
++ dev_priv->pch_irq_mask_reg = ~hotplug_mask;
++ dev_priv->pch_irq_enable_reg = hotplug_mask;
++
++ I915_WRITE(SDEIIR, I915_READ(SDEIIR));
++ I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg);
++ I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
++ (void) I915_READ(SDEIER);
++
+ return 0;
+ }
+
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -2121,6 +2121,7 @@
+ #define SDE_PORTC_HOTPLUG (1 << 9)
+ #define SDE_PORTB_HOTPLUG (1 << 8)
+ #define SDE_SDVOB_HOTPLUG (1 << 6)
++#define SDE_HOTPLUG_MASK (0xf << 8)
+
+ #define SDEISR 0xc4000
+ #define SDEIMR 0xc4004
--- /dev/null
+From c566ec49159b806db95a90fd8f37448376cd0ad2 Mon Sep 17 00:00:00 2001
+From: Zhenyu Wang <zhenyuw@linux.intel.com>
+Date: Thu, 17 Dec 2009 16:12:56 +0800
+Subject: drm/i915: Reload hangcheck timer too for Ironlake
+
+From: Zhenyu Wang <zhenyuw@linux.intel.com>
+
+commit c566ec49159b806db95a90fd8f37448376cd0ad2 upstream.
+
+Make sure hangcheck timer won't beat us unexpectedly on Ironlake.
+
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_irq.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -282,6 +282,8 @@ irqreturn_t igdng_irq_handler(struct drm
+ dev_priv->mm.irq_gem_seqno = seqno;
+ trace_i915_gem_request_complete(dev, seqno);
+ DRM_WAKEUP(&dev_priv->irq_queue);
++ dev_priv->hangcheck_count = 0;
++ mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
+ }
+
+ I915_WRITE(GTIIR, gt_iir);
--- /dev/null
+From 9926146b15fd96d78a4f7c32e7a26d50639369f4 Mon Sep 17 00:00:00 2001
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Date: Fri, 22 Jan 2010 22:56:16 +0000
+Subject: e1000/e1000e: don't use small hardware rx buffers
+
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+
+commit 9926146b15fd96d78a4f7c32e7a26d50639369f4 upstream.
+
+When testing the "e1000: enhance frame fragment detection" (and e1000e)
+patches we found some bugs with reducing the MTU size. The 1024 byte
+descriptor used with the 1000 mtu test also (re) introduced the
+(originally) reported bug, and causes us to need the e1000_clean_tx_irq
+"enhance frame fragment detection" fix.
+
+So what has occured here is that 2.6.32 is only vulnerable for mtu <
+1500 due to the jumbo specific routines in both e1000 and e1000e.
+So, 2.6.32 needs the 2kB buffer len fix for those smaller MTUs, but
+is not vulnerable to the original issue reported. It has been pointed
+out that this vulnerability needs to be patched in older kernels that
+don't have the e1000 jumbo routine. Without the jumbo routines, we
+need the "enhance frame fragment detection" fix the e1000, old
+e1000e is only vulnerable for < 1500 mtu, and needs a similar
+fix. We split the patches up to provide easy backport paths.
+
+There is only a slight bit of extra code when this fix and the
+original "enhance frame fragment detection" fixes are applied, so
+please apply both, even though it is a bit of overkill.
+
+Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/e1000/e1000_main.c | 20 +-------------------
+ drivers/net/e1000e/netdev.c | 20 +-------------------
+ 2 files changed, 2 insertions(+), 38 deletions(-)
+
+--- a/drivers/net/e1000/e1000_main.c
++++ b/drivers/net/e1000/e1000_main.c
+@@ -1698,18 +1698,6 @@ static void e1000_setup_rctl(struct e100
+ rctl &= ~E1000_RCTL_SZ_4096;
+ rctl |= E1000_RCTL_BSEX;
+ switch (adapter->rx_buffer_len) {
+- case E1000_RXBUFFER_256:
+- rctl |= E1000_RCTL_SZ_256;
+- rctl &= ~E1000_RCTL_BSEX;
+- break;
+- case E1000_RXBUFFER_512:
+- rctl |= E1000_RCTL_SZ_512;
+- rctl &= ~E1000_RCTL_BSEX;
+- break;
+- case E1000_RXBUFFER_1024:
+- rctl |= E1000_RCTL_SZ_1024;
+- rctl &= ~E1000_RCTL_BSEX;
+- break;
+ case E1000_RXBUFFER_2048:
+ default:
+ rctl |= E1000_RCTL_SZ_2048;
+@@ -3154,13 +3142,7 @@ static int e1000_change_mtu(struct net_d
+ * however with the new *_jumbo_rx* routines, jumbo receives will use
+ * fragmented skbs */
+
+- if (max_frame <= E1000_RXBUFFER_256)
+- adapter->rx_buffer_len = E1000_RXBUFFER_256;
+- else if (max_frame <= E1000_RXBUFFER_512)
+- adapter->rx_buffer_len = E1000_RXBUFFER_512;
+- else if (max_frame <= E1000_RXBUFFER_1024)
+- adapter->rx_buffer_len = E1000_RXBUFFER_1024;
+- else if (max_frame <= E1000_RXBUFFER_2048)
++ if (max_frame <= E1000_RXBUFFER_2048)
+ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+ else
+ #if (PAGE_SIZE >= E1000_RXBUFFER_16384)
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -2347,18 +2347,6 @@ static void e1000_setup_rctl(struct e100
+ rctl &= ~E1000_RCTL_SZ_4096;
+ rctl |= E1000_RCTL_BSEX;
+ switch (adapter->rx_buffer_len) {
+- case 256:
+- rctl |= E1000_RCTL_SZ_256;
+- rctl &= ~E1000_RCTL_BSEX;
+- break;
+- case 512:
+- rctl |= E1000_RCTL_SZ_512;
+- rctl &= ~E1000_RCTL_BSEX;
+- break;
+- case 1024:
+- rctl |= E1000_RCTL_SZ_1024;
+- rctl &= ~E1000_RCTL_BSEX;
+- break;
+ case 2048:
+ default:
+ rctl |= E1000_RCTL_SZ_2048;
+@@ -4338,13 +4326,7 @@ static int e1000_change_mtu(struct net_d
+ * fragmented skbs
+ */
+
+- if (max_frame <= 256)
+- adapter->rx_buffer_len = 256;
+- else if (max_frame <= 512)
+- adapter->rx_buffer_len = 512;
+- else if (max_frame <= 1024)
+- adapter->rx_buffer_len = 1024;
+- else if (max_frame <= 2048)
++ if (max_frame <= 2048)
+ adapter->rx_buffer_len = 2048;
+ else
+ adapter->rx_buffer_len = 4096;
--- /dev/null
+From 40a14deaf411592b57cb0720f0e8004293ab9865 Mon Sep 17 00:00:00 2001
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Date: Tue, 19 Jan 2010 14:15:38 +0000
+Subject: e1000: enhance frame fragment detection
+
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+
+commit 40a14deaf411592b57cb0720f0e8004293ab9865 upstream.
+
+Originally From: Neil Horman <nhorman@tuxdriver.com>
+Modified by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+
+Hey all-
+ A security discussion was recently given:
+http://events.ccc.de/congress/2009/Fahrplan//events/3596.en.html
+And a patch that I submitted awhile back was brought up. Apparently some of
+their testing revealed that they were able to force a buffer fragment in e1000
+in which the trailing fragment was greater than 4 bytes. As a result the
+fragment check I introduced failed to detect the fragement and a partial
+invalid frame was passed up into the network stack. I've written this patch
+to correct it. I'm in the process of testing it now, but it makes good
+logical sense to me. Effectively it maintains a per-adapter state variable
+which detects a non-EOP frame, and discards it and subsequent non-EOP frames
+leading up to _and_ _including_ the next positive-EOP frame (as it is by
+definition the last fragment). This should prevent any and all partial frames
+from entering the network stack from e1000.
+
+Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/e1000/e1000.h | 2 ++
+ drivers/net/e1000/e1000_main.c | 13 +++++++++++--
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/e1000/e1000.h
++++ b/drivers/net/e1000/e1000.h
+@@ -326,6 +326,8 @@ struct e1000_adapter {
+ /* for ioport free */
+ int bars;
+ int need_ioport;
++
++ bool discarding;
+ };
+
+ enum e1000_state_t {
+--- a/drivers/net/e1000/e1000_main.c
++++ b/drivers/net/e1000/e1000_main.c
+@@ -3827,13 +3827,22 @@ static bool e1000_clean_rx_irq(struct e1
+
+ length = le16_to_cpu(rx_desc->length);
+ /* !EOP means multiple descriptors were used to store a single
+- * packet, also make sure the frame isn't just CRC only */
+- if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) {
++ * packet, if thats the case we need to toss it. In fact, we
++ * to toss every packet with the EOP bit clear and the next
++ * frame that _does_ have the EOP bit set, as it is by
++ * definition only a frame fragment
++ */
++ if (unlikely(!(status & E1000_RXD_STAT_EOP)))
++ adapter->discarding = true;
++
++ if (adapter->discarding) {
+ /* All receives must fit into a single buffer */
+ E1000_DBG("%s: Receive packet consumed multiple"
+ " buffers\n", netdev->name);
+ /* recycle */
+ buffer_info->skb = skb;
++ if (status & E1000_RXD_STAT_EOP)
++ adapter->discarding = false;
+ goto next_desc;
+ }
+
--- /dev/null
+From b94b50289622e816adc9f94111cfc2679c80177c Mon Sep 17 00:00:00 2001
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Date: Tue, 19 Jan 2010 14:15:59 +0000
+Subject: e1000e: enhance frame fragment detection
+
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+
+commit b94b50289622e816adc9f94111cfc2679c80177c upstream.
+
+Originally patched by Neil Horman <nhorman@tuxdriver.com>
+
+e1000e could with a jumbo frame enabled interface, and packet split disabled,
+receive a packet that would overflow a single rx buffer. While in practice
+very hard to craft a packet that could abuse this, it is possible.
+
+this is related to CVE-2009-4538
+
+Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+CC: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/e1000e/e1000.h | 1 +
+ drivers/net/e1000e/netdev.c | 25 +++++++++++++++++++++----
+ 2 files changed, 22 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/e1000e/e1000.h
++++ b/drivers/net/e1000e/e1000.h
+@@ -417,6 +417,7 @@ struct e1000_info {
+ /* CRC Stripping defines */
+ #define FLAG2_CRC_STRIPPING (1 << 0)
+ #define FLAG2_HAS_PHY_WAKEUP (1 << 1)
++#define FLAG2_IS_DISCARDING (1 << 2)
+
+ #define E1000_RX_DESC_PS(R, i) \
+ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -482,14 +482,24 @@ static bool e1000_clean_rx_irq(struct e1
+
+ length = le16_to_cpu(rx_desc->length);
+
+- /* !EOP means multiple descriptors were used to store a single
+- * packet, also make sure the frame isn't just CRC only */
+- if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) {
++ /*
++ * !EOP means multiple descriptors were used to store a single
++ * packet, if that's the case we need to toss it. In fact, we
++ * need to toss every packet with the EOP bit clear and the
++ * next frame that _does_ have the EOP bit set, as it is by
++ * definition only a frame fragment
++ */
++ if (unlikely(!(status & E1000_RXD_STAT_EOP)))
++ adapter->flags2 |= FLAG2_IS_DISCARDING;
++
++ if (adapter->flags2 & FLAG2_IS_DISCARDING) {
+ /* All receives must fit into a single buffer */
+ e_dbg("%s: Receive packet consumed multiple buffers\n",
+ netdev->name);
+ /* recycle */
+ buffer_info->skb = skb;
++ if (status & E1000_RXD_STAT_EOP)
++ adapter->flags2 &= ~FLAG2_IS_DISCARDING;
+ goto next_desc;
+ }
+
+@@ -747,10 +757,16 @@ static bool e1000_clean_rx_irq_ps(struct
+ PCI_DMA_FROMDEVICE);
+ buffer_info->dma = 0;
+
+- if (!(staterr & E1000_RXD_STAT_EOP)) {
++ /* see !EOP comment in other rx routine */
++ if (!(staterr & E1000_RXD_STAT_EOP))
++ adapter->flags2 |= FLAG2_IS_DISCARDING;
++
++ if (adapter->flags2 & FLAG2_IS_DISCARDING) {
+ e_dbg("%s: Packet Split buffers didn't pick up the "
+ "full packet\n", netdev->name);
+ dev_kfree_skb_irq(skb);
++ if (staterr & E1000_RXD_STAT_EOP)
++ adapter->flags2 &= ~FLAG2_IS_DISCARDING;
+ goto next_desc;
+ }
+
+@@ -1120,6 +1136,7 @@ static void e1000_clean_rx_ring(struct e
+
+ rx_ring->next_to_clean = 0;
+ rx_ring->next_to_use = 0;
++ adapter->flags2 &= ~FLAG2_IS_DISCARDING;
+
+ writel(0, adapter->hw.hw_addr + rx_ring->head);
+ writel(0, adapter->hw.hw_addr + rx_ring->tail);
--- /dev/null
+From 04e4f2b18c8de1389d1e00fef0f42a8099910daf Mon Sep 17 00:00:00 2001
+From: Mike Frysinger <vapier@gentoo.org>
+Date: Wed, 6 Jan 2010 17:23:17 +0000
+Subject: FDPIC: Respect PT_GNU_STACK exec protection markings when creating NOMMU stack
+
+From: Mike Frysinger <vapier@gentoo.org>
+
+commit 04e4f2b18c8de1389d1e00fef0f42a8099910daf upstream.
+
+The current code will load the stack size and protection markings, but
+then only use the markings in the MMU code path. The NOMMU code path
+always passes PROT_EXEC to the mmap() call. While this doesn't matter
+to most people whilst the code is running, it will cause a pointless
+icache flush when starting every FDPIC application. Typically this
+icache flush will be of a region on the order of 128KB in size, or may
+be the entire icache, depending on the facilities available on the CPU.
+
+In the case where the arch default behaviour seems to be desired
+(EXSTACK_DEFAULT), we probe VM_STACK_FLAGS for VM_EXEC to determine
+whether we should be setting PROT_EXEC or not.
+
+For arches that support an MPU (Memory Protection Unit - an MMU without
+the virtual mapping capability), setting PROT_EXEC or not will make an
+important difference.
+
+It should be noted that this change also affects the executability of
+the brk region, since ELF-FDPIC has that share with the stack. However,
+this is probably irrelevant as NOMMU programs aren't likely to use the
+brk region, preferring instead allocation via mmap().
+
+Signed-off-by: Mike Frysinger <vapier@gentoo.org>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/blackfin/include/asm/page.h | 5 +++++
+ arch/frv/include/asm/page.h | 2 --
+ fs/binfmt_elf_fdpic.c | 13 +++++++++++--
+ 3 files changed, 16 insertions(+), 4 deletions(-)
+
+--- a/arch/blackfin/include/asm/page.h
++++ b/arch/blackfin/include/asm/page.h
+@@ -10,4 +10,9 @@
+ #include <asm-generic/page.h>
+ #define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
+
++#define VM_DATA_DEFAULT_FLAGS \
++ (VM_READ | VM_WRITE | \
++ ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
++ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
++
+ #endif
+--- a/arch/frv/include/asm/page.h
++++ b/arch/frv/include/asm/page.h
+@@ -63,12 +63,10 @@ extern unsigned long max_pfn;
+ #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+
+-#ifdef CONFIG_MMU
+ #define VM_DATA_DEFAULT_FLAGS \
+ (VM_READ | VM_WRITE | \
+ ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+-#endif
+
+ #endif /* __ASSEMBLY__ */
+
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -171,6 +171,9 @@ static int load_elf_fdpic_binary(struct
+ #ifdef ELF_FDPIC_PLAT_INIT
+ unsigned long dynaddr;
+ #endif
++#ifndef CONFIG_MMU
++ unsigned long stack_prot;
++#endif
+ struct file *interpreter = NULL; /* to shut gcc up */
+ char *interpreter_name = NULL;
+ int executable_stack;
+@@ -316,6 +319,8 @@ static int load_elf_fdpic_binary(struct
+ * defunct, deceased, etc. after this point we have to exit via
+ * error_kill */
+ set_personality(PER_LINUX_FDPIC);
++ if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
++ current->personality |= READ_IMPLIES_EXEC;
+ set_binfmt(&elf_fdpic_format);
+
+ current->mm->start_code = 0;
+@@ -377,9 +382,13 @@ static int load_elf_fdpic_binary(struct
+ if (stack_size < PAGE_SIZE * 2)
+ stack_size = PAGE_SIZE * 2;
+
++ stack_prot = PROT_READ | PROT_WRITE;
++ if (executable_stack == EXSTACK_ENABLE_X ||
++ (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
++ stack_prot |= PROT_EXEC;
++
+ down_write(¤t->mm->mmap_sem);
+- current->mm->start_brk = do_mmap(NULL, 0, stack_size,
+- PROT_READ | PROT_WRITE | PROT_EXEC,
++ current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN,
+ 0);
+
--- /dev/null
+From afc70ed05a07bfe171f7a5b8fdc80bdb073d314f Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sat, 23 Jan 2010 23:38:27 -0500
+Subject: Fix a leak in affs_fill_super()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit afc70ed05a07bfe171f7a5b8fdc80bdb073d314f upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/affs/super.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/affs/super.c
++++ b/fs/affs/super.c
+@@ -316,6 +316,8 @@ static int affs_fill_super(struct super_
+ &blocksize,&sbi->s_prefix,
+ sbi->s_volume, &mount_flags)) {
+ printk(KERN_ERR "AFFS: Error parsing options\n");
++ kfree(sbi->s_prefix);
++ kfree(sbi);
+ return -EINVAL;
+ }
+ /* N.B. after this point s_prefix must be released */
--- /dev/null
+From 217686e98321a4ff4c1a6cc535e511e37c5d2dbf Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sun, 24 Jan 2010 00:06:22 -0500
+Subject: fix affs parse_options()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 217686e98321a4ff4c1a6cc535e511e37c5d2dbf upstream.
+
+Error handling in that sucker got broken back in 2003. If function
+returns 0 on failure, it's not nice to add return -EINVAL into it.
+Adding return 1 on other failure exits is also not a good thing (and
+yes, original success exits with 1 and some of failure exits with 0
+are still there; so's the original logics in callers).
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/affs/super.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/fs/affs/super.c
++++ b/fs/affs/super.c
+@@ -203,7 +203,7 @@ parse_options(char *options, uid_t *uid,
+ switch (token) {
+ case Opt_bs:
+ if (match_int(&args[0], &n))
+- return -EINVAL;
++ return 0;
+ if (n != 512 && n != 1024 && n != 2048
+ && n != 4096) {
+ printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
+@@ -213,7 +213,7 @@ parse_options(char *options, uid_t *uid,
+ break;
+ case Opt_mode:
+ if (match_octal(&args[0], &option))
+- return 1;
++ return 0;
+ *mode = option & 0777;
+ *mount_opts |= SF_SETMODE;
+ break;
+@@ -231,21 +231,21 @@ parse_options(char *options, uid_t *uid,
+ break;
+ case Opt_reserved:
+ if (match_int(&args[0], reserved))
+- return 1;
++ return 0;
+ break;
+ case Opt_root:
+ if (match_int(&args[0], root))
+- return 1;
++ return 0;
+ break;
+ case Opt_setgid:
+ if (match_int(&args[0], &option))
+- return 1;
++ return 0;
+ *gid = option;
+ *mount_opts |= SF_SETGID;
+ break;
+ case Opt_setuid:
+ if (match_int(&args[0], &option))
+- return -EINVAL;
++ return 0;
+ *uid = option;
+ *mount_opts |= SF_SETUID;
+ break;
--- /dev/null
+From 12e9a45609054fb83d4a8b716a5265cc1a393e10 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Mon, 25 Jan 2010 18:44:58 -0500
+Subject: Fix failure exit in ipathfs
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 12e9a45609054fb83d4a8b716a5265cc1a393e10 upstream.
+
+deactivate_locked_super() will be done by caller of fill_super, doing
+it there as well is b0rken.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/infiniband/hw/ipath/ipath_fs.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/infiniband/hw/ipath/ipath_fs.c
++++ b/drivers/infiniband/hw/ipath/ipath_fs.c
+@@ -346,10 +346,8 @@ static int ipathfs_fill_super(struct sup
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ ret = create_device_files(sb, dd);
+- if (ret) {
+- deactivate_locked_super(sb);
++ if (ret)
+ goto bail;
+- }
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ }
+
--- /dev/null
+From 5998649f779b7148a8a0c10c46cfa99e27d34dfe Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sun, 24 Jan 2010 00:52:22 -0500
+Subject: Fix failure exits in bfs_fill_super()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 5998649f779b7148a8a0c10c46cfa99e27d34dfe upstream.
+
+double iput(), leaks...
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/bfs/inode.c | 43 +++++++++++++++++++++----------------------
+ 1 file changed, 21 insertions(+), 22 deletions(-)
+
+--- a/fs/bfs/inode.c
++++ b/fs/bfs/inode.c
+@@ -353,35 +353,35 @@ static int bfs_fill_super(struct super_b
+ struct inode *inode;
+ unsigned i, imap_len;
+ struct bfs_sb_info *info;
+- long ret = -EINVAL;
++ int ret = -EINVAL;
+ unsigned long i_sblock, i_eblock, i_eoff, s_size;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
++ mutex_init(&info->bfs_lock);
+ s->s_fs_info = info;
+
+ sb_set_blocksize(s, BFS_BSIZE);
+
+- bh = sb_bread(s, 0);
+- if(!bh)
++ info->si_sbh = sb_bread(s, 0);
++ if (!info->si_sbh)
+ goto out;
+- bfs_sb = (struct bfs_super_block *)bh->b_data;
++ bfs_sb = (struct bfs_super_block *)info->si_sbh->b_data;
+ if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) {
+ if (!silent)
+ printf("No BFS filesystem on %s (magic=%08x)\n",
+ s->s_id, le32_to_cpu(bfs_sb->s_magic));
+- goto out;
++ goto out1;
+ }
+ if (BFS_UNCLEAN(bfs_sb, s) && !silent)
+ printf("%s is unclean, continuing\n", s->s_id);
+
+ s->s_magic = BFS_MAGIC;
+- info->si_sbh = bh;
+
+ if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end)) {
+ printf("Superblock is corrupted\n");
+- goto out;
++ goto out1;
+ }
+
+ info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) /
+@@ -390,7 +390,7 @@ static int bfs_fill_super(struct super_b
+ imap_len = (info->si_lasti / 8) + 1;
+ info->si_imap = kzalloc(imap_len, GFP_KERNEL);
+ if (!info->si_imap)
+- goto out;
++ goto out1;
+ for (i = 0; i < BFS_ROOT_INO; i++)
+ set_bit(i, info->si_imap);
+
+@@ -398,15 +398,13 @@ static int bfs_fill_super(struct super_b
+ inode = bfs_iget(s, BFS_ROOT_INO);
+ if (IS_ERR(inode)) {
+ ret = PTR_ERR(inode);
+- kfree(info->si_imap);
+- goto out;
++ goto out2;
+ }
+ s->s_root = d_alloc_root(inode);
+ if (!s->s_root) {
+ iput(inode);
+ ret = -ENOMEM;
+- kfree(info->si_imap);
+- goto out;
++ goto out2;
+ }
+
+ info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS;
+@@ -419,10 +417,8 @@ static int bfs_fill_super(struct super_b
+ bh = sb_bread(s, info->si_blocks - 1);
+ if (!bh) {
+ printf("Last block not available: %lu\n", info->si_blocks - 1);
+- iput(inode);
+ ret = -EIO;
+- kfree(info->si_imap);
+- goto out;
++ goto out3;
+ }
+ brelse(bh);
+
+@@ -459,11 +455,8 @@ static int bfs_fill_super(struct super_b
+ printf("Inode 0x%08x corrupted\n", i);
+
+ brelse(bh);
+- s->s_root = NULL;
+- kfree(info->si_imap);
+- kfree(info);
+- s->s_fs_info = NULL;
+- return -EIO;
++ ret = -EIO;
++ goto out3;
+ }
+
+ if (!di->i_ino) {
+@@ -483,11 +476,17 @@ static int bfs_fill_super(struct super_b
+ s->s_dirt = 1;
+ }
+ dump_imap("read_super", s);
+- mutex_init(&info->bfs_lock);
+ return 0;
+
++out3:
++ dput(s->s_root);
++ s->s_root = NULL;
++out2:
++ kfree(info->si_imap);
++out1:
++ brelse(info->si_sbh);
+ out:
+- brelse(bh);
++ mutex_destroy(&info->bfs_lock);
+ kfree(info);
+ s->s_fs_info = NULL;
+ return ret;
--- /dev/null
+From 7e32b7bb734047c5e3cecf2e896b9cf8fc35d1e8 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Mon, 25 Jan 2010 06:05:54 -0500
+Subject: fix leak in romfs_fill_super()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 7e32b7bb734047c5e3cecf2e896b9cf8fc35d1e8 upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/romfs/super.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/romfs/super.c
++++ b/fs/romfs/super.c
+@@ -544,6 +544,7 @@ error:
+ error_rsb_inval:
+ ret = -EINVAL;
+ error_rsb:
++ kfree(rsb);
+ return ret;
+ }
+
--- /dev/null
+From 083c73c253c23c20359a344dfe1198ea628e6259 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Mon, 25 Jan 2010 06:16:19 -0500
+Subject: fix oops in fs/9p late mount failure
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 083c73c253c23c20359a344dfe1198ea628e6259 upstream.
+
+if 9P ->get_sb() fails late (at root inode or root dentry
+allocation), we'll hit its ->kill_sb() with NULL ->s_root
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/9p/vfs_super.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -188,7 +188,8 @@ static void v9fs_kill_super(struct super
+
+ P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
+
+- v9fs_dentry_release(s->s_root); /* clunk root */
++ if (s->s_root)
++ v9fs_dentry_release(s->s_root); /* clunk root */
+
+ kill_anon_super(s);
+
--- /dev/null
+From 29333920a5a46edcc9b728e2cf0134d5a9b516ee Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sun, 24 Jan 2010 00:04:07 -0500
+Subject: Fix remount races with symlink handling in affs
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 29333920a5a46edcc9b728e2cf0134d5a9b516ee upstream.
+
+A couple of fields in affs_sb_info is used in follow_link() and
+symlink() for handling AFFS "absolute" symlinks. Need locking
+against affs_remount() updates.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/affs/affs.h | 2 +-
+ fs/affs/namei.c | 7 +++++--
+ fs/affs/super.c | 17 ++++++++++++++---
+ fs/affs/symlink.c | 7 +++++--
+ 4 files changed, 25 insertions(+), 8 deletions(-)
+
+--- a/fs/affs/affs.h
++++ b/fs/affs/affs.h
+@@ -106,8 +106,8 @@ struct affs_sb_info {
+ u32 s_last_bmap;
+ struct buffer_head *s_bmap_bh;
+ char *s_prefix; /* Prefix for volumes and assigns. */
+- int s_prefix_len; /* Length of prefix. */
+ char s_volume[32]; /* Volume prefix for absolute symlinks. */
++ spinlock_t symlink_lock; /* protects the previous two */
+ };
+
+ #define SF_INTL 0x0001 /* International filesystem. */
+--- a/fs/affs/namei.c
++++ b/fs/affs/namei.c
+@@ -341,10 +341,13 @@ affs_symlink(struct inode *dir, struct d
+ p = (char *)AFFS_HEAD(bh)->table;
+ lc = '/';
+ if (*symname == '/') {
++ struct affs_sb_info *sbi = AFFS_SB(sb);
+ while (*symname == '/')
+ symname++;
+- while (AFFS_SB(sb)->s_volume[i]) /* Cannot overflow */
+- *p++ = AFFS_SB(sb)->s_volume[i++];
++ spin_lock(&sbi->symlink_lock);
++ while (sbi->s_volume[i]) /* Cannot overflow */
++ *p++ = sbi->s_volume[i++];
++ spin_unlock(&sbi->symlink_lock);
+ }
+ while (i < maxlen && (c = *symname++)) {
+ if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') {
+--- a/fs/affs/super.c
++++ b/fs/affs/super.c
+@@ -221,8 +221,6 @@ parse_options(char *options, uid_t *uid,
+ *mount_opts |= SF_MUFS;
+ break;
+ case Opt_prefix:
+- /* Free any previous prefix */
+- kfree(*prefix);
+ *prefix = match_strdup(&args[0]);
+ if (!*prefix)
+ return 0;
+@@ -311,6 +309,7 @@ static int affs_fill_super(struct super_
+ return -ENOMEM;
+ sb->s_fs_info = sbi;
+ mutex_init(&sbi->s_bmlock);
++ spin_lock_init(&sbi->symlink_lock);
+
+ if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
+ &blocksize,&sbi->s_prefix,
+@@ -518,14 +517,18 @@ affs_remount(struct super_block *sb, int
+ unsigned long mount_flags;
+ int res = 0;
+ char *new_opts = kstrdup(data, GFP_KERNEL);
++ char volume[32];
++ char *prefix = NULL;
+
+ pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
+
+ *flags |= MS_NODIRATIME;
+
++ memcpy(volume, sbi->s_volume, 32);
+ if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block,
+- &blocksize, &sbi->s_prefix, sbi->s_volume,
++ &blocksize, &prefix, volume,
+ &mount_flags)) {
++ kfree(prefix);
+ kfree(new_opts);
+ return -EINVAL;
+ }
+@@ -536,6 +539,14 @@ affs_remount(struct super_block *sb, int
+ sbi->s_mode = mode;
+ sbi->s_uid = uid;
+ sbi->s_gid = gid;
++ /* protect against readers */
++ spin_lock(&sbi->symlink_lock);
++ if (prefix) {
++ kfree(sbi->s_prefix);
++ sbi->s_prefix = prefix;
++ }
++ memcpy(sbi->s_volume, volume, 32);
++ spin_unlock(&sbi->symlink_lock);
+
+ if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
+ unlock_kernel();
+--- a/fs/affs/symlink.c
++++ b/fs/affs/symlink.c
+@@ -20,7 +20,6 @@ static int affs_symlink_readpage(struct
+ int i, j;
+ char c;
+ char lc;
+- char *pf;
+
+ pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
+
+@@ -32,11 +31,15 @@ static int affs_symlink_readpage(struct
+ j = 0;
+ lf = (struct slink_front *)bh->b_data;
+ lc = 0;
+- pf = AFFS_SB(inode->i_sb)->s_prefix ? AFFS_SB(inode->i_sb)->s_prefix : "/";
+
+ if (strchr(lf->symname,':')) { /* Handle assign or volume name */
++ struct affs_sb_info *sbi = AFFS_SB(inode->i_sb);
++ char *pf;
++ spin_lock(&sbi->symlink_lock);
++ pf = sbi->s_prefix ? sbi->s_prefix : "/";
+ while (i < 1023 && (c = pf[i]))
+ link[i++] = c;
++ spin_unlock(&sbi->symlink_lock);
+ while (i < 1023 && lf->symname[j] != ':')
+ link[i++] = lf->symname[j++];
+ if (i < 1023)
--- /dev/null
+From 93fb84b50fe03aabca8d9dea5d3ba521a07e8571 Mon Sep 17 00:00:00 2001
+From: David Härdeman <david@hardeman.nu>
+Date: Thu, 28 Jan 2010 22:28:27 -0800
+Subject: Input: winbond-cir - remove dmesg spam
+
+From: David Härdeman <david@hardeman.nu>
+
+commit 93fb84b50fe03aabca8d9dea5d3ba521a07e8571 upstream.
+
+I missed converting one dev_info call to deb_dbg before submitting the driver.
+Without this change, a message will be printed to dmesg for each button press
+if a RC6 remote is used.
+
+Signed-off-by: David Härdeman <david@hardeman.nu>
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/input/misc/winbond-cir.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/input/misc/winbond-cir.c
++++ b/drivers/input/misc/winbond-cir.c
+@@ -768,7 +768,7 @@ wbcir_parse_rc6(struct device *dev, stru
+ return;
+ }
+
+- dev_info(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X "
++ dev_dbg(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X "
+ "toggle %u mode %u scan 0x%08X\n",
+ address,
+ command,
--- /dev/null
+From a7016235a61d520e6806f38129001d935c4b6661 Mon Sep 17 00:00:00 2001
+From: Hugh Dickins <hugh.dickins@tiscali.co.uk>
+Date: Fri, 29 Jan 2010 17:46:34 +0000
+Subject: mm: fix migratetype bug which slowed swapping
+
+From: Hugh Dickins <hugh.dickins@tiscali.co.uk>
+
+commit a7016235a61d520e6806f38129001d935c4b6661 upstream.
+
+After memory pressure has forced it to dip into the reserves, 2.6.32's
+5f8dcc21211a3d4e3a7a5ca366b469fb88117f61 "page-allocator: split per-cpu
+list into one-list-per-migrate-type" has been returning MIGRATE_RESERVE
+pages to the MIGRATE_MOVABLE free_list: in some sense depleting reserves.
+
+Fix that in the most straightforward way (which, considering the overheads
+of alternative approaches, is Mel's preference): the right migratetype is
+already in page_private(page), but free_pcppages_bulk() wasn't using it.
+
+How did this bug show up? As a 20% slowdown in my tmpfs loop kbuild
+swapping tests, on PowerMac G5 with SLUB allocator. Bisecting to that
+commit was easy, but explaining the magnitude of the slowdown not easy.
+
+The same effect appears, but much less markedly, with SLAB, and even
+less markedly on other machines (the PowerMac divides into fewer zones
+than x86, I think that may be a factor). We guess that lumpy reclaim
+of short-lived high-order pages is implicated in some way, and probably
+this bug has been tickling a poor decision somewhere in page reclaim.
+
+But instrumentation hasn't told me much, I've run out of time and
+imagination to determine exactly what's going on, and shouldn't hold up
+the fix any longer: it's valid, and might even fix other misbehaviours.
+
+Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>
+Acked-by: Mel Gorman <mel@csn.ul.ie>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ mm/page_alloc.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -559,8 +559,9 @@ static void free_pcppages_bulk(struct zo
+ page = list_entry(list->prev, struct page, lru);
+ /* must delete as __free_one_page list manipulates */
+ list_del(&page->lru);
+- __free_one_page(page, zone, 0, migratetype);
+- trace_mm_page_pcpu_drain(page, 0, migratetype);
++ /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
++ __free_one_page(page, zone, 0, page_private(page));
++ trace_mm_page_pcpu_drain(page, 0, page_private(page));
+ } while (--count && --batch_free && !list_empty(list));
+ }
+ spin_unlock(&zone->lock);
acpi-fix-osc-regression-that-caused-aer-and-pciehp-not-to-load.patch
acpi-advertise-to-bios-in-_osc-_ost-on-_ppc-changes.patch
ubi-fix-volume-creation-input-checking.patch
+e1000-enhance-frame-fragment-detection.patch
+e1000e-enhance-frame-fragment-detection.patch
+e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch
+drm-i915-reload-hangcheck-timer-too-for-ironlake.patch
+drm-i915-add-acpi-opregion-support-for-ironlake.patch
+fix-a-leak-in-affs_fill_super.patch
+fix-failure-exits-in-bfs_fill_super.patch
+fix-oops-in-fs-9p-late-mount-failure.patch
+fix-leak-in-romfs_fill_super.patch
+fix-remount-races-with-symlink-handling-in-affs.patch
+fix-affs-parse_options.patch
+fix-failure-exit-in-ipathfs.patch
+mm-fix-migratetype-bug-which-slowed-swapping.patch
+fdpic-respect-pt_gnu_stack-exec-protection-markings-when-creating-nommu-stack.patch
+split-flush_old_exec-into-two-functions.patch
+sparc-tif_abi_pending-bit-removal.patch
+x86-get-rid-of-the-insane-tif_abi_pending-bit.patch
+drm-i915-add-display-hotplug-event-on-ironlake.patch
+input-winbond-cir-remove-dmesg-spam.patch
--- /dev/null
+From 94673e968cbcce07fa78dac4b0ae05d24b5816e1 Mon Sep 17 00:00:00 2001
+From: David Miller <davem@davemloft.net>
+Date: Thu, 28 Jan 2010 21:42:02 -0800
+Subject: sparc: TIF_ABI_PENDING bit removal
+
+From: David Miller <davem@davemloft.net>
+
+commit 94673e968cbcce07fa78dac4b0ae05d24b5816e1 upstream.
+
+Here are the sparc bits to remove TIF_ABI_PENDING now that
+set_personality() is called at the appropriate place in exec.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sparc/include/asm/elf_64.h | 13 +++----------
+ arch/sparc/include/asm/thread_info_64.h | 4 +---
+ arch/sparc/kernel/process_64.c | 8 --------
+ 3 files changed, 4 insertions(+), 21 deletions(-)
+
+--- a/arch/sparc/include/asm/elf_64.h
++++ b/arch/sparc/include/asm/elf_64.h
+@@ -196,17 +196,10 @@ static inline unsigned int sparc64_elf_h
+ #define ELF_PLATFORM (NULL)
+
+ #define SET_PERSONALITY(ex) \
+-do { unsigned long new_flags = current_thread_info()->flags; \
+- new_flags &= _TIF_32BIT; \
+- if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
+- new_flags |= _TIF_32BIT; \
++do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
++ set_thread_flag(TIF_32BIT); \
+ else \
+- new_flags &= ~_TIF_32BIT; \
+- if ((current_thread_info()->flags & _TIF_32BIT) \
+- != new_flags) \
+- set_thread_flag(TIF_ABI_PENDING); \
+- else \
+- clear_thread_flag(TIF_ABI_PENDING); \
++ clear_thread_flag(TIF_32BIT); \
+ /* flush_thread will update pgd cache */ \
+ if (personality(current->personality) != PER_LINUX32) \
+ set_personality(PER_LINUX | \
+--- a/arch/sparc/include/asm/thread_info_64.h
++++ b/arch/sparc/include/asm/thread_info_64.h
+@@ -227,12 +227,11 @@ register struct thread_info *current_thr
+ /* flag bit 8 is available */
+ #define TIF_SECCOMP 9 /* secure computing */
+ #define TIF_SYSCALL_AUDIT 10 /* syscall auditing active */
+-/* flag bit 11 is available */
+ /* NOTE: Thread flags >= 12 should be ones we have no interest
+ * in using in assembly, else we can't use the mask as
+ * an immediate value in instructions such as andcc.
+ */
+-#define TIF_ABI_PENDING 12
++/* flag bit 12 is available */
+ #define TIF_MEMDIE 13
+ #define TIF_POLLING_NRFLAG 14
+ #define TIF_FREEZE 15 /* is freezing for suspend */
+@@ -246,7 +245,6 @@ register struct thread_info *current_thr
+ #define _TIF_32BIT (1<<TIF_32BIT)
+ #define _TIF_SECCOMP (1<<TIF_SECCOMP)
+ #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+-#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
+ #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+ #define _TIF_FREEZE (1<<TIF_FREEZE)
+
+--- a/arch/sparc/kernel/process_64.c
++++ b/arch/sparc/kernel/process_64.c
+@@ -365,14 +365,6 @@ void flush_thread(void)
+ struct thread_info *t = current_thread_info();
+ struct mm_struct *mm;
+
+- if (test_ti_thread_flag(t, TIF_ABI_PENDING)) {
+- clear_ti_thread_flag(t, TIF_ABI_PENDING);
+- if (test_ti_thread_flag(t, TIF_32BIT))
+- clear_ti_thread_flag(t, TIF_32BIT);
+- else
+- set_ti_thread_flag(t, TIF_32BIT);
+- }
+-
+ mm = t->task->mm;
+ if (mm)
+ tsb_context_switch(mm);
--- /dev/null
+From 221af7f87b97431e3ee21ce4b0e77d5411cf1549 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Thu, 28 Jan 2010 22:14:42 -0800
+Subject: Split 'flush_old_exec' into two functions
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 221af7f87b97431e3ee21ce4b0e77d5411cf1549 upstream.
+
+'flush_old_exec()' is the point of no return when doing an execve(), and
+it is pretty badly misnamed. It doesn't just flush the old executable
+environment, it also starts up the new one.
+
+Which is very inconvenient for things like setting up the new
+personality, because we want the new personality to affect the starting
+of the new environment, but at the same time we do _not_ want the new
+personality to take effect if flushing the old one fails.
+
+As a result, the x86-64 '32-bit' personality is actually done using this
+insane "I'm going to change the ABI, but I haven't done it yet" bit
+(TIF_ABI_PENDING), with SET_PERSONALITY() not actually setting the
+personality, but just the "pending" bit, so that "flush_thread()" can do
+the actual personality magic.
+
+This patch in no way changes any of that insanity, but it does split the
+'flush_old_exec()' function up into a preparatory part that can fail
+(still called flush_old_exec()), and a new part that will actually set
+up the new exec environment (setup_new_exec()). All callers are changed
+to trivially comply with the new world order.
+
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sh/kernel/process_64.c | 2 +-
+ arch/x86/ia32/ia32_aout.c | 10 ++++++----
+ fs/binfmt_aout.c | 1 +
+ fs/binfmt_elf.c | 27 ++-------------------------
+ fs/binfmt_elf_fdpic.c | 3 +++
+ fs/binfmt_flat.c | 1 +
+ fs/binfmt_som.c | 1 +
+ fs/exec.c | 26 ++++++++++++++++----------
+ include/linux/binfmts.h | 1 +
+ include/linux/sched.h | 2 +-
+ 10 files changed, 33 insertions(+), 41 deletions(-)
+
+--- a/arch/sh/kernel/process_64.c
++++ b/arch/sh/kernel/process_64.c
+@@ -367,7 +367,7 @@ void exit_thread(void)
+ void flush_thread(void)
+ {
+
+- /* Called by fs/exec.c (flush_old_exec) to remove traces of a
++ /* Called by fs/exec.c (setup_new_exec) to remove traces of a
+ * previously running executable. */
+ #ifdef CONFIG_SH_FPU
+ if (last_task_used_math == current) {
+--- a/arch/x86/ia32/ia32_aout.c
++++ b/arch/x86/ia32/ia32_aout.c
+@@ -308,15 +308,17 @@ static int load_aout_binary(struct linux
+ if (retval)
+ return retval;
+
+- regs->cs = __USER32_CS;
+- regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
+- regs->r13 = regs->r14 = regs->r15 = 0;
+-
+ /* OK, This is the point of no return */
+ set_personality(PER_LINUX);
+ set_thread_flag(TIF_IA32);
+ clear_thread_flag(TIF_ABI_PENDING);
+
++ setup_new_exec(bprm);
++
++ regs->cs = __USER32_CS;
++ regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
++ regs->r13 = regs->r14 = regs->r15 = 0;
++
+ current->mm->end_code = ex.a_text +
+ (current->mm->start_code = N_TXTADDR(ex));
+ current->mm->end_data = ex.a_data +
+--- a/fs/binfmt_aout.c
++++ b/fs/binfmt_aout.c
+@@ -263,6 +263,7 @@ static int load_aout_binary(struct linux
+ #else
+ set_personality(PER_LINUX);
+ #endif
++ setup_new_exec(bprm);
+
+ current->mm->end_code = ex.a_text +
+ (current->mm->start_code = N_TXTADDR(ex));
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -662,27 +662,6 @@ static int load_elf_binary(struct linux_
+ if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
+ goto out_free_interp;
+
+- /*
+- * The early SET_PERSONALITY here is so that the lookup
+- * for the interpreter happens in the namespace of the
+- * to-be-execed image. SET_PERSONALITY can select an
+- * alternate root.
+- *
+- * However, SET_PERSONALITY is NOT allowed to switch
+- * this task into the new images's memory mapping
+- * policy - that is, TASK_SIZE must still evaluate to
+- * that which is appropriate to the execing application.
+- * This is because exit_mmap() needs to have TASK_SIZE
+- * evaluate to the size of the old image.
+- *
+- * So if (say) a 64-bit application is execing a 32-bit
+- * application it is the architecture's responsibility
+- * to defer changing the value of TASK_SIZE until the
+- * switch really is going to happen - do this in
+- * flush_thread(). - akpm
+- */
+- SET_PERSONALITY(loc->elf_ex);
+-
+ interpreter = open_exec(elf_interpreter);
+ retval = PTR_ERR(interpreter);
+ if (IS_ERR(interpreter))
+@@ -730,9 +709,6 @@ static int load_elf_binary(struct linux_
+ /* Verify the interpreter has a valid arch */
+ if (!elf_check_arch(&loc->interp_elf_ex))
+ goto out_free_dentry;
+- } else {
+- /* Executables without an interpreter also need a personality */
+- SET_PERSONALITY(loc->elf_ex);
+ }
+
+ /* Flush all traces of the currently running executable */
+@@ -752,7 +728,8 @@ static int load_elf_binary(struct linux_
+
+ if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+ current->flags |= PF_RANDOMIZE;
+- arch_pick_mmap_layout(current->mm);
++
++ setup_new_exec(bprm);
+
+ /* Do this so that we can load the interpreter, if need be. We will
+ change some of these later */
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -321,6 +321,9 @@ static int load_elf_fdpic_binary(struct
+ set_personality(PER_LINUX_FDPIC);
+ if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
+ current->personality |= READ_IMPLIES_EXEC;
++
++ setup_new_exec(bprm);
++
+ set_binfmt(&elf_fdpic_format);
+
+ current->mm->start_code = 0;
+--- a/fs/binfmt_flat.c
++++ b/fs/binfmt_flat.c
+@@ -519,6 +519,7 @@ static int load_flat_file(struct linux_b
+
+ /* OK, This is the point of no return */
+ set_personality(PER_LINUX_32BIT);
++ setup_new_exec(bprm);
+ }
+
+ /*
+--- a/fs/binfmt_som.c
++++ b/fs/binfmt_som.c
+@@ -227,6 +227,7 @@ load_som_binary(struct linux_binprm * bp
+ /* OK, This is the point of no return */
+ current->flags &= ~PF_FORKNOEXEC;
+ current->personality = PER_HPUX;
++ setup_new_exec(bprm);
+
+ /* Set the task size for HP-UX processes such that
+ * the gateway page is outside the address space.
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -931,9 +931,7 @@ void set_task_comm(struct task_struct *t
+
+ int flush_old_exec(struct linux_binprm * bprm)
+ {
+- char * name;
+- int i, ch, retval;
+- char tcomm[sizeof(current->comm)];
++ int retval;
+
+ /*
+ * Make sure we have a private signal table and that
+@@ -953,6 +951,20 @@ int flush_old_exec(struct linux_binprm *
+ goto out;
+
+ bprm->mm = NULL; /* We're using it now */
++ return 0;
++
++out:
++ return retval;
++}
++EXPORT_SYMBOL(flush_old_exec);
++
++void setup_new_exec(struct linux_binprm * bprm)
++{
++ int i, ch;
++ char * name;
++ char tcomm[sizeof(current->comm)];
++
++ arch_pick_mmap_layout(current->mm);
+
+ /* This is the point of no return */
+ current->sas_ss_sp = current->sas_ss_size = 0;
+@@ -1009,14 +1021,8 @@ int flush_old_exec(struct linux_binprm *
+
+ flush_signal_handlers(current, 0);
+ flush_old_files(current->files);
+-
+- return 0;
+-
+-out:
+- return retval;
+ }
+-
+-EXPORT_SYMBOL(flush_old_exec);
++EXPORT_SYMBOL(setup_new_exec);
+
+ /*
+ * Prepare credentials and lock ->cred_guard_mutex.
+--- a/include/linux/binfmts.h
++++ b/include/linux/binfmts.h
+@@ -101,6 +101,7 @@ extern int prepare_binprm(struct linux_b
+ extern int __must_check remove_arg_zero(struct linux_binprm *);
+ extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
+ extern int flush_old_exec(struct linux_binprm * bprm);
++extern void setup_new_exec(struct linux_binprm * bprm);
+
+ extern int suid_dumpable;
+ #define SUID_DUMP_DISABLE 0 /* No setuid dumping */
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -1354,7 +1354,7 @@ struct task_struct {
+ char comm[TASK_COMM_LEN]; /* executable name excluding path
+ - access with [gs]et_task_comm (which lock
+ it with task_lock())
+- - initialized normally by flush_old_exec */
++ - initialized normally by setup_new_exec */
+ /* file system info */
+ int link_count, total_link_count;
+ #ifdef CONFIG_SYSVIPC
--- /dev/null
+From 05d43ed8a89c159ff641d472f970e3f1baa66318 Mon Sep 17 00:00:00 2001
+From: H. Peter Anvin <hpa@zytor.com>
+Date: Thu, 28 Jan 2010 22:14:43 -0800
+Subject: x86: get rid of the insane TIF_ABI_PENDING bit
+
+From: H. Peter Anvin <hpa@zytor.com>
+
+commit 05d43ed8a89c159ff641d472f970e3f1baa66318 upstream.
+
+Now that the previous commit made it possible to do the personality
+setting at the point of no return, we do just that for ELF binaries.
+And suddenly all the reasons for that insane TIF_ABI_PENDING bit go
+away, and we can just make SET_PERSONALITY() just do the obvious thing
+for a 32-bit compat process.
+
+Everything becomes much more straightforward this way.
+
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/ia32/ia32_aout.c | 1 -
+ arch/x86/include/asm/elf.h | 10 ++--------
+ arch/x86/include/asm/thread_info.h | 2 --
+ arch/x86/kernel/process.c | 12 ------------
+ arch/x86/kernel/process_64.c | 11 +++++++++++
+ 5 files changed, 13 insertions(+), 23 deletions(-)
+
+--- a/arch/x86/ia32/ia32_aout.c
++++ b/arch/x86/ia32/ia32_aout.c
+@@ -311,7 +311,6 @@ static int load_aout_binary(struct linux
+ /* OK, This is the point of no return */
+ set_personality(PER_LINUX);
+ set_thread_flag(TIF_IA32);
+- clear_thread_flag(TIF_ABI_PENDING);
+
+ setup_new_exec(bprm);
+
+--- a/arch/x86/include/asm/elf.h
++++ b/arch/x86/include/asm/elf.h
+@@ -197,14 +197,8 @@ do { \
+ set_fs(USER_DS); \
+ } while (0)
+
+-#define COMPAT_SET_PERSONALITY(ex) \
+-do { \
+- if (test_thread_flag(TIF_IA32)) \
+- clear_thread_flag(TIF_ABI_PENDING); \
+- else \
+- set_thread_flag(TIF_ABI_PENDING); \
+- current->personality |= force_personality32; \
+-} while (0)
++void set_personality_ia32(void);
++#define COMPAT_SET_PERSONALITY(ex) set_personality_ia32()
+
+ #define COMPAT_ELF_PLATFORM ("i686")
+
+--- a/arch/x86/include/asm/thread_info.h
++++ b/arch/x86/include/asm/thread_info.h
+@@ -86,7 +86,6 @@ struct thread_info {
+ #define TIF_NOTSC 16 /* TSC is not accessible in userland */
+ #define TIF_IA32 17 /* 32bit process */
+ #define TIF_FORK 18 /* ret_from_fork */
+-#define TIF_ABI_PENDING 19
+ #define TIF_MEMDIE 20
+ #define TIF_DEBUG 21 /* uses debug registers */
+ #define TIF_IO_BITMAP 22 /* uses I/O bitmap */
+@@ -110,7 +109,6 @@ struct thread_info {
+ #define _TIF_NOTSC (1 << TIF_NOTSC)
+ #define _TIF_IA32 (1 << TIF_IA32)
+ #define _TIF_FORK (1 << TIF_FORK)
+-#define _TIF_ABI_PENDING (1 << TIF_ABI_PENDING)
+ #define _TIF_DEBUG (1 << TIF_DEBUG)
+ #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP)
+ #define _TIF_FREEZE (1 << TIF_FREEZE)
+--- a/arch/x86/kernel/process_64.c
++++ b/arch/x86/kernel/process_64.c
+@@ -540,6 +540,17 @@ sys_clone(unsigned long clone_flags, uns
+ return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+ }
+
++void set_personality_ia32(void)
++{
++ /* inherit personality from parent */
++
++ /* Make sure to be in 32bit mode */
++ set_thread_flag(TIF_IA32);
++
++ /* Prepare the first "return" to user space */
++ current_thread_info()->status |= TS_COMPAT;
++}
++
+ unsigned long get_wchan(struct task_struct *p)
+ {
+ unsigned long stack;
+--- a/arch/x86/kernel/process.c
++++ b/arch/x86/kernel/process.c
+@@ -91,18 +91,6 @@ void flush_thread(void)
+ {
+ struct task_struct *tsk = current;
+
+-#ifdef CONFIG_X86_64
+- if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) {
+- clear_tsk_thread_flag(tsk, TIF_ABI_PENDING);
+- if (test_tsk_thread_flag(tsk, TIF_IA32)) {
+- clear_tsk_thread_flag(tsk, TIF_IA32);
+- } else {
+- set_tsk_thread_flag(tsk, TIF_IA32);
+- current_thread_info()->status |= TS_COMPAT;
+- }
+- }
+-#endif
+-
+ clear_tsk_thread_flag(tsk, TIF_DEBUG);
+
+ tsk->thread.debugreg0 = 0;