From: Greg Kroah-Hartman Date: Thu, 6 Aug 2009 20:19:56 +0000 (-0700) Subject: start .27 queue X-Git-Tag: v2.6.30.5~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=58cf2b463ff8bda1ac2783b209ce90a6d37dc1a0;p=thirdparty%2Fkernel%2Fstable-queue.git start .27 queue --- diff --git a/queue-2.6.27/hugetlbfs-fix-i_blocks-accounting.patch b/queue-2.6.27/hugetlbfs-fix-i_blocks-accounting.patch new file mode 100644 index 00000000000..46521ceffe9 --- /dev/null +++ b/queue-2.6.27/hugetlbfs-fix-i_blocks-accounting.patch @@ -0,0 +1,56 @@ +From e4c6f8bed01f9f9a5c607bd689bf67e7b8a36bd8 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Wed, 29 Jul 2009 15:02:16 -0700 +Subject: hugetlbfs: fix i_blocks accounting + +From: Eric Sandeen + +commit e4c6f8bed01f9f9a5c607bd689bf67e7b8a36bd8 upstream. + +As reported in Red Hat bz #509671, i_blocks for files on hugetlbfs get +accounting wrong when doing something like: + + $ > foo + $ date > foo + date: write error: Invalid argument + $ /usr/bin/stat foo + File: `foo' + Size: 0 Blocks: 18446744073709547520 IO Block: 2097152 regular +... + +This is because hugetlb_unreserve_pages() is unconditionally removing +blocks_per_huge_page(h) on each call rather than using the freed amount. +If there were 0 blocks, it goes negative, resulting in the above. + +This is a regression from commit a5516438959d90b071ff0a484ce4f3f523dc3152 +("hugetlb: modular state for hugetlb page size") + +which did: + +- inode->i_blocks -= BLOCKS_PER_HUGEPAGE * freed; ++ inode->i_blocks -= blocks_per_huge_page(h); + +so just put back the freed multiplier, and it's all happy again. + +Signed-off-by: Eric Sandeen +Acked-by: Andi Kleen +Cc: William Lee Irwin III +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/hugetlb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2257,7 +2257,7 @@ void hugetlb_unreserve_pages(struct inod + long chg = region_truncate(&inode->i_mapping->private_list, offset); + + spin_lock(&inode->i_lock); +- inode->i_blocks -= blocks_per_huge_page(h); ++ inode->i_blocks -= (blocks_per_huge_page(h) * freed); + spin_unlock(&inode->i_lock); + + hugetlb_put_quota(inode->i_mapping, (chg - freed)); diff --git a/queue-2.6.27/hwmon-differentiate-between-lpc47m233-and-lpc47m292.patch b/queue-2.6.27/hwmon-differentiate-between-lpc47m233-and-lpc47m292.patch new file mode 100644 index 00000000000..8617d3a9b4f --- /dev/null +++ b/queue-2.6.27/hwmon-differentiate-between-lpc47m233-and-lpc47m292.patch @@ -0,0 +1,55 @@ +From 1b54ab450b180eaeeb0eee6f0f64349246a22c14 Mon Sep 17 00:00:00 2001 +From: Jean Delvare +Date: Tue, 28 Jul 2009 16:31:39 +0200 +Subject: hwmon: (smsc47m1) Differentiate between LPC47M233 and LPC47M292 + +From: Jean Delvare + +commit 1b54ab450b180eaeeb0eee6f0f64349246a22c14 upstream. + +The SMSC LPC47M233 and LPC47M292 chips have the same device ID but +are not compatible. + +Signed-off-by: Jean Delvare +Cc: Juerg Haefliger +Acked-by: Hans de Goede +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwmon/smsc47m1.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/hwmon/smsc47m1.c ++++ b/drivers/hwmon/smsc47m1.c +@@ -85,6 +85,7 @@ superio_exit(void) + #define SUPERIO_REG_ACT 0x30 + #define SUPERIO_REG_BASE 0x60 + #define SUPERIO_REG_DEVID 0x20 ++#define SUPERIO_REG_DEVREV 0x21 + + /* Logical device registers */ + +@@ -428,6 +429,9 @@ static int __init smsc47m1_find(unsigned + * The LPC47M292 (device id 0x6B) is somewhat compatible, but it + * supports a 3rd fan, and the pin configuration registers are + * unfortunately different. ++ * The LPC47M233 has the same device id (0x6B) but is not compatible. ++ * We check the high bit of the device revision register to ++ * differentiate them. + */ + switch (val) { + case 0x51: +@@ -447,6 +451,13 @@ static int __init smsc47m1_find(unsigned + sio_data->type = smsc47m1; + break; + case 0x6B: ++ if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) { ++ pr_debug(DRVNAME ": " ++ "Found SMSC LPC47M233, unsupported\n"); ++ superio_exit(); ++ return -ENODEV; ++ } ++ + pr_info(DRVNAME ": Found SMSC LPC47M292\n"); + sio_data->type = smsc47m2; + break; diff --git a/queue-2.6.27/i2c-tsl2550-fix-lux-value-in-dark-environment.patch b/queue-2.6.27/i2c-tsl2550-fix-lux-value-in-dark-environment.patch new file mode 100644 index 00000000000..ceb98928bfc --- /dev/null +++ b/queue-2.6.27/i2c-tsl2550-fix-lux-value-in-dark-environment.patch @@ -0,0 +1,59 @@ +From 96f699ad09c8b3c55cd229506a9add0047838e3e Mon Sep 17 00:00:00 2001 +From: Michele Jr De Candia +Date: Tue, 28 Jul 2009 16:33:03 +0200 +Subject: i2c/tsl2550: Fix lux value in dark environment + +From: Michele Jr De Candia + +commit 96f699ad09c8b3c55cd229506a9add0047838e3e upstream. + +I've tested TSL2550 driver and I've found a bug: when light is off, +returned value from tsl2550_calculate_lux function is -1 when it should +be 0 (sensor correctly read that light was off). + +I think the bug is that a zero c0 value (approximated value of ch0) is +misinterpreted as an error. + +Signed-off-by: Michele Jr De Candia +Acked-by: Rodolfo Giometti +Signed-off-by: Jean Delvare +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/i2c/chips/tsl2550.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/i2c/chips/tsl2550.c ++++ b/drivers/i2c/chips/tsl2550.c +@@ -27,7 +27,7 @@ + #include + + #define TSL2550_DRV_NAME "tsl2550" +-#define DRIVER_VERSION "1.1.1" ++#define DRIVER_VERSION "1.1.2" + + /* + * Defines +@@ -189,13 +189,16 @@ static int tsl2550_calculate_lux(u8 ch0, + u8 r = 128; + + /* Avoid division by 0 and count 1 cannot be greater than count 0 */ +- if (c0 && (c1 <= c0)) +- r = c1 * 128 / c0; ++ if (c1 <= c0) ++ if (c0) { ++ r = c1 * 128 / c0; ++ ++ /* Calculate LUX */ ++ lux = ((c0 - c1) * ratio_lut[r]) / 256; ++ } else ++ lux = 0; + else +- return -1; +- +- /* Calculate LUX */ +- lux = ((c0 - c1) * ratio_lut[r]) / 256; ++ return -EAGAIN; + + /* LUX range check */ + return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux; diff --git a/queue-2.6.27/libsas-reuse-the-original-port-when-hotplugging-phys-in-wide-ports.patch b/queue-2.6.27/libsas-reuse-the-original-port-when-hotplugging-phys-in-wide-ports.patch new file mode 100644 index 00000000000..018009a64d2 --- /dev/null +++ b/queue-2.6.27/libsas-reuse-the-original-port-when-hotplugging-phys-in-wide-ports.patch @@ -0,0 +1,66 @@ +From 5381837f125cc62ad703fbcdfcd7566fc81fd404 Mon Sep 17 00:00:00 2001 +From: Tom Peng +Date: Wed, 1 Jul 2009 20:37:26 +0800 +Subject: SCSI: libsas: reuse the original port when hotplugging phys in wide ports + +From: Tom Peng + +commit 5381837f125cc62ad703fbcdfcd7566fc81fd404 upstream. + +There's a hotplug problem in the way libsas allocates ports: it loops over the +available ports first trying to add to an existing for a wide port and +otherwise allocating the next free port. This scheme only works if the port +array is packed from zero, which fails if a port gets hot unplugged and the +array becomes sparse. In that case, a new port is formed even if there's a +wide port it should be part of. Fix this by creating two loops over all the +ports: the first to see if the phy should be part of a wide port and the +second to form a new port in an empty port slot. + +Signed-off-by: Tom Peng +Signed-off-by: Jack Wang +Signed-off-by: Lindar Liu +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/libsas/sas_port.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/libsas/sas_port.c ++++ b/drivers/scsi/libsas/sas_port.c +@@ -56,7 +56,7 @@ static void sas_form_port(struct asd_sas + } + } + +- /* find a port */ ++ /* see if the phy should be part of a wide port */ + spin_lock_irqsave(&sas_ha->phy_port_lock, flags); + for (i = 0; i < sas_ha->num_phys; i++) { + port = sas_ha->sas_port[i]; +@@ -69,12 +69,23 @@ static void sas_form_port(struct asd_sas + SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, + port->id); + break; +- } else if (*(u64 *) port->sas_addr == 0 && port->num_phys==0) { +- memcpy(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE); +- break; + } + spin_unlock(&port->phy_list_lock); + } ++ /* The phy does not match any existing port, create a new one */ ++ if (i == sas_ha->num_phys) { ++ for (i = 0; i < sas_ha->num_phys; i++) { ++ port = sas_ha->sas_port[i]; ++ spin_lock(&port->phy_list_lock); ++ if (*(u64 *)port->sas_addr == 0 ++ && port->num_phys == 0) { ++ memcpy(port->sas_addr, phy->sas_addr, ++ SAS_ADDR_SIZE); ++ break; ++ } ++ spin_unlock(&port->phy_list_lock); ++ } ++ } + + if (i >= sas_ha->num_phys) { + printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n", diff --git a/queue-2.6.27/make-scsi-sg-v4-driver-enabled-by-default-and-remove-experimental-dependency-since-udev-depends-on-bsg.patch b/queue-2.6.27/make-scsi-sg-v4-driver-enabled-by-default-and-remove-experimental-dependency-since-udev-depends-on-bsg.patch new file mode 100644 index 00000000000..18ace2c0433 --- /dev/null +++ b/queue-2.6.27/make-scsi-sg-v4-driver-enabled-by-default-and-remove-experimental-dependency-since-udev-depends-on-bsg.patch @@ -0,0 +1,50 @@ +From 14d9fa352592582e457cf75022202766baac1348 Mon Sep 17 00:00:00 2001 +From: John Stoffel +Date: Tue, 4 Aug 2009 22:10:17 +0200 +Subject: Make SCSI SG v4 driver enabled by default and remove EXPERIMENTAL dependency, since udev depends on BSG + +From: John Stoffel + +commit 14d9fa352592582e457cf75022202766baac1348 upstream. + +Make Block Layer SG support v4 the default, since recent udev versions +depend on this to access serial numbers and other low level info properly. + +This should be backported to older kernels as well, since most distros have +enabled this for a long time. + +Signed-off-by: John Stoffel +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + block/Kconfig | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/block/Kconfig ++++ b/block/Kconfig +@@ -67,9 +67,9 @@ config LSF + If unsure, say Y. + + config BLK_DEV_BSG +- bool "Block layer SG support v4 (EXPERIMENTAL)" +- depends on EXPERIMENTAL +- ---help--- ++ bool "Block layer SG support v4" ++ default y ++ help + Saying Y here will enable generic SG (SCSI generic) v4 support + for any block device. + +@@ -79,7 +79,10 @@ config BLK_DEV_BSG + protocols (e.g. Task Management Functions and SMP in Serial + Attached SCSI). + +- If unsure, say N. ++ This option is required by recent UDEV versions to properly ++ access device serial numbers, etc. ++ ++ If unsure, say Y. + + config BLK_DEV_INTEGRITY + bool "Block layer data integrity support" diff --git a/queue-2.6.27/page-allocator-preserve-pfn-ordering-when-__gfp_cold-is-set.patch b/queue-2.6.27/page-allocator-preserve-pfn-ordering-when-__gfp_cold-is-set.patch new file mode 100644 index 00000000000..0b79b3f5e7c --- /dev/null +++ b/queue-2.6.27/page-allocator-preserve-pfn-ordering-when-__gfp_cold-is-set.patch @@ -0,0 +1,83 @@ +From e084b2d95e48b31aa45f9c49ffc6cdae8bdb21d4 Mon Sep 17 00:00:00 2001 +From: Mel Gorman +Date: Wed, 29 Jul 2009 15:02:04 -0700 +Subject: page-allocator: preserve PFN ordering when __GFP_COLD is set + +From: Mel Gorman + +commit e084b2d95e48b31aa45f9c49ffc6cdae8bdb21d4 upstream. + +Fix a post-2.6.24 performace regression caused by +3dfa5721f12c3d5a441448086bee156887daa961 ("page-allocator: preserve PFN +ordering when __GFP_COLD is set"). + +Narayanan reports "The regression is around 15%. There is no disk controller +as our setup is based on Samsung OneNAND used as a memory mapped device on a +OMAP2430 based board." + +The page allocator tries to preserve contiguous PFN ordering when returning +pages such that repeated callers to the allocator have a strong chance of +getting physically contiguous pages, particularly when external fragmentation +is low. However, of the bulk of the allocations have __GFP_COLD set as they +are due to aio_read() for example, then the PFNs are in reverse PFN order. +This can cause performance degration when used with IO controllers that could +have merged the requests. + +This patch attempts to preserve the contiguous ordering of PFNs for users of +__GFP_COLD. + +Signed-off-by: Mel Gorman +Reported-by: Narayananu Gopalakrishnan +Tested-by: Narayanan Gopalakrishnan +Cc: KAMEZAWA Hiroyuki +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/page_alloc.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -846,7 +846,7 @@ static struct page *__rmqueue(struct zon + */ + static int rmqueue_bulk(struct zone *zone, unsigned int order, + unsigned long count, struct list_head *list, +- int migratetype) ++ int migratetype, int cold) + { + int i; + +@@ -865,7 +865,10 @@ static int rmqueue_bulk(struct zone *zon + * merge IO requests if the physical pages are ordered + * properly. + */ +- list_add(&page->lru, list); ++ if (likely(cold == 0)) ++ list_add(&page->lru, list); ++ else ++ list_add_tail(&page->lru, list); + set_page_private(page, migratetype); + list = &page->lru; + } +@@ -1068,7 +1071,8 @@ again: + local_irq_save(flags); + if (!pcp->count) { + pcp->count = rmqueue_bulk(zone, 0, +- pcp->batch, &pcp->list, migratetype); ++ pcp->batch, &pcp->list, ++ migratetype, cold); + if (unlikely(!pcp->count)) + goto failed; + } +@@ -1087,7 +1091,8 @@ again: + /* Allocate more to the pcp list if necessary */ + if (unlikely(&page->lru == &pcp->list)) { + pcp->count += rmqueue_bulk(zone, 0, +- pcp->batch, &pcp->list, migratetype); ++ pcp->batch, &pcp->list, ++ migratetype, cold); + page = list_entry(pcp->list.next, struct page, lru); + } + diff --git a/queue-2.6.27/series b/queue-2.6.27/series new file mode 100644 index 00000000000..36bd48267ca --- /dev/null +++ b/queue-2.6.27/series @@ -0,0 +1,10 @@ +hugetlbfs-fix-i_blocks-accounting.patch +hwmon-differentiate-between-lpc47m233-and-lpc47m292.patch +i2c-tsl2550-fix-lux-value-in-dark-environment.patch +libsas-reuse-the-original-port-when-hotplugging-phys-in-wide-ports.patch +make-scsi-sg-v4-driver-enabled-by-default-and-remove-experimental-dependency-since-udev-depends-on-bsg.patch +page-allocator-preserve-pfn-ordering-when-__gfp_cold-is-set.patch +sysfs-fix-hardlink-count-on-device_move.patch +thinkpad-acpi-disable-broken-bay-and-dock-subdrivers.patch +usb-storage-raise-timeout-in-usb_stor_bulk_max_lun.patch +x86-fix-assembly-constraints-in-native_save_fl.patch diff --git a/queue-2.6.27/sysfs-fix-hardlink-count-on-device_move.patch b/queue-2.6.27/sysfs-fix-hardlink-count-on-device_move.patch new file mode 100644 index 00000000000..98601b2b620 --- /dev/null +++ b/queue-2.6.27/sysfs-fix-hardlink-count-on-device_move.patch @@ -0,0 +1,40 @@ +From 0f58b44582001c8bcdb75f36cf85ebbe5170e959 Mon Sep 17 00:00:00 2001 +From: Peter Oberparleiter +Date: Tue, 14 Jul 2009 17:56:15 +0200 +Subject: sysfs: fix hardlink count on device_move + +From: Peter Oberparleiter + +commit 0f58b44582001c8bcdb75f36cf85ebbe5170e959 upstream. + +Update directory hardlink count when moving kobjects to a new parent. +Fixes the following problem which occurs when several devices are +moved to the same parent and then unregistered: + +> ls -laF /sys/devices/css0/defunct/ +> total 0 +> drwxr-xr-x 4294967295 root root 0 2009-07-14 17:02 ./ +> drwxr-xr-x 114 root root 0 2009-07-14 17:02 ../ +> drwxr-xr-x 2 root root 0 2009-07-14 17:01 power/ +> -rw-r--r-- 1 root root 4096 2009-07-14 17:01 uevent + +Signed-off-by: Peter Oberparleiter +Signed-off-by: Greg Kroah-Hartman + +--- + fs/sysfs/dir.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/sysfs/dir.c ++++ b/fs/sysfs/dir.c +@@ -914,8 +914,10 @@ again: + /* Remove from old parent's list and insert into new parent's list. */ + sysfs_unlink_sibling(sd); + sysfs_get(new_parent_sd); ++ drop_nlink(old_parent->d_inode); + sysfs_put(sd->s_parent); + sd->s_parent = new_parent_sd; ++ inc_nlink(new_parent->d_inode); + sysfs_link_sibling(sd); + + out_unlock: diff --git a/queue-2.6.27/thinkpad-acpi-disable-broken-bay-and-dock-subdrivers.patch b/queue-2.6.27/thinkpad-acpi-disable-broken-bay-and-dock-subdrivers.patch new file mode 100644 index 00000000000..66997670223 --- /dev/null +++ b/queue-2.6.27/thinkpad-acpi-disable-broken-bay-and-dock-subdrivers.patch @@ -0,0 +1,57 @@ +From 550e7fd8afb7664ae7cedb398c407694e2bf7d3c Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 1 Aug 2009 12:04:17 -0300 +Subject: thinkpad-acpi: disable broken bay and dock subdrivers + +From: Henrique de Moraes Holschuh + +commit 550e7fd8afb7664ae7cedb398c407694e2bf7d3c upstream. + +Currently, the ThinkPad-ACPI bay and dock drivers are completely +broken, and cause a NULL pointer derreference in kernel mode (and, +therefore, an OOPS) when they try to issue events (i.e. on dock, +undock, bay ejection, etc). + +OTOH, the standard ACPI dock driver can handle the hotplug bays and +docks of the ThinkPads just fine (including batteries) as of 2.6.27. +In fact, it does a much better job of it than thinkpad-acpi ever did. + +It is just not worth the hassle to find a way to fix this crap without +breaking the (deprecated) thinkpad-acpi dock/bay ABI. This is old, +deprecated code that sees little testing or use. + +As a quick fix suitable for -stable backports, mark the thinkpad-acpi +bay and dock subdrivers as BROKEN in Kconfig. The dead code will be +removed by a later patch. + +This fixes bugzilla #13669, and should be applied to 2.6.27 and later. + +Signed-off-by: Henrique de Moraes Holschuh +Reported-by: Joerg Platte +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/Kconfig | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -321,6 +321,7 @@ config THINKPAD_ACPI_DOCK + bool "Legacy Docking Station Support" + depends on THINKPAD_ACPI + depends on ACPI_DOCK=n ++ depends on BROKEN + default n + ---help--- + Allows the thinkpad_acpi driver to handle docking station events. +@@ -334,7 +335,8 @@ config THINKPAD_ACPI_DOCK + config THINKPAD_ACPI_BAY + bool "Legacy Removable Bay Support" + depends on THINKPAD_ACPI +- default y ++ depends on BROKEN ++ default n + ---help--- + Allows the thinkpad_acpi driver to handle removable bays. It will + electrically disable the device in the bay, and also generate diff --git a/queue-2.6.27/usb-storage-raise-timeout-in-usb_stor_bulk_max_lun.patch b/queue-2.6.27/usb-storage-raise-timeout-in-usb_stor_bulk_max_lun.patch new file mode 100644 index 00000000000..6320f1b760a --- /dev/null +++ b/queue-2.6.27/usb-storage-raise-timeout-in-usb_stor_bulk_max_lun.patch @@ -0,0 +1,33 @@ +From 7a777919bbeec3eac1d7904a728a60e9c2bb9c67 Mon Sep 17 00:00:00 2001 +From: Giacomo Lozito +Date: Mon, 13 Jul 2009 23:23:33 +0200 +Subject: USB: storage: raise timeout in usb_stor_Bulk_max_lun + +From: Giacomo Lozito + +commit 7a777919bbeec3eac1d7904a728a60e9c2bb9c67 upstream. + +Requests to get max LUN, for certain USB storage devices, require a +longer timeout before a correct reply is returned. This happens for a +Realtek USB Card Reader (0bda:0152), which has a max LUN of 3 but is set +to 0, thus losing functionality, because of the timeout occurring too +quickly. + +Raising the timeout value fixes the issue and might help other devices +to return a correct max LUN value as well. + +Signed-off-by: Giacomo Lozito +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- a/drivers/usb/storage/transport.c ++++ b/drivers/usb/storage/transport.c +@@ -961,7 +961,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us) + US_BULK_GET_MAX_LUN, + USB_DIR_IN | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, +- 0, us->ifnum, us->iobuf, 1, HZ); ++ 0, us->ifnum, us->iobuf, 1, 10*HZ); + + US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", + result, us->iobuf[0]); diff --git a/queue-2.6.27/x86-fix-assembly-constraints-in-native_save_fl.patch b/queue-2.6.27/x86-fix-assembly-constraints-in-native_save_fl.patch new file mode 100644 index 00000000000..984ae027a2c --- /dev/null +++ b/queue-2.6.27/x86-fix-assembly-constraints-in-native_save_fl.patch @@ -0,0 +1,68 @@ +From f1f029c7bfbf4ee1918b90a431ab823bed812504 Mon Sep 17 00:00:00 2001 +From: H. Peter Anvin +Date: Mon, 3 Aug 2009 16:33:40 -0700 +Subject: x86: fix assembly constraints in native_save_fl() + +From: H. Peter Anvin + +commit f1f029c7bfbf4ee1918b90a431ab823bed812504 upstream. + +From Gabe Black in bugzilla 13888: + +native_save_fl is implemented as follows: + + 11static inline unsigned long native_save_fl(void) + 12{ + 13 unsigned long flags; + 14 + 15 asm volatile("# __raw_save_flags\n\t" + 16 "pushf ; pop %0" + 17 : "=g" (flags) + 18 : /* no input */ + 19 : "memory"); + 20 + 21 return flags; + 22} + +If gcc chooses to put flags on the stack, for instance because this is +inlined into a larger function with more register pressure, the offset +of the flags variable from the stack pointer will change when the +pushf is performed. gcc doesn't attempt to understand that fact, and +address used for pop will still be the same. It will write to +somewhere near flags on the stack but not actually into it and +overwrite some other value. + +I saw this happen in the ide_device_add_all function when running in a +simulator I work on. I'm assuming that some quirk of how the simulated +hardware is set up caused the code path this is on to be executed when +it normally wouldn't. + +A simple fix might be to change "=g" to "=r". + +Reported-by: Gabe Black +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + include/asm-x86/irqflags.h | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/include/asm-x86/irqflags.h ++++ b/include/asm-x86/irqflags.h +@@ -12,9 +12,15 @@ static inline unsigned long native_save_ + { + unsigned long flags; + ++ /* ++ * Note: this needs to be "=r" not "=rm", because we have the ++ * stack offset from what gcc expects at the time the "pop" is ++ * executed, and so a memory reference with respect to the stack ++ * would end up using the wrong address. ++ */ + asm volatile("# __raw_save_flags\n\t" + "pushf ; pop %0" +- : "=g" (flags) ++ : "=r" (flags) + : /* no input */ + : "memory"); +