From: Greg Kroah-Hartman Date: Wed, 5 Aug 2009 20:44:55 +0000 (-0700) Subject: lots of .30 patches X-Git-Tag: v2.6.30.5~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=91dc69244fd9e55ea59c09347896b2344cca6469;p=thirdparty%2Fkernel%2Fstable-queue.git lots of .30 patches --- diff --git a/queue-2.6.30/cfg80211-add-two-missing-null-pointer-checks.patch b/queue-2.6.30/cfg80211-add-two-missing-null-pointer-checks.patch new file mode 100644 index 00000000000..991231d3b0e --- /dev/null +++ b/queue-2.6.30/cfg80211-add-two-missing-null-pointer-checks.patch @@ -0,0 +1,41 @@ +From cd3468bad96c00b5a512f551674f36776129520e Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 29 Jul 2009 22:07:44 +0200 +Subject: cfg80211: add two missing NULL pointer checks + +From: Johannes Berg + +commit cd3468bad96c00b5a512f551674f36776129520e upstream. + +These pointers can be NULL, the is_mesh() case isn't +ever hit in the current kernel, but cmp_ies() can be +hit under certain conditions. + +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + net/wireless/scan.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -118,7 +118,7 @@ static int cmp_ies(u8 num, u8 *ies1, siz + + if (!ie1 && !ie2) + return 0; +- if (!ie1) ++ if (!ie1 || !ie2) + return -1; + + r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1])); +@@ -171,6 +171,8 @@ static bool is_mesh(struct cfg80211_bss + ie = find_ie(WLAN_EID_MESH_CONFIG, + a->information_elements, + a->len_information_elements); ++ if (!ie) ++ return false; + if (ie[1] != IEEE80211_MESH_CONFIG_LEN) + return false; + diff --git a/queue-2.6.30/cifs-fix-error-handling-in-mount-time-dfs-referral-chasing-code.patch b/queue-2.6.30/cifs-fix-error-handling-in-mount-time-dfs-referral-chasing-code.patch new file mode 100644 index 00000000000..59f4aec9fcc --- /dev/null +++ b/queue-2.6.30/cifs-fix-error-handling-in-mount-time-dfs-referral-chasing-code.patch @@ -0,0 +1,99 @@ +From 7b91e2661addd8e2419cb45f6a322aa5dab9bcee Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 23 Jul 2009 15:22:30 -0400 +Subject: cifs: fix error handling in mount-time DFS referral chasing code + +From: Jeff Layton + +commit 7b91e2661addd8e2419cb45f6a322aa5dab9bcee upstream. + +If the referral is malformed or the hostname can't be resolved, then +the current code generates an oops. Fix it to handle these errors +gracefully. + +Reported-by: Sandro Mathys +Acked-by: Igor Mammedov +Signed-off-by: Jeff Layton +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifs_dfs_ref.c | 12 +++++++++--- + fs/cifs/connect.c | 13 ++++++++++--- + 2 files changed, 19 insertions(+), 6 deletions(-) + +--- a/fs/cifs/cifs_dfs_ref.c ++++ b/fs/cifs/cifs_dfs_ref.c +@@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(vo + * i.e. strips from UNC trailing path that is not part of share + * name and fixup missing '\' in the begining of DFS node refferal + * if neccessary. +- * Returns pointer to share name on success or NULL on error. ++ * Returns pointer to share name on success or ERR_PTR on error. + * Caller is responsible for freeing returned string. + */ + static char *cifs_get_share_name(const char *node_name) +@@ -68,7 +68,7 @@ static char *cifs_get_share_name(const c + UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, + GFP_KERNEL); + if (!UNC) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + /* get share name and server name */ + if (node_name[1] != '\\') { +@@ -87,7 +87,7 @@ static char *cifs_get_share_name(const c + cERROR(1, ("%s: no server name end in node name: %s", + __func__, node_name)); + kfree(UNC); +- return NULL; ++ return ERR_PTR(-EINVAL); + } + + /* find sharename end */ +@@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const c + return ERR_PTR(-EINVAL); + + *devname = cifs_get_share_name(ref->node_name); ++ if (IS_ERR(*devname)) { ++ rc = PTR_ERR(*devname); ++ *devname = NULL; ++ goto compose_mount_options_err; ++ } ++ + rc = dns_resolve_server_name_to_ip(*devname, &srvIP); + if (rc != 0) { + cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -2563,11 +2563,20 @@ remote_path_check: + + if (mount_data != mount_data_global) + kfree(mount_data); ++ + mount_data = cifs_compose_mount_options( + cifs_sb->mountdata, full_path + 1, + referrals, &fake_devname); +- kfree(fake_devname); ++ + free_dfs_info_array(referrals, num_referrals); ++ kfree(fake_devname); ++ kfree(full_path); ++ ++ if (IS_ERR(mount_data)) { ++ rc = PTR_ERR(mount_data); ++ mount_data = NULL; ++ goto mount_fail_check; ++ } + + if (tcon) + cifs_put_tcon(tcon); +@@ -2575,8 +2584,6 @@ remote_path_check: + cifs_put_smb_ses(pSesInfo); + + cleanup_volume_info(&volume_info); +- FreeXid(xid); +- kfree(full_path); + referral_walks_count++; + goto try_mount_again; + } diff --git a/queue-2.6.30/edac-x38-fix-mchbar-high-register-addr.patch b/queue-2.6.30/edac-x38-fix-mchbar-high-register-addr.patch new file mode 100644 index 00000000000..07fa4268c08 --- /dev/null +++ b/queue-2.6.30/edac-x38-fix-mchbar-high-register-addr.patch @@ -0,0 +1,33 @@ +From 3d768213a6c34a27fac1804143da8cf18b8b175f Mon Sep 17 00:00:00 2001 +From: Lu Zhihe +Date: Wed, 29 Jul 2009 15:02:09 -0700 +Subject: edac: x38 fix mchbar high register addr + +From: Lu Zhihe + +commit 3d768213a6c34a27fac1804143da8cf18b8b175f upstream. + +Intel X38 MCHBAR is a 64bits register, base from 0x48, so its higher base +is 0x4C. + +Signed-off-by: Lu Zhihe +Signed-off-by: Doug Thompson +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/edac/x38_edac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/edac/x38_edac.c ++++ b/drivers/edac/x38_edac.c +@@ -30,7 +30,7 @@ + /* Intel X38 register addresses - device 0 function 0 - DRAM Controller */ + + #define X38_MCHBAR_LOW 0x48 /* MCH Memory Mapped Register BAR */ +-#define X38_MCHBAR_HIGH 0x4b ++#define X38_MCHBAR_HIGH 0x4c + #define X38_MCHBAR_MASK 0xfffffc000ULL /* bits 35:14 */ + #define X38_MMR_WINDOW_SIZE 16384 + diff --git a/queue-2.6.30/hugetlbfs-fix-i_blocks-accounting.patch b/queue-2.6.30/hugetlbfs-fix-i_blocks-accounting.patch new file mode 100644 index 00000000000..8e246f1c763 --- /dev/null +++ b/queue-2.6.30/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 +@@ -2341,7 +2341,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.30/ide-fix-handling-of-unexpected-irqs-vs-request_irq.patch b/queue-2.6.30/ide-fix-handling-of-unexpected-irqs-vs-request_irq.patch new file mode 100644 index 00000000000..b29b6fc0062 --- /dev/null +++ b/queue-2.6.30/ide-fix-handling-of-unexpected-irqs-vs-request_irq.patch @@ -0,0 +1,74 @@ +From ffc36c7610731115c77700dcc53901920361c235 Mon Sep 17 00:00:00 2001 +From: Bartlomiej Zolnierkiewicz +Date: Tue, 23 Jun 2009 03:43:00 -0700 +Subject: ide: fix handling of unexpected IRQs vs request_irq() + +From: Bartlomiej Zolnierkiewicz + +commit ffc36c7610731115c77700dcc53901920361c235 upstream. + +Add ide_host_enable_irqs() helper and use it in ide_host_register() +before registering ports. Then remove no longer needed IRQ unmasking +from in init_irq(). + +This should fix the problem with "screaming" shared IRQ on the first +port (after request_irq() call while we have the unexpected IRQ pending +on the second port) which was uncovered by my rework of the serialized +interfaces support. + +Reported-by: Frans Pop +Tested-by: Frans Pop +Signed-off-by: Bartlomiej Zolnierkiewicz +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ide/ide-probe.c | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +--- a/drivers/ide/ide-probe.c ++++ b/drivers/ide/ide-probe.c +@@ -830,6 +830,24 @@ static int ide_port_setup_devices(ide_hw + return j; + } + ++static void ide_host_enable_irqs(struct ide_host *host) ++{ ++ ide_hwif_t *hwif; ++ int i; ++ ++ ide_host_for_each_port(i, hwif, host) { ++ if (hwif == NULL) ++ continue; ++ ++ /* clear any pending IRQs */ ++ hwif->tp_ops->read_status(hwif); ++ ++ /* unmask IRQs */ ++ if (hwif->io_ports.ctl_addr) ++ hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); ++ } ++} ++ + /* + * This routine sets up the IRQ for an IDE interface. + */ +@@ -843,9 +861,6 @@ static int init_irq (ide_hwif_t *hwif) + if (irq_handler == NULL) + irq_handler = ide_intr; + +- if (io_ports->ctl_addr) +- hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); +- + if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) + goto out_up; + +@@ -1389,6 +1404,8 @@ int ide_host_register(struct ide_host *h + ide_port_tune_devices(hwif); + } + ++ ide_host_enable_irqs(host); ++ + ide_host_for_each_port(i, hwif, host) { + if (hwif == NULL) + continue; diff --git a/queue-2.6.30/ide-relax-dma-info-validity-checking.patch b/queue-2.6.30/ide-relax-dma-info-validity-checking.patch new file mode 100644 index 00000000000..3298e6a5aa9 --- /dev/null +++ b/queue-2.6.30/ide-relax-dma-info-validity-checking.patch @@ -0,0 +1,100 @@ +From 346c17a6cf60375323adfaa4b8a9d841049f890e Mon Sep 17 00:00:00 2001 +From: Bartlomiej Zolnierkiewicz +Date: Mon, 22 Jun 2009 07:38:26 +0000 +Subject: ide: relax DMA info validity checking + +From: Bartlomiej Zolnierkiewicz + +commit 346c17a6cf60375323adfaa4b8a9d841049f890e upstream. + +There are some broken devices that report multiple DMA xfer modes +enabled at once (ATA spec doesn't allow it) but otherwise work fine +with DMA so just delete ide_id_dma_bug(). + +[ As discovered by detective work by Frans and Bart, due to how + handling of the ID block was handled before commit c419993 + ("ide-iops: only clear DMA words on setting DMA mode") this + check was always seeing zeros in the fields or other similar + garbage. Therefore this check wasn't actually checking anything. + Now that the tests actually check the real bits, all we see are + devices that trigger the check yet work perfectly fine, therefore + killing this useless check is the best thing to do. -DaveM ] + +Reported-by: Frans Pop +Signed-off-by: Bartlomiej Zolnierkiewicz +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ide/ide-dma.c | 21 --------------------- + drivers/ide/ide-iops.c | 3 --- + include/linux/ide.h | 2 -- + 3 files changed, 26 deletions(-) + +--- a/drivers/ide/ide-dma.c ++++ b/drivers/ide/ide-dma.c +@@ -362,9 +362,6 @@ static int ide_tune_dma(ide_drive_t *dri + if (__ide_dma_bad_drive(drive)) + return 0; + +- if (ide_id_dma_bug(drive)) +- return 0; +- + if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) + return config_drive_for_dma(drive); + +@@ -395,24 +392,6 @@ static int ide_dma_check(ide_drive_t *dr + return -1; + } + +-int ide_id_dma_bug(ide_drive_t *drive) +-{ +- u16 *id = drive->id; +- +- if (id[ATA_ID_FIELD_VALID] & 4) { +- if ((id[ATA_ID_UDMA_MODES] >> 8) && +- (id[ATA_ID_MWDMA_MODES] >> 8)) +- goto err_out; +- } else if ((id[ATA_ID_MWDMA_MODES] >> 8) && +- (id[ATA_ID_SWDMA_MODES] >> 8)) +- goto err_out; +- +- return 0; +-err_out: +- printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); +- return 1; +-} +- + int ide_set_dma(ide_drive_t *drive) + { + int rc; +--- a/drivers/ide/ide-iops.c ++++ b/drivers/ide/ide-iops.c +@@ -306,9 +306,6 @@ int ide_driveid_update(ide_drive_t *driv + + kfree(id); + +- if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive)) +- ide_dma_off(drive); +- + return 1; + out_err: + SELECT_MASK(drive, 0); +--- a/include/linux/ide.h ++++ b/include/linux/ide.h +@@ -1384,7 +1384,6 @@ int ide_in_drive_list(u16 *, const struc + #ifdef CONFIG_BLK_DEV_IDEDMA + int ide_dma_good_drive(ide_drive_t *); + int __ide_dma_bad_drive(ide_drive_t *); +-int ide_id_dma_bug(ide_drive_t *); + + u8 ide_find_dma_mode(ide_drive_t *, u8); + +@@ -1425,7 +1424,6 @@ void ide_dma_lost_irq(ide_drive_t *); + ide_startstop_t ide_dma_timeout_retry(ide_drive_t *, int); + + #else +-static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; } + static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; } + static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; } + static inline void ide_dma_off_quietly(ide_drive_t *drive) { ; } diff --git a/queue-2.6.30/libsas-reuse-the-original-port-when-hotplugging-phys-in-wide-ports.patch b/queue-2.6.30/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.30/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.30/make-scsi-sg-v4-driver-enabled-by-default-and-remove-experimental-dependency-since-udev-depends-on-bsg.patch b/queue-2.6.30/make-scsi-sg-v4-driver-enabled-by-default-and-remove-experimental-dependency-since-udev-depends-on-bsg.patch new file mode 100644 index 00000000000..164eb7c8bc9 --- /dev/null +++ b/queue-2.6.30/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 +@@ -45,9 +45,9 @@ config LBD + If unsure, say N. + + 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. + +@@ -57,7 +57,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.30/md-handle-growth-of-v1.x-metadata-correctly.patch b/queue-2.6.30/md-handle-growth-of-v1.x-metadata-correctly.patch new file mode 100644 index 00000000000..e111abc8913 --- /dev/null +++ b/queue-2.6.30/md-handle-growth-of-v1.x-metadata-correctly.patch @@ -0,0 +1,43 @@ +From 70471dafe3390243c598a3165dfb86b8b8b3f4fe Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Mon, 3 Aug 2009 10:59:57 +1000 +Subject: md: Handle growth of v1.x metadata correctly. + +From: NeilBrown + +commit 70471dafe3390243c598a3165dfb86b8b8b3f4fe upstream. + +The v1.x metadata does not have a fixed size and can grow +when devices are added. +If it grows enough to require an extra sector of storage, +we need to update the 'sb_size' to match. + +Without this, md can write out an incomplete superblock with a +bad checksum, which will be rejected when trying to re-assemble +the array. + +Signed-off-by: NeilBrown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/md.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -1410,8 +1410,14 @@ static void super_1_sync(mddev_t *mddev, + if (rdev2->desc_nr+1 > max_dev) + max_dev = rdev2->desc_nr+1; + +- if (max_dev > le32_to_cpu(sb->max_dev)) ++ if (max_dev > le32_to_cpu(sb->max_dev)) { ++ int bmask; + sb->max_dev = cpu_to_le32(max_dev); ++ rdev->sb_size = max_dev * 2 + 256; ++ bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1; ++ if (rdev->sb_size & bmask) ++ rdev->sb_size = (rdev->sb_size | bmask) + 1; ++ } + for (i=0; idev_roles[i] = cpu_to_le16(0xfffe); + diff --git a/queue-2.6.30/md-raid6-release-spare-page-at-stop.patch b/queue-2.6.30/md-raid6-release-spare-page-at-stop.patch new file mode 100644 index 00000000000..17f4c1c8a06 --- /dev/null +++ b/queue-2.6.30/md-raid6-release-spare-page-at-stop.patch @@ -0,0 +1,80 @@ +From 95fc17aac45300f45968aacd97a536ddd8db8101 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Fri, 31 Jul 2009 12:39:15 +1000 +Subject: md/raid6: release spare page at ->stop() + +From: Dan Williams + +commit 95fc17aac45300f45968aacd97a536ddd8db8101 upstream. + +Add missing call to safe_put_page from stop() by unifying open coded +raid5_conf_t de-allocation under free_conf(). + +Signed-off-by: Dan Williams +Signed-off-by: NeilBrown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/raid5.c | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -4310,6 +4310,15 @@ raid5_size(mddev_t *mddev, sector_t sect + return sectors * (raid_disks - conf->max_degraded); + } + ++static void free_conf(raid5_conf_t *conf) ++{ ++ shrink_stripes(conf); ++ safe_put_page(conf->spare_page); ++ kfree(conf->disks); ++ kfree(conf->stripe_hashtbl); ++ kfree(conf); ++} ++ + static raid5_conf_t *setup_conf(mddev_t *mddev) + { + raid5_conf_t *conf; +@@ -4439,11 +4448,7 @@ static raid5_conf_t *setup_conf(mddev_t + + abort: + if (conf) { +- shrink_stripes(conf); +- safe_put_page(conf->spare_page); +- kfree(conf->disks); +- kfree(conf->stripe_hashtbl); +- kfree(conf); ++ free_conf(conf); + return ERR_PTR(-EIO); + } else + return ERR_PTR(-ENOMEM); +@@ -4609,12 +4614,8 @@ abort: + md_unregister_thread(mddev->thread); + mddev->thread = NULL; + if (conf) { +- shrink_stripes(conf); + print_raid5_conf(conf); +- safe_put_page(conf->spare_page); +- kfree(conf->disks); +- kfree(conf->stripe_hashtbl); +- kfree(conf); ++ free_conf(conf); + } + mddev->private = NULL; + printk(KERN_ALERT "raid5: failed to run raid set %s\n", mdname(mddev)); +@@ -4629,13 +4630,10 @@ static int stop(mddev_t *mddev) + + md_unregister_thread(mddev->thread); + mddev->thread = NULL; +- shrink_stripes(conf); +- kfree(conf->stripe_hashtbl); + mddev->queue->backing_dev_info.congested_fn = NULL; + blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ + sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); +- kfree(conf->disks); +- kfree(conf); ++ free_conf(conf); + mddev->private = NULL; + return 0; + } diff --git a/queue-2.6.30/md-when-a-level-change-reduces-the-number-of-devices-remove-the-excess.patch b/queue-2.6.30/md-when-a-level-change-reduces-the-number-of-devices-remove-the-excess.patch new file mode 100644 index 00000000000..38a2aedaf11 --- /dev/null +++ b/queue-2.6.30/md-when-a-level-change-reduces-the-number-of-devices-remove-the-excess.patch @@ -0,0 +1,45 @@ +From 3a981b03f38dc3b8a69b77cbc679e66c1318a44a Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Mon, 3 Aug 2009 10:59:55 +1000 +Subject: md: when a level change reduces the number of devices, remove the excess. + +From: NeilBrown + +commit 3a981b03f38dc3b8a69b77cbc679e66c1318a44a upstream. + +When an array is changed from RAID6 to RAID5, fewer drives are +needed. So any device that is made superfluous by the level +conversion must be marked as not-active. +For the RAID6->RAID5 conversion, this will be a drive which only +has 'Q' blocks on it. + +Signed-off-by: NeilBrown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/md.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -2680,6 +2680,7 @@ level_store(mddev_t *mddev, const char * + ssize_t rv = len; + struct mdk_personality *pers; + void *priv; ++ mdk_rdev_t *rdev; + + if (mddev->pers == NULL) { + if (len == 0) +@@ -2759,6 +2760,12 @@ level_store(mddev_t *mddev, const char * + mddev_suspend(mddev); + mddev->pers->stop(mddev); + module_put(mddev->pers->owner); ++ /* Invalidate devices that are now superfluous */ ++ list_for_each_entry(rdev, &mddev->disks, same_set) ++ if (rdev->raid_disk >= mddev->raid_disks) { ++ rdev->raid_disk = -1; ++ clear_bit(In_sync, &rdev->flags); ++ } + mddev->pers = pers; + mddev->private = priv; + strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); diff --git a/queue-2.6.30/nilfs2-fix-oops-due-to-inconsistent-state-in-page-with-discrete-b-tree-nodes.patch b/queue-2.6.30/nilfs2-fix-oops-due-to-inconsistent-state-in-page-with-discrete-b-tree-nodes.patch new file mode 100644 index 00000000000..69ff1b55b0d --- /dev/null +++ b/queue-2.6.30/nilfs2-fix-oops-due-to-inconsistent-state-in-page-with-discrete-b-tree-nodes.patch @@ -0,0 +1,61 @@ +From a97778457f22181e8c38c4cd7d7e528378738a98 Mon Sep 17 00:00:00 2001 +From: Ryusuke Konishi +Date: Tue, 28 Jul 2009 17:55:29 +0900 +Subject: nilfs2: fix oops due to inconsistent state in page with discrete b-tree nodes + +From: Ryusuke Konishi + +commit a97778457f22181e8c38c4cd7d7e528378738a98 upstream. + +Andrea Gelmini gave me a report that a kernel oops hit on a nilfs +filesystem with a 1KB block size when doing rsync. + +This turned out to be caused by an inconsistency of dirty state +between a page and its buffers storing b-tree node blocks. + +If the page had multiple buffers split over multiple logs, and if the +logs were written at a time, a dirty flag remained in the page even +every dirty flag in the buffers was cleared. + +This will fix the failure by dropping the dirty flag properly for +pages with the discrete multiple b-tree nodes. + +Reported-by: Andrea Gelmini +Signed-off-by: Ryusuke Konishi +Tested-by: Andrea Gelmini +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nilfs2/segment.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -1876,12 +1876,26 @@ static void nilfs_end_page_io(struct pag + if (!page) + return; + +- if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page)) ++ if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page)) { + /* + * For b-tree node pages, this function may be called twice + * or more because they might be split in a segment. + */ ++ if (PageDirty(page)) { ++ /* ++ * For pages holding split b-tree node buffers, dirty ++ * flag on the buffers may be cleared discretely. ++ * In that case, the page is once redirtied for ++ * remaining buffers, and it must be cancelled if ++ * all the buffers get cleaned later. ++ */ ++ lock_page(page); ++ if (nilfs_page_buffers_clean(page)) ++ __nilfs_clear_page_dirty(page); ++ unlock_page(page); ++ } + return; ++ } + + __nilfs_end_page_io(page, err); + } diff --git a/queue-2.6.30/page-allocator-preserve-pfn-ordering-when-__gfp_cold-is-set.patch b/queue-2.6.30/page-allocator-preserve-pfn-ordering-when-__gfp_cold-is-set.patch new file mode 100644 index 00000000000..5f8afbaede1 --- /dev/null +++ b/queue-2.6.30/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 +@@ -858,7 +858,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; + +@@ -877,7 +877,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; + } +@@ -1077,7 +1080,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; + } +@@ -1096,7 +1100,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.30/parisc-isa-eeprom-fix-loff_t-usage.patch b/queue-2.6.30/parisc-isa-eeprom-fix-loff_t-usage.patch new file mode 100644 index 00000000000..2f964a2c4af --- /dev/null +++ b/queue-2.6.30/parisc-isa-eeprom-fix-loff_t-usage.patch @@ -0,0 +1,33 @@ +From 6b4dbcd86a9d464057fcc7abe4d0574093071fcc Mon Sep 17 00:00:00 2001 +From: Michael Buesch +Date: Mon, 20 Jul 2009 22:58:44 +0000 +Subject: parisc: isa-eeprom - Fix loff_t usage + +From: Michael Buesch + +commit 6b4dbcd86a9d464057fcc7abe4d0574093071fcc upstream. + +loff_t is a signed type. If userspace passes a negative ppos, the "count" +range check is weakened. "count"s bigger than HPEE_MAX_LENGTH will pass the check. +Also, if ppos is negative, the readb(eisa_eeprom_addr + *ppos) will poke in random +memory. + +Signed-off-by: Michael Buesch +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/parisc/eisa_eeprom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/parisc/eisa_eeprom.c ++++ b/drivers/parisc/eisa_eeprom.c +@@ -55,7 +55,7 @@ static ssize_t eisa_eeprom_read(struct f + ssize_t ret; + int i; + +- if (*ppos >= HPEE_MAX_LENGTH) ++ if (*ppos < 0 || *ppos >= HPEE_MAX_LENGTH) + return 0; + + count = *ppos + count < HPEE_MAX_LENGTH ? count : HPEE_MAX_LENGTH - *ppos; diff --git a/queue-2.6.30/pm-acpi-hp-g7000-notebook-needs-a-sci_en-resume-quirk.patch b/queue-2.6.30/pm-acpi-hp-g7000-notebook-needs-a-sci_en-resume-quirk.patch new file mode 100644 index 00000000000..6c7070e3b0b --- /dev/null +++ b/queue-2.6.30/pm-acpi-hp-g7000-notebook-needs-a-sci_en-resume-quirk.patch @@ -0,0 +1,43 @@ +From ec79be26875f6c1468784876cb99192b7f41c7a5 Mon Sep 17 00:00:00 2001 +From: Bartlomiej Zolnierkiewicz +Date: Wed, 29 Jul 2009 21:07:47 +0200 +Subject: PM / ACPI: HP G7000 Notebook needs a SCI_EN resume quirk + +From: Bartlomiej Zolnierkiewicz + +commit ec79be26875f6c1468784876cb99192b7f41c7a5 upstream. + +This fixes regression (battery "vanishing" on resume) introduced by +commit d0c71fe7ebc180f1b7bc7da1d39a07fc19eec768 ("ACPI Suspend: Enable +ACPI during resume if SCI_EN is not set") and also the issue with +the "screaming" IRQ 9. + +Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13745 + +Reported-and-tested-by: Alan Jenkins +Signed-off-by: Bartlomiej Zolnierkiewicz +Acked-by: Len Brown +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/sleep.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -397,6 +397,14 @@ static struct dmi_system_id __initdata a + }, + }, + { ++ .callback = init_set_sci_en_on_resume, ++ .ident = "Hewlett-Packard HP G7000 Notebook PC", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"), ++ }, ++ }, ++ { + .callback = init_old_suspend_ordering, + .ident = "Panasonic CF51-2L", + .matches = { diff --git a/queue-2.6.30/posix-timers-fix-oops-in-clock_nanosleep-with-clock_monotonic_raw.patch b/queue-2.6.30/posix-timers-fix-oops-in-clock_nanosleep-with-clock_monotonic_raw.patch new file mode 100644 index 00000000000..73235b8c3c0 --- /dev/null +++ b/queue-2.6.30/posix-timers-fix-oops-in-clock_nanosleep-with-clock_monotonic_raw.patch @@ -0,0 +1,48 @@ +From 70d715fd0597f18528f389b5ac59102263067744 Mon Sep 17 00:00:00 2001 +From: Hiroshi Shimamoto +Date: Mon, 3 Aug 2009 11:48:19 +0900 +Subject: posix-timers: Fix oops in clock_nanosleep() with CLOCK_MONOTONIC_RAW + +From: Hiroshi Shimamoto + +commit 70d715fd0597f18528f389b5ac59102263067744 upstream. + +Prevent calling do_nanosleep() with clockid +CLOCK_MONOTONIC_RAW, it may cause oops, such as NULL pointer +dereference. + +Signed-off-by: Hiroshi Shimamoto +Cc: Andrew Morton +Cc: Thomas Gleixner +Cc: John Stultz +LKML-Reference: <4A764FF3.50607@ct.jp.nec.com> +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/posix-timers.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/kernel/posix-timers.c ++++ b/kernel/posix-timers.c +@@ -202,6 +202,12 @@ static int no_timer_create(struct k_itim + return -EOPNOTSUPP; + } + ++static int no_nsleep(const clockid_t which_clock, int flags, ++ struct timespec *tsave, struct timespec __user *rmtp) ++{ ++ return -EOPNOTSUPP; ++} ++ + /* + * Return nonzero if we know a priori this clockid_t value is bogus. + */ +@@ -254,6 +260,7 @@ static __init int init_posix_timers(void + .clock_get = posix_get_monotonic_raw, + .clock_set = do_posix_clock_nosettime, + .timer_create = no_timer_create, ++ .nsleep = no_nsleep, + }; + + register_posix_clock(CLOCK_REALTIME, &clock_realtime); diff --git a/queue-2.6.30/powerpc-mpc83xx-fix-usb-mux-setup-for-mpc834x.patch b/queue-2.6.30/powerpc-mpc83xx-fix-usb-mux-setup-for-mpc834x.patch new file mode 100644 index 00000000000..e3ded3b2d91 --- /dev/null +++ b/queue-2.6.30/powerpc-mpc83xx-fix-usb-mux-setup-for-mpc834x.patch @@ -0,0 +1,129 @@ +From b7d66c88c968379ebe683a28c4005895497ebbad Mon Sep 17 00:00:00 2001 +From: Peter Korsgaard +Date: Tue, 9 Jun 2009 13:43:32 +0200 +Subject: powerpc/mpc83xx: Fix usb mux setup for mpc834x + +From: Peter Korsgaard + +commit b7d66c88c968379ebe683a28c4005895497ebbad upstream. + +usb0 and usb1 mux settings in the sicrl register were swapped (twice!) +in mpc834x_usb_cfg(), leading to various strange issues with fsl-ehci +and full speed devices. + +The USB port config on mpc834x is done using 2 muxes: Port 0 is always +used for MPH port 0, and port 1 can either be used for MPH port 1 or DR +(unless DR uses UTMI phy or OTG, then it uses both ports) - See 8349 RM +figure 1-4.. + +mpc8349_usb_cfg() had this inverted for the DR, and it also had the bit +positions of the usb0 / usb1 mux settings swapped. It would basically +work if you specified port1 instead of port0 for the MPH controller (and +happened to use ULPI phys), which is what all the 834x dts have done, +even though that configuration is physically invalid. + +Instead fix mpc8349_usb_cfg() and adjust the dts files to match reality. + +Signed-off-by: Peter Korsgaard +Signed-off-by: Kumar Gala +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/boot/dts/asp834x-redboot.dts | 2 +- + arch/powerpc/boot/dts/mpc8349emitx.dts | 2 +- + arch/powerpc/boot/dts/mpc834x_mds.dts | 2 +- + arch/powerpc/boot/dts/sbc8349.dts | 2 +- + arch/powerpc/platforms/83xx/mpc83xx.h | 4 ++-- + arch/powerpc/platforms/83xx/usb.c | 10 +++++----- + 6 files changed, 11 insertions(+), 11 deletions(-) + +--- a/arch/powerpc/boot/dts/asp834x-redboot.dts ++++ b/arch/powerpc/boot/dts/asp834x-redboot.dts +@@ -167,7 +167,7 @@ + interrupt-parent = <&ipic>; + interrupts = <39 0x8>; + phy_type = "ulpi"; +- port1; ++ port0; + }; + /* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */ + usb@23000 { +--- a/arch/powerpc/boot/dts/mpc8349emitx.dts ++++ b/arch/powerpc/boot/dts/mpc8349emitx.dts +@@ -156,7 +156,7 @@ + interrupt-parent = <&ipic>; + interrupts = <39 0x8>; + phy_type = "ulpi"; +- port1; ++ port0; + }; + + usb@23000 { +--- a/arch/powerpc/boot/dts/mpc834x_mds.dts ++++ b/arch/powerpc/boot/dts/mpc834x_mds.dts +@@ -153,7 +153,7 @@ + interrupt-parent = <&ipic>; + interrupts = <39 0x8>; + phy_type = "ulpi"; +- port1; ++ port0; + }; + /* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */ + usb@23000 { +--- a/arch/powerpc/boot/dts/sbc8349.dts ++++ b/arch/powerpc/boot/dts/sbc8349.dts +@@ -144,7 +144,7 @@ + interrupt-parent = <&ipic>; + interrupts = <39 0x8>; + phy_type = "ulpi"; +- port1; ++ port0; + }; + /* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */ + usb@23000 { +--- a/arch/powerpc/platforms/83xx/mpc83xx.h ++++ b/arch/powerpc/platforms/83xx/mpc83xx.h +@@ -22,8 +22,8 @@ + /* system i/o configuration register low */ + #define MPC83XX_SICRL_OFFS 0x114 + #define MPC834X_SICRL_USB_MASK 0x60000000 +-#define MPC834X_SICRL_USB0 0x40000000 +-#define MPC834X_SICRL_USB1 0x20000000 ++#define MPC834X_SICRL_USB0 0x20000000 ++#define MPC834X_SICRL_USB1 0x40000000 + #define MPC831X_SICRL_USB_MASK 0x00000c00 + #define MPC831X_SICRL_USB_ULPI 0x00000800 + #define MPC8315_SICRL_USB_MASK 0x000000fc +--- a/arch/powerpc/platforms/83xx/usb.c ++++ b/arch/powerpc/platforms/83xx/usb.c +@@ -47,25 +47,25 @@ int mpc834x_usb_cfg(void) + sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ + + prop = of_get_property(np, "phy_type", NULL); ++ port1_is_dr = 1; + if (prop && (!strcmp(prop, "utmi") || + !strcmp(prop, "utmi_wide"))) { + sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; + sicrh |= MPC834X_SICRH_USB_UTMI; +- port1_is_dr = 1; ++ port0_is_dr = 1; + } else if (prop && !strcmp(prop, "serial")) { + dr_mode = of_get_property(np, "dr_mode", NULL); + if (dr_mode && !strcmp(dr_mode, "otg")) { + sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; +- port1_is_dr = 1; ++ port0_is_dr = 1; + } else { +- sicrl |= MPC834X_SICRL_USB0; ++ sicrl |= MPC834X_SICRL_USB1; + } + } else if (prop && !strcmp(prop, "ulpi")) { +- sicrl |= MPC834X_SICRL_USB0; ++ sicrl |= MPC834X_SICRL_USB1; + } else { + printk(KERN_WARNING "834x USB PHY type not supported\n"); + } +- port0_is_dr = 1; + of_node_put(np); + } + np = of_find_compatible_node(NULL, NULL, "fsl-usb2-mph"); diff --git a/queue-2.6.30/series b/queue-2.6.30/series index 16fd0a0cc71..8844f080ee0 100644 --- a/queue-2.6.30/series +++ b/queue-2.6.30/series @@ -18,3 +18,29 @@ drm-i915-save-restore-cursor-state-on-suspend-resume.patch 0005-drm-i915-Hook-connector-to-encoder-during-load-detec.patch 0006-drm-i915-initialize-fence-registers-to-zero-when-loa.patch 0007-drm-i915-Set-SSC-frequency-for-8xx-chips-correctly.patch +sysfs-fix-hardlink-count-on-device_move.patch +usb-storage-raise-timeout-in-usb_stor_bulk_max_lun.patch +edac-x38-fix-mchbar-high-register-addr.patch +make-scsi-sg-v4-driver-enabled-by-default-and-remove-experimental-dependency-since-udev-depends-on-bsg.patch +libsas-reuse-the-original-port-when-hotplugging-phys-in-wide-ports.patch +cifs-fix-error-handling-in-mount-time-dfs-referral-chasing-code.patch +thinkpad-acpi-disable-broken-bay-and-dock-subdrivers.patch +thinkpad-acpi-fix-incorrect-use-of-tpacpi_brght_mode_ecnvram.patch +nilfs2-fix-oops-due-to-inconsistent-state-in-page-with-discrete-b-tree-nodes.patch +tracing-fix-invalid-function_graph-entry.patch +tracing-fix-missing-function_graph-events-when-we-splice_read-from-trace_pipe.patch +parisc-isa-eeprom-fix-loff_t-usage.patch +cfg80211-add-two-missing-null-pointer-checks.patch +posix-timers-fix-oops-in-clock_nanosleep-with-clock_monotonic_raw.patch +pm-acpi-hp-g7000-notebook-needs-a-sci_en-resume-quirk.patch +powerpc-mpc83xx-fix-usb-mux-setup-for-mpc834x.patch +hugetlbfs-fix-i_blocks-accounting.patch +page-allocator-preserve-pfn-ordering-when-__gfp_cold-is-set.patch +x86-fix-cpa-memtype-reserving-in-the-set_pages_array-cases.patch +x86-fix-assembly-constraints-in-native_save_fl.patch +x86-pat-fix-set_memory_wc-related-corruption.patch +md-raid6-release-spare-page-at-stop.patch +md-when-a-level-change-reduces-the-number-of-devices-remove-the-excess.patch +md-handle-growth-of-v1.x-metadata-correctly.patch +ide-fix-handling-of-unexpected-irqs-vs-request_irq.patch +ide-relax-dma-info-validity-checking.patch diff --git a/queue-2.6.30/sysfs-fix-hardlink-count-on-device_move.patch b/queue-2.6.30/sysfs-fix-hardlink-count-on-device_move.patch new file mode 100644 index 00000000000..b8de06cc299 --- /dev/null +++ b/queue-2.6.30/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 +@@ -939,8 +939,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.30/thinkpad-acpi-disable-broken-bay-and-dock-subdrivers.patch b/queue-2.6.30/thinkpad-acpi-disable-broken-bay-and-dock-subdrivers.patch new file mode 100644 index 00000000000..bf56bde79d5 --- /dev/null +++ b/queue-2.6.30/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/platform/x86/Kconfig | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -265,6 +265,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. +@@ -278,7 +279,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.30/thinkpad-acpi-fix-incorrect-use-of-tpacpi_brght_mode_ecnvram.patch b/queue-2.6.30/thinkpad-acpi-fix-incorrect-use-of-tpacpi_brght_mode_ecnvram.patch new file mode 100644 index 00000000000..5b7c2437b67 --- /dev/null +++ b/queue-2.6.30/thinkpad-acpi-fix-incorrect-use-of-tpacpi_brght_mode_ecnvram.patch @@ -0,0 +1,130 @@ +From 59fe4fe34d7afdf63208124f313be9056feaa2f4 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 1 Aug 2009 12:04:20 -0300 +Subject: thinkpad-acpi: fix incorrect use of TPACPI_BRGHT_MODE_ECNVRAM + +From: Henrique de Moraes Holschuh + +commit 59fe4fe34d7afdf63208124f313be9056feaa2f4 upstream. + +HBRV-based default selection of backlight control strategy didn't work +well, at least the X41 defines it but doesn't use it and I don't think +it will stop there. + +Switch to a white/blacklist. All models that have HBRV defined have +been included in the list, and initially all ATI GPUs will get +ECNVRAM, and the Intel GPUs will get UCMS_STEP. + +Symptoms of incorrect backlight mode selection are: + +1. Non-working backlight control through sysfs; + +2. Backlight gets reset to the lowest level at every shutdown, reboot + and when thinkpad-acpi gets unloaded; + +This fixes a regression in 2.6.30, bugzilla #13826 + +Signed-off-by: Henrique de Moraes Holschuh +Reported-by: Tobias Diedrich +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 61 ++++++++++++++++++++++++++--------- + 1 file changed, 47 insertions(+), 14 deletions(-) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -5757,14 +5757,48 @@ static struct backlight_ops ibm_backligh + + /* --------------------------------------------------------------------- */ + ++/* ++ * These are only useful for models that have only one possibility ++ * of GPU. If the BIOS model handles both ATI and Intel, don't use ++ * these quirks. ++ */ ++#define TPACPI_BRGHT_Q_NOEC 0x0001 /* Must NOT use EC HBRV */ ++#define TPACPI_BRGHT_Q_EC 0x0002 /* Should or must use EC HBRV */ ++#define TPACPI_BRGHT_Q_ASK 0x8000 /* Ask for user report */ ++ ++static const struct tpacpi_quirk brightness_quirk_table[] __initconst = { ++ /* Models with ATI GPUs known to require ECNVRAM mode */ ++ TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ ++ ++ /* Models with ATI GPUs (waiting confirmation) */ ++ TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), ++ TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), ++ TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), ++ TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), ++ ++ /* Models with Intel Extreme Graphics 2 (waiting confirmation) */ ++ TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), ++ TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), ++ TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), ++ ++ /* Models with Intel GMA900 */ ++ TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ ++ TPACPI_Q_IBM('7', '4', TPACPI_BRGHT_Q_NOEC), /* X41 */ ++ TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC), /* X41 Tablet */ ++}; ++ + static int __init brightness_init(struct ibm_init_struct *iibm) + { + int b; ++ unsigned long quirks; + + vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); + + mutex_init(&brightness_mutex); + ++ quirks = tpacpi_check_quirks(brightness_quirk_table, ++ ARRAY_SIZE(brightness_quirk_table)); ++ + /* + * We always attempt to detect acpi support, so as to switch + * Lenovo Vista BIOS to ACPI brightness mode even if we are not +@@ -5821,23 +5855,13 @@ static int __init brightness_init(struct + /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */ + if (brightness_mode == TPACPI_BRGHT_MODE_AUTO || + brightness_mode == TPACPI_BRGHT_MODE_MAX) { +- if (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) { +- /* +- * IBM models that define HBRV probably have +- * EC-based backlight level control +- */ +- if (acpi_evalf(ec_handle, NULL, "HBRV", "qd")) +- /* T40-T43, R50-R52, R50e, R51e, X31-X41 */ +- brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM; +- else +- /* all other IBM ThinkPads */ +- brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; +- } else +- /* All Lenovo ThinkPads */ ++ if (quirks & TPACPI_BRGHT_Q_EC) ++ brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM; ++ else + brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; + + dbg_printk(TPACPI_DBG_BRGHT, +- "selected brightness_mode=%d\n", ++ "driver auto-selected brightness_mode=%d\n", + brightness_mode); + } + +@@ -5858,6 +5882,15 @@ static int __init brightness_init(struct + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, + "brightness is supported\n"); + ++ if (quirks & TPACPI_BRGHT_Q_ASK) { ++ printk(TPACPI_NOTICE ++ "brightness: will use unverified default: " ++ "brightness_mode=%d\n", brightness_mode); ++ printk(TPACPI_NOTICE ++ "brightness: please report to %s whether it works well " ++ "or not on your ThinkPad\n", TPACPI_MAIL); ++ } ++ + ibm_backlight_device->props.max_brightness = + (tp_features.bright_16levels)? 15 : 7; + ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; diff --git a/queue-2.6.30/tracing-fix-invalid-function_graph-entry.patch b/queue-2.6.30/tracing-fix-invalid-function_graph-entry.patch new file mode 100644 index 00000000000..6002be96e4d --- /dev/null +++ b/queue-2.6.30/tracing-fix-invalid-function_graph-entry.patch @@ -0,0 +1,55 @@ +From 38ceb592fcac9110c6b3c87ea0a27bff68c43486 Mon Sep 17 00:00:00 2001 +From: Lai Jiangshan +Date: Tue, 28 Jul 2009 20:11:24 +0800 +Subject: tracing: Fix invalid function_graph entry + +From: Lai Jiangshan + +commit 38ceb592fcac9110c6b3c87ea0a27bff68c43486 upstream. + +When print_graph_entry() computes a function call entry event, it needs +to also check the next entry to guess if it matches the return event of +the current function entry. +In order to look at this next event, it needs to consume the current +entry before going ahead in the ring buffer. + +However, if the current event that gets consumed is the last one in the +ring buffer head page, the ring_buffer may reuse the page for writers. +The consumed entry will then become invalid because of possible +racy overwriting. + +Me must then handle this entry by making a copy of it. + +The fix also applies on 2.6.30 + +Signed-off-by: Lai Jiangshan +Cc: Steven Rostedt +LKML-Reference: <4A6EEAEC.3050508@cn.fujitsu.com> +Signed-off-by: Frederic Weisbecker +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/trace_functions_graph.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/kernel/trace/trace_functions_graph.c ++++ b/kernel/trace/trace_functions_graph.c +@@ -798,9 +798,16 @@ print_graph_function(struct trace_iterat + + switch (entry->type) { + case TRACE_GRAPH_ENT: { +- struct ftrace_graph_ent_entry *field; ++ /* ++ * print_graph_entry() may consume the current event, ++ * thus @field may become invalid, so we need to save it. ++ * sizeof(struct ftrace_graph_ent_entry) is very small, ++ * it can be safely saved at the stack. ++ */ ++ struct ftrace_graph_ent_entry *field, saved; + trace_assign_type(field, entry); +- return print_graph_entry(field, s, iter); ++ saved = *field; ++ return print_graph_entry(&saved, s, iter); + } + case TRACE_GRAPH_RET: { + struct ftrace_graph_ret_entry *field; diff --git a/queue-2.6.30/tracing-fix-missing-function_graph-events-when-we-splice_read-from-trace_pipe.patch b/queue-2.6.30/tracing-fix-missing-function_graph-events-when-we-splice_read-from-trace_pipe.patch new file mode 100644 index 00000000000..3a529848d72 --- /dev/null +++ b/queue-2.6.30/tracing-fix-missing-function_graph-events-when-we-splice_read-from-trace_pipe.patch @@ -0,0 +1,70 @@ +From 74e7ff8c50b6b022e6ffaa736b16a4dc161d3eaf Mon Sep 17 00:00:00 2001 +From: Lai Jiangshan +Date: Tue, 28 Jul 2009 20:17:22 +0800 +Subject: tracing: Fix missing function_graph events when we splice_read from trace_pipe + +From: Lai Jiangshan + +commit 74e7ff8c50b6b022e6ffaa736b16a4dc161d3eaf upstream. + +About a half events are missing when we splice_read +from trace_pipe. They are unexpectedly consumed because we ignore +the TRACE_TYPE_NO_CONSUME return value used by the function graph +tracer when it needs to consume the events by itself to walk on +the ring buffer. + +The same problem appears with ftrace_dump() + +Example of an output before this patch: + +1) | ktime_get_real() { +1) 2.846 us | read_hpet(); +1) 4.558 us | } +1) 6.195 us | } + +After this patch: + +0) | ktime_get_real() { +0) | getnstimeofday() { +0) 1.960 us | read_hpet(); +0) 3.597 us | } +0) 5.196 us | } + +The fix also applies on 2.6.30 + +Signed-off-by: Lai Jiangshan +Cc: Steven Rostedt +LKML-Reference: <4A6EEC52.90704@cn.fujitsu.com> +Signed-off-by: Frederic Weisbecker +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/trace.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -2993,7 +2993,8 @@ tracing_fill_pipe_page(size_t rem, struc + break; + } + +- trace_consume(iter); ++ if (ret != TRACE_TYPE_NO_CONSUME) ++ trace_consume(iter); + rem -= count; + if (!find_next_entry_inc(iter)) { + rem = 0; +@@ -4122,8 +4123,11 @@ static void __ftrace_dump(bool disable_t + iter.pos = -1; + + if (find_next_entry_inc(&iter) != NULL) { +- print_trace_line(&iter); +- trace_consume(&iter); ++ int ret; ++ ++ ret = print_trace_line(&iter); ++ if (ret != TRACE_TYPE_NO_CONSUME) ++ trace_consume(&iter); + } + + trace_printk_seq(&iter.seq); diff --git a/queue-2.6.30/usb-storage-raise-timeout-in-usb_stor_bulk_max_lun.patch b/queue-2.6.30/usb-storage-raise-timeout-in-usb_stor_bulk_max_lun.patch new file mode 100644 index 00000000000..4f7f0a2e8e6 --- /dev/null +++ b/queue-2.6.30/usb-storage-raise-timeout-in-usb_stor_bulk_max_lun.patch @@ -0,0 +1,37 @@ +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 + +--- + drivers/usb/storage/transport.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- 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_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.30/x86-fix-assembly-constraints-in-native_save_fl.patch b/queue-2.6.30/x86-fix-assembly-constraints-in-native_save_fl.patch new file mode 100644 index 00000000000..6549822ed1a --- /dev/null +++ b/queue-2.6.30/x86-fix-assembly-constraints-in-native_save_fl.patch @@ -0,0 +1,64 @@ +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 + +--- a/arch/x86/include/asm/irqflags.h ++++ b/arch/x86/include/asm/irqflags.h +@@ -12,9 +12,15 @@ static inline unsigned long native_save_fl(void) + { + 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"); + diff --git a/queue-2.6.30/x86-fix-cpa-memtype-reserving-in-the-set_pages_array-cases.patch b/queue-2.6.30/x86-fix-cpa-memtype-reserving-in-the-set_pages_array-cases.patch new file mode 100644 index 00000000000..2eda8884219 --- /dev/null +++ b/queue-2.6.30/x86-fix-cpa-memtype-reserving-in-the-set_pages_array-cases.patch @@ -0,0 +1,98 @@ +From 8523acfe40efc1a8d3da8f473ca67cb195b06f0c Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom +Date: Mon, 3 Aug 2009 09:25:45 +0200 +Subject: x86: Fix CPA memtype reserving in the set_pages_array*() cases + +From: Thomas Hellstrom + +commit 8523acfe40efc1a8d3da8f473ca67cb195b06f0c upstream. + +The code was incorrectly reserving memtypes using the page +virtual address instead of the physical address. Furthermore, +the code was not ignoring highmem pages as it ought to. + +( upstream does not pass in highmem pages yet - but upcoming + graphics code will do it and there's no reason to not handle + this properly in the CPA APIs.) + +Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=13884 + +Signed-off-by: Thomas Hellstrom +Acked-by: Suresh Siddha +Cc: dri-devel@lists.sourceforge.net +Cc: venkatesh.pallipadi@intel.com +LKML-Reference: <1249284345-7654-1-git-send-email-thellstrom@vmware.com> +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/mm/pageattr.c | 30 +++++++++++++++++++++--------- + 1 file changed, 21 insertions(+), 9 deletions(-) + +--- a/arch/x86/mm/pageattr.c ++++ b/arch/x86/mm/pageattr.c +@@ -590,9 +590,12 @@ static int __change_page_attr(struct cpa + unsigned int level; + pte_t *kpte, old_pte; + +- if (cpa->flags & CPA_PAGES_ARRAY) +- address = (unsigned long)page_address(cpa->pages[cpa->curpage]); +- else if (cpa->flags & CPA_ARRAY) ++ if (cpa->flags & CPA_PAGES_ARRAY) { ++ struct page *page = cpa->pages[cpa->curpage]; ++ if (unlikely(PageHighMem(page))) ++ return 0; ++ address = (unsigned long)page_address(page); ++ } else if (cpa->flags & CPA_ARRAY) + address = cpa->vaddr[cpa->curpage]; + else + address = *cpa->vaddr; +@@ -695,9 +698,12 @@ static int cpa_process_alias(struct cpa_ + * No need to redo, when the primary call touched the direct + * mapping already: + */ +- if (cpa->flags & CPA_PAGES_ARRAY) +- vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]); +- else if (cpa->flags & CPA_ARRAY) ++ if (cpa->flags & CPA_PAGES_ARRAY) { ++ struct page *page = cpa->pages[cpa->curpage]; ++ if (unlikely(PageHighMem(page))) ++ return 0; ++ vaddr = (unsigned long)page_address(page); ++ } else if (cpa->flags & CPA_ARRAY) + vaddr = cpa->vaddr[cpa->curpage]; + else + vaddr = *cpa->vaddr; +@@ -1118,7 +1124,9 @@ int set_pages_array_uc(struct page **pag + int free_idx; + + for (i = 0; i < addrinarray; i++) { +- start = (unsigned long)page_address(pages[i]); ++ if (PageHighMem(pages[i])) ++ continue; ++ start = page_to_pfn(pages[i]) << PAGE_SHIFT; + end = start + PAGE_SIZE; + if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL)) + goto err_out; +@@ -1131,7 +1139,9 @@ int set_pages_array_uc(struct page **pag + err_out: + free_idx = i; + for (i = 0; i < free_idx; i++) { +- start = (unsigned long)page_address(pages[i]); ++ if (PageHighMem(pages[i])) ++ continue; ++ start = page_to_pfn(pages[i]) << PAGE_SHIFT; + end = start + PAGE_SIZE; + free_memtype(start, end); + } +@@ -1160,7 +1170,9 @@ int set_pages_array_wb(struct page **pag + return retval; + + for (i = 0; i < addrinarray; i++) { +- start = (unsigned long)page_address(pages[i]); ++ if (PageHighMem(pages[i])) ++ continue; ++ start = page_to_pfn(pages[i]) << PAGE_SHIFT; + end = start + PAGE_SIZE; + free_memtype(start, end); + } diff --git a/queue-2.6.30/x86-pat-fix-set_memory_wc-related-corruption.patch b/queue-2.6.30/x86-pat-fix-set_memory_wc-related-corruption.patch new file mode 100644 index 00000000000..3bed8a1e816 --- /dev/null +++ b/queue-2.6.30/x86-pat-fix-set_memory_wc-related-corruption.patch @@ -0,0 +1,67 @@ +From bdc6340f4eb68295b1e7c0ade2356b56dca93d93 Mon Sep 17 00:00:00 2001 +From: Pallipadi, Venkatesh +Date: Thu, 30 Jul 2009 14:43:19 -0700 +Subject: x86, pat: Fix set_memory_wc related corruption + +From: Pallipadi, Venkatesh + +commit bdc6340f4eb68295b1e7c0ade2356b56dca93d93 upstream. + +Changeset 3869c4aa18835c8c61b44bd0f3ace36e9d3b5bd0 +that went in after 2.6.30-rc1 was a seemingly small change to _set_memory_wc() +to make it complaint with SDM requirements. But, introduced a nasty bug, which +can result in crash and/or strange corruptions when set_memory_wc is used. +One such crash reported here +http://lkml.org/lkml/2009/7/30/94 + +Actually, that changeset introduced two bugs. +* change_page_attr_set() takes &addr as first argument and can the addr value + might have changed on return, even for single page change_page_attr_set() + call. That will make the second change_page_attr_set() in this routine + operate on unrelated addr, that can eventually cause strange corruptions + and bad page state crash. +* The second change_page_attr_set() call, before setting _PAGE_CACHE_WC, should + clear the earlier _PAGE_CACHE_UC_MINUS, as otherwise cache attribute will not + be WC (will be UC instead). + +The patch below fixes both these problems. Sending a single patch to fix both +the problems, as the change is to the same line of code. The change to have a +addr_copy is not very clean. But, it is simpler than making more changes +through various routines in pageattr.c. + +A huge thanks to Jerome for reporting this problem and providing a simple test +case that helped us root cause the problem. + +Reported-by: Jerome Glisse +Signed-off-by: Venkatesh Pallipadi +Signed-off-by: Suresh Siddha +LKML-Reference: <20090730214319.GA1889@linux-os.sc.intel.com> +Acked-by: Dave Airlie +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/mm/pageattr.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/arch/x86/mm/pageattr.c ++++ b/arch/x86/mm/pageattr.c +@@ -1002,12 +1002,15 @@ EXPORT_SYMBOL(set_memory_array_uc); + int _set_memory_wc(unsigned long addr, int numpages) + { + int ret; ++ unsigned long addr_copy = addr; ++ + ret = change_page_attr_set(&addr, numpages, + __pgprot(_PAGE_CACHE_UC_MINUS), 0); +- + if (!ret) { +- ret = change_page_attr_set(&addr, numpages, +- __pgprot(_PAGE_CACHE_WC), 0); ++ ret = change_page_attr_set_clr(&addr_copy, numpages, ++ __pgprot(_PAGE_CACHE_WC), ++ __pgprot(_PAGE_CACHE_MASK), ++ 0, 0, NULL); + } + return ret; + }