From: Greg Kroah-Hartman Date: Mon, 12 Jan 2015 15:25:31 +0000 (-0800) Subject: 3.14-stable patches X-Git-Tag: v3.10.65~48 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=810637366a5dea0bd9b559c10efd8a27759bcec7;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: ath9k-fix-be-bk-queue-order.patch ath9k_hw-fix-hardware-queue-allocation.patch drivers-rtc-rtc-isl12057.c-fix-masking-of-register-values.patch drivers-rtc-rtc-sirfsoc.c-move-hardware-initilization-earlier-in-probe.patch ocfs2-fix-journal-commit-deadlock.patch ocfs2-fix-the-wrong-directory-passed-to-ocfs2_lookup_ino_from_name-when-link-file.patch --- diff --git a/queue-3.14/ath9k-fix-be-bk-queue-order.patch b/queue-3.14/ath9k-fix-be-bk-queue-order.patch new file mode 100644 index 00000000000..314979d8b52 --- /dev/null +++ b/queue-3.14/ath9k-fix-be-bk-queue-order.patch @@ -0,0 +1,33 @@ +From 78063d81d353e10cbdd279c490593113b8fdae1c Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sun, 30 Nov 2014 20:38:41 +0100 +Subject: ath9k: fix BE/BK queue order + +From: Felix Fietkau + +commit 78063d81d353e10cbdd279c490593113b8fdae1c upstream. + +Hardware queues are ordered by priority. Use queue index 0 for BK, which +has lower priority than BE. + +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/hw.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -216,8 +216,8 @@ + #define AH_WOW_BEACON_MISS BIT(3) + + enum ath_hw_txq_subtype { +- ATH_TXQ_AC_BE = 0, +- ATH_TXQ_AC_BK = 1, ++ ATH_TXQ_AC_BK = 0, ++ ATH_TXQ_AC_BE = 1, + ATH_TXQ_AC_VI = 2, + ATH_TXQ_AC_VO = 3, + }; diff --git a/queue-3.14/ath9k_hw-fix-hardware-queue-allocation.patch b/queue-3.14/ath9k_hw-fix-hardware-queue-allocation.patch new file mode 100644 index 00000000000..1f24559f259 --- /dev/null +++ b/queue-3.14/ath9k_hw-fix-hardware-queue-allocation.patch @@ -0,0 +1,40 @@ +From ad8fdccf9c197a89e2d2fa78c453283dcc2c343f Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sun, 30 Nov 2014 20:38:40 +0100 +Subject: ath9k_hw: fix hardware queue allocation + +From: Felix Fietkau + +commit ad8fdccf9c197a89e2d2fa78c453283dcc2c343f upstream. + +The driver passes the desired hardware queue index for a WMM data queue +in qinfo->tqi_subtype. This was ignored in ath9k_hw_setuptxqueue, which +instead relied on the order in which the function is called. + +Reported-by: Hubert Feurstein +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/mac.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -311,14 +311,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw + q = ATH9K_NUM_TX_QUEUES - 3; + break; + case ATH9K_TX_QUEUE_DATA: +- for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++) +- if (ah->txq[q].tqi_type == +- ATH9K_TX_QUEUE_INACTIVE) +- break; +- if (q == ATH9K_NUM_TX_QUEUES) { +- ath_err(common, "No available TX queue\n"); +- return -1; +- } ++ q = qinfo->tqi_subtype; + break; + default: + ath_err(common, "Invalid TX queue type: %u\n", type); diff --git a/queue-3.14/drivers-rtc-rtc-isl12057.c-fix-masking-of-register-values.patch b/queue-3.14/drivers-rtc-rtc-isl12057.c-fix-masking-of-register-values.patch new file mode 100644 index 00000000000..c6a8a8e7a57 --- /dev/null +++ b/queue-3.14/drivers-rtc-rtc-isl12057.c-fix-masking-of-register-values.patch @@ -0,0 +1,64 @@ +From 5945b2880363ed7648e62aabba770ec57ff2a316 Mon Sep 17 00:00:00 2001 +From: Arnaud Ebalard +Date: Wed, 10 Dec 2014 15:54:02 -0800 +Subject: drivers/rtc/rtc-isl12057.c: fix masking of register values +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Arnaud Ebalard + +commit 5945b2880363ed7648e62aabba770ec57ff2a316 upstream. + +When Intersil ISL12057 support was added by commit 70e123373c05 ("rtc: Add +support for Intersil ISL12057 I2C RTC chip"), two masks for time registers +values imported from the device were either wrong or omitted, leading to +additional bits from those registers to impact read values: + + - mask for hour register value when reading it in AM/PM mode. As + AM/PM mode is not the usual mode used by the driver, this error + would only have an impact on an externally configured RTC hour + later read by the driver. + - mask for month value. The lack of masking would provide an + erroneous value if century bit is set. + +This patch fixes those two masks. + +Fixes: 70e123373c05 ("rtc: Add support for Intersil ISL12057 I2C RTC chip") +Signed-off-by: Arnaud Ebalard +Cc: Mark Rutland +Cc: Alessandro Zummo +Cc: Peter Huewe +Cc: Linus Walleij +Cc: Thierry Reding +Cc: Mark Brown +Cc: Grant Likely +Acked-by: Uwe Kleine-König +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/rtc/rtc-isl12057.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/rtc/rtc-isl12057.c ++++ b/drivers/rtc/rtc-isl12057.c +@@ -89,7 +89,7 @@ static void isl12057_rtc_regs_to_tm(stru + tm->tm_min = bcd2bin(regs[ISL12057_REG_RTC_MN]); + + if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_MIL) { /* AM/PM */ +- tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x0f); ++ tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x1f); + if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_PM) + tm->tm_hour += 12; + } else { /* 24 hour mode */ +@@ -98,7 +98,7 @@ static void isl12057_rtc_regs_to_tm(stru + + tm->tm_mday = bcd2bin(regs[ISL12057_REG_RTC_DT]); + tm->tm_wday = bcd2bin(regs[ISL12057_REG_RTC_DW]) - 1; /* starts at 1 */ +- tm->tm_mon = bcd2bin(regs[ISL12057_REG_RTC_MO]) - 1; /* starts at 1 */ ++ tm->tm_mon = bcd2bin(regs[ISL12057_REG_RTC_MO] & 0x1f) - 1; /* ditto */ + tm->tm_year = bcd2bin(regs[ISL12057_REG_RTC_YR]) + 100; + } + diff --git a/queue-3.14/drivers-rtc-rtc-sirfsoc.c-move-hardware-initilization-earlier-in-probe.patch b/queue-3.14/drivers-rtc-rtc-sirfsoc.c-move-hardware-initilization-earlier-in-probe.patch new file mode 100644 index 00000000000..a8c10e9a26e --- /dev/null +++ b/queue-3.14/drivers-rtc-rtc-sirfsoc.c-move-hardware-initilization-earlier-in-probe.patch @@ -0,0 +1,57 @@ +From 0e95325525c4383565cea4f402f15a3113162d05 Mon Sep 17 00:00:00 2001 +From: Guo Zeng +Date: Wed, 10 Dec 2014 15:52:24 -0800 +Subject: drivers/rtc/rtc-sirfsoc.c: move hardware initilization earlier in probe + +From: Guo Zeng + +commit 0e95325525c4383565cea4f402f15a3113162d05 upstream. + +Move rtc register to be later than hardware initialization. The reason +is that devm_rtc_device_register() will do read_time() which is a +callback accessing hardware. This sometimes causes a hang in the +hardware related callback. + +Signed-off-by: Guo Zeng +Signed-off-by: Barry Song +Cc: Alessandro Zummo +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/rtc/rtc-sirfsoc.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/rtc/rtc-sirfsoc.c ++++ b/drivers/rtc/rtc-sirfsoc.c +@@ -290,14 +290,6 @@ static int sirfsoc_rtc_probe(struct plat + rtc_div = ((32768 / RTC_HZ) / 2) - 1; + sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV); + +- rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, +- &sirfsoc_rtc_ops, THIS_MODULE); +- if (IS_ERR(rtcdrv->rtc)) { +- err = PTR_ERR(rtcdrv->rtc); +- dev_err(&pdev->dev, "can't register RTC device\n"); +- return err; +- } +- + /* 0x3 -> RTC_CLK */ + sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK, + rtcdrv->rtc_base + RTC_CLOCK_SWITCH); +@@ -312,6 +304,14 @@ static int sirfsoc_rtc_probe(struct plat + rtcdrv->overflow_rtc = + sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE); + ++ rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, ++ &sirfsoc_rtc_ops, THIS_MODULE); ++ if (IS_ERR(rtcdrv->rtc)) { ++ err = PTR_ERR(rtcdrv->rtc); ++ dev_err(&pdev->dev, "can't register RTC device\n"); ++ return err; ++ } ++ + rtcdrv->irq = platform_get_irq(pdev, 0); + err = devm_request_irq( + &pdev->dev, diff --git a/queue-3.14/ocfs2-fix-journal-commit-deadlock.patch b/queue-3.14/ocfs2-fix-journal-commit-deadlock.patch new file mode 100644 index 00000000000..e4e0952d47a --- /dev/null +++ b/queue-3.14/ocfs2-fix-journal-commit-deadlock.patch @@ -0,0 +1,84 @@ +From 136f49b9171074872f2a14ad0ab10486d1ba13ca Mon Sep 17 00:00:00 2001 +From: Junxiao Bi +Date: Thu, 18 Dec 2014 16:17:37 -0800 +Subject: ocfs2: fix journal commit deadlock + +From: Junxiao Bi + +commit 136f49b9171074872f2a14ad0ab10486d1ba13ca upstream. + +For buffer write, page lock will be got in write_begin and released in +write_end, in ocfs2_write_end_nolock(), before it unlock the page in +ocfs2_free_write_ctxt(), it calls ocfs2_run_deallocs(), this will ask +for the read lock of journal->j_trans_barrier. Holding page lock and +ask for journal->j_trans_barrier breaks the locking order. + +This will cause a deadlock with journal commit threads, ocfs2cmt will +get write lock of journal->j_trans_barrier first, then it wakes up +kjournald2 to do the commit work, at last it waits until done. To +commit journal, kjournald2 needs flushing data first, it needs get the +cache page lock. + +Since some ocfs2 cluster locks are holding by write process, this +deadlock may hung the whole cluster. + +unlock pages before ocfs2_run_deallocs() can fix the locking order, also +put unlock before ocfs2_commit_trans() to make page lock is unlocked +before j_trans_barrier to preserve unlocking order. + +Signed-off-by: Junxiao Bi +Reviewed-by: Wengang Wang +Reviewed-by: Mark Fasheh +Cc: Joel Becker +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ocfs2/aops.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/fs/ocfs2/aops.c ++++ b/fs/ocfs2/aops.c +@@ -899,7 +899,7 @@ void ocfs2_unlock_and_free_pages(struct + } + } + +-static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) ++static void ocfs2_unlock_pages(struct ocfs2_write_ctxt *wc) + { + int i; + +@@ -920,7 +920,11 @@ static void ocfs2_free_write_ctxt(struct + page_cache_release(wc->w_target_page); + } + ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages); ++} + ++static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) ++{ ++ ocfs2_unlock_pages(wc); + brelse(wc->w_di_bh); + kfree(wc); + } +@@ -2045,11 +2049,19 @@ out_write_size: + di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); + ocfs2_journal_dirty(handle, wc->w_di_bh); + ++ /* unlock pages before dealloc since it needs acquiring j_trans_barrier ++ * lock, or it will cause a deadlock since journal commit threads holds ++ * this lock and will ask for the page lock when flushing the data. ++ * put it here to preserve the unlock order. ++ */ ++ ocfs2_unlock_pages(wc); ++ + ocfs2_commit_trans(osb, handle); + + ocfs2_run_deallocs(osb, &wc->w_dealloc); + +- ocfs2_free_write_ctxt(wc); ++ brelse(wc->w_di_bh); ++ kfree(wc); + + return copied; + } diff --git a/queue-3.14/ocfs2-fix-the-wrong-directory-passed-to-ocfs2_lookup_ino_from_name-when-link-file.patch b/queue-3.14/ocfs2-fix-the-wrong-directory-passed-to-ocfs2_lookup_ino_from_name-when-link-file.patch new file mode 100644 index 00000000000..4263a0f27d8 --- /dev/null +++ b/queue-3.14/ocfs2-fix-the-wrong-directory-passed-to-ocfs2_lookup_ino_from_name-when-link-file.patch @@ -0,0 +1,164 @@ +From 53dc20b9a3d928b0744dad5aee65b610de1cc85d Mon Sep 17 00:00:00 2001 +From: Xue jiufei +Date: Thu, 8 Jan 2015 14:32:23 -0800 +Subject: ocfs2: fix the wrong directory passed to ocfs2_lookup_ino_from_name() when link file + +From: Xue jiufei + +commit 53dc20b9a3d928b0744dad5aee65b610de1cc85d upstream. + +In ocfs2_link(), the parent directory inode passed to function +ocfs2_lookup_ino_from_name() is wrong. Parameter dir is the parent of +new_dentry not old_dentry. We should get old_dir from old_dentry and +lookup old_dentry in old_dir in case another node remove the old dentry. + +With this change, hard linking works again, when paths are relative with +at least one subdirectory. This is how the problem was reproducable: + + # mkdir a + # mkdir b + # touch a/test + # ln a/test b/test + ln: failed to create hard link `b/test' => `a/test': No such file or directory + +However when creating links in the same dir, it worked well. + +Now the link gets created. + +Fixes: 0e048316ff57 ("ocfs2: check existence of old dentry in ocfs2_link()") +Signed-off-by: joyce.xue +Reported-by: Szabo Aron - UBIT +Cc: Mark Fasheh +Cc: Joel Becker +Tested-by: Aron Szabo +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ocfs2/namei.c | 43 +++++++++++++++++++++++++++++++++++-------- + 1 file changed, 35 insertions(+), 8 deletions(-) + +--- a/fs/ocfs2/namei.c ++++ b/fs/ocfs2/namei.c +@@ -94,6 +94,14 @@ static int ocfs2_create_symlink_data(str + struct inode *inode, + const char *symname); + ++static int ocfs2_double_lock(struct ocfs2_super *osb, ++ struct buffer_head **bh1, ++ struct inode *inode1, ++ struct buffer_head **bh2, ++ struct inode *inode2, ++ int rename); ++ ++static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2); + /* An orphan dir name is an 8 byte value, printed as a hex string */ + #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) + +@@ -656,8 +664,10 @@ static int ocfs2_link(struct dentry *old + { + handle_t *handle; + struct inode *inode = old_dentry->d_inode; ++ struct inode *old_dir = old_dentry->d_parent->d_inode; + int err; + struct buffer_head *fe_bh = NULL; ++ struct buffer_head *old_dir_bh = NULL; + struct buffer_head *parent_fe_bh = NULL; + struct ocfs2_dinode *fe = NULL; + struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); +@@ -674,19 +684,33 @@ static int ocfs2_link(struct dentry *old + + dquot_initialize(dir); + +- err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT); ++ err = ocfs2_double_lock(osb, &old_dir_bh, old_dir, ++ &parent_fe_bh, dir, 0); + if (err < 0) { + if (err != -ENOENT) + mlog_errno(err); + return err; + } + ++ /* make sure both dirs have bhs ++ * get an extra ref on old_dir_bh if old==new */ ++ if (!parent_fe_bh) { ++ if (old_dir_bh) { ++ parent_fe_bh = old_dir_bh; ++ get_bh(parent_fe_bh); ++ } else { ++ mlog(ML_ERROR, "%s: no old_dir_bh!\n", osb->uuid_str); ++ err = -EIO; ++ goto out; ++ } ++ } ++ + if (!dir->i_nlink) { + err = -ENOENT; + goto out; + } + +- err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name, ++ err = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, + old_dentry->d_name.len, &old_de_ino); + if (err) { + err = -ENOENT; +@@ -779,10 +803,11 @@ out_unlock_inode: + ocfs2_inode_unlock(inode, 1); + + out: +- ocfs2_inode_unlock(dir, 1); ++ ocfs2_double_unlock(old_dir, dir); + + brelse(fe_bh); + brelse(parent_fe_bh); ++ brelse(old_dir_bh); + + ocfs2_free_dir_lookup_result(&lookup); + +@@ -991,14 +1016,15 @@ leave: + } + + /* +- * The only place this should be used is rename! ++ * The only place this should be used is rename and link! + * if they have the same id, then the 1st one is the only one locked. + */ + static int ocfs2_double_lock(struct ocfs2_super *osb, + struct buffer_head **bh1, + struct inode *inode1, + struct buffer_head **bh2, +- struct inode *inode2) ++ struct inode *inode2, ++ int rename) + { + int status; + struct ocfs2_inode_info *oi1 = OCFS2_I(inode1); +@@ -1028,7 +1054,7 @@ static int ocfs2_double_lock(struct ocfs + } + /* lock id2 */ + status = ocfs2_inode_lock_nested(inode2, bh2, 1, +- OI_LS_RENAME1); ++ rename == 1 ? OI_LS_RENAME1 : OI_LS_PARENT); + if (status < 0) { + if (status != -ENOENT) + mlog_errno(status); +@@ -1037,7 +1063,8 @@ static int ocfs2_double_lock(struct ocfs + } + + /* lock id1 */ +- status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_RENAME2); ++ status = ocfs2_inode_lock_nested(inode1, bh1, 1, ++ rename == 1 ? OI_LS_RENAME2 : OI_LS_PARENT); + if (status < 0) { + /* + * An error return must mean that no cluster locks +@@ -1137,7 +1164,7 @@ static int ocfs2_rename(struct inode *ol + + /* if old and new are the same, this'll just do one lock. */ + status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, +- &new_dir_bh, new_dir); ++ &new_dir_bh, new_dir, 1); + if (status < 0) { + mlog_errno(status); + goto bail;