From: Greg Kroah-Hartman Date: Wed, 1 Aug 2012 22:49:31 +0000 (-0700) Subject: 3.5-stable patches X-Git-Tag: v3.5.1~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=57140883acb1c8d5f1f7c0aa0b857bb3b7116fcd;p=thirdparty%2Fkernel%2Fstable-queue.git 3.5-stable patches added patches: acpi-ac-prevent-oops-on-some-boxes-due-to-missing-check-power_supply_register-return-value-check.patch acpi-apei-fixup-common-access-width-firmware-bug.patch atl1c-fix-issue-of-io-access-mode-for-ar8152-v2.1.patch btrfs-call-the-ordered-free-operation-without-any-locks-held.patch cgroup-cgroup_rm_files-was-calling-simple_unlink-with-the-wrong-inode.patch cifs-ensure-that-we-always-do-cifsfileinfo_get-under-the-spinlock.patch cifs-reinstate-sec-ntlmv2-mount-option.patch iommu-amd-add-missing-spin_lock-initialization.patch iommu-amd-fix-hotplug-with-iommu-pt.patch kmsg-properly-print-over-long-continuation-lines.patch mwifiex-correction-in-mcs-index-check.patch qeth-repair-crash-in-qeth_l3_vlan_rx_kill_vid.patch rtlwifi-rtl8192cu-change-buffer-allocation-for-synchronous-reads.patch rtlwifi-rtl8192de-fix-phy-based-version-calculation.patch s390-idle-fix-sequence-handling-vs-cpu-hotplug.patch s390-mm-downgrade-page-table-after-fork-of-a-31-bit-process.patch s390-mm-fix-fault-handling-for-page-table-walk-case.patch spi-pl022-disable-port-when-unused.patch stable-update-references-to-older-2.6-versions-for-3.x.patch staging-zsmalloc-finish-conversion-to-a-separate-module.patch tg3-add-device-id-of-apple-thunderbolt-ethernet-device.patch tg3-fix-race-condition-in-tg3_get_stats64.patch tg3-fix-read-dma-workaround-for-5719-a0.patch udf-improve-table-length-check-to-avoid-possible-overflow.patch workqueue-perform-cpu-down-operations-from-low-priority-cpu_notifier.patch --- diff --git a/queue-3.5/acpi-ac-prevent-oops-on-some-boxes-due-to-missing-check-power_supply_register-return-value-check.patch b/queue-3.5/acpi-ac-prevent-oops-on-some-boxes-due-to-missing-check-power_supply_register-return-value-check.patch new file mode 100644 index 00000000000..573644fed82 --- /dev/null +++ b/queue-3.5/acpi-ac-prevent-oops-on-some-boxes-due-to-missing-check-power_supply_register-return-value-check.patch @@ -0,0 +1,42 @@ +From f197ac13f6eeb351b31250b9ab7d0da17434ea36 Mon Sep 17 00:00:00 2001 +From: Lan Tianyu +Date: Fri, 20 Jul 2012 13:29:16 +0800 +Subject: ACPI/AC: prevent OOPS on some boxes due to missing check power_supply_register() return value check + +From: Lan Tianyu + +commit f197ac13f6eeb351b31250b9ab7d0da17434ea36 upstream. + +In the ac.c, power_supply_register()'s return value is not checked. + +As a result, the driver's add() ops may return success +even though the device failed to initialize. + +For example, some BIOS may describe two ACADs in the same DSDT. +The second ACAD device will fail to register, +but ACPI driver's add() ops returns sucessfully. +The ACPI device will receive ACPI notification and cause OOPS. + +https://bugzilla.redhat.com/show_bug.cgi?id=772730 + +Signed-off-by: Lan Tianyu +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/ac.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/ac.c ++++ b/drivers/acpi/ac.c +@@ -292,7 +292,9 @@ static int acpi_ac_add(struct acpi_devic + ac->charger.properties = ac_props; + ac->charger.num_properties = ARRAY_SIZE(ac_props); + ac->charger.get_property = get_ac_property; +- power_supply_register(&ac->device->dev, &ac->charger); ++ result = power_supply_register(&ac->device->dev, &ac->charger); ++ if (result) ++ goto end; + + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", + acpi_device_name(device), acpi_device_bid(device), diff --git a/queue-3.5/acpi-apei-fixup-common-access-width-firmware-bug.patch b/queue-3.5/acpi-apei-fixup-common-access-width-firmware-bug.patch new file mode 100644 index 00000000000..cd6e381cf25 --- /dev/null +++ b/queue-3.5/acpi-apei-fixup-common-access-width-firmware-bug.patch @@ -0,0 +1,41 @@ +From f712c71f7b2b43b894d1e92e1b77385fcad8815f Mon Sep 17 00:00:00 2001 +From: Jean Delvare +Date: Tue, 12 Jun 2012 10:43:28 +0200 +Subject: ACPI, APEI: Fixup common access width firmware bug + +From: Jean Delvare + +commit f712c71f7b2b43b894d1e92e1b77385fcad8815f upstream. + +Many firmwares have a common register definition bug where 8-bit +access width is specified for a 32-bit register. Ideally this should +be fixed in the BIOS, but earlier versions of the kernel did not +complain, so fix that up silently. + +This closes kernel bug #43282: +https://bugzilla.kernel.org/show_bug.cgi?id=43282 + +Signed-off-by: Jean Delvare +Acked-by: Huang Ying +Acked-by: Gary Hade +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/apei/apei-base.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/acpi/apei/apei-base.c ++++ b/drivers/acpi/apei/apei-base.c +@@ -586,6 +586,11 @@ static int apei_check_gar(struct acpi_ge + } + *access_bit_width = 1UL << (access_size_code + 2); + ++ /* Fixup common BIOS bug */ ++ if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && ++ *access_bit_width < 32) ++ *access_bit_width = 32; ++ + if ((bit_width + bit_offset) > *access_bit_width) { + pr_warning(FW_BUG APEI_PFX + "Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n", diff --git a/queue-3.5/atl1c-fix-issue-of-io-access-mode-for-ar8152-v2.1.patch b/queue-3.5/atl1c-fix-issue-of-io-access-mode-for-ar8152-v2.1.patch new file mode 100644 index 00000000000..c6b8a7e500e --- /dev/null +++ b/queue-3.5/atl1c-fix-issue-of-io-access-mode-for-ar8152-v2.1.patch @@ -0,0 +1,83 @@ +From fa0afcd10951afad2022dda09777d2bf70cdab3d Mon Sep 17 00:00:00 2001 +From: Cloud Ren +Date: Thu, 19 Jul 2012 17:01:58 +0000 +Subject: atl1c: fix issue of io access mode for AR8152 v2.1 + +From: Cloud Ren + +commit fa0afcd10951afad2022dda09777d2bf70cdab3d upstream. + +When io access mode is enabled by BOOTROM or BIOS for AR8152 v2.1, +the register can't be read/write by memory access mode. +Clearing Bit 8 of Register 0x21c could fixed the issue. + +Signed-off-by: Cloud Ren +Signed-off-by: xiong +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 5 +++++ + drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 16 +++++++++++++++- + 2 files changed, 20 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h +@@ -74,6 +74,8 @@ void atl1c_post_phy_linkchg(struct atl1c + #define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ + #define L2CB_V10 0xc0 + #define L2CB_V11 0xc1 ++#define L2CB_V20 0xc0 ++#define L2CB_V21 0xc1 + + /* register definition */ + #define REG_DEVICE_CAP 0x5C +@@ -87,6 +89,9 @@ void atl1c_post_phy_linkchg(struct atl1c + #define LINK_CTRL_L1_EN 0x02 + #define LINK_CTRL_EXT_SYNC 0x80 + ++#define REG_PCIE_IND_ACC_ADDR 0x80 ++#define REG_PCIE_IND_ACC_DATA 0x84 ++ + #define REG_DEV_SERIALNUM_CTRL 0x200 + #define REG_DEV_MAC_SEL_MASK 0x0 /* 0:EUI; 1:MAC */ + #define REG_DEV_MAC_SEL_SHIFT 0 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +@@ -739,6 +739,8 @@ static const struct atl1c_platform_patch + + static void __devinit atl1c_patch_assign(struct atl1c_hw *hw) + { ++ struct pci_dev *pdev = hw->adapter->pdev; ++ u32 misc_ctrl; + int i = 0; + + hw->msi_lnkpatch = false; +@@ -753,6 +755,18 @@ static void __devinit atl1c_patch_assign + } + i++; + } ++ ++ if (hw->device_id == PCI_DEVICE_ID_ATHEROS_L2C_B2 && ++ hw->revision_id == L2CB_V21) { ++ /* config acess mode */ ++ pci_write_config_dword(pdev, REG_PCIE_IND_ACC_ADDR, ++ REG_PCIE_DEV_MISC_CTRL); ++ pci_read_config_dword(pdev, REG_PCIE_IND_ACC_DATA, &misc_ctrl); ++ misc_ctrl &= ~0x100; ++ pci_write_config_dword(pdev, REG_PCIE_IND_ACC_ADDR, ++ REG_PCIE_DEV_MISC_CTRL); ++ pci_write_config_dword(pdev, REG_PCIE_IND_ACC_DATA, misc_ctrl); ++ } + } + /* + * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) +@@ -780,7 +794,7 @@ static int __devinit atl1c_sw_init(struc + hw->device_id = pdev->device; + hw->subsystem_vendor_id = pdev->subsystem_vendor; + hw->subsystem_id = pdev->subsystem_device; +- AT_READ_REG(hw, PCI_CLASS_REVISION, &revision); ++ pci_read_config_dword(pdev, PCI_CLASS_REVISION, &revision); + hw->revision_id = revision & 0xFF; + /* before link up, we assume hibernate is true */ + hw->hibernate = true; diff --git a/queue-3.5/btrfs-call-the-ordered-free-operation-without-any-locks-held.patch b/queue-3.5/btrfs-call-the-ordered-free-operation-without-any-locks-held.patch new file mode 100644 index 00000000000..2f248cd9384 --- /dev/null +++ b/queue-3.5/btrfs-call-the-ordered-free-operation-without-any-locks-held.patch @@ -0,0 +1,45 @@ +From e9fbcb42201c862fd6ab45c48ead4f47bb2dea9d Mon Sep 17 00:00:00 2001 +From: Chris Mason +Date: Wed, 25 Jul 2012 15:57:13 -0400 +Subject: Btrfs: call the ordered free operation without any locks held + +From: Chris Mason + +commit e9fbcb42201c862fd6ab45c48ead4f47bb2dea9d upstream. + +Each ordered operation has a free callback, and this was called with the +worker spinlock held. Josef made the free callback also call iput, +which we can't do with the spinlock. + +This drops the spinlock for the free operation and grabs it again before +moving through the rest of the list. We'll circle back around to this +and find a cleaner way that doesn't bounce the lock around so much. + +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/async-thread.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/async-thread.c ++++ b/fs/btrfs/async-thread.c +@@ -206,10 +206,17 @@ static noinline void run_ordered_complet + + work->ordered_func(work); + +- /* now take the lock again and call the freeing code */ ++ /* now take the lock again and drop our item from the list */ + spin_lock(&workers->order_lock); + list_del(&work->order_list); ++ spin_unlock(&workers->order_lock); ++ ++ /* ++ * we don't want to call the ordered free functions ++ * with the lock held though ++ */ + work->ordered_free(work); ++ spin_lock(&workers->order_lock); + } + + spin_unlock(&workers->order_lock); diff --git a/queue-3.5/cgroup-cgroup_rm_files-was-calling-simple_unlink-with-the-wrong-inode.patch b/queue-3.5/cgroup-cgroup_rm_files-was-calling-simple_unlink-with-the-wrong-inode.patch new file mode 100644 index 00000000000..1f8bb52b5e9 --- /dev/null +++ b/queue-3.5/cgroup-cgroup_rm_files-was-calling-simple_unlink-with-the-wrong-inode.patch @@ -0,0 +1,39 @@ +From ce27e317ba22b359bde02216afab934dac3af095 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Tue, 3 Jul 2012 10:38:06 -0700 +Subject: cgroup: cgroup_rm_files() was calling simple_unlink() with the wrong inode + +From: Tejun Heo + +commit ce27e317ba22b359bde02216afab934dac3af095 upstream. + +While refactoring cgroup file removal path, 05ef1d7c4a "cgroup: +introduce struct cfent" incorrectly changed the @dir argument of +simple_unlink() to the inode of the file being deleted instead of that +of the containing directory. + +The effect of this bug is minor - ctime and mtime of the parent +weren't properly updated on file deletion. + +Fix it by using @cgrp->dentry->d_inode instead. + +Signed-off-by: Tejun Heo +Reported-by: Al Viro +Acked-by: Li Zefan +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/cgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/cgroup.c ++++ b/kernel/cgroup.c +@@ -954,7 +954,7 @@ static int cgroup_rm_file(struct cgroup + + dget(d); + d_delete(d); +- simple_unlink(d->d_inode, d); ++ simple_unlink(cgrp->dentry->d_inode, d); + list_del_init(&cfe->node); + dput(d); + diff --git a/queue-3.5/cifs-ensure-that-we-always-do-cifsfileinfo_get-under-the-spinlock.patch b/queue-3.5/cifs-ensure-that-we-always-do-cifsfileinfo_get-under-the-spinlock.patch new file mode 100644 index 00000000000..d1f1e7c9e1b --- /dev/null +++ b/queue-3.5/cifs-ensure-that-we-always-do-cifsfileinfo_get-under-the-spinlock.patch @@ -0,0 +1,101 @@ +From 764a1b1acecedfe204cb2e80d8e2cc7c6df1b0b8 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Wed, 25 Jul 2012 14:59:54 -0400 +Subject: cifs: ensure that we always do cifsFileInfo_get under the spinlock + +From: Jeff Layton + +commit 764a1b1acecedfe204cb2e80d8e2cc7c6df1b0b8 upstream. + +The readpages bug is a regression that was introduced in 6993f74a5. +This also fixes a couple of similar bugs in the uncached read and write +codepaths. + +Also, prevent this sort of thing in the future by having cifsFileInfo_get +take the spinlock itself, and adding a _locked variant for use in places +that are already holding the lock. The _put code has always done that +so this makes for a less confusing interface. + +Reviewed-by: Pavel Shilovsky +Signed-off-by: Jeff Layton +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifsglob.h | 6 +++--- + fs/cifs/file.c | 17 ++++++++++++----- + 2 files changed, 15 insertions(+), 8 deletions(-) + +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -657,13 +657,13 @@ struct cifs_io_parms { + * Take a reference on the file private data. Must be called with + * cifs_file_list_lock held. + */ +-static inline +-struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file) ++static inline void ++cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file) + { + ++cifs_file->count; +- return cifs_file; + } + ++struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file); + void cifsFileInfo_put(struct cifsFileInfo *cifs_file); + + /* +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -284,6 +284,15 @@ cifs_new_fileinfo(__u16 fileHandle, stru + + static void cifs_del_lock_waiters(struct cifsLockInfo *lock); + ++struct cifsFileInfo * ++cifsFileInfo_get(struct cifsFileInfo *cifs_file) ++{ ++ spin_lock(&cifs_file_list_lock); ++ cifsFileInfo_get_locked(cifs_file); ++ spin_unlock(&cifs_file_list_lock); ++ return cifs_file; ++} ++ + /* + * Release a reference on the file private data. This may involve closing + * the filehandle out on the server. Must be called without holding +@@ -1563,7 +1572,7 @@ struct cifsFileInfo *find_readable_file( + if (!open_file->invalidHandle) { + /* found a good file */ + /* lock it so it will not be closed on us */ +- cifsFileInfo_get(open_file); ++ cifsFileInfo_get_locked(open_file); + spin_unlock(&cifs_file_list_lock); + return open_file; + } /* else might as well continue, and look for +@@ -1615,7 +1624,7 @@ refind_writable: + if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { + if (!open_file->invalidHandle) { + /* found a good writable file */ +- cifsFileInfo_get(open_file); ++ cifsFileInfo_get_locked(open_file); + spin_unlock(&cifs_file_list_lock); + return open_file; + } else { +@@ -1632,7 +1641,7 @@ refind_writable: + + if (inv_file) { + any_available = false; +- cifsFileInfo_get(inv_file); ++ cifsFileInfo_get_locked(inv_file); + } + + spin_unlock(&cifs_file_list_lock); +@@ -3082,8 +3091,6 @@ static int cifs_readpages(struct file *f + break; + } + +- spin_lock(&cifs_file_list_lock); +- spin_unlock(&cifs_file_list_lock); + rdata->cfile = cifsFileInfo_get(open_file); + rdata->mapping = mapping; + rdata->offset = offset; diff --git a/queue-3.5/cifs-reinstate-sec-ntlmv2-mount-option.patch b/queue-3.5/cifs-reinstate-sec-ntlmv2-mount-option.patch new file mode 100644 index 00000000000..cf455cfae39 --- /dev/null +++ b/queue-3.5/cifs-reinstate-sec-ntlmv2-mount-option.patch @@ -0,0 +1,57 @@ +From 7659624ffb550d69c87f9af9ae63e717daa874bd Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Mon, 23 Jul 2012 20:34:17 -0400 +Subject: cifs: reinstate sec=ntlmv2 mount option +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jeff Layton + +commit 7659624ffb550d69c87f9af9ae63e717daa874bd upstream. + +sec=ntlmv2 as a mount option got dropped in the mount option overhaul. + +Cc: Sachin Prabhu +Reported-by: Günter Kukkukk +Signed-off-by: Jeff Layton +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/connect.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -238,8 +238,8 @@ static const match_table_t cifs_mount_op + enum { + Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p, + Opt_sec_ntlmsspi, Opt_sec_ntlmssp, +- Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i, +- Opt_sec_nontlm, Opt_sec_lanman, ++ Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2, ++ Opt_sec_ntlmv2i, Opt_sec_lanman, + Opt_sec_none, + + Opt_sec_err +@@ -253,8 +253,9 @@ static const match_table_t cifs_secflavo + { Opt_sec_ntlmssp, "ntlmssp" }, + { Opt_ntlm, "ntlm" }, + { Opt_sec_ntlmi, "ntlmi" }, ++ { Opt_sec_ntlmv2, "nontlm" }, ++ { Opt_sec_ntlmv2, "ntlmv2" }, + { Opt_sec_ntlmv2i, "ntlmv2i" }, +- { Opt_sec_nontlm, "nontlm" }, + { Opt_sec_lanman, "lanman" }, + { Opt_sec_none, "none" }, + +@@ -1167,7 +1168,7 @@ static int cifs_parse_security_flavors(c + case Opt_sec_ntlmi: + vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; + break; +- case Opt_sec_nontlm: ++ case Opt_sec_ntlmv2: + vol->secFlg |= CIFSSEC_MAY_NTLMV2; + break; + case Opt_sec_ntlmv2i: diff --git a/queue-3.5/iommu-amd-add-missing-spin_lock-initialization.patch b/queue-3.5/iommu-amd-add-missing-spin_lock-initialization.patch new file mode 100644 index 00000000000..bf54ec96c34 --- /dev/null +++ b/queue-3.5/iommu-amd-add-missing-spin_lock-initialization.patch @@ -0,0 +1,31 @@ +From 2c13d47a1a7ee8808796016c617aef25fd1d1925 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Thu, 19 Jul 2012 10:56:10 +0200 +Subject: iommu/amd: Add missing spin_lock initialization + +From: Joerg Roedel + +commit 2c13d47a1a7ee8808796016c617aef25fd1d1925 upstream. + +Add missing spin_lock initialization in +amd_iommu_bind_pasid() function and make lockdep happy +again. + +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/amd_iommu_v2.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/iommu/amd_iommu_v2.c ++++ b/drivers/iommu/amd_iommu_v2.c +@@ -681,6 +681,8 @@ int amd_iommu_bind_pasid(struct pci_dev + + atomic_set(&pasid_state->count, 1); + init_waitqueue_head(&pasid_state->wq); ++ spin_lock_init(&pasid_state->lock); ++ + pasid_state->task = task; + pasid_state->mm = get_task_mm(task); + pasid_state->device_state = dev_state; diff --git a/queue-3.5/iommu-amd-fix-hotplug-with-iommu-pt.patch b/queue-3.5/iommu-amd-fix-hotplug-with-iommu-pt.patch new file mode 100644 index 00000000000..2c48cb64a22 --- /dev/null +++ b/queue-3.5/iommu-amd-fix-hotplug-with-iommu-pt.patch @@ -0,0 +1,52 @@ +From 2c9195e990297068d0f1f1bd8e2f1d09538009da Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Thu, 19 Jul 2012 13:42:54 +0200 +Subject: iommu/amd: Fix hotplug with iommu=pt + +From: Joerg Roedel + +commit 2c9195e990297068d0f1f1bd8e2f1d09538009da upstream. + +This did not work because devices are not put into the +pt_domain. Fix this. + +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/amd_iommu.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/iommu/amd_iommu.c ++++ b/drivers/iommu/amd_iommu.c +@@ -2254,6 +2254,18 @@ static int device_change_notifier(struct + + iommu_init_device(dev); + ++ /* ++ * dev_data is still NULL and ++ * got initialized in iommu_init_device ++ */ ++ dev_data = get_dev_data(dev); ++ ++ if (iommu_pass_through || dev_data->iommu_v2) { ++ dev_data->passthrough = true; ++ attach_device(dev, pt_domain); ++ break; ++ } ++ + domain = domain_for_device(dev); + + /* allocate a protection domain if a device is added */ +@@ -2271,10 +2283,7 @@ static int device_change_notifier(struct + + dev_data = get_dev_data(dev); + +- if (!dev_data->passthrough) +- dev->archdata.dma_ops = &amd_iommu_dma_ops; +- else +- dev->archdata.dma_ops = &nommu_dma_ops; ++ dev->archdata.dma_ops = &amd_iommu_dma_ops; + + break; + case BUS_NOTIFY_DEL_DEVICE: diff --git a/queue-3.5/kmsg-properly-print-over-long-continuation-lines.patch b/queue-3.5/kmsg-properly-print-over-long-continuation-lines.patch new file mode 100644 index 00000000000..6e722339e34 --- /dev/null +++ b/queue-3.5/kmsg-properly-print-over-long-continuation-lines.patch @@ -0,0 +1,146 @@ +From 70498253186586e5dca7bc3ebd3415203b059fbc Mon Sep 17 00:00:00 2001 +From: Kay Sievers +Date: Mon, 16 Jul 2012 18:35:29 -0700 +Subject: kmsg - properly print over-long continuation lines + +From: Kay Sievers + +commit 70498253186586e5dca7bc3ebd3415203b059fbc upstream. + +Reserve PREFIX_MAX bytes in the LOG_LINE_MAX line when buffering a +continuation line, to be able to properly prefix the LOG_LINE_MAX +line with the syslog prefix and timestamp when printing it. + +Reported-By: Dave Jones +Signed-off-by: Kay Sievers +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/printk.c | 33 +++++++++++++++++++-------------- + 1 file changed, 19 insertions(+), 14 deletions(-) + +--- a/kernel/printk.c ++++ b/kernel/printk.c +@@ -235,7 +235,8 @@ static u32 log_next_idx; + static u64 clear_seq; + static u32 clear_idx; + +-#define LOG_LINE_MAX 1024 ++#define PREFIX_MAX 32 ++#define LOG_LINE_MAX 1024 - PREFIX_MAX + + /* record buffer */ + #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) +@@ -876,7 +877,7 @@ static size_t msg_print_text(const struc + + if (buf) { + if (print_prefix(msg, syslog, NULL) + +- text_len + 1>= size - len) ++ text_len + 1 >= size - len) + break; + + if (prefix) +@@ -907,7 +908,7 @@ static int syslog_print(char __user *buf + struct log *msg; + int len = 0; + +- text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); ++ text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); + if (!text) + return -ENOMEM; + +@@ -930,7 +931,8 @@ static int syslog_print(char __user *buf + + skip = syslog_partial; + msg = log_from_idx(syslog_idx); +- n = msg_print_text(msg, syslog_prev, true, text, LOG_LINE_MAX); ++ n = msg_print_text(msg, syslog_prev, true, text, ++ LOG_LINE_MAX + PREFIX_MAX); + if (n - syslog_partial <= size) { + /* message fits into buffer, move forward */ + syslog_idx = log_next(syslog_idx); +@@ -969,7 +971,7 @@ static int syslog_print_all(char __user + char *text; + int len = 0; + +- text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); ++ text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); + if (!text) + return -ENOMEM; + +@@ -1022,7 +1024,8 @@ static int syslog_print_all(char __user + struct log *msg = log_from_idx(idx); + int textlen; + +- textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX); ++ textlen = msg_print_text(msg, prev, true, text, ++ LOG_LINE_MAX + PREFIX_MAX); + if (textlen < 0) { + len = textlen; + break; +@@ -1352,15 +1355,15 @@ static struct cont { + bool flushed:1; /* buffer sealed and committed */ + } cont; + +-static void cont_flush(void) ++static void cont_flush(enum log_flags flags) + { + if (cont.flushed) + return; + if (cont.len == 0) + return; + +- log_store(cont.facility, cont.level, LOG_NOCONS, cont.ts_nsec, +- NULL, 0, cont.buf, cont.len); ++ log_store(cont.facility, cont.level, LOG_NOCONS | flags, ++ cont.ts_nsec, NULL, 0, cont.buf, cont.len); + + cont.flushed = true; + } +@@ -1371,7 +1374,8 @@ static bool cont_add(int facility, int l + return false; + + if (cont.len + len > sizeof(cont.buf)) { +- cont_flush(); ++ /* the line gets too long, split it up in separate records */ ++ cont_flush(LOG_CONT); + return false; + } + +@@ -1507,7 +1511,7 @@ asmlinkage int vprintk_emit(int facility + * or another task also prints continuation lines. + */ + if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) +- cont_flush(); ++ cont_flush(0); + + /* buffer line if possible, otherwise store it right away */ + if (!cont_add(facility, level, text, text_len)) +@@ -1525,7 +1529,7 @@ asmlinkage int vprintk_emit(int facility + if (cont.len && cont.owner == current) { + if (!(lflags & LOG_PREFIX)) + stored = cont_add(facility, level, text, text_len); +- cont_flush(); ++ cont_flush(0); + } + + if (!stored) +@@ -1618,7 +1622,8 @@ EXPORT_SYMBOL(printk); + + #else + +-#define LOG_LINE_MAX 0 ++#define LOG_LINE_MAX 0 ++#define PREFIX_MAX 0 + static struct cont { + size_t len; + size_t cons; +@@ -1923,7 +1928,7 @@ static enum log_flags console_prev; + */ + void console_unlock(void) + { +- static char text[LOG_LINE_MAX]; ++ static char text[LOG_LINE_MAX + PREFIX_MAX]; + static u64 seen_seq; + unsigned long flags; + bool wake_klogd = false; diff --git a/queue-3.5/mwifiex-correction-in-mcs-index-check.patch b/queue-3.5/mwifiex-correction-in-mcs-index-check.patch new file mode 100644 index 00000000000..27fa16026e4 --- /dev/null +++ b/queue-3.5/mwifiex-correction-in-mcs-index-check.patch @@ -0,0 +1,39 @@ +From fe020120cb863ba918c6d603345342a880272c4d Mon Sep 17 00:00:00 2001 +From: Amitkumar Karwar +Date: Wed, 11 Jul 2012 18:12:57 -0700 +Subject: mwifiex: correction in mcs index check + +From: Amitkumar Karwar + +commit fe020120cb863ba918c6d603345342a880272c4d upstream. + +mwifiex driver supports 2x2 chips as well. Hence valid mcs values +are 0 to 15. The check for mcs index is corrected in this patch. + +For example: if 40MHz is enabled and mcs index is 11, "iw link" +command would show "tx bitrate: 108.0 MBit/s" without this patch. +Now it shows "tx bitrate: 108.0 MBit/s MCS 11 40Mhz" with the patch. + +Signed-off-by: Amitkumar Karwar +Signed-off-by: Bing Zhao +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/mwifiex/cfg80211.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/mwifiex/cfg80211.c ++++ b/drivers/net/wireless/mwifiex/cfg80211.c +@@ -634,9 +634,9 @@ mwifiex_dump_station_info(struct mwifiex + + /* + * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid +- * MCS index values for us are 0 to 7. ++ * MCS index values for us are 0 to 15. + */ +- if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 8)) { ++ if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) { + sinfo->txrate.mcs = priv->tx_rate; + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + /* 40MHz rate */ diff --git a/queue-3.5/qeth-repair-crash-in-qeth_l3_vlan_rx_kill_vid.patch b/queue-3.5/qeth-repair-crash-in-qeth_l3_vlan_rx_kill_vid.patch new file mode 100644 index 00000000000..a3c64704b98 --- /dev/null +++ b/queue-3.5/qeth-repair-crash-in-qeth_l3_vlan_rx_kill_vid.patch @@ -0,0 +1,46 @@ +From eabfbe6230ee7363681e7a561948d362b87169f0 Mon Sep 17 00:00:00 2001 +From: Frank Blaschka +Date: Tue, 24 Jul 2012 22:34:29 +0000 +Subject: qeth: repair crash in qeth_l3_vlan_rx_kill_vid() + +From: Frank Blaschka + +commit eabfbe6230ee7363681e7a561948d362b87169f0 upstream. + +Commit efc73f4b "net: Fix memory leak - vlan_info struct" adds deletion of +VLAN 0 for devices with feature NETIF_F_HW_VLAN_FILTER. For driver +qeth these are the layer 3 devices. Usually there exists no +separate vlan net_device for VLAN 0. Thus the qeth functions +qeth_l3_free_vlan_addresses4() and qeth_l3_free_vlan_addresses6() +require an extra checking if function __vlan_find_dev_deep() +returns with a net_device. + +Signed-off-by: Ursula Braun +Signed-off-by: Frank Blaschka +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/net/qeth_l3_main.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/s390/net/qeth_l3_main.c ++++ b/drivers/s390/net/qeth_l3_main.c +@@ -1760,6 +1760,8 @@ static void qeth_l3_free_vlan_addresses4 + QETH_CARD_TEXT(card, 4, "frvaddr4"); + + netdev = __vlan_find_dev_deep(card->dev, vid); ++ if (!netdev) ++ return; + in_dev = in_dev_get(netdev); + if (!in_dev) + return; +@@ -1788,6 +1790,8 @@ static void qeth_l3_free_vlan_addresses6 + QETH_CARD_TEXT(card, 4, "frvaddr6"); + + netdev = __vlan_find_dev_deep(card->dev, vid); ++ if (!netdev) ++ return; + in6_dev = in6_dev_get(netdev); + if (!in6_dev) + return; diff --git a/queue-3.5/rtlwifi-rtl8192cu-change-buffer-allocation-for-synchronous-reads.patch b/queue-3.5/rtlwifi-rtl8192cu-change-buffer-allocation-for-synchronous-reads.patch new file mode 100644 index 00000000000..4887e6a9143 --- /dev/null +++ b/queue-3.5/rtlwifi-rtl8192cu-change-buffer-allocation-for-synchronous-reads.patch @@ -0,0 +1,72 @@ +From 3ce4d85b76010525adedcc2555fa164bf706a2f3 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Wed, 11 Jul 2012 14:37:28 -0500 +Subject: rtlwifi: rtl8192cu: Change buffer allocation for synchronous reads + +From: Larry Finger + +commit 3ce4d85b76010525adedcc2555fa164bf706a2f3 upstream. + +In commit a7959c1, the USB part of rtlwifi was switched to convert +_usb_read_sync() to using a preallocated buffer rather than one +that has been acquired using kmalloc. Although this routine is named +as though it were synchronous, there seem to be simultaneous users, +and the selection of the index to the data buffer is not multi-user +safe. This situation is addressed by adding a new spinlock. The routine +cannot sleep, thus a mutex is not allowed. + +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rtlwifi/usb.c | 14 +++++++++++--- + drivers/net/wireless/rtlwifi/wifi.h | 1 + + 2 files changed, 12 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/rtlwifi/usb.c ++++ b/drivers/net/wireless/rtlwifi/usb.c +@@ -131,15 +131,19 @@ static u32 _usb_read_sync(struct rtl_pri + u8 request; + u16 wvalue; + u16 index; +- __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; ++ __le32 *data; ++ unsigned long flags; + ++ spin_lock_irqsave(&rtlpriv->locks.usb_lock, flags); ++ if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) ++ rtlpriv->usb_data_index = 0; ++ data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; ++ spin_unlock_irqrestore(&rtlpriv->locks.usb_lock, flags); + request = REALTEK_USB_VENQT_CMD_REQ; + index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ + + wvalue = (u16)addr; + _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); +- if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) +- rtlpriv->usb_data_index = 0; + return le32_to_cpu(*data); + } + +@@ -951,6 +955,10 @@ int __devinit rtl_usb_probe(struct usb_i + GFP_KERNEL); + if (!rtlpriv->usb_data) + return -ENOMEM; ++ ++ /* this spin lock must be initialized early */ ++ spin_lock_init(&rtlpriv->locks.usb_lock); ++ + rtlpriv->usb_data_index = 0; + init_completion(&rtlpriv->firmware_loading_complete); + SET_IEEE80211_DEV(hw, &intf->dev); +--- a/drivers/net/wireless/rtlwifi/wifi.h ++++ b/drivers/net/wireless/rtlwifi/wifi.h +@@ -1555,6 +1555,7 @@ struct rtl_locks { + spinlock_t rf_ps_lock; + spinlock_t rf_lock; + spinlock_t waitq_lock; ++ spinlock_t usb_lock; + + /*Dual mac*/ + spinlock_t cck_and_rw_pagea_lock; diff --git a/queue-3.5/rtlwifi-rtl8192de-fix-phy-based-version-calculation.patch b/queue-3.5/rtlwifi-rtl8192de-fix-phy-based-version-calculation.patch new file mode 100644 index 00000000000..09c13cbd98f --- /dev/null +++ b/queue-3.5/rtlwifi-rtl8192de-fix-phy-based-version-calculation.patch @@ -0,0 +1,59 @@ +From f1b00f4dab29b57bdf1bc03ef12020b280fd2a72 Mon Sep 17 00:00:00 2001 +From: Forest Bond +Date: Fri, 13 Jul 2012 12:26:06 -0400 +Subject: rtlwifi: rtl8192de: Fix phy-based version calculation + +From: Forest Bond + +commit f1b00f4dab29b57bdf1bc03ef12020b280fd2a72 upstream. + +Commit d83579e2a50ac68389e6b4c58b845c702cf37516 incorporated some +changes from the vendor driver that made it newly important that the +calculated hardware version correctly include the CHIP_92D bit, as all +of the IS_92D_* macros were changed to depend on it. However, this bit +was being unset for dual-mac, dual-phy devices. The vendor driver +behavior was modified to not do this, but unfortunately this change was +not picked up along with the others. This caused scanning in the 2.4GHz +band to be broken, and possibly other bugs as well. + +This patch brings the version calculation logic in parity with the +vendor driver in this regard, and in doing so fixes the regression. +However, the version calculation code in general continues to be largely +incoherent and messy, and needs to be cleaned up. + +Signed-off-by: Forest Bond +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rtlwifi/rtl8192de/phy.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +@@ -3345,21 +3345,21 @@ void rtl92d_phy_config_macphymode_info(s + switch (rtlhal->macphymode) { + case DUALMAC_SINGLEPHY: + rtlphy->rf_type = RF_2T2R; +- rtlhal->version |= CHIP_92D_SINGLEPHY; ++ rtlhal->version |= RF_TYPE_2T2R; + rtlhal->bandset = BAND_ON_BOTH; + rtlhal->current_bandtype = BAND_ON_2_4G; + break; + + case SINGLEMAC_SINGLEPHY: + rtlphy->rf_type = RF_2T2R; +- rtlhal->version |= CHIP_92D_SINGLEPHY; ++ rtlhal->version |= RF_TYPE_2T2R; + rtlhal->bandset = BAND_ON_BOTH; + rtlhal->current_bandtype = BAND_ON_2_4G; + break; + + case DUALMAC_DUALPHY: + rtlphy->rf_type = RF_1T1R; +- rtlhal->version &= (~CHIP_92D_SINGLEPHY); ++ rtlhal->version &= RF_TYPE_1T1R; + /* Now we let MAC0 run on 5G band. */ + if (rtlhal->interfaceindex == 0) { + rtlhal->bandset = BAND_ON_5G; diff --git a/queue-3.5/s390-idle-fix-sequence-handling-vs-cpu-hotplug.patch b/queue-3.5/s390-idle-fix-sequence-handling-vs-cpu-hotplug.patch new file mode 100644 index 00000000000..71b4e0c9e88 --- /dev/null +++ b/queue-3.5/s390-idle-fix-sequence-handling-vs-cpu-hotplug.patch @@ -0,0 +1,75 @@ +From 0008204ffe85d23382d6fd0f971f3f0fbe70bae2 Mon Sep 17 00:00:00 2001 +From: Heiko Carstens +Date: Fri, 13 Jul 2012 15:45:33 +0200 +Subject: s390/idle: fix sequence handling vs cpu hotplug + +From: Heiko Carstens + +commit 0008204ffe85d23382d6fd0f971f3f0fbe70bae2 upstream. + +The s390 idle accounting code uses a sequence counter which gets used +when the per cpu idle statistics get updated and read. + +One assumption on read access is that only when the sequence counter is +even and did not change while reading all values the result is valid. +On cpu hotplug however the per cpu data structure gets initialized via +a cpu hotplug notifier on CPU_ONLINE. +CPU_ONLINE however is too late, since the onlined cpu is already running +and might access the per cpu data. Worst case is that the data structure +gets initialized while an idle thread is updating its idle statistics. +This will result in an uneven sequence counter after an update. + +As a result user space tools like top, which access /proc/stat in order +to get idle stats, will busy loop waiting for the sequence counter to +become even again, which will never happen until the queried cpu will +update its idle statistics again. And even then the sequence counter +will only have an even value for a couple of cpu cycles. + +Fix this by moving the initialization of the per cpu idle statistics +to cpu_init(). I prefer that solution in favor of changing the +notifier to CPU_UP_PREPARE, which would be a different solution to +the problem. + +Signed-off-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kernel/processor.c | 2 ++ + arch/s390/kernel/smp.c | 3 --- + 2 files changed, 2 insertions(+), 3 deletions(-) + +--- a/arch/s390/kernel/processor.c ++++ b/arch/s390/kernel/processor.c +@@ -26,12 +26,14 @@ static DEFINE_PER_CPU(struct cpuid, cpu_ + void __cpuinit cpu_init(void) + { + struct cpuid *id = &per_cpu(cpu_id, smp_processor_id()); ++ struct s390_idle_data *idle = &__get_cpu_var(s390_idle); + + get_cpu_id(id); + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + BUG_ON(current->mm); + enter_lazy_tlb(&init_mm, current); ++ memset(idle, 0, sizeof(*idle)); + } + + /* +--- a/arch/s390/kernel/smp.c ++++ b/arch/s390/kernel/smp.c +@@ -984,14 +984,11 @@ static int __cpuinit smp_cpu_notify(stru + unsigned int cpu = (unsigned int)(long)hcpu; + struct cpu *c = &pcpu_devices[cpu].cpu; + struct device *s = &c->dev; +- struct s390_idle_data *idle; + int err = 0; + + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: +- idle = &per_cpu(s390_idle, cpu); +- memset(idle, 0, sizeof(struct s390_idle_data)); + err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); + break; + case CPU_DEAD: diff --git a/queue-3.5/s390-mm-downgrade-page-table-after-fork-of-a-31-bit-process.patch b/queue-3.5/s390-mm-downgrade-page-table-after-fork-of-a-31-bit-process.patch new file mode 100644 index 00000000000..303cb8362e4 --- /dev/null +++ b/queue-3.5/s390-mm-downgrade-page-table-after-fork-of-a-31-bit-process.patch @@ -0,0 +1,130 @@ +From 0f6f281b731d20bfe75c13f85d33f3f05b440222 Mon Sep 17 00:00:00 2001 +From: Martin Schwidefsky +Date: Thu, 26 Jul 2012 08:53:06 +0200 +Subject: s390/mm: downgrade page table after fork of a 31 bit process + +From: Martin Schwidefsky + +commit 0f6f281b731d20bfe75c13f85d33f3f05b440222 upstream. + +The downgrade of the 4 level page table created by init_new_context is +currently done only in start_thread31. If a 31 bit process forks the +new mm uses a 4 level page table, including the task size of 2<<42 +that goes along with it. This is incorrect as now a 31 bit process +can map memory beyond 2GB. Define arch_dup_mmap to do the downgrade +after fork. + +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/include/asm/mmu_context.h | 14 +++++++++++++- + arch/s390/include/asm/processor.h | 2 ++ + arch/s390/mm/mmap.c | 12 ++++++++++-- + arch/s390/mm/pgtable.c | 5 ----- + 4 files changed, 25 insertions(+), 8 deletions(-) + +--- a/arch/s390/include/asm/mmu_context.h ++++ b/arch/s390/include/asm/mmu_context.h +@@ -13,7 +13,6 @@ + #include + #include + #include +-#include + + static inline int init_new_context(struct task_struct *tsk, + struct mm_struct *mm) +@@ -93,4 +92,17 @@ static inline void activate_mm(struct mm + switch_mm(prev, next, current); + } + ++static inline void arch_dup_mmap(struct mm_struct *oldmm, ++ struct mm_struct *mm) ++{ ++#ifdef CONFIG_64BIT ++ if (oldmm->context.asce_limit < mm->context.asce_limit) ++ crst_table_downgrade(mm, oldmm->context.asce_limit); ++#endif ++} ++ ++static inline void arch_exit_mmap(struct mm_struct *mm) ++{ ++} ++ + #endif /* __S390_MMU_CONTEXT_H */ +--- a/arch/s390/include/asm/processor.h ++++ b/arch/s390/include/asm/processor.h +@@ -122,7 +122,9 @@ struct stack_frame { + regs->psw.mask = psw_user_bits | PSW_MASK_BA; \ + regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ + regs->gprs[15] = new_stackp; \ ++ __tlb_flush_mm(current->mm); \ + crst_table_downgrade(current->mm, 1UL << 31); \ ++ update_mm(current->mm, current); \ + } while (0) + + /* Forward declaration, a strange C thing */ +--- a/arch/s390/mm/mmap.c ++++ b/arch/s390/mm/mmap.c +@@ -105,9 +105,15 @@ void arch_pick_mmap_layout(struct mm_str + + int s390_mmap_check(unsigned long addr, unsigned long len) + { ++ int rc; ++ + if (!is_compat_task() && +- len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) +- return crst_table_upgrade(current->mm, 1UL << 53); ++ len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) { ++ rc = crst_table_upgrade(current->mm, 1UL << 53); ++ if (rc) ++ return rc; ++ update_mm(current->mm, current); ++ } + return 0; + } + +@@ -127,6 +133,7 @@ s390_get_unmapped_area(struct file *filp + rc = crst_table_upgrade(mm, 1UL << 53); + if (rc) + return (unsigned long) rc; ++ update_mm(mm, current); + area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); + } + return area; +@@ -149,6 +156,7 @@ s390_get_unmapped_area_topdown(struct fi + rc = crst_table_upgrade(mm, 1UL << 53); + if (rc) + return (unsigned long) rc; ++ update_mm(mm, current); + area = arch_get_unmapped_area_topdown(filp, addr, len, + pgoff, flags); + } +--- a/arch/s390/mm/pgtable.c ++++ b/arch/s390/mm/pgtable.c +@@ -85,7 +85,6 @@ repeat: + crst_table_free(mm, table); + if (mm->context.asce_limit < limit) + goto repeat; +- update_mm(mm, current); + return 0; + } + +@@ -93,9 +92,6 @@ void crst_table_downgrade(struct mm_stru + { + pgd_t *pgd; + +- if (mm->context.asce_limit <= limit) +- return; +- __tlb_flush_mm(mm); + while (mm->context.asce_limit > limit) { + pgd = mm->pgd; + switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) { +@@ -118,7 +114,6 @@ void crst_table_downgrade(struct mm_stru + mm->task_size = mm->context.asce_limit; + crst_table_free(mm, (unsigned long *) pgd); + } +- update_mm(mm, current); + } + #endif + diff --git a/queue-3.5/s390-mm-fix-fault-handling-for-page-table-walk-case.patch b/queue-3.5/s390-mm-fix-fault-handling-for-page-table-walk-case.patch new file mode 100644 index 00000000000..4e4a5e53de3 --- /dev/null +++ b/queue-3.5/s390-mm-fix-fault-handling-for-page-table-walk-case.patch @@ -0,0 +1,69 @@ +From 008c2e8f247f0a8db1e8e26139da12f3a3abcda0 Mon Sep 17 00:00:00 2001 +From: Heiko Carstens +Date: Fri, 27 Jul 2012 09:45:39 +0200 +Subject: s390/mm: fix fault handling for page table walk case + +From: Heiko Carstens + +commit 008c2e8f247f0a8db1e8e26139da12f3a3abcda0 upstream. + +Make sure the kernel does not incorrectly create a SIGBUS signal during +user space accesses: + +For user space accesses in the switched addressing mode case the kernel +may walk page tables and access user address space via the kernel +mapping. If a page table entry is invalid the function __handle_fault() +gets called in order to emulate a page fault and trigger all the usual +actions like paging in a missing page etc. by calling handle_mm_fault(). + +If handle_mm_fault() returns with an error fixup handling is necessary. +For the switched addressing mode case all errors need to be mapped to +-EFAULT, so that the calling uaccess function can return -EFAULT to +user space. + +Unfortunately the __handle_fault() incorrectly calls do_sigbus() if +VM_FAULT_SIGBUS is set. This however should only happen if a page fault +was triggered by a user space instruction. For kernel mode uaccesses +the correct action is to only return -EFAULT. +So user space may incorrectly see SIGBUS signals because of this bug. + +For current machines this would only be possible for the switched +addressing mode case in conjunction with futex operations. + +Signed-off-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/mm/fault.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/arch/s390/mm/fault.c ++++ b/arch/s390/mm/fault.c +@@ -443,6 +443,7 @@ int __handle_fault(unsigned long uaddr, + struct pt_regs regs; + int access, fault; + ++ /* Emulate a uaccess fault from kernel mode. */ + regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK; + if (!irqs_disabled()) + regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT; +@@ -452,12 +453,12 @@ int __handle_fault(unsigned long uaddr, + regs.int_parm_long = (uaddr & PAGE_MASK) | 2; + access = write ? VM_WRITE : VM_READ; + fault = do_exception(®s, access); +- if (unlikely(fault)) { +- if (fault & VM_FAULT_OOM) +- return -EFAULT; +- else if (fault & VM_FAULT_SIGBUS) +- do_sigbus(®s); +- } ++ /* ++ * Since the fault happened in kernel mode while performing a uaccess ++ * all we need to do now is emulating a fixup in case "fault" is not ++ * zero. ++ * For the calling uaccess functions this results always in -EFAULT. ++ */ + return fault ? -EFAULT : 0; + } + diff --git a/queue-3.5/series b/queue-3.5/series index 96e00af56a5..793d61c072b 100644 --- a/queue-3.5/series +++ b/queue-3.5/series @@ -49,3 +49,28 @@ mac80211-fix-read-outside-array-bounds.patch mac80211-fail-authentication-when-ap-denied-authentication.patch iwlwifi-check-bss-ctx-active-before-call-mac80211.patch iwlwifi-fix-debug-print-in-iwl_sta_calc_ht_flags.patch +atl1c-fix-issue-of-io-access-mode-for-ar8152-v2.1.patch +rtlwifi-rtl8192cu-change-buffer-allocation-for-synchronous-reads.patch +rtlwifi-rtl8192de-fix-phy-based-version-calculation.patch +mwifiex-correction-in-mcs-index-check.patch +s390-idle-fix-sequence-handling-vs-cpu-hotplug.patch +s390-mm-downgrade-page-table-after-fork-of-a-31-bit-process.patch +s390-mm-fix-fault-handling-for-page-table-walk-case.patch +cgroup-cgroup_rm_files-was-calling-simple_unlink-with-the-wrong-inode.patch +iommu-amd-add-missing-spin_lock-initialization.patch +iommu-amd-fix-hotplug-with-iommu-pt.patch +udf-improve-table-length-check-to-avoid-possible-overflow.patch +stable-update-references-to-older-2.6-versions-for-3.x.patch +staging-zsmalloc-finish-conversion-to-a-separate-module.patch +workqueue-perform-cpu-down-operations-from-low-priority-cpu_notifier.patch +acpi-apei-fixup-common-access-width-firmware-bug.patch +acpi-ac-prevent-oops-on-some-boxes-due-to-missing-check-power_supply_register-return-value-check.patch +kmsg-properly-print-over-long-continuation-lines.patch +btrfs-call-the-ordered-free-operation-without-any-locks-held.patch +cifs-reinstate-sec-ntlmv2-mount-option.patch +cifs-ensure-that-we-always-do-cifsfileinfo_get-under-the-spinlock.patch +spi-pl022-disable-port-when-unused.patch +qeth-repair-crash-in-qeth_l3_vlan_rx_kill_vid.patch +tg3-add-device-id-of-apple-thunderbolt-ethernet-device.patch +tg3-fix-read-dma-workaround-for-5719-a0.patch +tg3-fix-race-condition-in-tg3_get_stats64.patch diff --git a/queue-3.5/spi-pl022-disable-port-when-unused.patch b/queue-3.5/spi-pl022-disable-port-when-unused.patch new file mode 100644 index 00000000000..ba7fc9ab26d --- /dev/null +++ b/queue-3.5/spi-pl022-disable-port-when-unused.patch @@ -0,0 +1,38 @@ +From fd316941cfee1fbd12746afea83720fb7823888a Mon Sep 17 00:00:00 2001 +From: Virupax Sadashivpetimath +Date: Tue, 12 Jun 2012 15:10:58 +0200 +Subject: spi/pl022: disable port when unused + +From: Virupax Sadashivpetimath + +commit fd316941cfee1fbd12746afea83720fb7823888a upstream. + +Commit ffbbdd21329f3e15eeca6df2d4bc11c04d9d91c0 +"spi: create a message queueing infrastructure" +Accidentally deleted the logic to disable the port +when unused leading to higher power consumption. +Fix this up. + +Cc: Vinit Shenoy +Signed-off-by: Virupax Sadashivpetimath +Signed-off-by: Linus Walleij +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/spi/spi-pl022.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/spi/spi-pl022.c ++++ b/drivers/spi/spi-pl022.c +@@ -489,6 +489,11 @@ static void giveback(struct pl022 *pl022 + pl022->cur_transfer = NULL; + pl022->cur_chip = NULL; + spi_finalize_current_message(pl022->master); ++ ++ /* disable the SPI/SSP operation */ ++ writew((readw(SSP_CR1(pl022->virtbase)) & ++ (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); ++ + } + + /** diff --git a/queue-3.5/stable-update-references-to-older-2.6-versions-for-3.x.patch b/queue-3.5/stable-update-references-to-older-2.6-versions-for-3.x.patch new file mode 100644 index 00000000000..60f7d082048 --- /dev/null +++ b/queue-3.5/stable-update-references-to-older-2.6-versions-for-3.x.patch @@ -0,0 +1,58 @@ +From 2584f5212d97b664be250ad5700a2d0fee31a10d Mon Sep 17 00:00:00 2001 +From: Paul Gortmaker +Date: Tue, 5 Jun 2012 11:15:50 -0400 +Subject: stable: update references to older 2.6 versions for 3.x + +From: Paul Gortmaker + +commit 2584f5212d97b664be250ad5700a2d0fee31a10d upstream. + +Also add information on where the respective trees are. + +Signed-off-by: Paul Gortmaker +Acked-by: Rob Landley +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/stable_kernel_rules.txt | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +--- a/Documentation/stable_kernel_rules.txt ++++ b/Documentation/stable_kernel_rules.txt +@@ -1,4 +1,4 @@ +-Everything you ever wanted to know about Linux 2.6 -stable releases. ++Everything you ever wanted to know about Linux -stable releases. + + Rules on what kind of patches are accepted, and which ones are not, into the + "-stable" tree: +@@ -42,10 +42,10 @@ Procedure for submitting patches to the + cherry-picked than this can be specified in the following format in + the sign-off area: + +- Cc: # .32.x: a1f84a3: sched: Check for idle +- Cc: # .32.x: 1b9508f: sched: Rate-limit newidle +- Cc: # .32.x: fd21073: sched: Fix affinity logic +- Cc: # .32.x ++ Cc: # 3.3.x: a1f84a3: sched: Check for idle ++ Cc: # 3.3.x: 1b9508f: sched: Rate-limit newidle ++ Cc: # 3.3.x: fd21073: sched: Fix affinity logic ++ Cc: # 3.3.x + Signed-off-by: Ingo Molnar + + The tag sequence has the meaning of: +@@ -79,6 +79,15 @@ Review cycle: + security kernel team, and not go through the normal review cycle. + Contact the kernel security team for more details on this procedure. + ++Trees: ++ ++ - The queues of patches, for both completed versions and in progress ++ versions can be found at: ++ http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git ++ - The finalized and tagged releases of all stable kernels can be found ++ in separate branches per version at: ++ http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git ++ + + Review committee: + diff --git a/queue-3.5/staging-zsmalloc-finish-conversion-to-a-separate-module.patch b/queue-3.5/staging-zsmalloc-finish-conversion-to-a-separate-module.patch new file mode 100644 index 00000000000..3c7912ae5af --- /dev/null +++ b/queue-3.5/staging-zsmalloc-finish-conversion-to-a-separate-module.patch @@ -0,0 +1,91 @@ +From 069f101fa463351f528773d73b74e9b606b3f66a Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Wed, 20 Jun 2012 02:31:11 +0100 +Subject: staging: zsmalloc: Finish conversion to a separate module + +From: Ben Hutchings + +commit 069f101fa463351f528773d73b74e9b606b3f66a upstream. + +ZSMALLOC is tristate, but the code has no MODULE_LICENSE and since it +depends on GPL-only symbols it cannot be loaded as a module. This in +turn breaks zram which now depends on it. I assume it's meant to be +Dual BSD/GPL like the other z-stuff. + +There is also no module_exit, which will make it impossible to unload. +Add the appropriate module_init and module_exit declarations suggested +by comments. + +Reported-by: Christian Ohm +References: http://bugs.debian.org/677273 +Signed-off-by: Ben Hutchings +Reviewed-by: Jonathan Nieder +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/zsmalloc/zsmalloc-main.c | 33 ++++++------------------------- + 1 file changed, 7 insertions(+), 26 deletions(-) + +--- a/drivers/staging/zsmalloc/zsmalloc-main.c ++++ b/drivers/staging/zsmalloc/zsmalloc-main.c +@@ -425,12 +425,6 @@ static struct page *find_get_zspage(stru + } + + +-/* +- * If this becomes a separate module, register zs_init() with +- * module_init(), zs_exit with module_exit(), and remove zs_initialized +-*/ +-static int zs_initialized; +- + static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action, + void *pcpu) + { +@@ -489,7 +483,7 @@ fail: + + struct zs_pool *zs_create_pool(const char *name, gfp_t flags) + { +- int i, error, ovhd_size; ++ int i, ovhd_size; + struct zs_pool *pool; + + if (!name) +@@ -516,28 +510,9 @@ struct zs_pool *zs_create_pool(const cha + + } + +- /* +- * If this becomes a separate module, register zs_init with +- * module_init, and remove this block +- */ +- if (!zs_initialized) { +- error = zs_init(); +- if (error) +- goto cleanup; +- zs_initialized = 1; +- } +- + pool->flags = flags; + pool->name = name; + +- error = 0; /* Success */ +- +-cleanup: +- if (error) { +- zs_destroy_pool(pool); +- pool = NULL; +- } +- + return pool; + } + EXPORT_SYMBOL_GPL(zs_create_pool); +@@ -753,3 +728,9 @@ u64 zs_get_total_size_bytes(struct zs_po + return npages << PAGE_SHIFT; + } + EXPORT_SYMBOL_GPL(zs_get_total_size_bytes); ++ ++module_init(zs_init); ++module_exit(zs_exit); ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_AUTHOR("Nitin Gupta "); diff --git a/queue-3.5/tg3-add-device-id-of-apple-thunderbolt-ethernet-device.patch b/queue-3.5/tg3-add-device-id-of-apple-thunderbolt-ethernet-device.patch new file mode 100644 index 00000000000..a03d6ee1a2a --- /dev/null +++ b/queue-3.5/tg3-add-device-id-of-apple-thunderbolt-ethernet-device.patch @@ -0,0 +1,31 @@ +From 02eca3f5f5e458c3a5d7b772bc8042ee2a4ebedf Mon Sep 17 00:00:00 2001 +From: Greg KH +Date: Thu, 12 Jul 2012 15:39:44 +0000 +Subject: tg3: add device id of Apple Thunderbolt Ethernet device + +From: Greg KH + +commit 02eca3f5f5e458c3a5d7b772bc8042ee2a4ebedf upstream. + +The Apple Thunderbolt ethernet device is already listed in the driver, +but not hooked up in the MODULE_DEVICE_TABLE(). This fixes that and +allows it to work properly. + +Signed-off-by: Greg Kroah-Hartman +Acked-by: Michael Chan +Signed-off-by: David S. Miller + +--- + drivers/net/ethernet/broadcom/tg3.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -298,6 +298,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_t + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)}, + {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, + {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, + {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, diff --git a/queue-3.5/tg3-fix-race-condition-in-tg3_get_stats64.patch b/queue-3.5/tg3-fix-race-condition-in-tg3_get_stats64.patch new file mode 100644 index 00000000000..55ce97240d0 --- /dev/null +++ b/queue-3.5/tg3-fix-race-condition-in-tg3_get_stats64.patch @@ -0,0 +1,36 @@ +From 0f566b208b41918053b2e67399673aaec02dde5d Mon Sep 17 00:00:00 2001 +From: Michael Chan +Date: Sun, 29 Jul 2012 19:15:44 +0000 +Subject: tg3: Fix race condition in tg3_get_stats64() + +From: Michael Chan + +commit 0f566b208b41918053b2e67399673aaec02dde5d upstream. + +Spinlock should be taken before checking for tp->hw_stats. + +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/broadcom/tg3.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -12282,10 +12282,12 @@ static struct rtnl_link_stats64 *tg3_get + { + struct tg3 *tp = netdev_priv(dev); + +- if (!tp->hw_stats) ++ spin_lock_bh(&tp->lock); ++ if (!tp->hw_stats) { ++ spin_unlock_bh(&tp->lock); + return &tp->net_stats_prev; ++ } + +- spin_lock_bh(&tp->lock); + tg3_get_nstats(tp, stats); + spin_unlock_bh(&tp->lock); + diff --git a/queue-3.5/tg3-fix-read-dma-workaround-for-5719-a0.patch b/queue-3.5/tg3-fix-read-dma-workaround-for-5719-a0.patch new file mode 100644 index 00000000000..8854ce7b316 --- /dev/null +++ b/queue-3.5/tg3-fix-read-dma-workaround-for-5719-a0.patch @@ -0,0 +1,31 @@ +From 10ce95d6ef36c65df7dcd3b8fcf86913f8b298bd Mon Sep 17 00:00:00 2001 +From: Michael Chan +Date: Sun, 29 Jul 2012 19:15:42 +0000 +Subject: tg3: Fix Read DMA workaround for 5719 A0. + +From: Michael Chan + +commit 10ce95d6ef36c65df7dcd3b8fcf86913f8b298bd upstream. + +The workaround was mis-applied to all 5719 and 5720 chips. + +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/broadcom/tg3.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -8975,8 +8975,7 @@ static int tg3_reset_hw(struct tg3 *tp, + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + tg3_flag(tp, 57765_PLUS)) { + val = tr32(TG3_RDMA_RSRVCTRL_REG); +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { ++ if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0) { + val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK | + TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK | + TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK); diff --git a/queue-3.5/udf-improve-table-length-check-to-avoid-possible-overflow.patch b/queue-3.5/udf-improve-table-length-check-to-avoid-possible-overflow.patch new file mode 100644 index 00000000000..0fac681566a --- /dev/null +++ b/queue-3.5/udf-improve-table-length-check-to-avoid-possible-overflow.patch @@ -0,0 +1,33 @@ +From 57b9655d01ef057a523e810d29c37ac09b80eead Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 10 Jul 2012 17:58:04 +0200 +Subject: udf: Improve table length check to avoid possible overflow + +From: Jan Kara + +commit 57b9655d01ef057a523e810d29c37ac09b80eead upstream. + +When a partition table length is corrupted to be close to 1 << 32, the +check for its length may overflow on 32-bit systems and we will think +the length is valid. Later on the kernel can crash trying to read beyond +end of buffer. Fix the check to avoid possible overflow. + +Reported-by: Ben Hutchings +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/udf/super.c ++++ b/fs/udf/super.c +@@ -1283,7 +1283,7 @@ static int udf_load_logicalvol(struct su + BUG_ON(ident != TAG_IDENT_LVD); + lvd = (struct logicalVolDesc *)bh->b_data; + table_len = le32_to_cpu(lvd->mapTableLength); +- if (sizeof(*lvd) + table_len > sb->s_blocksize) { ++ if (table_len > sb->s_blocksize - sizeof(*lvd)) { + udf_err(sb, "error loading logical volume descriptor: " + "Partition table too long (%u > %lu)\n", table_len, + sb->s_blocksize - sizeof(*lvd)); diff --git a/queue-3.5/workqueue-perform-cpu-down-operations-from-low-priority-cpu_notifier.patch b/queue-3.5/workqueue-perform-cpu-down-operations-from-low-priority-cpu_notifier.patch new file mode 100644 index 00000000000..06f42797fb4 --- /dev/null +++ b/queue-3.5/workqueue-perform-cpu-down-operations-from-low-priority-cpu_notifier.patch @@ -0,0 +1,115 @@ +From 6575820221f7a4dd6eadecf7bf83cdd154335eda Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Tue, 17 Jul 2012 12:39:26 -0700 +Subject: workqueue: perform cpu down operations from low priority cpu_notifier() + +From: Tejun Heo + +commit 6575820221f7a4dd6eadecf7bf83cdd154335eda upstream. + +Currently, all workqueue cpu hotplug operations run off +CPU_PRI_WORKQUEUE which is higher than normal notifiers. This is to +ensure that workqueue is up and running while bringing up a CPU before +other notifiers try to use workqueue on the CPU. + +Per-cpu workqueues are supposed to remain working and bound to the CPU +for normal CPU_DOWN_PREPARE notifiers. This holds mostly true even +with workqueue offlining running with higher priority because +workqueue CPU_DOWN_PREPARE only creates a bound trustee thread which +runs the per-cpu workqueue without concurrency management without +explicitly detaching the existing workers. + +However, if the trustee needs to create new workers, it creates +unbound workers which may wander off to other CPUs while +CPU_DOWN_PREPARE notifiers are in progress. Furthermore, if the CPU +down is cancelled, the per-CPU workqueue may end up with workers which +aren't bound to the CPU. + +While reliably reproducible with a convoluted artificial test-case +involving scheduling and flushing CPU burning work items from CPU down +notifiers, this isn't very likely to happen in the wild, and, even +when it happens, the effects are likely to be hidden by the following +successful CPU down. + +Fix it by using different priorities for up and down notifiers - high +priority for up operations and low priority for down operations. + +Workqueue cpu hotplug operations will soon go through further cleanup. + +Signed-off-by: Tejun Heo +Acked-by: "Rafael J. Wysocki" +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/cpu.h | 5 +++-- + kernel/workqueue.c | 38 +++++++++++++++++++++++++++++++++++++- + 2 files changed, 40 insertions(+), 3 deletions(-) + +--- a/include/linux/cpu.h ++++ b/include/linux/cpu.h +@@ -73,8 +73,9 @@ enum { + /* migration should happen before other stuff but after perf */ + CPU_PRI_PERF = 20, + CPU_PRI_MIGRATION = 10, +- /* prepare workqueues for other notifiers */ +- CPU_PRI_WORKQUEUE = 5, ++ /* bring up workqueues before normal notifiers and down after */ ++ CPU_PRI_WORKQUEUE_UP = 5, ++ CPU_PRI_WORKQUEUE_DOWN = -5, + }; + + #define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */ +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -3590,6 +3590,41 @@ static int __devinit workqueue_cpu_callb + return notifier_from_errno(0); + } + ++/* ++ * Workqueues should be brought up before normal priority CPU notifiers. ++ * This will be registered high priority CPU notifier. ++ */ ++static int __devinit workqueue_cpu_up_callback(struct notifier_block *nfb, ++ unsigned long action, ++ void *hcpu) ++{ ++ switch (action & ~CPU_TASKS_FROZEN) { ++ case CPU_UP_PREPARE: ++ case CPU_UP_CANCELED: ++ case CPU_DOWN_FAILED: ++ case CPU_ONLINE: ++ return workqueue_cpu_callback(nfb, action, hcpu); ++ } ++ return NOTIFY_OK; ++} ++ ++/* ++ * Workqueues should be brought down after normal priority CPU notifiers. ++ * This will be registered as low priority CPU notifier. ++ */ ++static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb, ++ unsigned long action, ++ void *hcpu) ++{ ++ switch (action & ~CPU_TASKS_FROZEN) { ++ case CPU_DOWN_PREPARE: ++ case CPU_DYING: ++ case CPU_POST_DEAD: ++ return workqueue_cpu_callback(nfb, action, hcpu); ++ } ++ return NOTIFY_OK; ++} ++ + #ifdef CONFIG_SMP + + struct work_for_cpu { +@@ -3783,7 +3818,8 @@ static int __init init_workqueues(void) + unsigned int cpu; + int i; + +- cpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE); ++ cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); ++ cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); + + /* initialize gcwqs */ + for_each_gcwq_cpu(cpu) {