]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.32 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 7 Apr 2010 22:26:32 +0000 (15:26 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 7 Apr 2010 22:26:32 +0000 (15:26 -0700)
40 files changed:
queue-2.6.32/alsa-hda-fix-0-db-offset-for-lenovo-thinkpad-models-using-ad1981.patch [new file with mode: 0644]
queue-2.6.32/alsa-mixart-range-checking-proc-file.patch [new file with mode: 0644]
queue-2.6.32/backlight-mbp_nvidia_bl-add-five-more-macbook-variants.patch [new file with mode: 0644]
queue-2.6.32/eeepc-laptop-add-hotplug_disable-parameter.patch [new file with mode: 0644]
queue-2.6.32/eeepc-laptop-disable-cpu-speed-control-on-eeepc-701.patch [new file with mode: 0644]
queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1005pe.patch [new file with mode: 0644]
queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1201n.patch [new file with mode: 0644]
queue-2.6.32/eeepc-laptop-dmi-blacklist-to-disable-pci-hotplug-code.patch [new file with mode: 0644]
queue-2.6.32/ext3-don-t-update-the-superblock-in-ext3_statfs.patch [new file with mode: 0644]
queue-2.6.32/ext3-journal-all-modifications-in-ext3_xattr_set_handle.patch [new file with mode: 0644]
queue-2.6.32/hid-fix-oops-in-gyration_event.patch [new file with mode: 0644]
queue-2.6.32/kvm-fix-segment-descriptor-loading.patch [new file with mode: 0644]
queue-2.6.32/kvm-svm-reset-cr0-properly-on-vcpu-reset.patch [new file with mode: 0644]
queue-2.6.32/kvm-vmx-disable-unrestricted-guest-when-ept-disabled.patch [new file with mode: 0644]
queue-2.6.32/kvm-vmx-update-instruction-length-on-intercepted-bp.patch [new file with mode: 0644]
queue-2.6.32/kvm-vmx-use-macros-instead-of-hex-value-on-cr0-initialization.patch [new file with mode: 0644]
queue-2.6.32/kvm-x86-disable-paravirt-mmu-reporting.patch [new file with mode: 0644]
queue-2.6.32/kvm-x86-emulator-add-virtual-8086-mode-of-emulation.patch [new file with mode: 0644]
queue-2.6.32/kvm-x86-emulator-check-iopl-level-during-io-instruction-emulation.patch [new file with mode: 0644]
queue-2.6.32/kvm-x86-emulator-fix-memory-access-during-x86-emulation.patch [new file with mode: 0644]
queue-2.6.32/kvm-x86-emulator-fix-popf-emulation.patch [new file with mode: 0644]
queue-2.6.32/libata-disable-ncq-on-crucial-c300-ssd.patch [new file with mode: 0644]
queue-2.6.32/libata-unlock-hpa-if-device-shrunk.patch [new file with mode: 0644]
queue-2.6.32/pata_via-add-via-vx900-support.patch [new file with mode: 0644]
queue-2.6.32/raw-fsync-method-is-now-required.patch [new file with mode: 0644]
queue-2.6.32/readahead-fix-null-filp-dereference.patch [new file with mode: 0644]
queue-2.6.32/resource-move-kernel-function-inside-__kernel__.patch [new file with mode: 0644]
queue-2.6.32/series
queue-2.6.32/thinkpad-acpi-adopt-input-device.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-convert-to-seq_file.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-expose-module-parameters.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-fix-some-version-quirks.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-issue-backlight-class-events.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-lock-down-video-output-state-access.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-log-initial-state-of-rfkill-switches.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-log-temperatures-on-termal-alarm-v2.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-silence-bogus-complain-during-rmmod.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-sync-input-device-ev_sw-initial-state.patch [new file with mode: 0644]
queue-2.6.32/thinkpad-acpi-use-input_set_capability.patch [new file with mode: 0644]
queue-2.6.32/x86-amd-get-multi-node-cpu-info-from-nodeid-msr-instead-of-pci-config-space.patch [new file with mode: 0644]

diff --git a/queue-2.6.32/alsa-hda-fix-0-db-offset-for-lenovo-thinkpad-models-using-ad1981.patch b/queue-2.6.32/alsa-hda-fix-0-db-offset-for-lenovo-thinkpad-models-using-ad1981.patch
new file mode 100644 (file)
index 0000000..426e81d
--- /dev/null
@@ -0,0 +1,41 @@
+From b8e80cf386419453678b01bef830f53445ebb15d Mon Sep 17 00:00:00 2001
+From: Daniel T Chen <crimsun@ubuntu.com>
+Date: Tue, 30 Mar 2010 13:29:28 -0400
+Subject: ALSA: hda: Fix 0 dB offset for Lenovo Thinkpad models using AD1981
+
+From: Daniel T Chen <crimsun@ubuntu.com>
+
+commit b8e80cf386419453678b01bef830f53445ebb15d upstream.
+
+BugLink: https://launchpad.net/bugs/551606
+
+The OR's hardware distorts at PCM 100% because it does not correspond to
+0 dB. Fix this in patch_ad1981() for all models using the Thinkpad
+quirk.
+
+Reported-by: Jane Silber
+Signed-off-by: Daniel T Chen <crimsun@ubuntu.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/patch_analog.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/sound/pci/hda/patch_analog.c
++++ b/sound/pci/hda/patch_analog.c
+@@ -1789,6 +1789,14 @@ static int patch_ad1981(struct hda_codec
+       case AD1981_THINKPAD:
+               spec->mixers[0] = ad1981_thinkpad_mixers;
+               spec->input_mux = &ad1981_thinkpad_capture_source;
++              /* set the upper-limit for mixer amp to 0dB for avoiding the
++               * possible damage by overloading
++               */
++              snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
++                                        (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
++                                        (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
++                                        (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
++                                        (1 << AC_AMPCAP_MUTE_SHIFT));
+               break;
+       case AD1981_TOSHIBA:
+               spec->mixers[0] = ad1981_hp_mixers;
diff --git a/queue-2.6.32/alsa-mixart-range-checking-proc-file.patch b/queue-2.6.32/alsa-mixart-range-checking-proc-file.patch
new file mode 100644 (file)
index 0000000..0773423
--- /dev/null
@@ -0,0 +1,69 @@
+From b0cc58a25d04160d39a80e436847eaa2fbc5aa09 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <error27@gmail.com>
+Date: Tue, 6 Apr 2010 19:31:26 +0300
+Subject: ALSA: mixart: range checking proc file
+
+From: Dan Carpenter <error27@gmail.com>
+
+commit b0cc58a25d04160d39a80e436847eaa2fbc5aa09 upstream.
+
+The original code doesn't take into consideration that the value of
+MIXART_BA0_SIZE - pos can be less than zero which would lead to a large
+unsigned value for "count".
+
+Also I moved the check that read size is a multiple of 4 bytes below
+the code that adjusts "count".
+
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/mixart/mixart.c |   24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+--- a/sound/pci/mixart/mixart.c
++++ b/sound/pci/mixart/mixart.c
+@@ -1161,13 +1161,15 @@ static long snd_mixart_BA0_read(struct s
+                               unsigned long count, unsigned long pos)
+ {
+       struct mixart_mgr *mgr = entry->private_data;
++      unsigned long maxsize;
+-      count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
+-      if(count <= 0)
++      if (pos >= MIXART_BA0_SIZE)
+               return 0;
+-      if(pos + count > MIXART_BA0_SIZE)
+-              count = (long)(MIXART_BA0_SIZE - pos);
+-      if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count))
++      maxsize = MIXART_BA0_SIZE - pos;
++      if (count > maxsize)
++              count = maxsize;
++      count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
++      if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
+               return -EFAULT;
+       return count;
+ }
+@@ -1180,13 +1182,15 @@ static long snd_mixart_BA1_read(struct s
+                               unsigned long count, unsigned long pos)
+ {
+       struct mixart_mgr *mgr = entry->private_data;
++      unsigned long maxsize;
+-      count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
+-      if(count <= 0)
++      if (pos > MIXART_BA1_SIZE)
+               return 0;
+-      if(pos + count > MIXART_BA1_SIZE)
+-              count = (long)(MIXART_BA1_SIZE - pos);
+-      if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count))
++      maxsize = MIXART_BA1_SIZE - pos;
++      if (count > maxsize)
++              count = maxsize;
++      count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
++      if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
+               return -EFAULT;
+       return count;
+ }
diff --git a/queue-2.6.32/backlight-mbp_nvidia_bl-add-five-more-macbook-variants.patch b/queue-2.6.32/backlight-mbp_nvidia_bl-add-five-more-macbook-variants.patch
new file mode 100644 (file)
index 0000000..99604a5
--- /dev/null
@@ -0,0 +1,73 @@
+From 36bc5ee6a8d13333980fa54e97d3469d3d4cda98 Mon Sep 17 00:00:00 2001
+From: Evan McClain <evan.mcclain@gatech.edu>
+Date: Tue, 9 Mar 2010 19:20:58 -0500
+Subject: backlight: mbp_nvidia_bl - add five more MacBook variants
+
+From: Evan McClain <evan.mcclain@gatech.edu>
+
+commit 36bc5ee6a8d13333980fa54e97d3469d3d4cda98 upstream.
+
+This adds the MacBook 1,1 2,1 3,1 4,1 and 4,2 to the DMI tables.
+
+Signed-off-by: Evan McClain <evan.mcclain@gatech.edu>
+Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/video/backlight/mbp_nvidia_bl.c |   45 ++++++++++++++++++++++++++++++++
+ 1 file changed, 45 insertions(+)
+
+--- a/drivers/video/backlight/mbp_nvidia_bl.c
++++ b/drivers/video/backlight/mbp_nvidia_bl.c
+@@ -139,6 +139,51 @@ static int mbp_dmi_match(const struct dm
+ static const struct dmi_system_id __initdata mbp_device_table[] = {
+       {
+               .callback       = mbp_dmi_match,
++              .ident          = "MacBook 1,1",
++              .matches        = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
++              },
++              .driver_data    = (void *)&intel_chipset_data,
++      },
++      {
++              .callback       = mbp_dmi_match,
++              .ident          = "MacBook 2,1",
++              .matches        = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
++              },
++              .driver_data    = (void *)&intel_chipset_data,
++      },
++      {
++              .callback       = mbp_dmi_match,
++              .ident          = "MacBook 3,1",
++              .matches        = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "MacBook3,1"),
++              },
++              .driver_data    = (void *)&intel_chipset_data,
++      },
++      {
++              .callback       = mbp_dmi_match,
++              .ident          = "MacBook 4,1",
++              .matches        = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,1"),
++              },
++              .driver_data    = (void *)&intel_chipset_data,
++      },
++      {
++              .callback       = mbp_dmi_match,
++              .ident          = "MacBook 4,2",
++              .matches        = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,2"),
++              },
++              .driver_data    = (void *)&intel_chipset_data,
++      },
++      {
++              .callback       = mbp_dmi_match,
+               .ident          = "MacBookPro 3,1",
+               .matches        = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
diff --git a/queue-2.6.32/eeepc-laptop-add-hotplug_disable-parameter.patch b/queue-2.6.32/eeepc-laptop-add-hotplug_disable-parameter.patch
new file mode 100644 (file)
index 0000000..198ce87
--- /dev/null
@@ -0,0 +1,48 @@
+From: Corentin Chary <corentincj@iksaif.net>
+Date: Wed, 6 Jan 2010 22:07:40 +0100
+Subject: eeepc-laptop: add hotplug_disable parameter
+
+commit 322a1356be96bcc4b97e8e370f6468c821330077 upstream.
+
+Some new models need to disable wireless hotplug.
+For the moment, we don't know excactly what models need that,
+except 1005HA.
+Users will be able to use that param as a workaround.
+
+[bwh: Backported to 2.6.32]
+
+Signed-off-by: Corentin Chary <corentincj@iksaif.net>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Cc: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/eeepc-laptop.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/platform/x86/eeepc-laptop.c
++++ b/drivers/platform/x86/eeepc-laptop.c
+@@ -254,6 +254,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Coop
+ MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
+ MODULE_LICENSE("GPL");
++static bool hotplug_disabled;
++
++module_param(hotplug_disabled, bool, 0644);
++MODULE_PARM_DESC(hotplug_disabled,
++               "Disable hotplug for wireless device. "
++               "If your laptop need that, please report to "
++               "acpi4asus-user@lists.sourceforge.net.");
++
+ /*
+  * ACPI Helpers
+  */
+@@ -1305,6 +1313,8 @@ static int __devinit eeepc_hotk_add(stru
+       device->driver_data = ehotk;
+       ehotk->device = device;
++      ehotk->hotplug_disabled = hotplug_disabled;
++
+       eeepc_dmi_check();
+       result = eeepc_hotk_check();
diff --git a/queue-2.6.32/eeepc-laptop-disable-cpu-speed-control-on-eeepc-701.patch b/queue-2.6.32/eeepc-laptop-disable-cpu-speed-control-on-eeepc-701.patch
new file mode 100644 (file)
index 0000000..e2def8b
--- /dev/null
@@ -0,0 +1,183 @@
+From: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
+Date: Wed, 6 Jan 2010 22:07:37 +0100
+Subject: eeepc-laptop: disable cpu speed control on EeePC 701
+
+commit da8ba01deb98f3dc0558b1f5a37e64f40bba7904 upstream.
+
+The EeePC 4G ("701") implements CFVS, but it is not supported by the
+pre-installed OS, and the original option to change it in the BIOS
+setup screen was removed in later versions.  Judging by the lack of
+"Super Hybrid Engine" on Asus product pages, this applies to all "701"
+models (4G/4G Surf/2G Surf).
+
+So Asus made a deliberate decision not to support it on this model.
+We have several reports that using it can cause the system to hang [1].
+That said, it does not happen all the time.  Some users do not
+experience it at all (and apparently wish to continue "right-clocking").
+
+Check for the EeePC 701 using DMI.  If met, then disable writes to the
+"cpufv" sysfs attribute and log an explanatory message.
+
+Add a "cpufv_disabled" attribute which allow users to override this
+policy.  Writing to this attribute will log a second message.
+
+The sysfs attribute is more useful than a module option, because it
+makes it easier for userspace scripts to provide consistent behaviour
+(according to user configuration), regardless of whether the kernel
+includes this change.
+
+[1] <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=559578>
+
+[bwh: Backported to 2.6.32]
+
+Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
+Signed-off-by: Corentin Chary <corentincj@iksaif.net>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Cc: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/eeepc-laptop.c |   84 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 84 insertions(+)
+
+--- a/drivers/platform/x86/eeepc-laptop.c
++++ b/drivers/platform/x86/eeepc-laptop.c
+@@ -34,6 +34,7 @@
+ #include <linux/rfkill.h>
+ #include <linux/pci.h>
+ #include <linux/pci_hotplug.h>
++#include <linux/dmi.h>
+ #define EEEPC_LAPTOP_VERSION  "0.1"
+@@ -135,6 +136,7 @@ struct eeepc_hotk {
+       acpi_handle handle;             /* the handle of the hotk device */
+       u32 cm_supported;               /* the control methods supported
+                                          by this BIOS */
++      bool cpufv_disabled;
+       uint init_flag;                 /* Init flags */
+       u16 event_count[128];           /* count for each event */
+       struct input_dev *inputdev;
+@@ -467,6 +469,8 @@ static ssize_t store_cpufv(struct device
+       struct eeepc_cpufv c;
+       int rv, value;
++      if (ehotk->cpufv_disabled)
++              return -EPERM;
+       if (get_cpufv(&c))
+               return -ENODEV;
+       rv = parse_arg(buf, count, &value);
+@@ -478,6 +482,38 @@ static ssize_t store_cpufv(struct device
+       return rv;
+ }
++static ssize_t show_cpufv_disabled(struct device *dev,
++                        struct device_attribute *attr,
++                        char *buf)
++{
++      return sprintf(buf, "%d\n", ehotk->cpufv_disabled);
++}
++
++static ssize_t store_cpufv_disabled(struct device *dev,
++                         struct device_attribute *attr,
++                         const char *buf, size_t count)
++{
++      int rv, value;
++
++      rv = parse_arg(buf, count, &value);
++      if (rv < 0)
++              return rv;
++
++      switch (value) {
++      case 0:
++              if (ehotk->cpufv_disabled)
++                      pr_warning("cpufv enabled (not officially supported "
++                              "on this model)\n");
++              ehotk->cpufv_disabled = false;
++              return rv;
++      case 1:
++              return -EPERM;
++      default:
++              return -EINVAL;
++      }
++}
++
++
+ static struct device_attribute dev_attr_cpufv = {
+       .attr = {
+               .name = "cpufv",
+@@ -493,12 +529,22 @@ static struct device_attribute dev_attr_
+       .show   = show_available_cpufv
+ };
++static struct device_attribute dev_attr_cpufv_disabled = {
++      .attr = {
++              .name = "cpufv_disabled",
++              .mode = 0644 },
++      .show   = show_cpufv_disabled,
++      .store  = store_cpufv_disabled
++};
++
++
+ static struct attribute *platform_attributes[] = {
+       &dev_attr_camera.attr,
+       &dev_attr_cardr.attr,
+       &dev_attr_disp.attr,
+       &dev_attr_cpufv.attr,
+       &dev_attr_available_cpufv.attr,
++      &dev_attr_cpufv_disabled.attr,
+       NULL
+ };
+@@ -564,6 +610,42 @@ static int eeepc_setkeycode(struct input
+       return -EINVAL;
+ }
++static void eeepc_dmi_check(void)
++{
++      const char *model;
++
++      /*
++       * Blacklist for setting cpufv (cpu speed).
++       *
++       * EeePC 4G ("701") implements CFVS, but it is not supported
++       * by the pre-installed OS, and the original option to change it
++       * in the BIOS setup screen was removed in later versions.
++       *
++       * Judging by the lack of "Super Hybrid Engine" on Asus product pages,
++       * this applies to all "701" models (4G/4G Surf/2G Surf).
++       *
++       * So Asus made a deliberate decision not to support it on this model.
++       * We have several reports that using it can cause the system to hang
++       *
++       * The hang has also been reported on a "702" (Model name "8G"?).
++       *
++       * We avoid dmi_check_system() / dmi_match(), because they use
++       * substring matching.  We don't want to affect the "701SD"
++       * and "701SDX" models, because they do support S.H.E.
++       */
++
++      model = dmi_get_system_info(DMI_PRODUCT_NAME);
++      if (!model)
++              return;
++
++      if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
++              ehotk->cpufv_disabled = true;
++              pr_info("model %s does not officially support setting cpu "
++                      "speed\n", model);
++              pr_info("cpufv disabled to avoid instability\n");
++      }
++}
++
+ static void cmsg_quirk(int cm, const char *name)
+ {
+       int dummy;
+@@ -1208,6 +1290,8 @@ static int __devinit eeepc_hotk_add(stru
+       device->driver_data = ehotk;
+       ehotk->device = device;
++      eeepc_dmi_check();
++
+       result = eeepc_hotk_check();
+       if (result)
+               goto fail_platform_driver;
diff --git a/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1005pe.patch b/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1005pe.patch
new file mode 100644 (file)
index 0000000..b90f01d
--- /dev/null
@@ -0,0 +1,34 @@
+From: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
+Date: Sat, 20 Feb 2010 11:02:24 +0000
+Subject: eeepc-laptop: disable wireless hotplug for 1005PE
+
+commit ced69c59811f05b2f8378467cbb82ac6ed3c6a5a upstream.
+
+The wireless hotplug code is not needed on this model, and it disables
+the wired ethernet card.  (Like on the 1005HA and 1201N).
+
+References: <http://lists.alioth.debian.org/pipermail/debian-eeepc-devel/2010-February/003281.html>
+
+[bwh: Backported to 2.6.32]
+
+Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
+Reported-by: Ansgar Burchardt <ansgar@43-1.org>
+Cc: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/eeepc-laptop.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/platform/x86/eeepc-laptop.c
++++ b/drivers/platform/x86/eeepc-laptop.c
+@@ -660,7 +660,8 @@ static void eeepc_dmi_check(void)
+        * hotplug code. In fact, current hotplug code seems to unplug another
+        * device...
+        */
+-      if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) {
++      if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 ||
++          strcmp(model, "1005PE") == 0) {
+               ehotk->hotplug_disabled = true;
+               pr_info("wlan hotplug disabled\n");
+       }
diff --git a/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1201n.patch b/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1201n.patch
new file mode 100644 (file)
index 0000000..18d88d5
--- /dev/null
@@ -0,0 +1,28 @@
+From: Corentin Chary <corentincj@iksaif.net>
+Date: Wed, 6 Jan 2010 22:07:41 +0100
+Subject: eeepc-laptop: disable wireless hotplug for 1201N
+
+commit 4194e2f551a6308e6ab34ac88210bf54858aa7df upstream.
+
+[bwh: Backported to 2.6.32]
+
+Signed-off-by: Corentin Chary <corentincj@iksaif.net>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Cc: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/eeepc-laptop.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/platform/x86/eeepc-laptop.c
++++ b/drivers/platform/x86/eeepc-laptop.c
+@@ -660,7 +660,7 @@ static void eeepc_dmi_check(void)
+        * hotplug code. In fact, current hotplug code seems to unplug another
+        * device...
+        */
+-      if (strcmp(model, "1005HA") == 0) {
++      if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) {
+               ehotk->hotplug_disabled = true;
+               pr_info("wlan hotplug disabled\n");
+       }
diff --git a/queue-2.6.32/eeepc-laptop-dmi-blacklist-to-disable-pci-hotplug-code.patch b/queue-2.6.32/eeepc-laptop-dmi-blacklist-to-disable-pci-hotplug-code.patch
new file mode 100644 (file)
index 0000000..4665ecf
--- /dev/null
@@ -0,0 +1,82 @@
+From: Corentin Chary <corentincj@iksaif.net>
+Date: Wed, 6 Jan 2010 22:07:38 +0100
+Subject: eeepc-laptop: dmi blacklist to disable pci hotplug code
+
+commit 10ae4b5663ff3092553bfbd867e7bd474ce6c553 upstream.
+
+This is a short term workaround for Eeepc 1005HA.
+
+refs: <http://bugzilla.kernel.org/show_bug.cgi?id=14570>
+
+[bwh: Backported to 2.6.32]
+
+Signed-off-by: Corentin Chary <corentincj@iksaif.net>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Cc: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/eeepc-laptop.c |   25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
+
+--- a/drivers/platform/x86/eeepc-laptop.c
++++ b/drivers/platform/x86/eeepc-laptop.c
+@@ -137,6 +137,7 @@ struct eeepc_hotk {
+       u32 cm_supported;               /* the control methods supported
+                                          by this BIOS */
+       bool cpufv_disabled;
++      bool hotplug_disabled;
+       uint init_flag;                 /* Init flags */
+       u16 event_count[128];           /* count for each event */
+       struct input_dev *inputdev;
+@@ -614,6 +615,10 @@ static void eeepc_dmi_check(void)
+ {
+       const char *model;
++      model = dmi_get_system_info(DMI_PRODUCT_NAME);
++      if (!model)
++              return;
++
+       /*
+        * Blacklist for setting cpufv (cpu speed).
+        *
+@@ -633,17 +638,24 @@ static void eeepc_dmi_check(void)
+        * substring matching.  We don't want to affect the "701SD"
+        * and "701SDX" models, because they do support S.H.E.
+        */
+-
+-      model = dmi_get_system_info(DMI_PRODUCT_NAME);
+-      if (!model)
+-              return;
+-
+       if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
+               ehotk->cpufv_disabled = true;
+               pr_info("model %s does not officially support setting cpu "
+                       "speed\n", model);
+               pr_info("cpufv disabled to avoid instability\n");
+       }
++
++      /*
++       * Blacklist for wlan hotplug
++       *
++       * Eeepc 1005HA doesn't work like others models and don't need the
++       * hotplug code. In fact, current hotplug code seems to unplug another
++       * device...
++       */
++      if (strcmp(model, "1005HA") == 0) {
++              ehotk->hotplug_disabled = true;
++              pr_info("wlan hotplug disabled\n");
++      }
+ }
+ static void cmsg_quirk(int cm, const char *name)
+@@ -1177,6 +1189,9 @@ static int eeepc_rfkill_init(struct devi
+       if (result && result != -ENODEV)
+               goto exit;
++      if (ehotk->hotplug_disabled)
++              return 0;
++
+       result = eeepc_setup_pci_hotplug();
+       /*
+        * If we get -EBUSY then something else is handling the PCI hotplug -
diff --git a/queue-2.6.32/ext3-don-t-update-the-superblock-in-ext3_statfs.patch b/queue-2.6.32/ext3-don-t-update-the-superblock-in-ext3_statfs.patch
new file mode 100644 (file)
index 0000000..dc5bf62
--- /dev/null
@@ -0,0 +1,48 @@
+From b918397542388de75bd86c32fbfa820e5d629fa9 Mon Sep 17 00:00:00 2001
+From: Eric Sandeen <sandeen@redhat.com>
+Date: Mon, 16 Nov 2009 16:34:51 -0600
+Subject: ext3: Don't update the superblock in ext3_statfs()
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+commit b918397542388de75bd86c32fbfa820e5d629fa9 upstream.
+
+commit a71ce8c6c9bf269b192f352ea555217815cf027e updated ext3_statfs()
+to update the on-disk superblock counters, but modified this buffer
+directly without any journaling of the change.  This is one of the
+accesses that was causing the crc errors in journal replay as seen in
+kernel.org bugzilla #14354.
+
+The modifications were originally to keep the sb "more" in sync,
+so that a readonly fsck of the device didn't flag this as an
+error (as often), but apparently e2fsprogs deals with this differently
+now, anyway.
+
+Based on Ted's patch for ext4, which was in turn based on my
+work on that bug and another preliminary patch...
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Cc: maximilian attems <max@stro.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ext3/super.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -2686,13 +2686,11 @@ static int ext3_statfs (struct dentry *
+       buf->f_bsize = sb->s_blocksize;
+       buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
+       buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
+-      es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
+       buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
+       if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
+               buf->f_bavail = 0;
+       buf->f_files = le32_to_cpu(es->s_inodes_count);
+       buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
+-      es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
+       buf->f_namelen = EXT3_NAME_LEN;
+       fsid = le64_to_cpup((void *)es->s_uuid) ^
+              le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/queue-2.6.32/ext3-journal-all-modifications-in-ext3_xattr_set_handle.patch b/queue-2.6.32/ext3-journal-all-modifications-in-ext3_xattr_set_handle.patch
new file mode 100644 (file)
index 0000000..5e82600
--- /dev/null
@@ -0,0 +1,49 @@
+From d965736b8cb42ae51ba9c3f13488035a98d025c6 Mon Sep 17 00:00:00 2001
+From: Eric Sandeen <sandeen@redhat.com>
+Date: Mon, 16 Nov 2009 16:27:30 -0600
+Subject: ext3: journal all modifications in ext3_xattr_set_handle
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+commit d965736b8cb42ae51ba9c3f13488035a98d025c6 upstream.
+
+ext3_xattr_set_handle() was zeroing out an inode outside
+of journaling constraints; this is one of the accesses that
+was causing the crc errors in journal replay as seen in
+kernel.org bugzilla #14354.
+
+Although ext3 doesn't have the crc issue, modifications
+out of journal control are a Bad Thing.
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Cc: maximilian attems <max@stro.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ext3/xattr.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/fs/ext3/xattr.c
++++ b/fs/ext3/xattr.c
+@@ -960,6 +960,10 @@ ext3_xattr_set_handle(handle_t *handle,
+       if (error)
+               goto cleanup;
++      error = ext3_journal_get_write_access(handle, is.iloc.bh);
++      if (error)
++              goto cleanup;
++
+       if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
+               struct ext3_inode *raw_inode = ext3_raw_inode(&is.iloc);
+               memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size);
+@@ -985,9 +989,6 @@ ext3_xattr_set_handle(handle_t *handle,
+               if (flags & XATTR_CREATE)
+                       goto cleanup;
+       }
+-      error = ext3_journal_get_write_access(handle, is.iloc.bh);
+-      if (error)
+-              goto cleanup;
+       if (!value) {
+               if (!is.s.not_found)
+                       error = ext3_xattr_ibody_set(handle, inode, &i, &is);
diff --git a/queue-2.6.32/hid-fix-oops-in-gyration_event.patch b/queue-2.6.32/hid-fix-oops-in-gyration_event.patch
new file mode 100644 (file)
index 0000000..f92c7e5
--- /dev/null
@@ -0,0 +1,37 @@
+From d8e4ebf8b603bdcd091540e6b5bddf0dec10d516 Mon Sep 17 00:00:00 2001
+From: Jiri Kosina <jkosina@suse.cz>
+Date: Tue, 23 Mar 2010 16:32:37 +0100
+Subject: HID: fix oops in gyration_event()
+
+From: Jiri Kosina <jkosina@suse.cz>
+
+commit d8e4ebf8b603bdcd091540e6b5bddf0dec10d516 upstream.
+
+Fix oops caused by dereferencing field->hidinput in cases where
+the device hasn't been claimed by hid-input.
+
+Reported-by: Andreas Demmer <mail@andreas-demmer.de>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/hid/hid-gyration.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/hid-gyration.c
++++ b/drivers/hid/hid-gyration.c
+@@ -53,10 +53,13 @@ static int gyration_input_mapping(struct
+ static int gyration_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+ {
+-      struct input_dev *input = field->hidinput->input;
++
++      if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
++              return 0;
+       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+                       (usage->hid & 0xff) == 0x82) {
++              struct input_dev *input = field->hidinput->input;
+               input_event(input, usage->type, usage->code, 1);
+               input_sync(input);
+               input_event(input, usage->type, usage->code, 0);
diff --git a/queue-2.6.32/kvm-fix-segment-descriptor-loading.patch b/queue-2.6.32/kvm-fix-segment-descriptor-loading.patch
new file mode 100644 (file)
index 0000000..e11e758
--- /dev/null
@@ -0,0 +1,339 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:44:22 2010
+From: Gleb Natapov <gleb@redhat.com>
+Date: Fri, 19 Mar 2010 15:47:34 +0100
+Subject: KVM: Fix segment descriptor loading
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-7-git-send-email-stefan.bader@canonical.com>
+
+
+From: Gleb Natapov <gleb@redhat.com>
+
+commit c697518a861e6c43b92b848895f9926580ee63c3 upstream
+
+Add proper error and permission checking. This patch also change task
+switching code to load segment selectors before segment descriptors, like
+SDM requires, otherwise permission checking during segment descriptor
+loading will be incorrect.
+
+Signed-off-by: Gleb Natapov <gleb@redhat.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/include/asm/kvm_host.h |    3 
+ arch/x86/kvm/emulate.c          |   28 +-----
+ arch/x86/kvm/x86.c              |  173 ++++++++++++++++++++++++++++++++++------
+ 3 files changed, 158 insertions(+), 46 deletions(-)
+
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -602,8 +602,7 @@ int emulator_set_dr(struct x86_emulate_c
+                   unsigned long value);
+ void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
+-int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
+-                              int type_bits, int seg);
++int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg);
+ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason);
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -1396,7 +1396,7 @@ static int emulate_ret_far(struct x86_em
+       rc = emulate_pop(ctxt, ops, &cs, c->op_bytes);
+       if (rc)
+               return rc;
+-      rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, 1, VCPU_SREG_CS);
++      rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, VCPU_SREG_CS);
+       return rc;
+ }
+@@ -1992,12 +1992,11 @@ special_insn:
+               break;
+       case 0x8e: { /* mov seg, r/m16 */
+               uint16_t sel;
+-              int type_bits;
+-              int err;
+               sel = c->src.val;
+-              if (c->modrm_reg == VCPU_SREG_CS) {
++              if (c->modrm_reg == VCPU_SREG_CS ||
++                  c->modrm_reg > VCPU_SREG_GS) {
+                       kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+                       goto done;
+               }
+@@ -2005,18 +2004,7 @@ special_insn:
+               if (c->modrm_reg == VCPU_SREG_SS)
+                       toggle_interruptibility(ctxt, X86_SHADOW_INT_MOV_SS);
+-              if (c->modrm_reg <= 5) {
+-                      type_bits = (c->modrm_reg == 1) ? 9 : 1;
+-                      err = kvm_load_segment_descriptor(ctxt->vcpu, sel,
+-                                                        type_bits, c->modrm_reg);
+-              } else {
+-                      printk(KERN_INFO "Invalid segreg in modrm byte 0x%02x\n",
+-                                      c->modrm);
+-                      goto cannot_emulate;
+-              }
+-
+-              if (err < 0)
+-                      goto cannot_emulate;
++              rc = kvm_load_segment_descriptor(ctxt->vcpu, sel, c->modrm_reg);
+               c->dst.type = OP_NONE;  /* Disable writeback. */
+               break;
+@@ -2186,11 +2174,9 @@ special_insn:
+       case 0xe9: /* jmp rel */
+               goto jmp;
+       case 0xea: /* jmp far */
+-              if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val, 9,
+-                                      VCPU_SREG_CS) < 0) {
+-                      DPRINTF("jmp far: Failed to load CS descriptor\n");
+-                      goto cannot_emulate;
+-              }
++              if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val,
++                                              VCPU_SREG_CS))
++                      goto done;
+               c->eip = c->src.val;
+               break;
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -4207,7 +4207,7 @@ static int kvm_load_realmode_segment(str
+               .unusable = 0,
+       };
+       kvm_x86_ops->set_segment(vcpu, &segvar, seg);
+-      return 0;
++      return X86EMUL_CONTINUE;
+ }
+ static int is_vm86_segment(struct kvm_vcpu *vcpu, int seg)
+@@ -4217,24 +4217,113 @@ static int is_vm86_segment(struct kvm_vc
+               (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_VM);
+ }
+-int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
+-                              int type_bits, int seg)
++int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg)
+ {
+       struct kvm_segment kvm_seg;
++      struct desc_struct seg_desc;
++      u8 dpl, rpl, cpl;
++      unsigned err_vec = GP_VECTOR;
++      u32 err_code = 0;
++      bool null_selector = !(selector & ~0x3); /* 0000-0003 are null */
++      int ret;
+       if (is_vm86_segment(vcpu, seg) || !(vcpu->arch.cr0 & X86_CR0_PE))
+               return kvm_load_realmode_segment(vcpu, selector, seg);
+-      if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg))
+-              return 1;
+-      kvm_seg.type |= type_bits;
+-      if (seg != VCPU_SREG_SS && seg != VCPU_SREG_CS &&
+-          seg != VCPU_SREG_LDTR)
+-              if (!kvm_seg.s)
+-                      kvm_seg.unusable = 1;
++      /* NULL selector is not valid for TR, CS and SS */
++      if ((seg == VCPU_SREG_CS || seg == VCPU_SREG_SS || seg == VCPU_SREG_TR)
++          && null_selector)
++              goto exception;
++
++      /* TR should be in GDT only */
++      if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
++              goto exception;
++
++      ret = load_guest_segment_descriptor(vcpu, selector, &seg_desc);
++      if (ret)
++              return ret;
++
++      seg_desct_to_kvm_desct(&seg_desc, selector, &kvm_seg);
++
++      if (null_selector) { /* for NULL selector skip all following checks */
++              kvm_seg.unusable = 1;
++              goto load;
++      }
++
++      err_code = selector & 0xfffc;
++      err_vec = GP_VECTOR;
++
++      /* can't load system descriptor into segment selecor */
++      if (seg <= VCPU_SREG_GS && !kvm_seg.s)
++              goto exception;
++
++      if (!kvm_seg.present) {
++              err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR;
++              goto exception;
++      }
++
++      rpl = selector & 3;
++      dpl = kvm_seg.dpl;
++      cpl = kvm_x86_ops->get_cpl(vcpu);
++
++      switch (seg) {
++      case VCPU_SREG_SS:
++              /*
++               * segment is not a writable data segment or segment
++               * selector's RPL != CPL or segment selector's RPL != CPL
++               */
++              if (rpl != cpl || (kvm_seg.type & 0xa) != 0x2 || dpl != cpl)
++                      goto exception;
++              break;
++      case VCPU_SREG_CS:
++              if (!(kvm_seg.type & 8))
++                      goto exception;
++
++              if (kvm_seg.type & 4) {
++                      /* conforming */
++                      if (dpl > cpl)
++                              goto exception;
++              } else {
++                      /* nonconforming */
++                      if (rpl > cpl || dpl != cpl)
++                              goto exception;
++              }
++              /* CS(RPL) <- CPL */
++              selector = (selector & 0xfffc) | cpl;
++              break;
++      case VCPU_SREG_TR:
++              if (kvm_seg.s || (kvm_seg.type != 1 && kvm_seg.type != 9))
++                      goto exception;
++              break;
++      case VCPU_SREG_LDTR:
++              if (kvm_seg.s || kvm_seg.type != 2)
++                      goto exception;
++              break;
++      default: /*  DS, ES, FS, or GS */
++              /*
++               * segment is not a data or readable code segment or
++               * ((segment is a data or nonconforming code segment)
++               * and (both RPL and CPL > DPL))
++               */
++              if ((kvm_seg.type & 0xa) == 0x8 ||
++                  (((kvm_seg.type & 0xc) != 0xc) && (rpl > dpl && cpl > dpl)))
++                      goto exception;
++              break;
++      }
++
++      if (!kvm_seg.unusable && kvm_seg.s) {
++              /* mark segment as accessed */
++              kvm_seg.type |= 1;
++              seg_desc.type |= 1;
++              save_guest_segment_descriptor(vcpu, selector, &seg_desc);
++      }
++load:
+       kvm_set_segment(vcpu, &kvm_seg, seg);
+-      return 0;
++      return X86EMUL_CONTINUE;
++exception:
++      kvm_queue_exception_e(vcpu, err_vec, err_code);
++      return X86EMUL_PROPAGATE_FAULT;
+ }
+ static void save_state_to_tss32(struct kvm_vcpu *vcpu,
+@@ -4260,6 +4349,14 @@ static void save_state_to_tss32(struct k
+       tss->ldt_selector = get_segment_selector(vcpu, VCPU_SREG_LDTR);
+ }
++static void kvm_load_segment_selector(struct kvm_vcpu *vcpu, u16 sel, int seg)
++{
++      struct kvm_segment kvm_seg;
++      kvm_get_segment(vcpu, &kvm_seg, seg);
++      kvm_seg.selector = sel;
++      kvm_set_segment(vcpu, &kvm_seg, seg);
++}
++
+ static int load_state_from_tss32(struct kvm_vcpu *vcpu,
+                                 struct tss_segment_32 *tss)
+ {
+@@ -4277,25 +4374,41 @@ static int load_state_from_tss32(struct
+       kvm_register_write(vcpu, VCPU_REGS_RSI, tss->esi);
+       kvm_register_write(vcpu, VCPU_REGS_RDI, tss->edi);
+-      if (kvm_load_segment_descriptor(vcpu, tss->ldt_selector, 0, VCPU_SREG_LDTR))
++      /*
++       * SDM says that segment selectors are loaded before segment
++       * descriptors
++       */
++      kvm_load_segment_selector(vcpu, tss->ldt_selector, VCPU_SREG_LDTR);
++      kvm_load_segment_selector(vcpu, tss->es, VCPU_SREG_ES);
++      kvm_load_segment_selector(vcpu, tss->cs, VCPU_SREG_CS);
++      kvm_load_segment_selector(vcpu, tss->ss, VCPU_SREG_SS);
++      kvm_load_segment_selector(vcpu, tss->ds, VCPU_SREG_DS);
++      kvm_load_segment_selector(vcpu, tss->fs, VCPU_SREG_FS);
++      kvm_load_segment_selector(vcpu, tss->gs, VCPU_SREG_GS);
++
++      /*
++       * Now load segment descriptors. If fault happenes at this stage
++       * it is handled in a context of new task
++       */
++      if (kvm_load_segment_descriptor(vcpu, tss->ldt_selector, VCPU_SREG_LDTR))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
++      if (kvm_load_segment_descriptor(vcpu, tss->es, VCPU_SREG_ES))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
++      if (kvm_load_segment_descriptor(vcpu, tss->cs, VCPU_SREG_CS))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
++      if (kvm_load_segment_descriptor(vcpu, tss->ss, VCPU_SREG_SS))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
++      if (kvm_load_segment_descriptor(vcpu, tss->ds, VCPU_SREG_DS))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->fs, 1, VCPU_SREG_FS))
++      if (kvm_load_segment_descriptor(vcpu, tss->fs, VCPU_SREG_FS))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->gs, 1, VCPU_SREG_GS))
++      if (kvm_load_segment_descriptor(vcpu, tss->gs, VCPU_SREG_GS))
+               return 1;
+       return 0;
+ }
+@@ -4336,19 +4449,33 @@ static int load_state_from_tss16(struct
+       kvm_register_write(vcpu, VCPU_REGS_RSI, tss->si);
+       kvm_register_write(vcpu, VCPU_REGS_RDI, tss->di);
+-      if (kvm_load_segment_descriptor(vcpu, tss->ldt, 0, VCPU_SREG_LDTR))
++      /*
++       * SDM says that segment selectors are loaded before segment
++       * descriptors
++       */
++      kvm_load_segment_selector(vcpu, tss->ldt, VCPU_SREG_LDTR);
++      kvm_load_segment_selector(vcpu, tss->es, VCPU_SREG_ES);
++      kvm_load_segment_selector(vcpu, tss->cs, VCPU_SREG_CS);
++      kvm_load_segment_selector(vcpu, tss->ss, VCPU_SREG_SS);
++      kvm_load_segment_selector(vcpu, tss->ds, VCPU_SREG_DS);
++
++      /*
++       * Now load segment descriptors. If fault happenes at this stage
++       * it is handled in a context of new task
++       */
++      if (kvm_load_segment_descriptor(vcpu, tss->ldt, VCPU_SREG_LDTR))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
++      if (kvm_load_segment_descriptor(vcpu, tss->es, VCPU_SREG_ES))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
++      if (kvm_load_segment_descriptor(vcpu, tss->cs, VCPU_SREG_CS))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
++      if (kvm_load_segment_descriptor(vcpu, tss->ss, VCPU_SREG_SS))
+               return 1;
+-      if (kvm_load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
++      if (kvm_load_segment_descriptor(vcpu, tss->ds, VCPU_SREG_DS))
+               return 1;
+       return 0;
+ }
diff --git a/queue-2.6.32/kvm-svm-reset-cr0-properly-on-vcpu-reset.patch b/queue-2.6.32/kvm-svm-reset-cr0-properly-on-vcpu-reset.patch
new file mode 100644 (file)
index 0000000..6d7f461
--- /dev/null
@@ -0,0 +1,55 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:47:43 2010
+From: Eduardo Habkost <ehabkost@redhat.com>
+Date: Fri, 19 Mar 2010 15:47:37 +0100
+Subject: KVM: SVM: Reset cr0 properly on vcpu reset
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-10-git-send-email-stefan.bader@canonical.com>
+
+
+From: Eduardo Habkost <ehabkost@redhat.com>
+
+commit 18fa000ae453767b59ab97477925895a3f0c46ea upstream
+
+svm_vcpu_reset() was not properly resetting the contents of the guest-visible
+cr0 register, causing the following issue:
+https://bugzilla.redhat.com/show_bug.cgi?id=525699
+
+Without resetting cr0 properly, the vcpu was running the SIPI bootstrap routine
+with paging enabled, making the vcpu get a pagefault exception while trying to
+run it.
+
+Instead of setting vmcb->save.cr0 directly, the new code just resets
+kvm->arch.cr0 and calls kvm_set_cr0(). The bits that were set/cleared on
+vmcb->save.cr0 (PG, WP, !CD, !NW) will be set properly by svm_set_cr0().
+
+kvm_set_cr0() is used instead of calling svm_set_cr0() directly to make sure
+kvm_mmu_reset_context() is called to reset the mmu to nonpaging mode.
+
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/kvm/svm.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -625,11 +625,12 @@ static void init_vmcb(struct vcpu_svm *s
+       save->rip = 0x0000fff0;
+       svm->vcpu.arch.regs[VCPU_REGS_RIP] = save->rip;
+-      /*
+-       * cr0 val on cpu init should be 0x60000010, we enable cpu
+-       * cache by default. the orderly way is to enable cache in bios.
++      /* This is the guest-visible cr0 value.
++       * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0.
+        */
+-      save->cr0 = 0x00000010 | X86_CR0_PG | X86_CR0_WP;
++      svm->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
++      kvm_set_cr0(&svm->vcpu, svm->vcpu.arch.cr0);
++
+       save->cr4 = X86_CR4_PAE;
+       /* rdx = ?? */
diff --git a/queue-2.6.32/kvm-vmx-disable-unrestricted-guest-when-ept-disabled.patch b/queue-2.6.32/kvm-vmx-disable-unrestricted-guest-when-ept-disabled.patch
new file mode 100644 (file)
index 0000000..ec9d8c5
--- /dev/null
@@ -0,0 +1,38 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:48:04 2010
+From: Sheng Yang <sheng@linux.intel.com>
+Date: Fri, 19 Mar 2010 15:47:38 +0100
+Subject: KVM: VMX: Disable unrestricted guest when EPT disabled
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-11-git-send-email-stefan.bader@canonical.com>
+
+
+From: Sheng Yang <sheng@linux.intel.com>
+
+commit 046d87103addc117f0d397196e85189722d4d7de upstream
+
+Otherwise would cause VMEntry failure when using ept=0 on unrestricted guest
+supported processors.
+
+Signed-off-by: Sheng Yang <sheng@linux.intel.com>
+Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/kvm/vmx.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -2302,8 +2302,10 @@ static int vmx_vcpu_setup(struct vcpu_vm
+                               ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+               if (vmx->vpid == 0)
+                       exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
+-              if (!enable_ept)
++              if (!enable_ept) {
+                       exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
++                      enable_unrestricted_guest = 0;
++              }
+               if (!enable_unrestricted_guest)
+                       exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
+               vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
diff --git a/queue-2.6.32/kvm-vmx-update-instruction-length-on-intercepted-bp.patch b/queue-2.6.32/kvm-vmx-update-instruction-length-on-intercepted-bp.patch
new file mode 100644 (file)
index 0000000..2df3d05
--- /dev/null
@@ -0,0 +1,56 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:44:45 2010
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Fri, 19 Mar 2010 15:47:35 +0100
+Subject: KVM: VMX: Update instruction length on intercepted BP
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-8-git-send-email-stefan.bader@canonical.com>
+
+
+From: Jan Kiszka <jan.kiszka@siemens.com>
+
+commit c573cd22939e54fc1b8e672054a505048987a7cb upstream
+
+We intercept #BP while in guest debugging mode. As VM exits due to
+intercepted exceptions do not necessarily come with valid
+idt_vectoring, we have to update event_exit_inst_len explicitly in such
+cases. At least in the absence of migration, this ensures that
+re-injections of #BP will find and use the correct instruction length.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/kvm/vmx.c |   13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -2674,6 +2674,12 @@ static int handle_rmode_exception(struct
+               kvm_queue_exception(vcpu, vec);
+               return 1;
+       case BP_VECTOR:
++              /*
++               * Update instruction length as we may reinject the exception
++               * from user space while in guest debugging mode.
++               */
++              to_vmx(vcpu)->vcpu.arch.event_exit_inst_len =
++                      vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+               if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
+                       return 0;
+               /* fall through */
+@@ -2790,6 +2796,13 @@ static int handle_exception(struct kvm_v
+               kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7);
+               /* fall through */
+       case BP_VECTOR:
++              /*
++               * Update instruction length as we may reinject #BP from
++               * user space while in guest debugging mode. Reading it for
++               * #DB as well causes no harm, it is not used in that case.
++               */
++              vmx->vcpu.arch.event_exit_inst_len =
++                      vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+               kvm_run->exit_reason = KVM_EXIT_DEBUG;
+               kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
+               kvm_run->debug.arch.exception = ex_no;
diff --git a/queue-2.6.32/kvm-vmx-use-macros-instead-of-hex-value-on-cr0-initialization.patch b/queue-2.6.32/kvm-vmx-use-macros-instead-of-hex-value-on-cr0-initialization.patch
new file mode 100644 (file)
index 0000000..b6980ea
--- /dev/null
@@ -0,0 +1,34 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:47:24 2010
+From: Eduardo Habkost <ehabkost@redhat.com>
+Date: Fri, 19 Mar 2010 15:47:36 +0100
+Subject: KVM: VMX: Use macros instead of hex value on cr0 initialization
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-9-git-send-email-stefan.bader@canonical.com>
+
+
+From: Eduardo Habkost <ehabkost@redhat.com>
+
+commit fa40052ca04bdbbeb20b839cc8ffe9fa7beefbe9 upstream
+
+This should have no effect, it is just to make the code clearer.
+
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/kvm/vmx.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -2510,7 +2510,7 @@ static int vmx_vcpu_reset(struct kvm_vcp
+       if (vmx->vpid != 0)
+               vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
+-      vmx->vcpu.arch.cr0 = 0x60000010;
++      vmx->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
+       vmx_set_cr0(&vmx->vcpu, vmx->vcpu.arch.cr0); /* enter rmode */
+       vmx_set_cr4(&vmx->vcpu, 0);
+       vmx_set_efer(&vmx->vcpu, 0);
diff --git a/queue-2.6.32/kvm-x86-disable-paravirt-mmu-reporting.patch b/queue-2.6.32/kvm-x86-disable-paravirt-mmu-reporting.patch
new file mode 100644 (file)
index 0000000..b1f10dd
--- /dev/null
@@ -0,0 +1,40 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:48:33 2010
+From: Marcelo Tosatti <mtosatti@redhat.com>
+Date: Fri, 19 Mar 2010 15:47:39 +0100
+Subject: KVM: x86: disable paravirt mmu reporting
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-12-git-send-email-stefan.bader@canonical.com>
+
+
+From: Marcelo Tosatti <mtosatti@redhat.com>
+
+commit a68a6a7282373bedba8a2ed751b6384edb983a64 upstream
+
+Disable paravirt MMU capability reporting, so that new (or rebooted)
+guests switch to native operation.
+
+Paravirt MMU is a burden to maintain and does not bring significant
+advantages compared to shadow anymore.
+
+Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/kvm/x86.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -1242,8 +1242,8 @@ int kvm_dev_ioctl_check_extension(long e
+       case KVM_CAP_NR_MEMSLOTS:
+               r = KVM_MEMORY_SLOTS;
+               break;
+-      case KVM_CAP_PV_MMU:
+-              r = !tdp_enabled;
++      case KVM_CAP_PV_MMU:    /* obsolete */
++              r = 0;
+               break;
+       case KVM_CAP_IOMMU:
+               r = iommu_found();
diff --git a/queue-2.6.32/kvm-x86-emulator-add-virtual-8086-mode-of-emulation.patch b/queue-2.6.32/kvm-x86-emulator-add-virtual-8086-mode-of-emulation.patch
new file mode 100644 (file)
index 0000000..e823869
--- /dev/null
@@ -0,0 +1,94 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:41:50 2010
+From: Gleb Natapov <gleb@redhat.com>
+Date: Fri, 19 Mar 2010 15:47:30 +0100
+Subject: KVM: x86 emulator: Add Virtual-8086 mode of emulation
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-3-git-send-email-stefan.bader@canonical.com>
+
+
+From: Gleb Natapov <gleb@redhat.com>
+
+commit a0044755679f3e761b8b95995e5f2db2b7efd0f6 upstream
+
+For some instructions CPU behaves differently for real-mode and
+virtual 8086. Let emulator know which mode cpu is in, so it will
+not poke into vcpu state directly.
+
+Signed-off-by: Gleb Natapov <gleb@redhat.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/include/asm/kvm_emulate.h |    1 +
+ arch/x86/kvm/emulate.c             |   14 +++++++-------
+ arch/x86/kvm/x86.c                 |    3 ++-
+ 3 files changed, 10 insertions(+), 8 deletions(-)
+
+--- a/arch/x86/include/asm/kvm_emulate.h
++++ b/arch/x86/include/asm/kvm_emulate.h
+@@ -168,6 +168,7 @@ struct x86_emulate_ctxt {
+ /* Execution mode, passed to the emulator. */
+ #define X86EMUL_MODE_REAL     0       /* Real mode.             */
++#define X86EMUL_MODE_VM86     1       /* Virtual 8086 mode.     */
+ #define X86EMUL_MODE_PROT16   2       /* 16-bit protected mode. */
+ #define X86EMUL_MODE_PROT32   4       /* 32-bit protected mode. */
+ #define X86EMUL_MODE_PROT64   8       /* 64-bit (long) mode.    */
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -895,6 +895,7 @@ x86_decode_insn(struct x86_emulate_ctxt
+       switch (mode) {
+       case X86EMUL_MODE_REAL:
++      case X86EMUL_MODE_VM86:
+       case X86EMUL_MODE_PROT16:
+               def_op_bytes = def_ad_bytes = 2;
+               break;
+@@ -1453,7 +1454,7 @@ emulate_syscall(struct x86_emulate_ctxt
+       /* syscall is not available in real mode */
+       if (c->lock_prefix || ctxt->mode == X86EMUL_MODE_REAL
+-              || !(ctxt->vcpu->arch.cr0 & X86_CR0_PE))
++          || ctxt->mode == X86EMUL_MODE_VM86)
+               return -1;
+       setup_syscalls_segments(ctxt, &cs, &ss);
+@@ -1505,9 +1506,8 @@ emulate_sysenter(struct x86_emulate_ctxt
+       if (c->lock_prefix)
+               return -1;
+-      /* inject #GP if in real mode or paging is disabled */
+-      if (ctxt->mode == X86EMUL_MODE_REAL ||
+-              !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) {
++      /* inject #GP if in real mode */
++      if (ctxt->mode == X86EMUL_MODE_REAL) {
+               kvm_inject_gp(ctxt->vcpu, 0);
+               return -1;
+       }
+@@ -1571,9 +1571,9 @@ emulate_sysexit(struct x86_emulate_ctxt
+       if (c->lock_prefix)
+               return -1;
+-      /* inject #GP if in real mode or paging is disabled */
+-      if (ctxt->mode == X86EMUL_MODE_REAL
+-              || !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) {
++      /* inject #GP if in real mode or Virtual 8086 mode */
++      if (ctxt->mode == X86EMUL_MODE_REAL ||
++          ctxt->mode == X86EMUL_MODE_VM86) {
+               kvm_inject_gp(ctxt->vcpu, 0);
+               return -1;
+       }
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2828,8 +2828,9 @@ int emulate_instruction(struct kvm_vcpu
+               vcpu->arch.emulate_ctxt.vcpu = vcpu;
+               vcpu->arch.emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu);
+               vcpu->arch.emulate_ctxt.mode =
++                      (!(vcpu->arch.cr0 & X86_CR0_PE)) ? X86EMUL_MODE_REAL :
+                       (vcpu->arch.emulate_ctxt.eflags & X86_EFLAGS_VM)
+-                      ? X86EMUL_MODE_REAL : cs_l
++                      ? X86EMUL_MODE_VM86 : cs_l
+                       ? X86EMUL_MODE_PROT64 : cs_db
+                       ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
diff --git a/queue-2.6.32/kvm-x86-emulator-check-iopl-level-during-io-instruction-emulation.patch b/queue-2.6.32/kvm-x86-emulator-check-iopl-level-during-io-instruction-emulation.patch
new file mode 100644 (file)
index 0000000..e474656
--- /dev/null
@@ -0,0 +1,204 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:42:27 2010
+From: Gleb Natapov <gleb@redhat.com>
+Date: Fri, 19 Mar 2010 15:47:32 +0100
+Subject: KVM: x86 emulator: Check IOPL level during io instruction emulation
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-5-git-send-email-stefan.bader@canonical.com>
+
+
+From: Gleb Natapov <gleb@redhat.com>
+
+commit f850e2e603bf5a05b0aee7901857cf85715aa694 upstream
+
+Make emulator check that vcpu is allowed to execute IN, INS, OUT,
+OUTS, CLI, STI.
+
+Signed-off-by: Gleb Natapov <gleb@redhat.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/include/asm/kvm_host.h |    1 
+ arch/x86/kvm/emulate.c          |   89 ++++++++++++++++++++++++++++++++++++----
+ arch/x86/kvm/x86.c              |   10 +---
+ 3 files changed, 87 insertions(+), 13 deletions(-)
+
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -663,6 +663,7 @@ void kvm_disable_tdp(void);
+ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
+ int complete_pio(struct kvm_vcpu *vcpu);
++bool kvm_check_iopl(struct kvm_vcpu *vcpu);
+ struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn);
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -1620,6 +1620,57 @@ emulate_sysexit(struct x86_emulate_ctxt
+       return 0;
+ }
++static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt)
++{
++      int iopl;
++      if (ctxt->mode == X86EMUL_MODE_REAL)
++              return false;
++      if (ctxt->mode == X86EMUL_MODE_VM86)
++              return true;
++      iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
++      return kvm_x86_ops->get_cpl(ctxt->vcpu) > iopl;
++}
++
++static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
++                                          struct x86_emulate_ops *ops,
++                                          u16 port, u16 len)
++{
++      struct kvm_segment tr_seg;
++      int r;
++      u16 io_bitmap_ptr;
++      u8 perm, bit_idx = port & 0x7;
++      unsigned mask = (1 << len) - 1;
++
++      kvm_get_segment(ctxt->vcpu, &tr_seg, VCPU_SREG_TR);
++      if (tr_seg.unusable)
++              return false;
++      if (tr_seg.limit < 103)
++              return false;
++      r = ops->read_std(tr_seg.base + 102, &io_bitmap_ptr, 2, ctxt->vcpu,
++                        NULL);
++      if (r != X86EMUL_CONTINUE)
++              return false;
++      if (io_bitmap_ptr + port/8 > tr_seg.limit)
++              return false;
++      r = ops->read_std(tr_seg.base + io_bitmap_ptr + port/8, &perm, 1,
++                        ctxt->vcpu, NULL);
++      if (r != X86EMUL_CONTINUE)
++              return false;
++      if ((perm >> bit_idx) & mask)
++              return false;
++      return true;
++}
++
++static bool emulator_io_permited(struct x86_emulate_ctxt *ctxt,
++                               struct x86_emulate_ops *ops,
++                               u16 port, u16 len)
++{
++      if (emulator_bad_iopl(ctxt))
++              if (!emulator_io_port_access_allowed(ctxt, ops, port, len))
++                      return false;
++      return true;
++}
++
+ int
+ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+ {
+@@ -1779,7 +1830,12 @@ special_insn:
+               break;
+       case 0x6c:              /* insb */
+       case 0x6d:              /* insw/insd */
+-               if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
++              if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX],
++                                        (c->d & ByteOp) ? 1 : c->op_bytes)) {
++                      kvm_inject_gp(ctxt->vcpu, 0);
++                      goto done;
++              }
++              if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
+                               1,
+                               (c->d & ByteOp) ? 1 : c->op_bytes,
+                               c->rep_prefix ?
+@@ -1795,6 +1851,11 @@ special_insn:
+               return 0;
+       case 0x6e:              /* outsb */
+       case 0x6f:              /* outsw/outsd */
++              if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX],
++                                        (c->d & ByteOp) ? 1 : c->op_bytes)) {
++                      kvm_inject_gp(ctxt->vcpu, 0);
++                      goto done;
++              }
+               if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
+                               0,
+                               (c->d & ByteOp) ? 1 : c->op_bytes,
+@@ -2094,7 +2155,13 @@ special_insn:
+       case 0xef: /* out (e/r)ax,dx */
+               port = c->regs[VCPU_REGS_RDX];
+               io_dir_in = 0;
+-      do_io:  if (kvm_emulate_pio(ctxt->vcpu, NULL, io_dir_in,
++      do_io:
++              if (!emulator_io_permited(ctxt, ops, port,
++                                        (c->d & ByteOp) ? 1 : c->op_bytes)) {
++                      kvm_inject_gp(ctxt->vcpu, 0);
++                      goto done;
++              }
++              if (kvm_emulate_pio(ctxt->vcpu, NULL, io_dir_in,
+                                  (c->d & ByteOp) ? 1 : c->op_bytes,
+                                  port) != 0) {
+                       c->eip = saved_eip;
+@@ -2119,13 +2186,21 @@ special_insn:
+               c->dst.type = OP_NONE;  /* Disable writeback. */
+               break;
+       case 0xfa: /* cli */
+-              ctxt->eflags &= ~X86_EFLAGS_IF;
+-              c->dst.type = OP_NONE;  /* Disable writeback. */
++              if (emulator_bad_iopl(ctxt))
++                      kvm_inject_gp(ctxt->vcpu, 0);
++              else {
++                      ctxt->eflags &= ~X86_EFLAGS_IF;
++                      c->dst.type = OP_NONE;  /* Disable writeback. */
++              }
+               break;
+       case 0xfb: /* sti */
+-              toggle_interruptibility(ctxt, X86_SHADOW_INT_STI);
+-              ctxt->eflags |= X86_EFLAGS_IF;
+-              c->dst.type = OP_NONE;  /* Disable writeback. */
++              if (emulator_bad_iopl(ctxt))
++                      kvm_inject_gp(ctxt->vcpu, 0);
++              else {
++                      toggle_interruptibility(ctxt, X86_SHADOW_INT_STI);
++                      ctxt->eflags |= X86_EFLAGS_IF;
++                      c->dst.type = OP_NONE;  /* Disable writeback. */
++              }
+               break;
+       case 0xfc: /* cld */
+               ctxt->eflags &= ~EFLG_DF;
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -3079,6 +3079,8 @@ int kvm_emulate_pio(struct kvm_vcpu *vcp
+ {
+       unsigned long val;
++      trace_kvm_pio(!in, port, size, 1);
++
+       vcpu->run->exit_reason = KVM_EXIT_IO;
+       vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
+       vcpu->run->io.size = vcpu->arch.pio.size = size;
+@@ -3090,9 +3092,6 @@ int kvm_emulate_pio(struct kvm_vcpu *vcp
+       vcpu->arch.pio.down = 0;
+       vcpu->arch.pio.rep = 0;
+-      trace_kvm_pio(vcpu->run->io.direction == KVM_EXIT_IO_OUT, port,
+-                    size, 1);
+-
+       val = kvm_register_read(vcpu, VCPU_REGS_RAX);
+       memcpy(vcpu->arch.pio_data, &val, 4);
+@@ -3111,6 +3110,8 @@ int kvm_emulate_pio_string(struct kvm_vc
+       unsigned now, in_page;
+       int ret = 0;
++      trace_kvm_pio(!in, port, size, count);
++
+       vcpu->run->exit_reason = KVM_EXIT_IO;
+       vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
+       vcpu->run->io.size = vcpu->arch.pio.size = size;
+@@ -3122,9 +3123,6 @@ int kvm_emulate_pio_string(struct kvm_vc
+       vcpu->arch.pio.down = down;
+       vcpu->arch.pio.rep = rep;
+-      trace_kvm_pio(vcpu->run->io.direction == KVM_EXIT_IO_OUT, port,
+-                    size, count);
+-
+       if (!count) {
+               kvm_x86_ops->skip_emulated_instruction(vcpu);
+               return 1;
diff --git a/queue-2.6.32/kvm-x86-emulator-fix-memory-access-during-x86-emulation.patch b/queue-2.6.32/kvm-x86-emulator-fix-memory-access-during-x86-emulation.patch
new file mode 100644 (file)
index 0000000..7bb6c34
--- /dev/null
@@ -0,0 +1,512 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:42:11 2010
+From: Gleb Natapov <gleb@redhat.com>
+Date: Fri, 19 Mar 2010 15:47:31 +0100
+Subject: KVM: x86 emulator: fix memory access during x86 emulation
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-4-git-send-email-stefan.bader@canonical.com>
+
+
+From: Gleb Natapov <gleb@redhat.com>
+
+commit 1871c6020d7308afb99127bba51f04548e7ca84e upstream
+
+Currently when x86 emulator needs to access memory, page walk is done with
+broadest permission possible, so if emulated instruction was executed
+by userspace process it can still access kernel memory. Fix that by
+providing correct memory access to page walker during emulation.
+
+Signed-off-by: Gleb Natapov <gleb@redhat.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/include/asm/kvm_emulate.h |   14 +++
+ arch/x86/include/asm/kvm_host.h    |    7 +
+ arch/x86/kvm/emulate.c             |    6 -
+ arch/x86/kvm/mmu.c                 |   17 +---
+ arch/x86/kvm/mmu.h                 |    6 +
+ arch/x86/kvm/paging_tmpl.h         |   11 ++-
+ arch/x86/kvm/x86.c                 |  131 ++++++++++++++++++++++++++++---------
+ 7 files changed, 142 insertions(+), 50 deletions(-)
+
+--- a/arch/x86/include/asm/kvm_emulate.h
++++ b/arch/x86/include/asm/kvm_emulate.h
+@@ -54,13 +54,23 @@ struct x86_emulate_ctxt;
+ struct x86_emulate_ops {
+       /*
+        * read_std: Read bytes of standard (non-emulated/special) memory.
+-       *           Used for instruction fetch, stack operations, and others.
++       *           Used for descriptor reading.
+        *  @addr:  [IN ] Linear address from which to read.
+        *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
+        *  @bytes: [IN ] Number of bytes to read from memory.
+        */
+       int (*read_std)(unsigned long addr, void *val,
+-                      unsigned int bytes, struct kvm_vcpu *vcpu);
++                      unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error);
++
++      /*
++       * fetch: Read bytes of standard (non-emulated/special) memory.
++       *        Used for instruction fetch.
++       *  @addr:  [IN ] Linear address from which to read.
++       *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
++       *  @bytes: [IN ] Number of bytes to read from memory.
++       */
++      int (*fetch)(unsigned long addr, void *val,
++                      unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error);
+       /*
+        * read_emulated: Read bytes from emulated/special memory area.
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -256,7 +256,8 @@ struct kvm_mmu {
+       void (*new_cr3)(struct kvm_vcpu *vcpu);
+       int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
+       void (*free)(struct kvm_vcpu *vcpu);
+-      gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva);
++      gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
++                          u32 *error);
+       void (*prefetch_page)(struct kvm_vcpu *vcpu,
+                             struct kvm_mmu_page *page);
+       int (*sync_page)(struct kvm_vcpu *vcpu,
+@@ -645,6 +646,10 @@ void __kvm_mmu_free_some_pages(struct kv
+ int kvm_mmu_load(struct kvm_vcpu *vcpu);
+ void kvm_mmu_unload(struct kvm_vcpu *vcpu);
+ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
++gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
++gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
++gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
++gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
+ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -612,7 +612,7 @@ static int do_fetch_insn_byte(struct x86
+       if (linear < fc->start || linear >= fc->end) {
+               size = min(15UL, PAGE_SIZE - offset_in_page(linear));
+-              rc = ops->read_std(linear, fc->data, size, ctxt->vcpu);
++              rc = ops->fetch(linear, fc->data, size, ctxt->vcpu, NULL);
+               if (rc)
+                       return rc;
+               fc->start = linear;
+@@ -667,11 +667,11 @@ static int read_descriptor(struct x86_em
+               op_bytes = 3;
+       *address = 0;
+       rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2,
+-                         ctxt->vcpu);
++                         ctxt->vcpu, NULL);
+       if (rc)
+               return rc;
+       rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes,
+-                         ctxt->vcpu);
++                         ctxt->vcpu, NULL);
+       return rc;
+ }
+--- a/arch/x86/kvm/mmu.c
++++ b/arch/x86/kvm/mmu.c
+@@ -136,12 +136,6 @@ module_param(oos_shadow, bool, 0644);
+ #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK \
+                       | PT64_NX_MASK)
+-#define PFERR_PRESENT_MASK (1U << 0)
+-#define PFERR_WRITE_MASK (1U << 1)
+-#define PFERR_USER_MASK (1U << 2)
+-#define PFERR_RSVD_MASK (1U << 3)
+-#define PFERR_FETCH_MASK (1U << 4)
+-
+ #define PT_PDPE_LEVEL 3
+ #define PT_DIRECTORY_LEVEL 2
+ #define PT_PAGE_TABLE_LEVEL 1
+@@ -1639,7 +1633,7 @@ struct page *gva_to_page(struct kvm_vcpu
+ {
+       struct page *page;
+-      gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
++      gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL);
+       if (gpa == UNMAPPED_GVA)
+               return NULL;
+@@ -2162,8 +2156,11 @@ void kvm_mmu_sync_roots(struct kvm_vcpu
+       spin_unlock(&vcpu->kvm->mmu_lock);
+ }
+-static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
++static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr,
++                                u32 access, u32 *error)
+ {
++      if (error)
++              *error = 0;
+       return vaddr;
+ }
+@@ -2747,7 +2744,7 @@ int kvm_mmu_unprotect_page_virt(struct k
+       if (tdp_enabled)
+               return 0;
+-      gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
++      gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL);
+       spin_lock(&vcpu->kvm->mmu_lock);
+       r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT);
+@@ -3245,7 +3242,7 @@ static void audit_mappings_page(struct k
+               if (is_shadow_present_pte(ent) && !is_last_spte(ent, level))
+                       audit_mappings_page(vcpu, ent, va, level - 1);
+               else {
+-                      gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, va);
++                      gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, va, NULL);
+                       gfn_t gfn = gpa >> PAGE_SHIFT;
+                       pfn_t pfn = gfn_to_pfn(vcpu->kvm, gfn);
+                       hpa_t hpa = (hpa_t)pfn << PAGE_SHIFT;
+--- a/arch/x86/kvm/mmu.h
++++ b/arch/x86/kvm/mmu.h
+@@ -37,6 +37,12 @@
+ #define PT32_ROOT_LEVEL 2
+ #define PT32E_ROOT_LEVEL 3
++#define PFERR_PRESENT_MASK (1U << 0)
++#define PFERR_WRITE_MASK (1U << 1)
++#define PFERR_USER_MASK (1U << 2)
++#define PFERR_RSVD_MASK (1U << 3)
++#define PFERR_FETCH_MASK (1U << 4)
++
+ int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]);
+ static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
+--- a/arch/x86/kvm/paging_tmpl.h
++++ b/arch/x86/kvm/paging_tmpl.h
+@@ -491,18 +491,23 @@ static void FNAME(invlpg)(struct kvm_vcp
+       spin_unlock(&vcpu->kvm->mmu_lock);
+ }
+-static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
++static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr, u32 access,
++                             u32 *error)
+ {
+       struct guest_walker walker;
+       gpa_t gpa = UNMAPPED_GVA;
+       int r;
+-      r = FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
++      r = FNAME(walk_addr)(&walker, vcpu, vaddr,
++                           !!(access & PFERR_WRITE_MASK),
++                           !!(access & PFERR_USER_MASK),
++                           !!(access & PFERR_FETCH_MASK));
+       if (r) {
+               gpa = gfn_to_gpa(walker.gfn);
+               gpa |= vaddr & ~PAGE_MASK;
+-      }
++      } else if (error)
++              *error = walker.error_code;
+       return gpa;
+ }
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2505,14 +2505,41 @@ static int vcpu_mmio_read(struct kvm_vcp
+       return kvm_io_bus_read(&vcpu->kvm->mmio_bus, addr, len, v);
+ }
+-static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes,
+-                             struct kvm_vcpu *vcpu)
++gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
++{
++      u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
++      return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error);
++}
++
++ gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
++{
++      u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
++      access |= PFERR_FETCH_MASK;
++      return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error);
++}
++
++gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
++{
++      u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
++      access |= PFERR_WRITE_MASK;
++      return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error);
++}
++
++/* uses this to access any guest's mapped memory without checking CPL */
++gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
++{
++      return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, 0, error);
++}
++
++static int kvm_read_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
++                                    struct kvm_vcpu *vcpu, u32 access,
++                                    u32 *error)
+ {
+       void *data = val;
+       int r = X86EMUL_CONTINUE;
+       while (bytes) {
+-              gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
++              gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr, access, error);
+               unsigned offset = addr & (PAGE_SIZE-1);
+               unsigned toread = min(bytes, (unsigned)PAGE_SIZE - offset);
+               int ret;
+@@ -2535,14 +2562,37 @@ out:
+       return r;
+ }
++/* used for instruction fetching */
++static int kvm_fetch_guest_virt(gva_t addr, void *val, unsigned int bytes,
++                              struct kvm_vcpu *vcpu, u32 *error)
++{
++      u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
++      return kvm_read_guest_virt_helper(addr, val, bytes, vcpu,
++                                        access | PFERR_FETCH_MASK, error);
++}
++
++static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes,
++                             struct kvm_vcpu *vcpu, u32 *error)
++{
++      u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
++      return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
++                                        error);
++}
++
++static int kvm_read_guest_virt_system(gva_t addr, void *val, unsigned int bytes,
++                             struct kvm_vcpu *vcpu, u32 *error)
++{
++      return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, error);
++}
++
+ static int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes,
+-                              struct kvm_vcpu *vcpu)
++                              struct kvm_vcpu *vcpu, u32 *error)
+ {
+       void *data = val;
+       int r = X86EMUL_CONTINUE;
+       while (bytes) {
+-              gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
++              gpa_t gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error);
+               unsigned offset = addr & (PAGE_SIZE-1);
+               unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset);
+               int ret;
+@@ -2572,6 +2622,7 @@ static int emulator_read_emulated(unsign
+                                 struct kvm_vcpu *vcpu)
+ {
+       gpa_t                 gpa;
++      u32 error_code;
+       if (vcpu->mmio_read_completed) {
+               memcpy(val, vcpu->mmio_data, bytes);
+@@ -2581,17 +2632,20 @@ static int emulator_read_emulated(unsign
+               return X86EMUL_CONTINUE;
+       }
+-      gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
++      gpa = kvm_mmu_gva_to_gpa_read(vcpu, addr, &error_code);
++
++      if (gpa == UNMAPPED_GVA) {
++              kvm_inject_page_fault(vcpu, addr, error_code);
++              return X86EMUL_PROPAGATE_FAULT;
++      }
+       /* For APIC access vmexit */
+       if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
+               goto mmio;
+-      if (kvm_read_guest_virt(addr, val, bytes, vcpu)
++      if (kvm_read_guest_virt(addr, val, bytes, vcpu, NULL)
+                               == X86EMUL_CONTINUE)
+               return X86EMUL_CONTINUE;
+-      if (gpa == UNMAPPED_GVA)
+-              return X86EMUL_PROPAGATE_FAULT;
+ mmio:
+       /*
+@@ -2630,11 +2684,12 @@ static int emulator_write_emulated_onepa
+                                          struct kvm_vcpu *vcpu)
+ {
+       gpa_t                 gpa;
++      u32 error_code;
+-      gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
++      gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, &error_code);
+       if (gpa == UNMAPPED_GVA) {
+-              kvm_inject_page_fault(vcpu, addr, 2);
++              kvm_inject_page_fault(vcpu, addr, error_code);
+               return X86EMUL_PROPAGATE_FAULT;
+       }
+@@ -2698,7 +2753,7 @@ static int emulator_cmpxchg_emulated(uns
+               char *kaddr;
+               u64 val;
+-              gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
++              gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, NULL);
+               if (gpa == UNMAPPED_GVA ||
+                  (gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
+@@ -2777,7 +2832,7 @@ void kvm_report_emulation_failure(struct
+       rip_linear = rip + get_segment_base(vcpu, VCPU_SREG_CS);
+-      kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu);
++      kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu, NULL);
+       printk(KERN_ERR "emulation failed (%s) rip %lx %02x %02x %02x %02x\n",
+              context, rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]);
+@@ -2785,7 +2840,8 @@ void kvm_report_emulation_failure(struct
+ EXPORT_SYMBOL_GPL(kvm_report_emulation_failure);
+ static struct x86_emulate_ops emulate_ops = {
+-      .read_std            = kvm_read_guest_virt,
++      .read_std            = kvm_read_guest_virt_system,
++      .fetch               = kvm_fetch_guest_virt,
+       .read_emulated       = emulator_read_emulated,
+       .write_emulated      = emulator_write_emulated,
+       .cmpxchg_emulated    = emulator_cmpxchg_emulated,
+@@ -2922,12 +2978,17 @@ static int pio_copy_data(struct kvm_vcpu
+       gva_t q = vcpu->arch.pio.guest_gva;
+       unsigned bytes;
+       int ret;
++      u32 error_code;
+       bytes = vcpu->arch.pio.size * vcpu->arch.pio.cur_count;
+       if (vcpu->arch.pio.in)
+-              ret = kvm_write_guest_virt(q, p, bytes, vcpu);
++              ret = kvm_write_guest_virt(q, p, bytes, vcpu, &error_code);
+       else
+-              ret = kvm_read_guest_virt(q, p, bytes, vcpu);
++              ret = kvm_read_guest_virt(q, p, bytes, vcpu, &error_code);
++
++      if (ret == X86EMUL_PROPAGATE_FAULT)
++              kvm_inject_page_fault(vcpu, q, error_code);
++
+       return ret;
+ }
+@@ -2948,7 +3009,7 @@ int complete_pio(struct kvm_vcpu *vcpu)
+               if (io->in) {
+                       r = pio_copy_data(vcpu);
+                       if (r)
+-                              return r;
++                              goto out;
+               }
+               delta = 1;
+@@ -2975,7 +3036,7 @@ int complete_pio(struct kvm_vcpu *vcpu)
+                       kvm_register_write(vcpu, VCPU_REGS_RSI, val);
+               }
+       }
+-
++out:
+       io->count -= io->cur_count;
+       io->cur_count = 0;
+@@ -3095,10 +3156,8 @@ int kvm_emulate_pio_string(struct kvm_vc
+       if (!vcpu->arch.pio.in) {
+               /* string PIO write */
+               ret = pio_copy_data(vcpu);
+-              if (ret == X86EMUL_PROPAGATE_FAULT) {
+-                      kvm_inject_gp(vcpu, 0);
++              if (ret == X86EMUL_PROPAGATE_FAULT)
+                       return 1;
+-              }
+               if (ret == 0 && !pio_string_write(vcpu)) {
+                       complete_pio(vcpu);
+                       if (vcpu->arch.pio.count == 0)
+@@ -4078,7 +4137,9 @@ static int load_guest_segment_descriptor
+               kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc);
+               return 1;
+       }
+-      return kvm_read_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu);
++      return kvm_read_guest_virt_system(dtable.base + index*8,
++                                        seg_desc, sizeof(*seg_desc),
++                                        vcpu, NULL);
+ }
+ /* allowed just for 8 bytes segments */
+@@ -4092,15 +4153,23 @@ static int save_guest_segment_descriptor
+       if (dtable.limit < index * 8 + 7)
+               return 1;
+-      return kvm_write_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu);
++      return kvm_write_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu, NULL);
++}
++
++static gpa_t get_tss_base_addr_write(struct kvm_vcpu *vcpu,
++                             struct desc_struct *seg_desc)
++{
++      u32 base_addr = get_desc_base(seg_desc);
++
++      return kvm_mmu_gva_to_gpa_write(vcpu, base_addr, NULL);
+ }
+-static gpa_t get_tss_base_addr(struct kvm_vcpu *vcpu,
++static gpa_t get_tss_base_addr_read(struct kvm_vcpu *vcpu,
+                            struct desc_struct *seg_desc)
+ {
+       u32 base_addr = get_desc_base(seg_desc);
+-      return vcpu->arch.mmu.gva_to_gpa(vcpu, base_addr);
++      return kvm_mmu_gva_to_gpa_read(vcpu, base_addr, NULL);
+ }
+ static u16 get_segment_selector(struct kvm_vcpu *vcpu, int seg)
+@@ -4303,7 +4372,7 @@ static int kvm_task_switch_16(struct kvm
+                           sizeof tss_segment_16))
+               goto out;
+-      if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
++      if (kvm_read_guest(vcpu->kvm, get_tss_base_addr_read(vcpu, nseg_desc),
+                          &tss_segment_16, sizeof tss_segment_16))
+               goto out;
+@@ -4311,7 +4380,7 @@ static int kvm_task_switch_16(struct kvm
+               tss_segment_16.prev_task_link = old_tss_sel;
+               if (kvm_write_guest(vcpu->kvm,
+-                                  get_tss_base_addr(vcpu, nseg_desc),
++                                  get_tss_base_addr_write(vcpu, nseg_desc),
+                                   &tss_segment_16.prev_task_link,
+                                   sizeof tss_segment_16.prev_task_link))
+                       goto out;
+@@ -4342,7 +4411,7 @@ static int kvm_task_switch_32(struct kvm
+                           sizeof tss_segment_32))
+               goto out;
+-      if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
++      if (kvm_read_guest(vcpu->kvm, get_tss_base_addr_read(vcpu, nseg_desc),
+                          &tss_segment_32, sizeof tss_segment_32))
+               goto out;
+@@ -4350,7 +4419,7 @@ static int kvm_task_switch_32(struct kvm
+               tss_segment_32.prev_task_link = old_tss_sel;
+               if (kvm_write_guest(vcpu->kvm,
+-                                  get_tss_base_addr(vcpu, nseg_desc),
++                                  get_tss_base_addr_write(vcpu, nseg_desc),
+                                   &tss_segment_32.prev_task_link,
+                                   sizeof tss_segment_32.prev_task_link))
+                       goto out;
+@@ -4373,7 +4442,7 @@ int kvm_task_switch(struct kvm_vcpu *vcp
+       u32 old_tss_base = get_segment_base(vcpu, VCPU_SREG_TR);
+       u16 old_tss_sel = get_segment_selector(vcpu, VCPU_SREG_TR);
+-      old_tss_base = vcpu->arch.mmu.gva_to_gpa(vcpu, old_tss_base);
++      old_tss_base = kvm_mmu_gva_to_gpa_write(vcpu, old_tss_base, NULL);
+       /* FIXME: Handle errors. Failure to read either TSS or their
+        * descriptors should generate a pagefault.
+@@ -4582,7 +4651,7 @@ int kvm_arch_vcpu_ioctl_translate(struct
+       vcpu_load(vcpu);
+       down_read(&vcpu->kvm->slots_lock);
+-      gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, vaddr);
++      gpa = kvm_mmu_gva_to_gpa_system(vcpu, vaddr, NULL);
+       up_read(&vcpu->kvm->slots_lock);
+       tr->physical_address = gpa;
+       tr->valid = gpa != UNMAPPED_GVA;
diff --git a/queue-2.6.32/kvm-x86-emulator-fix-popf-emulation.patch b/queue-2.6.32/kvm-x86-emulator-fix-popf-emulation.patch
new file mode 100644 (file)
index 0000000..07d6ec4
--- /dev/null
@@ -0,0 +1,107 @@
+From stefan.bader@canonical.com  Wed Apr  7 14:42:41 2010
+From: Gleb Natapov <gleb@redhat.com>
+Date: Fri, 19 Mar 2010 15:47:33 +0100
+Subject: KVM: x86 emulator: Fix popf emulation
+To: stable@kernel.org
+Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
+Message-ID: <1269010059-25309-6-git-send-email-stefan.bader@canonical.com>
+
+
+From: Gleb Natapov <gleb@redhat.com>
+
+commit d4c6a1549c056f1d817e8f6f2f97d8b44933472f upstream
+
+POPF behaves differently depending on current CPU mode. Emulate correct
+logic to prevent guest from changing flags that it can't change otherwise.
+
+Signed-off-by: Gleb Natapov <gleb@redhat.com>
+Signed-off-by: Avi Kivity <avi@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/kvm/emulate.c |   55 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 54 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -339,11 +339,18 @@ static u32 group2_table[] = {
+ };
+ /* EFLAGS bit definitions. */
++#define EFLG_ID (1<<21)
++#define EFLG_VIP (1<<20)
++#define EFLG_VIF (1<<19)
++#define EFLG_AC (1<<18)
+ #define EFLG_VM (1<<17)
+ #define EFLG_RF (1<<16)
++#define EFLG_IOPL (3<<12)
++#define EFLG_NT (1<<14)
+ #define EFLG_OF (1<<11)
+ #define EFLG_DF (1<<10)
+ #define EFLG_IF (1<<9)
++#define EFLG_TF (1<<8)
+ #define EFLG_SF (1<<7)
+ #define EFLG_ZF (1<<6)
+ #define EFLG_AF (1<<4)
+@@ -1205,6 +1212,49 @@ static int emulate_pop(struct x86_emulat
+       return rc;
+ }
++static int emulate_popf(struct x86_emulate_ctxt *ctxt,
++                     struct x86_emulate_ops *ops,
++                     void *dest, int len)
++{
++      int rc;
++      unsigned long val, change_mask;
++      int iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
++      int cpl = kvm_x86_ops->get_cpl(ctxt->vcpu);
++
++      rc = emulate_pop(ctxt, ops, &val, len);
++      if (rc != X86EMUL_CONTINUE)
++              return rc;
++
++      change_mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_OF
++              | EFLG_TF | EFLG_DF | EFLG_NT | EFLG_RF | EFLG_AC | EFLG_ID;
++
++      switch(ctxt->mode) {
++      case X86EMUL_MODE_PROT64:
++      case X86EMUL_MODE_PROT32:
++      case X86EMUL_MODE_PROT16:
++              if (cpl == 0)
++                      change_mask |= EFLG_IOPL;
++              if (cpl <= iopl)
++                      change_mask |= EFLG_IF;
++              break;
++      case X86EMUL_MODE_VM86:
++              if (iopl < 3) {
++                      kvm_inject_gp(ctxt->vcpu, 0);
++                      return X86EMUL_PROPAGATE_FAULT;
++              }
++              change_mask |= EFLG_IF;
++              break;
++      default: /* real mode */
++              change_mask |= (EFLG_IOPL | EFLG_IF);
++              break;
++      }
++
++      *(unsigned long *)dest =
++              (ctxt->eflags & ~change_mask) | (val & change_mask);
++
++      return rc;
++}
++
+ static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
+                               struct x86_emulate_ops *ops)
+ {
+@@ -1995,7 +2045,10 @@ special_insn:
+               c->dst.type = OP_REG;
+               c->dst.ptr = (unsigned long *) &ctxt->eflags;
+               c->dst.bytes = c->op_bytes;
+-              goto pop_instruction;
++              rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes);
++              if (rc != X86EMUL_CONTINUE)
++                      goto done;
++              break;
+       case 0xa0 ... 0xa1:     /* mov */
+               c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
+               c->dst.val = c->src.val;
diff --git a/queue-2.6.32/libata-disable-ncq-on-crucial-c300-ssd.patch b/queue-2.6.32/libata-disable-ncq-on-crucial-c300-ssd.patch
new file mode 100644 (file)
index 0000000..00bbe2e
--- /dev/null
@@ -0,0 +1,55 @@
+From 68b0ddb289220b6d4d865be128939663be34959d Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Mon, 5 Apr 2010 10:51:26 +0900
+Subject: libata: disable NCQ on Crucial C300 SSD
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 68b0ddb289220b6d4d865be128939663be34959d upstream.
+
+Crucial said,
+
+  Thank you for contacting us. We know that with our M225 line of SSDs
+  you sometimes need to disable NCQ (native command queuing) to avoid
+  just the type of errors you're seeing. Our recommendation for the
+  M225 is to add libata.force=noncq to your Linux kernel boot options,
+  under the kernel ATA library option.
+
+  I have sent your feedback to the engineers working on the C300, and
+  asked them to please pass it on to the firmware team. I have been
+  notified that they are in the process of testing and finalizing a
+  new firmware version, that you can expect to see released around the
+  end of April. We’ll keep you posted as to when it will be available
+  for download.
+
+So, turn off NCQ on the drive w/ the current firmware revision.
+
+Reported in the following bug.
+
+  https://bugzilla.kernel.org/show_bug.cgi?id=15573
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: lethalwp@scarlet.be
+Reported-by: Luke Macken <lmacken@redhat.com>
+Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/ata/libata-core.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -4348,6 +4348,9 @@ static const struct ata_blacklist_entry
+       { "HTS541080G9SA00",    "MB4OC60D",     ATA_HORKAGE_NONCQ, },
+       { "HTS541010G9SA00",    "MBZOC60D",     ATA_HORKAGE_NONCQ, },
++      /* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */
++      { "C300-CTFDDAC128MAG", "0001",         ATA_HORKAGE_NONCQ, },
++
+       /* devices which puke on READ_NATIVE_MAX */
+       { "HDS724040KLSA80",    "KFAOA20N",     ATA_HORKAGE_BROKEN_HPA, },
+       { "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA },
diff --git a/queue-2.6.32/libata-unlock-hpa-if-device-shrunk.patch b/queue-2.6.32/libata-unlock-hpa-if-device-shrunk.patch
new file mode 100644 (file)
index 0000000..9ab9b60
--- /dev/null
@@ -0,0 +1,149 @@
+From 445d211b0da4e9a6e6d576edff85085c2aaf53df Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Mon, 5 Apr 2010 10:33:13 +0900
+Subject: libata: unlock HPA if device shrunk
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 445d211b0da4e9a6e6d576edff85085c2aaf53df upstream.
+
+Some BIOSes don't configure HPA during boot but do so while resuming.
+This causes harddrives to shrink during resume making libata detach
+and reattach them.  This can be worked around by unlocking HPA if old
+size equals native size.
+
+Add ATA_DFLAG_UNLOCK_HPA so that HPA unlocking can be controlled
+per-device and update ata_dev_revalidate() such that it sets
+ATA_DFLAG_UNLOCK_HPA and fails with -EIO when the above condition is
+detected.
+
+This patch fixes the following bug.
+
+  https://bugzilla.kernel.org/show_bug.cgi?id=15396
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Oleksandr Yermolenko <yaa.bta@gmail.com>
+Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
+
+---
+ drivers/ata/libata-core.c |   74 +++++++++++++++++++++++++++-------------------
+ include/linux/libata.h    |    1 
+ 2 files changed, 46 insertions(+), 29 deletions(-)
+
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -1493,6 +1493,7 @@ static int ata_hpa_resize(struct ata_dev
+ {
+       struct ata_eh_context *ehc = &dev->link->eh_context;
+       int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
++      bool unlock_hpa = ata_ignore_hpa || dev->flags & ATA_DFLAG_UNLOCK_HPA;
+       u64 sectors = ata_id_n_sectors(dev->id);
+       u64 native_sectors;
+       int rc;
+@@ -1509,7 +1510,7 @@ static int ata_hpa_resize(struct ata_dev
+               /* If device aborted the command or HPA isn't going to
+                * be unlocked, skip HPA resizing.
+                */
+-              if (rc == -EACCES || !ata_ignore_hpa) {
++              if (rc == -EACCES || !unlock_hpa) {
+                       ata_dev_printk(dev, KERN_WARNING, "HPA support seems "
+                                      "broken, skipping HPA handling\n");
+                       dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
+@@ -1524,7 +1525,7 @@ static int ata_hpa_resize(struct ata_dev
+       dev->n_native_sectors = native_sectors;
+       /* nothing to do? */
+-      if (native_sectors <= sectors || !ata_ignore_hpa) {
++      if (native_sectors <= sectors || !unlock_hpa) {
+               if (!print_info || native_sectors == sectors)
+                       return 0;
+@@ -4180,36 +4181,51 @@ int ata_dev_revalidate(struct ata_device
+               goto fail;
+       /* verify n_sectors hasn't changed */
+-      if (dev->class == ATA_DEV_ATA && n_sectors &&
+-          dev->n_sectors != n_sectors) {
+-              ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch "
+-                             "%llu != %llu\n",
+-                             (unsigned long long)n_sectors,
+-                             (unsigned long long)dev->n_sectors);
+-              /*
+-               * Something could have caused HPA to be unlocked
+-               * involuntarily.  If n_native_sectors hasn't changed
+-               * and the new size matches it, keep the device.
+-               */
+-              if (dev->n_native_sectors == n_native_sectors &&
+-                  dev->n_sectors > n_sectors &&
+-                  dev->n_sectors == n_native_sectors) {
+-                      ata_dev_printk(dev, KERN_WARNING,
+-                                     "new n_sectors matches native, probably "
+-                                     "late HPA unlock, continuing\n");
+-                      /* keep using the old n_sectors */
+-                      dev->n_sectors = n_sectors;
+-              } else {
+-                      /* restore original n_[native]_sectors and fail */
+-                      dev->n_native_sectors = n_native_sectors;
+-                      dev->n_sectors = n_sectors;
+-                      rc = -ENODEV;
+-                      goto fail;
+-              }
++      if (dev->class != ATA_DEV_ATA || !n_sectors ||
++          dev->n_sectors == n_sectors)
++              return 0;
++
++      /* n_sectors has changed */
++      ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n",
++                     (unsigned long long)n_sectors,
++                     (unsigned long long)dev->n_sectors);
++
++      /*
++       * Something could have caused HPA to be unlocked
++       * involuntarily.  If n_native_sectors hasn't changed and the
++       * new size matches it, keep the device.
++       */
++      if (dev->n_native_sectors == n_native_sectors &&
++          dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) {
++              ata_dev_printk(dev, KERN_WARNING,
++                             "new n_sectors matches native, probably "
++                             "late HPA unlock, continuing\n");
++              /* keep using the old n_sectors */
++              dev->n_sectors = n_sectors;
++              return 0;
+       }
+-      return 0;
++      /*
++       * Some BIOSes boot w/o HPA but resume w/ HPA locked.  Try
++       * unlocking HPA in those cases.
++       *
++       * https://bugzilla.kernel.org/show_bug.cgi?id=15396
++       */
++      if (dev->n_native_sectors == n_native_sectors &&
++          dev->n_sectors < n_sectors && n_sectors == n_native_sectors &&
++          !(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) {
++              ata_dev_printk(dev, KERN_WARNING,
++                             "old n_sectors matches native, probably "
++                             "late HPA lock, will try to unlock HPA\n");
++              /* try unlocking HPA */
++              dev->flags |= ATA_DFLAG_UNLOCK_HPA;
++              rc = -EIO;
++      } else
++              rc = -ENODEV;
++      /* restore original n_[native_]sectors and fail */
++      dev->n_native_sectors = n_native_sectors;
++      dev->n_sectors = n_sectors;
+  fail:
+       ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
+       return rc;
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -146,6 +146,7 @@ enum {
+       ATA_DFLAG_SLEEPING      = (1 << 15), /* device is sleeping */
+       ATA_DFLAG_DUBIOUS_XFER  = (1 << 16), /* data transfer not verified */
+       ATA_DFLAG_NO_UNLOAD     = (1 << 17), /* device doesn't support unload */
++      ATA_DFLAG_UNLOCK_HPA    = (1 << 18), /* unlock HPA */
+       ATA_DFLAG_INIT_MASK     = (1 << 24) - 1,
+       ATA_DFLAG_DETACH        = (1 << 24),
diff --git a/queue-2.6.32/pata_via-add-via-vx900-support.patch b/queue-2.6.32/pata_via-add-via-vx900-support.patch
new file mode 100644 (file)
index 0000000..f8e37c8
--- /dev/null
@@ -0,0 +1,27 @@
+From 4f1deba435ef75380c1d06fda860c7a15ea16fdf Mon Sep 17 00:00:00 2001
+From: JosephChan@via.com.tw <JosephChan@via.com.tw>
+Date: Fri, 19 Mar 2010 14:08:11 +0800
+Subject: pata_via: Add VIA VX900 support
+
+From: JosephChan@via.com.tw <JosephChan@via.com.tw>
+
+commit 4f1deba435ef75380c1d06fda860c7a15ea16fdf upstream.
+
+Signed-off-by: Joseph Chan <josephchan@via.com.tw>
+Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/ata/pata_via.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/ata/pata_via.c
++++ b/drivers/ata/pata_via.c
+@@ -661,6 +661,7 @@ static const struct pci_device_id via[]
+       { PCI_VDEVICE(VIA, 0x3164), },
+       { PCI_VDEVICE(VIA, 0x5324), },
+       { PCI_VDEVICE(VIA, 0xC409), VIA_IDFLAG_SINGLE },
++      { PCI_VDEVICE(VIA, 0x9001), VIA_IDFLAG_SINGLE },
+       { },
+ };
diff --git a/queue-2.6.32/raw-fsync-method-is-now-required.patch b/queue-2.6.32/raw-fsync-method-is-now-required.patch
new file mode 100644 (file)
index 0000000..4b5ddfe
--- /dev/null
@@ -0,0 +1,89 @@
+From 55ab3a1ff843e3f0e24d2da44e71bffa5d853010 Mon Sep 17 00:00:00 2001
+From: Anton Blanchard <anton@samba.org>
+Date: Tue, 6 Apr 2010 14:34:58 -0700
+Subject: raw: fsync method is now required
+
+From: Anton Blanchard <anton@samba.org>
+
+commit 55ab3a1ff843e3f0e24d2da44e71bffa5d853010 upstream.
+
+Commit 148f948ba877f4d3cdef036b1ff6d9f68986706a (vfs: Introduce new
+helpers for syncing after writing to O_SYNC file or IS_SYNC inode) broke
+the raw driver.
+
+We now call through generic_file_aio_write -> generic_write_sync ->
+vfs_fsync_range.  vfs_fsync_range has:
+
+        if (!fop || !fop->fsync) {
+                ret = -EINVAL;
+                goto out;
+        }
+
+But drivers/char/raw.c doesn't set an fsync method.
+
+We have two options: fix it or remove the raw driver completely.  I'm
+happy to do either, the fact this has been broken for so long suggests it
+is rarely used.
+
+The patch below adds an fsync method to the raw driver.  My knowledge of
+the block layer is pretty sketchy so this could do with a once over.
+
+If we instead decide to remove the raw driver, this patch might still be
+useful as a backport to 2.6.33 and 2.6.32.
+
+Signed-off-by: Anton Blanchard <anton@samba.org>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: Alexander Viro <viro@zeniv.linux.org.uk>
+Cc: Jens Axboe <jens.axboe@oracle.com>
+Reviewed-by: Jeff Moyer <jmoyer@redhat.com>
+Tested-by: Jeff Moyer <jmoyer@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/raw.c |    1 +
+ fs/block_dev.c     |    3 ++-
+ include/linux/fs.h |    1 +
+ 3 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/raw.c
++++ b/drivers/char/raw.c
+@@ -247,6 +247,7 @@ static const struct file_operations raw_
+       .aio_read =     generic_file_aio_read,
+       .write  =       do_sync_write,
+       .aio_write =    blkdev_aio_write,
++      .fsync  =       block_fsync,
+       .open   =       raw_open,
+       .release=       raw_release,
+       .ioctl  =       raw_ioctl,
+--- a/fs/block_dev.c
++++ b/fs/block_dev.c
+@@ -404,7 +404,7 @@ static loff_t block_llseek(struct file *
+  *    NULL first argument is nfsd_sync_dir() and that's not a directory.
+  */
+  
+-static int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
++int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
+ {
+       return sync_blockdev(I_BDEV(filp->f_mapping->host));
+ }
+@@ -423,6 +423,7 @@ static struct inode *bdev_alloc_inode(st
+               return NULL;
+       return &ei->vfs_inode;
+ }
++EXPORT_SYMBOL(block_fsync);
+ static void bdev_destroy_inode(struct inode *inode)
+ {
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2225,6 +2225,7 @@ extern int generic_segment_checks(const
+ /* fs/block_dev.c */
+ extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t pos);
++extern int block_fsync(struct file *filp, struct dentry *dentry, int datasync);
+ /* fs/splice.c */
+ extern ssize_t generic_file_splice_read(struct file *, loff_t *,
diff --git a/queue-2.6.32/readahead-fix-null-filp-dereference.patch b/queue-2.6.32/readahead-fix-null-filp-dereference.patch
new file mode 100644 (file)
index 0000000..ffede33
--- /dev/null
@@ -0,0 +1,37 @@
+From 70655c06bd3f25111312d63985888112aed15ac5 Mon Sep 17 00:00:00 2001
+From: Wu Fengguang <fengguang.wu@intel.com>
+Date: Tue, 6 Apr 2010 14:34:53 -0700
+Subject: readahead: fix NULL filp dereference
+
+From: Wu Fengguang <fengguang.wu@intel.com>
+
+commit 70655c06bd3f25111312d63985888112aed15ac5 upstream.
+
+btrfs relocate_file_extent_cluster() calls us with NULL filp:
+
+  [ 4005.426805] BUG: unable to handle kernel NULL pointer dereference at 00000021
+  [ 4005.426818] IP: [<c109a130>] page_cache_sync_readahead+0x18/0x3e
+
+Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
+Cc: Yan Zheng <yanzheng@21cn.com>
+Reported-by: Kirill A. Shutemov <kirill@shutemov.name>
+Tested-by: Kirill A. Shutemov <kirill@shutemov.name>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ mm/readahead.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -502,7 +502,7 @@ void page_cache_sync_readahead(struct ad
+               return;
+       /* be dumb */
+-      if (filp->f_mode & FMODE_RANDOM) {
++      if (filp && (filp->f_mode & FMODE_RANDOM)) {
+               force_page_cache_readahead(mapping, filp, offset, req_size);
+               return;
+       }
diff --git a/queue-2.6.32/resource-move-kernel-function-inside-__kernel__.patch b/queue-2.6.32/resource-move-kernel-function-inside-__kernel__.patch
new file mode 100644 (file)
index 0000000..aa6ba5f
--- /dev/null
@@ -0,0 +1,76 @@
+From max@stro.at  Wed Apr  7 14:36:07 2010
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Fri, 19 Mar 2010 02:51:56 +0100
+Subject: resource: move kernel function inside __KERNEL__
+To: Greg KH <greg@kroah.com>
+Cc: stable@kernel.org, Jiri Slaby <jslaby@suse.cz>
+Message-ID: <20100319015156.GC4424@stro.at>
+
+commit 96d07d211739fd2450ac54e81d00fa40fcd4b1bd upstream
+From: Jiri Slaby <jslaby@suse.cz>
+
+resource: move kernel function inside __KERNEL__
+
+It is an internal function. Move it inside __KERNEL__ ifdef, along
+with task_struct declaration.
+
+Then we get:
+#--- /usr/include/linux/resource.h       2009-09-14 15:09:29.000000000 +0200
+#+++ usr/include/linux/resource.h       2010-01-04 11:30:54.000000000 +0100
+#@@ -3,8 +3,6 @@
+#
+##include <linux/time.h>
+#
+#-struct task_struct;
+#-
+#/*
+#* Resource control/accounting header file for linux
+#*/
+#@@ -70,6 +68,5 @@
+#*/
+##include <asm/resource.h>
+#
+#-int getrusage(struct task_struct *p, int who, struct rusage *ru);
+#
+##endif
+#
+#***********
+
+include/linux/Kbuild is untouched, since unifdef is run even on
+headers-y nowadays.
+
+backport to 2.6.32 by maximilian attems <max@stro.at>
+Patch commented out by gregkh due to quilt complaining.
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Cc: maximilian attems <max@stro.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/resource.h |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/include/linux/resource.h
++++ b/include/linux/resource.h
+@@ -3,8 +3,6 @@
+ #include <linux/time.h>
+-struct task_struct;
+-
+ /*
+  * Resource control/accounting header file for linux
+  */
+@@ -70,6 +68,12 @@ struct rlimit {
+  */
+ #include <asm/resource.h>
++#ifdef __KERNEL__
++
++struct task_struct;
++
+ int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
++#endif /* __KERNEL__ */
++
+ #endif
index 9d4f7112977953f4d729ce8fe3a4c4f6db696a80..3909603fffb1edde47bbfc053e69766959a1d619 100644 (file)
@@ -41,3 +41,42 @@ genirq-force-msi-irq-handlers-to-run-with-interrupts-disabled.patch
 tty-release_one_tty-forgets-to-put-pids.patch
 lis3-fix-show-rate-for-8-bits-chips.patch
 pata_ali-fix-regression-with-old-devices.patch
+hid-fix-oops-in-gyration_event.patch
+raw-fsync-method-is-now-required.patch
+readahead-fix-null-filp-dereference.patch
+alsa-mixart-range-checking-proc-file.patch
+alsa-hda-fix-0-db-offset-for-lenovo-thinkpad-models-using-ad1981.patch
+x86-amd-get-multi-node-cpu-info-from-nodeid-msr-instead-of-pci-config-space.patch
+resource-move-kernel-function-inside-__kernel__.patch
+backlight-mbp_nvidia_bl-add-five-more-macbook-variants.patch
+kvm-x86-emulator-add-virtual-8086-mode-of-emulation.patch
+kvm-x86-emulator-fix-memory-access-during-x86-emulation.patch
+kvm-x86-emulator-check-iopl-level-during-io-instruction-emulation.patch
+kvm-x86-emulator-fix-popf-emulation.patch
+kvm-fix-segment-descriptor-loading.patch
+kvm-vmx-update-instruction-length-on-intercepted-bp.patch
+kvm-vmx-use-macros-instead-of-hex-value-on-cr0-initialization.patch
+kvm-svm-reset-cr0-properly-on-vcpu-reset.patch
+kvm-vmx-disable-unrestricted-guest-when-ept-disabled.patch
+kvm-x86-disable-paravirt-mmu-reporting.patch
+pata_via-add-via-vx900-support.patch
+ext3-don-t-update-the-superblock-in-ext3_statfs.patch
+ext3-journal-all-modifications-in-ext3_xattr_set_handle.patch
+thinkpad-acpi-fix-some-version-quirks.patch
+thinkpad-acpi-issue-backlight-class-events.patch
+thinkpad-acpi-silence-bogus-complain-during-rmmod.patch
+thinkpad-acpi-adopt-input-device.patch
+thinkpad-acpi-expose-module-parameters.patch
+thinkpad-acpi-log-temperatures-on-termal-alarm-v2.patch
+thinkpad-acpi-use-input_set_capability.patch
+thinkpad-acpi-sync-input-device-ev_sw-initial-state.patch
+thinkpad-acpi-log-initial-state-of-rfkill-switches.patch
+thinkpad-acpi-convert-to-seq_file.patch
+thinkpad-acpi-lock-down-video-output-state-access.patch
+eeepc-laptop-disable-cpu-speed-control-on-eeepc-701.patch
+eeepc-laptop-dmi-blacklist-to-disable-pci-hotplug-code.patch
+eeepc-laptop-add-hotplug_disable-parameter.patch
+eeepc-laptop-disable-wireless-hotplug-for-1201n.patch
+eeepc-laptop-disable-wireless-hotplug-for-1005pe.patch
+libata-disable-ncq-on-crucial-c300-ssd.patch
+libata-unlock-hpa-if-device-shrunk.patch
diff --git a/queue-2.6.32/thinkpad-acpi-adopt-input-device.patch b/queue-2.6.32/thinkpad-acpi-adopt-input-device.patch
new file mode 100644 (file)
index 0000000..5cac209
--- /dev/null
@@ -0,0 +1,31 @@
+From d112ef95d4ec1ee7fe7123e3f21e4aac0d57570c Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Wed, 9 Dec 2009 01:36:26 +0000
+Subject: thinkpad-acpi: adopt input device
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit d112ef95d4ec1ee7fe7123e3f21e4aac0d57570c upstream.
+
+Properly init the parent field of the input device.  Thanks to Alan
+Jenkins, who noted this problem in a different driver.
+
+Reported-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/thinkpad_acpi.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -8385,6 +8385,7 @@ static int __init thinkpad_acpi_module_i
+                                               PCI_VENDOR_ID_IBM;
+               tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
+               tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
++              tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
+       }
+       for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
+               ret = ibm_init(&ibms_init[i]);
diff --git a/queue-2.6.32/thinkpad-acpi-convert-to-seq_file.patch b/queue-2.6.32/thinkpad-acpi-convert-to-seq_file.patch
new file mode 100644 (file)
index 0000000..05dc51a
--- /dev/null
@@ -0,0 +1,648 @@
+From 887965e6576a78f71b9b98dec43fd1c73becd2e8 Mon Sep 17 00:00:00 2001
+From: Alexey Dobriyan <adobriyan@gmail.com>
+Date: Tue, 15 Dec 2009 21:51:12 -0200
+Subject: thinkpad-acpi: convert to seq_file
+
+From: Alexey Dobriyan <adobriyan@gmail.com>
+
+commit 887965e6576a78f71b9b98dec43fd1c73becd2e8 upstream.
+
+(hmh@hmh.eng.br: Updated to apply to 2.6.32.y)
+
+Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/thinkpad_acpi.c |  282 ++++++++++++++++-------------------
+ 1 file changed, 131 insertions(+), 151 deletions(-)
+
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -61,6 +61,7 @@
+ #include <linux/nvram.h>
+ #include <linux/proc_fs.h>
++#include <linux/seq_file.h>
+ #include <linux/sysfs.h>
+ #include <linux/backlight.h>
+ #include <linux/fb.h>
+@@ -256,7 +257,7 @@ struct tp_acpi_drv_struct {
+ struct ibm_struct {
+       char *name;
+-      int (*read) (char *);
++      int (*read) (struct seq_file *);
+       int (*write) (char *);
+       void (*exit) (void);
+       void (*resume) (void);
+@@ -776,36 +777,25 @@ static int __init register_tpacpi_subdri
+  ****************************************************************************
+  ****************************************************************************/
+-static int dispatch_procfs_read(char *page, char **start, off_t off,
+-                      int count, int *eof, void *data)
++static int dispatch_proc_show(struct seq_file *m, void *v)
+ {
+-      struct ibm_struct *ibm = data;
+-      int len;
++      struct ibm_struct *ibm = m->private;
+       if (!ibm || !ibm->read)
+               return -EINVAL;
++      return ibm->read(m);
++}
+-      len = ibm->read(page);
+-      if (len < 0)
+-              return len;
+-
+-      if (len <= off + count)
+-              *eof = 1;
+-      *start = page + off;
+-      len -= off;
+-      if (len > count)
+-              len = count;
+-      if (len < 0)
+-              len = 0;
+-
+-      return len;
++static int dispatch_proc_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, dispatch_proc_show, PDE(inode)->data);
+ }
+-static int dispatch_procfs_write(struct file *file,
++static ssize_t dispatch_proc_write(struct file *file,
+                       const char __user *userbuf,
+-                      unsigned long count, void *data)
++                      size_t count, loff_t *pos)
+ {
+-      struct ibm_struct *ibm = data;
++      struct ibm_struct *ibm = PDE(file->f_path.dentry->d_inode)->data;
+       char *kernbuf;
+       int ret;
+@@ -834,6 +824,15 @@ static int dispatch_procfs_write(struct
+       return ret;
+ }
++static const struct file_operations dispatch_proc_fops = {
++      .owner          = THIS_MODULE,
++      .open           = dispatch_proc_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release,
++      .write          = dispatch_proc_write,
++};
++
+ static char *next_cmd(char **cmds)
+ {
+       char *start = *cmds;
+@@ -1388,12 +1387,11 @@ static ssize_t tpacpi_rfk_sysfs_enable_s
+ }
+ /* procfs -------------------------------------------------------------- */
+-static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p)
++static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id,
++                                struct seq_file *m)
+ {
+-      int len = 0;
+-
+       if (id >= TPACPI_RFK_SW_MAX)
+-              len += sprintf(p + len, "status:\t\tnot supported\n");
++              seq_printf(m, "status:\t\tnot supported\n");
+       else {
+               int status;
+@@ -1407,13 +1405,13 @@ static int tpacpi_rfk_procfs_read(const
+                               return status;
+               }
+-              len += sprintf(p + len, "status:\t\t%s\n",
++              seq_printf(m, "status:\t\t%s\n",
+                               (status == TPACPI_RFK_RADIO_ON) ?
+                                       "enabled" : "disabled");
+-              len += sprintf(p + len, "commands:\tenable, disable\n");
++              seq_printf(m, "commands:\tenable, disable\n");
+       }
+-      return len;
++      return 0;
+ }
+ static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf)
+@@ -1891,14 +1889,11 @@ static int __init thinkpad_acpi_driver_i
+       return 0;
+ }
+-static int thinkpad_acpi_driver_read(char *p)
++static int thinkpad_acpi_driver_read(struct seq_file *m)
+ {
+-      int len = 0;
+-
+-      len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC);
+-      len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION);
+-
+-      return len;
++      seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC);
++      seq_printf(m, "version:\t%s\n", TPACPI_VERSION);
++      return 0;
+ }
+ static struct ibm_struct thinkpad_acpi_driver_data = {
+@@ -3754,14 +3749,13 @@ static void hotkey_resume(void)
+ }
+ /* procfs -------------------------------------------------------------- */
+-static int hotkey_read(char *p)
++static int hotkey_read(struct seq_file *m)
+ {
+       int res, status;
+-      int len = 0;
+       if (!tp_features.hotkey) {
+-              len += sprintf(p + len, "status:\t\tnot supported\n");
+-              return len;
++              seq_printf(m, "status:\t\tnot supported\n");
++              return 0;
+       }
+       if (mutex_lock_killable(&hotkey_mutex))
+@@ -3773,17 +3767,16 @@ static int hotkey_read(char *p)
+       if (res)
+               return res;
+-      len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
++      seq_printf(m, "status:\t\t%s\n", enabled(status, 0));
+       if (hotkey_all_mask) {
+-              len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_user_mask);
+-              len += sprintf(p + len,
+-                             "commands:\tenable, disable, reset, <mask>\n");
++              seq_printf(m, "mask:\t\t0x%08x\n", hotkey_user_mask);
++              seq_printf(m, "commands:\tenable, disable, reset, <mask>\n");
+       } else {
+-              len += sprintf(p + len, "mask:\t\tnot supported\n");
+-              len += sprintf(p + len, "commands:\tenable, disable, reset\n");
++              seq_printf(m, "mask:\t\tnot supported\n");
++              seq_printf(m, "commands:\tenable, disable, reset\n");
+       }
+-      return len;
++      return 0;
+ }
+ static void hotkey_enabledisable_warn(bool enable)
+@@ -4050,9 +4043,9 @@ static int __init bluetooth_init(struct
+ }
+ /* procfs -------------------------------------------------------------- */
+-static int bluetooth_read(char *p)
++static int bluetooth_read(struct seq_file *m)
+ {
+-      return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p);
++      return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, m);
+ }
+ static int bluetooth_write(char *buf)
+@@ -4241,9 +4234,9 @@ static int __init wan_init(struct ibm_in
+ }
+ /* procfs -------------------------------------------------------------- */
+-static int wan_read(char *p)
++static int wan_read(struct seq_file *m)
+ {
+-      return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p);
++      return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, m);
+ }
+ static int wan_write(char *buf)
+@@ -4618,14 +4611,13 @@ static int video_expand_toggle(void)
+       /* not reached */
+ }
+-static int video_read(char *p)
++static int video_read(struct seq_file *m)
+ {
+       int status, autosw;
+-      int len = 0;
+       if (video_supported == TPACPI_VIDEO_NONE) {
+-              len += sprintf(p + len, "status:\t\tnot supported\n");
+-              return len;
++              seq_printf(m, "status:\t\tnot supported\n");
++              return 0;
+       }
+       status = video_outputsw_get();
+@@ -4636,20 +4628,20 @@ static int video_read(char *p)
+       if (autosw < 0)
+               return autosw;
+-      len += sprintf(p + len, "status:\t\tsupported\n");
+-      len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
+-      len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
++      seq_printf(m, "status:\t\tsupported\n");
++      seq_printf(m, "lcd:\t\t%s\n", enabled(status, 0));
++      seq_printf(m, "crt:\t\t%s\n", enabled(status, 1));
+       if (video_supported == TPACPI_VIDEO_NEW)
+-              len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
+-      len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
+-      len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
+-      len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
++              seq_printf(m, "dvi:\t\t%s\n", enabled(status, 3));
++      seq_printf(m, "auto:\t\t%s\n", enabled(autosw, 0));
++      seq_printf(m, "commands:\tlcd_enable, lcd_disable\n");
++      seq_printf(m, "commands:\tcrt_enable, crt_disable\n");
+       if (video_supported == TPACPI_VIDEO_NEW)
+-              len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
+-      len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
+-      len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
++              seq_printf(m, "commands:\tdvi_enable, dvi_disable\n");
++      seq_printf(m, "commands:\tauto_enable, auto_disable\n");
++      seq_printf(m, "commands:\tvideo_switch, expand_toggle\n");
+-      return len;
++      return 0;
+ }
+ static int video_write(char *buf)
+@@ -4841,25 +4833,24 @@ static void light_exit(void)
+               flush_workqueue(tpacpi_wq);
+ }
+-static int light_read(char *p)
++static int light_read(struct seq_file *m)
+ {
+-      int len = 0;
+       int status;
+       if (!tp_features.light) {
+-              len += sprintf(p + len, "status:\t\tnot supported\n");
++              seq_printf(m, "status:\t\tnot supported\n");
+       } else if (!tp_features.light_status) {
+-              len += sprintf(p + len, "status:\t\tunknown\n");
+-              len += sprintf(p + len, "commands:\ton, off\n");
++              seq_printf(m, "status:\t\tunknown\n");
++              seq_printf(m, "commands:\ton, off\n");
+       } else {
+               status = light_get_status();
+               if (status < 0)
+                       return status;
+-              len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
+-              len += sprintf(p + len, "commands:\ton, off\n");
++              seq_printf(m, "status:\t\t%s\n", onoff(status, 0));
++              seq_printf(m, "commands:\ton, off\n");
+       }
+-      return len;
++      return 0;
+ }
+ static int light_write(char *buf)
+@@ -4937,20 +4928,18 @@ static void cmos_exit(void)
+       device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
+ }
+-static int cmos_read(char *p)
++static int cmos_read(struct seq_file *m)
+ {
+-      int len = 0;
+-
+       /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
+          R30, R31, T20-22, X20-21 */
+       if (!cmos_handle)
+-              len += sprintf(p + len, "status:\t\tnot supported\n");
++              seq_printf(m, "status:\t\tnot supported\n");
+       else {
+-              len += sprintf(p + len, "status:\t\tsupported\n");
+-              len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
++              seq_printf(m, "status:\t\tsupported\n");
++              seq_printf(m, "commands:\t<cmd> (<cmd> is 0-21)\n");
+       }
+-      return len;
++      return 0;
+ }
+ static int cmos_write(char *buf)
+@@ -5325,15 +5314,13 @@ static int __init led_init(struct ibm_in
+       ((s) == TPACPI_LED_OFF ? "off" : \
+               ((s) == TPACPI_LED_ON ? "on" : "blinking"))
+-static int led_read(char *p)
++static int led_read(struct seq_file *m)
+ {
+-      int len = 0;
+-
+       if (!led_supported) {
+-              len += sprintf(p + len, "status:\t\tnot supported\n");
+-              return len;
++              seq_printf(m, "status:\t\tnot supported\n");
++              return 0;
+       }
+-      len += sprintf(p + len, "status:\t\tsupported\n");
++      seq_printf(m, "status:\t\tsupported\n");
+       if (led_supported == TPACPI_LED_570) {
+               /* 570 */
+@@ -5342,15 +5329,15 @@ static int led_read(char *p)
+                       status = led_get_status(i);
+                       if (status < 0)
+                               return -EIO;
+-                      len += sprintf(p + len, "%d:\t\t%s\n",
++                      seq_printf(m, "%d:\t\t%s\n",
+                                      i, str_led_status(status));
+               }
+       }
+-      len += sprintf(p + len, "commands:\t"
++      seq_printf(m, "commands:\t"
+                      "<led> on, <led> off, <led> blink (<led> is 0-15)\n");
+-      return len;
++      return 0;
+ }
+ static int led_write(char *buf)
+@@ -5423,18 +5410,16 @@ static int __init beep_init(struct ibm_i
+       return (beep_handle)? 0 : 1;
+ }
+-static int beep_read(char *p)
++static int beep_read(struct seq_file *m)
+ {
+-      int len = 0;
+-
+       if (!beep_handle)
+-              len += sprintf(p + len, "status:\t\tnot supported\n");
++              seq_printf(m, "status:\t\tnot supported\n");
+       else {
+-              len += sprintf(p + len, "status:\t\tsupported\n");
+-              len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
++              seq_printf(m, "status:\t\tsupported\n");
++              seq_printf(m, "commands:\t<cmd> (<cmd> is 0-17)\n");
+       }
+-      return len;
++      return 0;
+ }
+ static int beep_write(char *buf)
+@@ -5795,9 +5780,8 @@ static void thermal_exit(void)
+       }
+ }
+-static int thermal_read(char *p)
++static int thermal_read(struct seq_file *m)
+ {
+-      int len = 0;
+       int n, i;
+       struct ibm_thermal_sensors_struct t;
+@@ -5805,16 +5789,16 @@ static int thermal_read(char *p)
+       if (unlikely(n < 0))
+               return n;
+-      len += sprintf(p + len, "temperatures:\t");
++      seq_printf(m, "temperatures:\t");
+       if (n > 0) {
+               for (i = 0; i < (n - 1); i++)
+-                      len += sprintf(p + len, "%d ", t.temp[i] / 1000);
+-              len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
++                      seq_printf(m, "%d ", t.temp[i] / 1000);
++              seq_printf(m, "%d\n", t.temp[i] / 1000);
+       } else
+-              len += sprintf(p + len, "not supported\n");
++              seq_printf(m, "not supported\n");
+-      return len;
++      return 0;
+ }
+ static struct ibm_struct thermal_driver_data = {
+@@ -5829,39 +5813,38 @@ static struct ibm_struct thermal_driver_
+ static u8 ecdump_regs[256];
+-static int ecdump_read(char *p)
++static int ecdump_read(struct seq_file *m)
+ {
+-      int len = 0;
+       int i, j;
+       u8 v;
+-      len += sprintf(p + len, "EC      "
++      seq_printf(m, "EC      "
+                      " +00 +01 +02 +03 +04 +05 +06 +07"
+                      " +08 +09 +0a +0b +0c +0d +0e +0f\n");
+       for (i = 0; i < 256; i += 16) {
+-              len += sprintf(p + len, "EC 0x%02x:", i);
++              seq_printf(m, "EC 0x%02x:", i);
+               for (j = 0; j < 16; j++) {
+                       if (!acpi_ec_read(i + j, &v))
+                               break;
+                       if (v != ecdump_regs[i + j])
+-                              len += sprintf(p + len, " *%02x", v);
++                              seq_printf(m, " *%02x", v);
+                       else
+-                              len += sprintf(p + len, "  %02x", v);
++                              seq_printf(m, "  %02x", v);
+                       ecdump_regs[i + j] = v;
+               }
+-              len += sprintf(p + len, "\n");
++              seq_putc(m, '\n');
+               if (j != 16)
+                       break;
+       }
+       /* These are way too dangerous to advertise openly... */
+ #if 0
+-      len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
++      seq_printf(m, "commands:\t0x<offset> 0x<value>"
+                      " (<offset> is 00-ff, <value> is 00-ff)\n");
+-      len += sprintf(p + len, "commands:\t0x<offset> <value>  "
++      seq_printf(m, "commands:\t0x<offset> <value>  "
+                      " (<offset> is 00-ff, <value> is 0-255)\n");
+ #endif
+-      return len;
++      return 0;
+ }
+ static int ecdump_write(char *buf)
+@@ -6314,23 +6297,22 @@ static void brightness_exit(void)
+       tpacpi_brightness_checkpoint_nvram();
+ }
+-static int brightness_read(char *p)
++static int brightness_read(struct seq_file *m)
+ {
+-      int len = 0;
+       int level;
+       level = brightness_get(NULL);
+       if (level < 0) {
+-              len += sprintf(p + len, "level:\t\tunreadable\n");
++              seq_printf(m, "level:\t\tunreadable\n");
+       } else {
+-              len += sprintf(p + len, "level:\t\t%d\n", level);
+-              len += sprintf(p + len, "commands:\tup, down\n");
+-              len += sprintf(p + len, "commands:\tlevel <level>"
++              seq_printf(m, "level:\t\t%d\n", level);
++              seq_printf(m, "commands:\tup, down\n");
++              seq_printf(m, "commands:\tlevel <level>"
+                              " (<level> is 0-%d)\n",
+                              (tp_features.bright_16levels) ? 15 : 7);
+       }
+-      return len;
++      return 0;
+ }
+ static int brightness_write(char *buf)
+@@ -6387,22 +6369,21 @@ static struct ibm_struct brightness_driv
+ static int volume_offset = 0x30;
+-static int volume_read(char *p)
++static int volume_read(struct seq_file *m)
+ {
+-      int len = 0;
+       u8 level;
+       if (!acpi_ec_read(volume_offset, &level)) {
+-              len += sprintf(p + len, "level:\t\tunreadable\n");
++              seq_printf(m, "level:\t\tunreadable\n");
+       } else {
+-              len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
+-              len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
+-              len += sprintf(p + len, "commands:\tup, down, mute\n");
+-              len += sprintf(p + len, "commands:\tlevel <level>"
++              seq_printf(m, "level:\t\t%d\n", level & 0xf);
++              seq_printf(m, "mute:\t\t%s\n", onoff(level, 6));
++              seq_printf(m, "commands:\tup, down, mute\n");
++              seq_printf(m, "commands:\tlevel <level>"
+                              " (<level> is 0-15)\n");
+       }
+-      return len;
++      return 0;
+ }
+ static int volume_write(char *buf)
+@@ -7554,9 +7535,8 @@ static void fan_resume(void)
+       }
+ }
+-static int fan_read(char *p)
++static int fan_read(struct seq_file *m)
+ {
+-      int len = 0;
+       int rc;
+       u8 status;
+       unsigned int speed = 0;
+@@ -7568,7 +7548,7 @@ static int fan_read(char *p)
+               if (rc < 0)
+                       return rc;
+-              len += sprintf(p + len, "status:\t\t%s\n"
++              seq_printf(m, "status:\t\t%s\n"
+                              "level:\t\t%d\n",
+                              (status != 0) ? "enabled" : "disabled", status);
+               break;
+@@ -7579,54 +7559,54 @@ static int fan_read(char *p)
+               if (rc < 0)
+                       return rc;
+-              len += sprintf(p + len, "status:\t\t%s\n",
++              seq_printf(m, "status:\t\t%s\n",
+                              (status != 0) ? "enabled" : "disabled");
+               rc = fan_get_speed(&speed);
+               if (rc < 0)
+                       return rc;
+-              len += sprintf(p + len, "speed:\t\t%d\n", speed);
++              seq_printf(m, "speed:\t\t%d\n", speed);
+               if (status & TP_EC_FAN_FULLSPEED)
+                       /* Disengaged mode takes precedence */
+-                      len += sprintf(p + len, "level:\t\tdisengaged\n");
++                      seq_printf(m, "level:\t\tdisengaged\n");
+               else if (status & TP_EC_FAN_AUTO)
+-                      len += sprintf(p + len, "level:\t\tauto\n");
++                      seq_printf(m, "level:\t\tauto\n");
+               else
+-                      len += sprintf(p + len, "level:\t\t%d\n", status);
++                      seq_printf(m, "level:\t\t%d\n", status);
+               break;
+       case TPACPI_FAN_NONE:
+       default:
+-              len += sprintf(p + len, "status:\t\tnot supported\n");
++              seq_printf(m, "status:\t\tnot supported\n");
+       }
+       if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
+-              len += sprintf(p + len, "commands:\tlevel <level>");
++              seq_printf(m, "commands:\tlevel <level>");
+               switch (fan_control_access_mode) {
+               case TPACPI_FAN_WR_ACPI_SFAN:
+-                      len += sprintf(p + len, " (<level> is 0-7)\n");
++                      seq_printf(m, " (<level> is 0-7)\n");
+                       break;
+               default:
+-                      len += sprintf(p + len, " (<level> is 0-7, "
++                      seq_printf(m, " (<level> is 0-7, "
+                                      "auto, disengaged, full-speed)\n");
+                       break;
+               }
+       }
+       if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
+-              len += sprintf(p + len, "commands:\tenable, disable\n"
++              seq_printf(m, "commands:\tenable, disable\n"
+                              "commands:\twatchdog <timeout> (<timeout> "
+                              "is 0 (off), 1-120 (seconds))\n");
+       if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
+-              len += sprintf(p + len, "commands:\tspeed <speed>"
++              seq_printf(m, "commands:\tspeed <speed>"
+                              " (<speed> is 0-65535)\n");
+-      return len;
++      return 0;
+ }
+ static int fan_write_cmd_level(const char *cmd, int *rc)
+@@ -7907,19 +7887,19 @@ static int __init ibm_init(struct ibm_in
+               "%s installed\n", ibm->name);
+       if (ibm->read) {
+-              entry = create_proc_entry(ibm->name,
+-                                        S_IFREG | S_IRUGO | S_IWUSR,
+-                                        proc_dir);
++              mode_t mode;
++
++              mode = S_IRUGO;
++              if (ibm->write)
++                      mode |= S_IWUSR;
++              entry = proc_create_data(ibm->name, mode, proc_dir,
++                                       &dispatch_proc_fops, ibm);
+               if (!entry) {
+                       printk(TPACPI_ERR "unable to create proc entry %s\n",
+                              ibm->name);
+                       ret = -ENODEV;
+                       goto err_out;
+               }
+-              entry->data = ibm;
+-              entry->read_proc = &dispatch_procfs_read;
+-              if (ibm->write)
+-                      entry->write_proc = &dispatch_procfs_write;
+               ibm->flags.proc_created = 1;
+       }
diff --git a/queue-2.6.32/thinkpad-acpi-expose-module-parameters.patch b/queue-2.6.32/thinkpad-acpi-expose-module-parameters.patch
new file mode 100644 (file)
index 0000000..d6720fa
--- /dev/null
@@ -0,0 +1,95 @@
+From b09c72259e88cec3d602aef987a3209297f3a9c2 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Wed, 9 Dec 2009 01:36:27 +0000
+Subject: thinkpad-acpi: expose module parameters
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit b09c72259e88cec3d602aef987a3209297f3a9c2 upstream.
+
+Export the normal (non-command) module paramenters as mode 0444, so
+that they will show up in sysfs.
+
+These parameters must not be changed at runtime as a rule, with very
+few exceptions.
+
+Reported-by: Ferenc Wagner <wferi@niif.hu>
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/thinkpad_acpi.c |   20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -8126,32 +8126,32 @@ static int __init set_ibm_param(const ch
+       return -EINVAL;
+ }
+-module_param(experimental, int, 0);
++module_param(experimental, int, 0444);
+ MODULE_PARM_DESC(experimental,
+                "Enables experimental features when non-zero");
+ module_param_named(debug, dbg_level, uint, 0);
+ MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
+-module_param(force_load, bool, 0);
++module_param(force_load, bool, 0444);
+ MODULE_PARM_DESC(force_load,
+                "Attempts to load the driver even on a "
+                "mis-identified ThinkPad when true");
+-module_param_named(fan_control, fan_control_allowed, bool, 0);
++module_param_named(fan_control, fan_control_allowed, bool, 0444);
+ MODULE_PARM_DESC(fan_control,
+                "Enables setting fan parameters features when true");
+-module_param_named(brightness_mode, brightness_mode, uint, 0);
++module_param_named(brightness_mode, brightness_mode, uint, 0444);
+ MODULE_PARM_DESC(brightness_mode,
+                "Selects brightness control strategy: "
+                "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM");
+-module_param(brightness_enable, uint, 0);
++module_param(brightness_enable, uint, 0444);
+ MODULE_PARM_DESC(brightness_enable,
+                "Enables backlight control when 1, disables when 0");
+-module_param(hotkey_report_mode, uint, 0);
++module_param(hotkey_report_mode, uint, 0444);
+ MODULE_PARM_DESC(hotkey_report_mode,
+                "used for backwards compatibility with userspace, "
+                "see documentation");
+@@ -8174,25 +8174,25 @@ TPACPI_PARAM(volume);
+ TPACPI_PARAM(fan);
+ #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+-module_param(dbg_wlswemul, uint, 0);
++module_param(dbg_wlswemul, uint, 0444);
+ MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation");
+ module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0);
+ MODULE_PARM_DESC(wlsw_state,
+                "Initial state of the emulated WLSW switch");
+-module_param(dbg_bluetoothemul, uint, 0);
++module_param(dbg_bluetoothemul, uint, 0444);
+ MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation");
+ module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0);
+ MODULE_PARM_DESC(bluetooth_state,
+                "Initial state of the emulated bluetooth switch");
+-module_param(dbg_wwanemul, uint, 0);
++module_param(dbg_wwanemul, uint, 0444);
+ MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation");
+ module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0);
+ MODULE_PARM_DESC(wwan_state,
+                "Initial state of the emulated WWAN switch");
+-module_param(dbg_uwbemul, uint, 0);
++module_param(dbg_uwbemul, uint, 0444);
+ MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation");
+ module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0);
+ MODULE_PARM_DESC(uwb_state,
diff --git a/queue-2.6.32/thinkpad-acpi-fix-some-version-quirks.patch b/queue-2.6.32/thinkpad-acpi-fix-some-version-quirks.patch
new file mode 100644 (file)
index 0000000..a818b31
--- /dev/null
@@ -0,0 +1,41 @@
+From 90765c6aee568137521ba19347c744b5abde8161 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Wed, 9 Dec 2009 01:36:23 +0000
+Subject: thinkpad-acpi: fix some version quirks
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit 90765c6aee568137521ba19347c744b5abde8161 upstream.
+
+Update some of the BIOS/EC version quirks.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/thinkpad_acpi.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -1779,7 +1779,7 @@ static const struct tpacpi_quirk tpacpi_
+       TPV_QL1('7', '9',  'E', '3',  '5', '0'), /* T60/p */
+       TPV_QL1('7', 'C',  'D', '2',  '2', '2'), /* R60, R60i */
+-      TPV_QL0('7', 'E',  'D', '0'),            /* R60e, R60i */
++      TPV_QL1('7', 'E',  'D', '0',  '1', '5'), /* R60e, R60i */
+       /*      BIOS FW    BIOS VERS  EC FW     EC VERS */
+       TPV_QI2('1', 'W',  '9', '0',  '1', 'V', '2', '8'), /* R50e (1) */
+@@ -1795,8 +1795,8 @@ static const struct tpacpi_quirk tpacpi_
+       TPV_QI1('7', '4',  '6', '4',  '2', '7'), /* X41 (0) */
+       TPV_QI1('7', '5',  '6', '0',  '2', '0'), /* X41t (0) */
+-      TPV_QL0('7', 'B',  'D', '7'),            /* X60/s */
+-      TPV_QL0('7', 'J',  '3', '0'),            /* X60t */
++      TPV_QL1('7', 'B',  'D', '7',  '4', '0'), /* X60/s */
++      TPV_QL1('7', 'J',  '3', '0',  '1', '3'), /* X60t */
+       /* (0) - older versions lack DMI EC fw string and functionality */
+       /* (1) - older versions known to lack functionality */
diff --git a/queue-2.6.32/thinkpad-acpi-issue-backlight-class-events.patch b/queue-2.6.32/thinkpad-acpi-issue-backlight-class-events.patch
new file mode 100644 (file)
index 0000000..87004ed
--- /dev/null
@@ -0,0 +1,158 @@
+From 347a26860e2293b1347996876d3550499c7bb31f Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Wed, 9 Dec 2009 01:36:24 +0000
+Subject: thinkpad-acpi: issue backlight class events
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit 347a26860e2293b1347996876d3550499c7bb31f upstream.
+
+Take advantage of the new events capabilities of the backlight class to
+notify userspace of backlight changes.
+
+This depends on "backlight: Allow drivers to update the core, and
+generate events on changes", by Matthew Garrett.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Cc: Matthew Garrett <mjg@redhat.com>
+Cc: Richard Purdie <rpurdie@linux.intel.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+
+---
+ Documentation/laptops/thinkpad-acpi.txt |   51 +++++++-------------------------
+ drivers/platform/x86/thinkpad_acpi.c    |   24 ++++++++++++++-
+ 2 files changed, 35 insertions(+), 40 deletions(-)
+
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -460,6 +460,8 @@ event      code    Key             Notes
+                               For Lenovo ThinkPads with a new
+                               BIOS, it has to be handled either
+                               by the ACPI OSI, or by userspace.
++                              The driver does the right thing,
++                              never mess with this.
+ 0x1011        0x10    FN+END          Brightness down.  See brightness
+                               up for details.
+@@ -582,46 +584,15 @@ with hotkey_report_mode.
+ Brightness hotkey notes:
+-These are the current sane choices for brightness key mapping in
+-thinkpad-acpi:
++Don't mess with the brightness hotkeys in a Thinkpad.  If you want
++notifications for OSD, use the sysfs backlight class event support.
+-For IBM and Lenovo models *without* ACPI backlight control (the ones on
+-which thinkpad-acpi will autoload its backlight interface by default,
+-and on which ACPI video does not export a backlight interface):
+-
+-1. Don't enable or map the brightness hotkeys in thinkpad-acpi, as
+-   these older firmware versions unfortunately won't respect the hotkey
+-   mask for brightness keys anyway, and always reacts to them.  This
+-   usually work fine, unless X.org drivers are doing something to block
+-   the BIOS.  In that case, use (3) below.  This is the default mode of
+-   operation.
+-
+-2. Enable the hotkeys, but map them to something else that is NOT
+-   KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause
+-   userspace to try to change the backlight level, and use that as an
+-   on-screen-display hint.
+-
+-3. IF AND ONLY IF X.org drivers find a way to block the firmware from
+-   automatically changing the brightness, enable the hotkeys and map
+-   them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to
+-   something that calls xbacklight.  thinkpad-acpi will not be able to
+-   change brightness in that case either, so you should disable its
+-   backlight interface.
+-
+-For Lenovo models *with* ACPI backlight control:
+-
+-1. Load up ACPI video and use that.  ACPI video will report ACPI
+-   events for brightness change keys.  Do not mess with thinkpad-acpi
+-   defaults in this case.  thinkpad-acpi should not have anything to do
+-   with backlight events in a scenario where ACPI video is loaded:
+-   brightness hotkeys must be disabled, and the backlight interface is
+-   to be kept disabled as well.  This is the default mode of operation.
+-
+-2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi,
+-   and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN.  Process
+-   these keys on userspace somehow (e.g. by calling xbacklight).
+-   The driver will do this automatically if it detects that ACPI video
+-   has been disabled.
++The driver will issue KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN events
++automatically for the cases were userspace has to do something to
++implement brightness changes.  When you override these events, you will
++either fail to handle properly the ThinkPads that require explicit
++action to change backlight brightness, or the ThinkPads that require
++that no action be taken to work properly.
+ Bluetooth
+@@ -1465,3 +1436,5 @@ Sysfs interface changelog:
+               and it is always able to disable hot keys.  Very old
+               thinkpads are properly supported.  hotkey_bios_mask
+               is deprecated and marked for removal.
++
++0x020600:     Marker for backlight change event support.
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -22,7 +22,7 @@
+  */
+ #define TPACPI_VERSION "0.23"
+-#define TPACPI_SYSFS_VERSION 0x020500
++#define TPACPI_SYSFS_VERSION 0x020600
+ /*
+  *  Changelog:
+@@ -6083,6 +6083,12 @@ static int brightness_get(struct backlig
+       return status & TP_EC_BACKLIGHT_LVLMSK;
+ }
++static void tpacpi_brightness_notify_change(void)
++{
++      backlight_force_update(ibm_backlight_device,
++                             BACKLIGHT_UPDATE_HOTKEY);
++}
++
+ static struct backlight_ops ibm_backlight_data = {
+       .get_brightness = brightness_get,
+       .update_status  = brightness_update_status,
+@@ -6237,6 +6243,12 @@ static int __init brightness_init(struct
+       ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
+       backlight_update_status(ibm_backlight_device);
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
++                      "brightness: registering brightness hotkeys "
++                      "as change notification\n");
++      tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
++                              | TP_ACPI_HKEY_BRGHTUP_MASK
++                              | TP_ACPI_HKEY_BRGHTDWN_MASK);;
+       return 0;
+ }
+@@ -6313,6 +6325,9 @@ static int brightness_write(char *buf)
+        * Doing it this way makes the syscall restartable in case of EINTR
+        */
+       rc = brightness_set(level);
++      if (!rc && ibm_backlight_device)
++              backlight_force_update(ibm_backlight_device,
++                                      BACKLIGHT_UPDATE_SYSFS);
+       return (rc == -EINTR)? -ERESTARTSYS : rc;
+ }
+@@ -7712,6 +7727,13 @@ static struct ibm_struct fan_driver_data
+  */
+ static void tpacpi_driver_event(const unsigned int hkey_event)
+ {
++      if (ibm_backlight_device) {
++              switch (hkey_event) {
++              case TP_HKEY_EV_BRGHT_UP:
++              case TP_HKEY_EV_BRGHT_DOWN:
++                      tpacpi_brightness_notify_change();
++              }
++      }
+ }
diff --git a/queue-2.6.32/thinkpad-acpi-lock-down-video-output-state-access.patch b/queue-2.6.32/thinkpad-acpi-lock-down-video-output-state-access.patch
new file mode 100644 (file)
index 0000000..620846a
--- /dev/null
@@ -0,0 +1,117 @@
+From b525c06cdbd8a3963f0173ccd23f9147d4c384b5 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Thu, 25 Feb 2010 22:22:22 -0300
+Subject: thinkpad-acpi: lock down video output state access
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit b525c06cdbd8a3963f0173ccd23f9147d4c384b5 upstream.
+
+Given the right combination of ThinkPad and X.org, just reading the
+video output control state is enough to hard-crash X.org.
+
+Until the day I somehow find out a model or BIOS cut date to not
+provide this feature to ThinkPads that can do video switching through
+X RandR, change permissions so that only processes with CAP_SYS_ADMIN
+can access any sort of video output control state.
+
+This bug could be considered a local DoS I suppose, as it allows any
+non-privledged local user to cause some versions of X.org to
+hard-crash some ThinkPads.
+
+Reported-by: Jidanni <jidanni@jidanni.org>
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/laptops/thinkpad-acpi.txt |    4 ++++
+ drivers/platform/x86/Kconfig            |   10 ++++++++--
+ drivers/platform/x86/thinkpad_acpi.c    |   15 +++++++++++++--
+ 3 files changed, 25 insertions(+), 4 deletions(-)
+
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -650,6 +650,10 @@ LCD, CRT or DVI (if available). The foll
+       echo expand_toggle > /proc/acpi/ibm/video
+       echo video_switch > /proc/acpi/ibm/video
++NOTE: Access to this feature is restricted to processes owning the
++CAP_SYS_ADMIN capability for safety reasons, as it can interact badly
++enough with some versions of X.org to crash it.
++
+ Each video output device can be enabled or disabled individually.
+ Reading /proc/acpi/ibm/video shows the status of each device.
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -291,9 +291,15 @@ config THINKPAD_ACPI_VIDEO
+         server running, phase of the moon, and the current mood of
+         Schroedinger's cat.  If you can use X.org's RandR to control
+         your ThinkPad's video output ports instead of this feature,
+-        don't think twice: do it and say N here to save some memory.
++        don't think twice: do it and say N here to save memory and avoid
++        bad interactions with X.org.
+-        If you are not sure, say Y here.
++        NOTE: access to this feature is limited to processes with the
++        CAP_SYS_ADMIN capability, to avoid local DoS issues in platforms
++        where it interacts badly with X.org.
++
++        If you are not sure, say Y here but do try to check if you could
++        be using X.org RandR instead.
+ config THINKPAD_ACPI_HOTKEY_POLL
+       bool "Support NVRAM polling for hot keys"
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -281,6 +281,7 @@ struct ibm_init_struct {
+       char param[32];
+       int (*init) (struct ibm_init_struct *);
++      mode_t base_procfs_mode;
+       struct ibm_struct *data;
+ };
+@@ -4620,6 +4621,10 @@ static int video_read(struct seq_file *m
+               return 0;
+       }
++      /* Even reads can crash X.org, so... */
++      if (!capable(CAP_SYS_ADMIN))
++              return -EPERM;
++
+       status = video_outputsw_get();
+       if (status < 0)
+               return status;
+@@ -4653,6 +4658,10 @@ static int video_write(char *buf)
+       if (video_supported == TPACPI_VIDEO_NONE)
+               return -ENODEV;
++      /* Even reads can crash X.org, let alone writes... */
++      if (!capable(CAP_SYS_ADMIN))
++              return -EPERM;
++
+       enable = 0;
+       disable = 0;
+@@ -7887,9 +7896,10 @@ static int __init ibm_init(struct ibm_in
+               "%s installed\n", ibm->name);
+       if (ibm->read) {
+-              mode_t mode;
++              mode_t mode = iibm->base_procfs_mode;
+-              mode = S_IRUGO;
++              if (!mode)
++                      mode = S_IRUGO;
+               if (ibm->write)
+                       mode |= S_IWUSR;
+               entry = proc_create_data(ibm->name, mode, proc_dir,
+@@ -8080,6 +8090,7 @@ static struct ibm_init_struct ibms_init[
+ #ifdef CONFIG_THINKPAD_ACPI_VIDEO
+       {
+               .init = video_init,
++              .base_procfs_mode = S_IRUSR,
+               .data = &video_driver_data,
+       },
+ #endif
diff --git a/queue-2.6.32/thinkpad-acpi-log-initial-state-of-rfkill-switches.patch b/queue-2.6.32/thinkpad-acpi-log-initial-state-of-rfkill-switches.patch
new file mode 100644 (file)
index 0000000..7a60056
--- /dev/null
@@ -0,0 +1,51 @@
+From 5451a923bbdcff6ae665947e120af7238b21a9d2 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Tue, 15 Dec 2009 21:51:07 -0200
+Subject: thinkpad-acpi: log initial state of rfkill switches
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit 5451a923bbdcff6ae665947e120af7238b21a9d2 upstream.
+
+We already log the initial state of the hardware rfkill switch (WLSW),
+might as well log the state of the softswitches as well.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Cc: Josip Rodin <joy+kernel@entuzijast.net>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/thinkpad_acpi.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -1264,6 +1264,7 @@ static int __init tpacpi_new_rfkill(cons
+       struct tpacpi_rfk *atp_rfk;
+       int res;
+       bool sw_state = false;
++      bool hw_state;
+       int sw_status;
+       BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
+@@ -1298,7 +1299,8 @@ static int __init tpacpi_new_rfkill(cons
+                       rfkill_init_sw_state(atp_rfk->rfkill, sw_state);
+               }
+       }
+-      rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state());
++      hw_state = tpacpi_rfk_check_hwblock_state();
++      rfkill_set_hw_state(atp_rfk->rfkill, hw_state);
+       res = rfkill_register(atp_rfk->rfkill);
+       if (res < 0) {
+@@ -1311,6 +1313,9 @@ static int __init tpacpi_new_rfkill(cons
+       }
+       tpacpi_rfkill_switches[id] = atp_rfk;
++
++      printk(TPACPI_INFO "rfkill switch %s: radio is %sblocked\n",
++              name, (sw_state || hw_state) ? "" : "un");
+       return 0;
+ }
diff --git a/queue-2.6.32/thinkpad-acpi-log-temperatures-on-termal-alarm-v2.patch b/queue-2.6.32/thinkpad-acpi-log-temperatures-on-termal-alarm-v2.patch
new file mode 100644 (file)
index 0000000..0f27641
--- /dev/null
@@ -0,0 +1,142 @@
+From 9ebd9e833648745fa5ac6998b9e0153ccd3ba839 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Wed, 9 Dec 2009 01:36:28 +0000
+Subject: thinkpad-acpi: log temperatures on termal alarm (v2)
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit 9ebd9e833648745fa5ac6998b9e0153ccd3ba839 upstream.
+
+Log temperatures on any of the EC thermal alarms.  It could be
+useful to help tracking down what is happening...
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Acked-by: Pavel Machek <pavel@ucw.cz>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/thinkpad_acpi.c |   57 +++++++++++++++++++++++++++--------
+ 1 file changed, 45 insertions(+), 12 deletions(-)
+
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -3548,49 +3548,57 @@ static bool hotkey_notify_usrevent(const
+       }
+ }
++static void thermal_dump_all_sensors(void);
++
+ static bool hotkey_notify_thermal(const u32 hkey,
+                                bool *send_acpi_ev,
+                                bool *ignore_acpi_ev)
+ {
++      bool known = true;
++
+       /* 0x6000-0x6FFF: thermal alarms */
+       *send_acpi_ev = true;
+       *ignore_acpi_ev = false;
+       switch (hkey) {
++      case TP_HKEY_EV_THM_TABLE_CHANGED:
++              printk(TPACPI_INFO
++                      "EC reports that Thermal Table has changed\n");
++              /* recommended action: do nothing, we don't have
++               * Lenovo ATM information */
++              return true;
+       case TP_HKEY_EV_ALARM_BAT_HOT:
+               printk(TPACPI_CRIT
+                       "THERMAL ALARM: battery is too hot!\n");
+               /* recommended action: warn user through gui */
+-              return true;
++              break;
+       case TP_HKEY_EV_ALARM_BAT_XHOT:
+               printk(TPACPI_ALERT
+                       "THERMAL EMERGENCY: battery is extremely hot!\n");
+               /* recommended action: immediate sleep/hibernate */
+-              return true;
++              break;
+       case TP_HKEY_EV_ALARM_SENSOR_HOT:
+               printk(TPACPI_CRIT
+                       "THERMAL ALARM: "
+                       "a sensor reports something is too hot!\n");
+               /* recommended action: warn user through gui, that */
+               /* some internal component is too hot */
+-              return true;
++              break;
+       case TP_HKEY_EV_ALARM_SENSOR_XHOT:
+               printk(TPACPI_ALERT
+                       "THERMAL EMERGENCY: "
+                       "a sensor reports something is extremely hot!\n");
+               /* recommended action: immediate sleep/hibernate */
+-              return true;
+-      case TP_HKEY_EV_THM_TABLE_CHANGED:
+-              printk(TPACPI_INFO
+-                      "EC reports that Thermal Table has changed\n");
+-              /* recommended action: do nothing, we don't have
+-               * Lenovo ATM information */
+-              return true;
++              break;
+       default:
+               printk(TPACPI_ALERT
+                        "THERMAL ALERT: unknown thermal alarm received\n");
+-              return false;
++              known = false;
+       }
++
++      thermal_dump_all_sensors();
++
++      return known;
+ }
+ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
+@@ -5472,8 +5480,11 @@ enum { /* TPACPI_THERMAL_TPEC_* */
+       TP_EC_THERMAL_TMP0 = 0x78,      /* ACPI EC regs TMP 0..7 */
+       TP_EC_THERMAL_TMP8 = 0xC0,      /* ACPI EC regs TMP 8..15 */
+       TP_EC_THERMAL_TMP_NA = -128,    /* ACPI EC sensor not available */
++
++      TPACPI_THERMAL_SENSOR_NA = -128000, /* Sensor not available */
+ };
++
+ #define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
+ struct ibm_thermal_sensors_struct {
+       s32 temp[TPACPI_MAX_THERMAL_SENSORS];
+@@ -5563,6 +5574,28 @@ static int thermal_get_sensors(struct ib
+       return n;
+ }
++static void thermal_dump_all_sensors(void)
++{
++      int n, i;
++      struct ibm_thermal_sensors_struct t;
++
++      n = thermal_get_sensors(&t);
++      if (n <= 0)
++              return;
++
++      printk(TPACPI_NOTICE
++              "temperatures (Celsius):");
++
++      for (i = 0; i < n; i++) {
++              if (t.temp[i] != TPACPI_THERMAL_SENSOR_NA)
++                      printk(KERN_CONT " %d", (int)(t.temp[i] / 1000));
++              else
++                      printk(KERN_CONT " N/A");
++      }
++
++      printk(KERN_CONT "\n");
++}
++
+ /* sysfs temp##_input -------------------------------------------------- */
+ static ssize_t thermal_temp_input_show(struct device *dev,
+@@ -5578,7 +5611,7 @@ static ssize_t thermal_temp_input_show(s
+       res = thermal_get_sensor(idx, &value);
+       if (res)
+               return res;
+-      if (value == TP_EC_THERMAL_TMP_NA * 1000)
++      if (value == TPACPI_THERMAL_SENSOR_NA)
+               return -ENXIO;
+       return snprintf(buf, PAGE_SIZE, "%d\n", value);
diff --git a/queue-2.6.32/thinkpad-acpi-silence-bogus-complain-during-rmmod.patch b/queue-2.6.32/thinkpad-acpi-silence-bogus-complain-during-rmmod.patch
new file mode 100644 (file)
index 0000000..94a510b
--- /dev/null
@@ -0,0 +1,34 @@
+From 6b30eb7d211840ba1a03f855d9e7b80a921368f2 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Wed, 9 Dec 2009 01:36:25 +0000
+Subject: thinkpad-acpi: silence bogus complain during rmmod
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit 6b30eb7d211840ba1a03f855d9e7b80a921368f2 upstream.
+
+Fix this bogus warning during module shutdown, when
+backlight event reporting is enabled:
+
+"thinkpad_acpi: required events 0x00018000 not enabled!"
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/thinkpad_acpi.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -2190,7 +2190,8 @@ static int hotkey_mask_set(u32 mask)
+                      fwmask, hotkey_acpi_mask);
+       }
+-      hotkey_mask_warn_incomplete_mask();
++      if (tpacpi_lifecycle != TPACPI_LIFE_EXITING)
++              hotkey_mask_warn_incomplete_mask();
+       return rc;
+ }
diff --git a/queue-2.6.32/thinkpad-acpi-sync-input-device-ev_sw-initial-state.patch b/queue-2.6.32/thinkpad-acpi-sync-input-device-ev_sw-initial-state.patch
new file mode 100644 (file)
index 0000000..b897300
--- /dev/null
@@ -0,0 +1,92 @@
+From d89a727aff649f6768f7a34ee57f031ebf8bab4c Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Tue, 15 Dec 2009 21:51:06 -0200
+Subject: thinkpad-acpi: sync input device EV_SW initial state
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit d89a727aff649f6768f7a34ee57f031ebf8bab4c upstream.
+
+Before we register the input device, sync the input layer EV_SW state
+through a call to input_report_switch(), to avoid issuing a gratuitous
+event for the initial state of these switches.
+
+This fixes some annoyances caused by the interaction with rfkill and
+EV_SW SW_RFKILL_ALL events.
+
+Reported-by: Kevin Locke <kevin@kevinlocke.name>
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Cc: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
+Cc: Johannes Berg <johannes@sipsolutions.net>
+Cc: Dmitry Torokhov <dtor@mail.ru>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/thinkpad_acpi.c |   14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -3188,6 +3188,8 @@ static int __init hotkey_init(struct ibm
+       int res, i;
+       int status;
+       int hkeyv;
++      bool radiosw_state  = false;
++      bool tabletsw_state = false;
+       unsigned long quirks;
+@@ -3293,6 +3295,7 @@ static int __init hotkey_init(struct ibm
+ #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+       if (dbg_wlswemul) {
+               tp_features.hotkey_wlsw = 1;
++              radiosw_state = !!tpacpi_wlsw_emulstate;
+               printk(TPACPI_INFO
+                       "radio switch emulation enabled\n");
+       } else
+@@ -3300,6 +3303,7 @@ static int __init hotkey_init(struct ibm
+       /* Not all thinkpads have a hardware radio switch */
+       if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
+               tp_features.hotkey_wlsw = 1;
++              radiosw_state = !!status;
+               printk(TPACPI_INFO
+                       "radio switch found; radios are %s\n",
+                       enabled(status, 0));
+@@ -3311,11 +3315,11 @@ static int __init hotkey_init(struct ibm
+       /* For X41t, X60t, X61t Tablets... */
+       if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
+               tp_features.hotkey_tablet = 1;
++              tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK);
+               printk(TPACPI_INFO
+                       "possible tablet mode switch found; "
+                       "ThinkPad in %s mode\n",
+-                      (status & TP_HOTKEY_TABLET_MASK)?
+-                              "tablet" : "laptop");
++                      (tabletsw_state) ? "tablet" : "laptop");
+               res = add_to_attr_set(hotkey_dev_attributes,
+                               &dev_attr_hotkey_tablet_mode.attr);
+       }
+@@ -3366,9 +3370,13 @@ static int __init hotkey_init(struct ibm
+       if (tp_features.hotkey_wlsw) {
+               input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL);
++              input_report_switch(tpacpi_inputdev,
++                                  SW_RFKILL_ALL, radiosw_state);
+       }
+       if (tp_features.hotkey_tablet) {
+               input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE);
++              input_report_switch(tpacpi_inputdev,
++                                  SW_TABLET_MODE, tabletsw_state);
+       }
+       /* Do not issue duplicate brightness change events to
+@@ -3435,8 +3443,6 @@ static int __init hotkey_init(struct ibm
+       tpacpi_inputdev->close = &hotkey_inputdev_close;
+       hotkey_poll_setup_safe(true);
+-      tpacpi_send_radiosw_update();
+-      tpacpi_input_send_tabletsw();
+       return 0;
diff --git a/queue-2.6.32/thinkpad-acpi-use-input_set_capability.patch b/queue-2.6.32/thinkpad-acpi-use-input_set_capability.patch
new file mode 100644 (file)
index 0000000..704e221
--- /dev/null
@@ -0,0 +1,57 @@
+From 792979c8032b8f5adb77ea986db7082fff04c8e7 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Wed, 9 Dec 2009 01:36:29 +0000
+Subject: thinkpad-acpi: use input_set_capability
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+commit 792979c8032b8f5adb77ea986db7082fff04c8e7 upstream.
+
+Use input_set_capability() instead of set_bit.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Cc: Dmitry Torokhov <dtor@mail.ru>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/thinkpad_acpi.c |   14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -3350,16 +3350,14 @@ static int __init hotkey_init(struct ibm
+                       TPACPI_HOTKEY_MAP_SIZE);
+       }
+-      set_bit(EV_KEY, tpacpi_inputdev->evbit);
+-      set_bit(EV_MSC, tpacpi_inputdev->evbit);
+-      set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
++      input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
+       tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
+       tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
+       tpacpi_inputdev->keycode = hotkey_keycode_map;
+       for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
+               if (hotkey_keycode_map[i] != KEY_RESERVED) {
+-                      set_bit(hotkey_keycode_map[i],
+-                              tpacpi_inputdev->keybit);
++                      input_set_capability(tpacpi_inputdev, EV_KEY,
++                                              hotkey_keycode_map[i]);
+               } else {
+                       if (i < sizeof(hotkey_reserved_mask)*8)
+                               hotkey_reserved_mask |= 1 << i;
+@@ -3367,12 +3365,10 @@ static int __init hotkey_init(struct ibm
+       }
+       if (tp_features.hotkey_wlsw) {
+-              set_bit(EV_SW, tpacpi_inputdev->evbit);
+-              set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit);
++              input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL);
+       }
+       if (tp_features.hotkey_tablet) {
+-              set_bit(EV_SW, tpacpi_inputdev->evbit);
+-              set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
++              input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE);
+       }
+       /* Do not issue duplicate brightness change events to
diff --git a/queue-2.6.32/x86-amd-get-multi-node-cpu-info-from-nodeid-msr-instead-of-pci-config-space.patch b/queue-2.6.32/x86-amd-get-multi-node-cpu-info-from-nodeid-msr-instead-of-pci-config-space.patch
new file mode 100644 (file)
index 0000000..f0fed9e
--- /dev/null
@@ -0,0 +1,119 @@
+From 9d260ebc09a0ad6b5c73e17676df42c7bc75ff64 Mon Sep 17 00:00:00 2001
+From: Andreas Herrmann <herrmann.der.user@googlemail.com>
+Date: Wed, 16 Dec 2009 15:43:55 +0100
+Subject: x86, amd: Get multi-node CPU info from NodeId MSR instead of PCI config space
+
+From: Andreas Herrmann <herrmann.der.user@googlemail.com>
+
+commit 9d260ebc09a0ad6b5c73e17676df42c7bc75ff64 upstream.
+
+Use NodeId MSR to get NodeId and number of nodes per processor.
+
+Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
+LKML-Reference: <20091216144355.GB28798@alberich.amd.com>
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/include/asm/cpufeature.h |    1 
+ arch/x86/include/asm/msr-index.h  |    1 
+ arch/x86/kernel/cpu/amd.c         |   53 ++++++++++----------------------------
+ 3 files changed, 17 insertions(+), 38 deletions(-)
+
+--- a/arch/x86/include/asm/cpufeature.h
++++ b/arch/x86/include/asm/cpufeature.h
+@@ -153,6 +153,7 @@
+ #define X86_FEATURE_SSE5      (6*32+11) /* SSE-5 */
+ #define X86_FEATURE_SKINIT    (6*32+12) /* SKINIT/STGI instructions */
+ #define X86_FEATURE_WDT               (6*32+13) /* Watchdog timer */
++#define X86_FEATURE_NODEID_MSR        (6*32+19) /* NodeId MSR */
+ /*
+  * Auxiliary flags: Linux defined - For features scattered in various
+--- a/arch/x86/include/asm/msr-index.h
++++ b/arch/x86/include/asm/msr-index.h
+@@ -125,6 +125,7 @@
+ #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
+ #define FAM10H_MMIO_CONF_BASE_MASK    0xfffffff
+ #define FAM10H_MMIO_CONF_BASE_SHIFT   20
++#define MSR_FAM10H_NODE_ID            0xc001100c
+ /* K8 MSRs */
+ #define MSR_K8_TOP_MEM1                       0xc001001a
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -254,59 +254,36 @@ static int __cpuinit nearby_node(int api
+ /*
+  * Fixup core topology information for AMD multi-node processors.
+- * Assumption 1: Number of cores in each internal node is the same.
+- * Assumption 2: Mixed systems with both single-node and dual-node
+- *               processors are not supported.
++ * Assumption: Number of cores in each internal node is the same.
+  */
+ #ifdef CONFIG_X86_HT
+ static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
+ {
+-#ifdef CONFIG_PCI
+-      u32 t, cpn;
+-      u8 n, n_id;
++      unsigned long long value;
++      u32 nodes, cores_per_node;
+       int cpu = smp_processor_id();
++      if (!cpu_has(c, X86_FEATURE_NODEID_MSR))
++              return;
++
+       /* fixup topology information only once for a core */
+       if (cpu_has(c, X86_FEATURE_AMD_DCM))
+               return;
+-      /* check for multi-node processor on boot cpu */
+-      t = read_pci_config(0, 24, 3, 0xe8);
+-      if (!(t & (1 << 29)))
++      rdmsrl(MSR_FAM10H_NODE_ID, value);
++
++      nodes = ((value >> 3) & 7) + 1;
++      if (nodes == 1)
+               return;
+       set_cpu_cap(c, X86_FEATURE_AMD_DCM);
++      cores_per_node = c->x86_max_cores / nodes;
+-      /* cores per node: each internal node has half the number of cores */
+-      cpn = c->x86_max_cores >> 1;
+-
+-      /* even-numbered NB_id of this dual-node processor */
+-      n = c->phys_proc_id << 1;
++      /* store NodeID, use llc_shared_map to store sibling info */
++      per_cpu(cpu_llc_id, cpu) = value & 7;
+-      /*
+-       * determine internal node id and assign cores fifty-fifty to
+-       * each node of the dual-node processor
+-       */
+-      t = read_pci_config(0, 24 + n, 3, 0xe8);
+-      n = (t>>30) & 0x3;
+-      if (n == 0) {
+-              if (c->cpu_core_id < cpn)
+-                      n_id = 0;
+-              else
+-                      n_id = 1;
+-      } else {
+-              if (c->cpu_core_id < cpn)
+-                      n_id = 1;
+-              else
+-                      n_id = 0;
+-      }
+-
+-      /* compute entire NodeID, use llc_shared_map to store sibling info */
+-      per_cpu(cpu_llc_id, cpu) = (c->phys_proc_id << 1) + n_id;
+-
+-      /* fixup core id to be in range from 0 to cpn */
+-      c->cpu_core_id = c->cpu_core_id % cpn;
+-#endif
++      /* fixup core id to be in range from 0 to (cores_per_node - 1) */
++      c->cpu_core_id = c->cpu_core_id % cores_per_node;
+ }
+ #endif