From: Greg Kroah-Hartman Date: Sun, 1 May 2016 23:32:23 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.14.68~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=240f44bc4f82d18740a72ea8f9c8d0004fc3ff7f;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: asoc-rt5640-correct-the-digital-interface-data-select.patch asoc-s3c24xx-use-const-snd_soc_component_driver-pointer.patch efi-fix-out-of-bounds-read-in-variable_matches.patch workqueue-fix-ghost-pending-flag-while-doing-mq-io.patch --- diff --git a/queue-3.14/asoc-rt5640-correct-the-digital-interface-data-select.patch b/queue-3.14/asoc-rt5640-correct-the-digital-interface-data-select.patch new file mode 100644 index 00000000000..93d24b1b0c0 --- /dev/null +++ b/queue-3.14/asoc-rt5640-correct-the-digital-interface-data-select.patch @@ -0,0 +1,92 @@ +From 653aa4645244042826f105aab1be3d01b3d493ca Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Fri, 18 Mar 2016 14:54:22 +0800 +Subject: ASoC: rt5640: Correct the digital interface data select + +From: Sugar Zhang + +commit 653aa4645244042826f105aab1be3d01b3d493ca upstream. + +this patch corrects the interface adc/dac control register definition +according to datasheet. + +Signed-off-by: Sugar Zhang +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/rt5640.c | 2 +- + sound/soc/codecs/rt5640.h | 36 ++++++++++++++++++------------------ + 2 files changed, 19 insertions(+), 19 deletions(-) + +--- a/sound/soc/codecs/rt5640.c ++++ b/sound/soc/codecs/rt5640.c +@@ -359,7 +359,7 @@ static unsigned int bst_tlv[] = { + + /* Interface data select */ + static const char * const rt5640_data_select[] = { +- "Normal", "left copy to right", "right copy to left", "Swap"}; ++ "Normal", "Swap", "left copy to right", "right copy to left"}; + + static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, + RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); +--- a/sound/soc/codecs/rt5640.h ++++ b/sound/soc/codecs/rt5640.h +@@ -435,39 +435,39 @@ + #define RT5640_IF1_DAC_SEL_MASK (0x3 << 14) + #define RT5640_IF1_DAC_SEL_SFT 14 + #define RT5640_IF1_DAC_SEL_NOR (0x0 << 14) +-#define RT5640_IF1_DAC_SEL_L2R (0x1 << 14) +-#define RT5640_IF1_DAC_SEL_R2L (0x2 << 14) +-#define RT5640_IF1_DAC_SEL_SWAP (0x3 << 14) ++#define RT5640_IF1_DAC_SEL_SWAP (0x1 << 14) ++#define RT5640_IF1_DAC_SEL_L2R (0x2 << 14) ++#define RT5640_IF1_DAC_SEL_R2L (0x3 << 14) + #define RT5640_IF1_ADC_SEL_MASK (0x3 << 12) + #define RT5640_IF1_ADC_SEL_SFT 12 + #define RT5640_IF1_ADC_SEL_NOR (0x0 << 12) +-#define RT5640_IF1_ADC_SEL_L2R (0x1 << 12) +-#define RT5640_IF1_ADC_SEL_R2L (0x2 << 12) +-#define RT5640_IF1_ADC_SEL_SWAP (0x3 << 12) ++#define RT5640_IF1_ADC_SEL_SWAP (0x1 << 12) ++#define RT5640_IF1_ADC_SEL_L2R (0x2 << 12) ++#define RT5640_IF1_ADC_SEL_R2L (0x3 << 12) + #define RT5640_IF2_DAC_SEL_MASK (0x3 << 10) + #define RT5640_IF2_DAC_SEL_SFT 10 + #define RT5640_IF2_DAC_SEL_NOR (0x0 << 10) +-#define RT5640_IF2_DAC_SEL_L2R (0x1 << 10) +-#define RT5640_IF2_DAC_SEL_R2L (0x2 << 10) +-#define RT5640_IF2_DAC_SEL_SWAP (0x3 << 10) ++#define RT5640_IF2_DAC_SEL_SWAP (0x1 << 10) ++#define RT5640_IF2_DAC_SEL_L2R (0x2 << 10) ++#define RT5640_IF2_DAC_SEL_R2L (0x3 << 10) + #define RT5640_IF2_ADC_SEL_MASK (0x3 << 8) + #define RT5640_IF2_ADC_SEL_SFT 8 + #define RT5640_IF2_ADC_SEL_NOR (0x0 << 8) +-#define RT5640_IF2_ADC_SEL_L2R (0x1 << 8) +-#define RT5640_IF2_ADC_SEL_R2L (0x2 << 8) +-#define RT5640_IF2_ADC_SEL_SWAP (0x3 << 8) ++#define RT5640_IF2_ADC_SEL_SWAP (0x1 << 8) ++#define RT5640_IF2_ADC_SEL_L2R (0x2 << 8) ++#define RT5640_IF2_ADC_SEL_R2L (0x3 << 8) + #define RT5640_IF3_DAC_SEL_MASK (0x3 << 6) + #define RT5640_IF3_DAC_SEL_SFT 6 + #define RT5640_IF3_DAC_SEL_NOR (0x0 << 6) +-#define RT5640_IF3_DAC_SEL_L2R (0x1 << 6) +-#define RT5640_IF3_DAC_SEL_R2L (0x2 << 6) +-#define RT5640_IF3_DAC_SEL_SWAP (0x3 << 6) ++#define RT5640_IF3_DAC_SEL_SWAP (0x1 << 6) ++#define RT5640_IF3_DAC_SEL_L2R (0x2 << 6) ++#define RT5640_IF3_DAC_SEL_R2L (0x3 << 6) + #define RT5640_IF3_ADC_SEL_MASK (0x3 << 4) + #define RT5640_IF3_ADC_SEL_SFT 4 + #define RT5640_IF3_ADC_SEL_NOR (0x0 << 4) +-#define RT5640_IF3_ADC_SEL_L2R (0x1 << 4) +-#define RT5640_IF3_ADC_SEL_R2L (0x2 << 4) +-#define RT5640_IF3_ADC_SEL_SWAP (0x3 << 4) ++#define RT5640_IF3_ADC_SEL_SWAP (0x1 << 4) ++#define RT5640_IF3_ADC_SEL_L2R (0x2 << 4) ++#define RT5640_IF3_ADC_SEL_R2L (0x3 << 4) + + /* REC Left Mixer Control 1 (0x3b) */ + #define RT5640_G_HP_L_RM_L_MASK (0x7 << 13) diff --git a/queue-3.14/asoc-s3c24xx-use-const-snd_soc_component_driver-pointer.patch b/queue-3.14/asoc-s3c24xx-use-const-snd_soc_component_driver-pointer.patch new file mode 100644 index 00000000000..86f32f1319d --- /dev/null +++ b/queue-3.14/asoc-s3c24xx-use-const-snd_soc_component_driver-pointer.patch @@ -0,0 +1,53 @@ +From ba4bc32eaa39ba7687f0958ae90eec94da613b46 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Mon, 25 Jan 2016 18:07:33 +0100 +Subject: ASoC: s3c24xx: use const snd_soc_component_driver pointer + +From: Arnd Bergmann + +commit ba4bc32eaa39ba7687f0958ae90eec94da613b46 upstream. + +An older patch to convert the API in the s3c i2s driver +ended up passing a const pointer into a function that takes +a non-const pointer, so we now get a warning: + +sound/soc/samsung/s3c2412-i2s.c: In function 's3c2412_iis_dev_probe': +sound/soc/samsung/s3c2412-i2s.c:172:9: error: passing argument 3 of 's3c_i2sv2_register_component' discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers] + +However, the s3c_i2sv2_register_component() function again +passes the pointer into another function taking a const, so +we just need to change its prototype. + +Fixes: eca3b01d0885 ("ASoC: switch over to use snd_soc_register_component() on s3c i2s") +Signed-off-by: Arnd Bergmann +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/samsung/s3c-i2s-v2.c | 2 +- + sound/soc/samsung/s3c-i2s-v2.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/samsung/s3c-i2s-v2.c ++++ b/sound/soc/samsung/s3c-i2s-v2.c +@@ -726,7 +726,7 @@ static int s3c2412_i2s_resume(struct snd + #endif + + int s3c_i2sv2_register_component(struct device *dev, int id, +- struct snd_soc_component_driver *cmp_drv, ++ const struct snd_soc_component_driver *cmp_drv, + struct snd_soc_dai_driver *dai_drv) + { + struct snd_soc_dai_ops *ops = dai_drv->ops; +--- a/sound/soc/samsung/s3c-i2s-v2.h ++++ b/sound/soc/samsung/s3c-i2s-v2.h +@@ -101,7 +101,7 @@ extern int s3c_i2sv2_probe(struct snd_so + * soc core. + */ + extern int s3c_i2sv2_register_component(struct device *dev, int id, +- struct snd_soc_component_driver *cmp_drv, ++ const struct snd_soc_component_driver *cmp_drv, + struct snd_soc_dai_driver *dai_drv); + + #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ diff --git a/queue-3.14/efi-fix-out-of-bounds-read-in-variable_matches.patch b/queue-3.14/efi-fix-out-of-bounds-read-in-variable_matches.patch new file mode 100644 index 00000000000..cc7e533432a --- /dev/null +++ b/queue-3.14/efi-fix-out-of-bounds-read-in-variable_matches.patch @@ -0,0 +1,93 @@ +From 630ba0cc7a6dbafbdee43795617c872b35cde1b4 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 21 Apr 2016 18:21:11 +0200 +Subject: efi: Fix out-of-bounds read in variable_matches() + +From: Laszlo Ersek + +commit 630ba0cc7a6dbafbdee43795617c872b35cde1b4 upstream. + +The variable_matches() function can currently read "var_name[len]", for +example when: + + - var_name[0] == 'a', + - len == 1 + - match_name points to the NUL-terminated string "ab". + +This function is supposed to accept "var_name" inputs that are not +NUL-terminated (hence the "len" parameter"). Document the function, and +access "var_name[*match]" only if "*match" is smaller than "len". + +Reported-by: Chris Wilson +Signed-off-by: Laszlo Ersek +Cc: Peter Jones +Cc: Matthew Garrett +Cc: Jason Andryuk +Cc: Jani Nikula +Link: http://thread.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/86906 +Signed-off-by: Matt Fleming +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firmware/efi/vars.c | 39 +++++++++++++++++++++++++++------------ + 1 file changed, 27 insertions(+), 12 deletions(-) + +--- a/drivers/firmware/efi/vars.c ++++ b/drivers/firmware/efi/vars.c +@@ -202,29 +202,44 @@ static const struct variable_validate va + { NULL_GUID, "", NULL }, + }; + ++/* ++ * Check if @var_name matches the pattern given in @match_name. ++ * ++ * @var_name: an array of @len non-NUL characters. ++ * @match_name: a NUL-terminated pattern string, optionally ending in "*". A ++ * final "*" character matches any trailing characters @var_name, ++ * including the case when there are none left in @var_name. ++ * @match: on output, the number of non-wildcard characters in @match_name ++ * that @var_name matches, regardless of the return value. ++ * @return: whether @var_name fully matches @match_name. ++ */ + static bool + variable_matches(const char *var_name, size_t len, const char *match_name, + int *match) + { + for (*match = 0; ; (*match)++) { + char c = match_name[*match]; +- char u = var_name[*match]; + +- /* Wildcard in the matching name means we've matched */ +- if (c == '*') ++ switch (c) { ++ case '*': ++ /* Wildcard in @match_name means we've matched. */ + return true; + +- /* Case sensitive match */ +- if (!c && *match == len) +- return true; +- +- if (c != u) ++ case '\0': ++ /* @match_name has ended. Has @var_name too? */ ++ return (*match == len); ++ ++ default: ++ /* ++ * We've reached a non-wildcard char in @match_name. ++ * Continue only if there's an identical character in ++ * @var_name. ++ */ ++ if (*match < len && c == var_name[*match]) ++ continue; + return false; +- +- if (!c) +- return true; ++ } + } +- return true; + } + + bool diff --git a/queue-3.14/series b/queue-3.14/series index dd6427d7f6b..eb01ad371c3 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -14,3 +14,7 @@ pinctrl-single-fix-pcs_parse_bits_in_pinctrl_entry-to-use-__ffs-than-ffs.patch i2c-cpm-fix-build-break-due-to-incompatible-pointer-types.patch i2c-exynos5-fix-possible-abba-deadlock-by-keeping-i2c-clock-prepared.patch edac-i7core-sb_edac-don-t-return-notify_bad-from-mce_decoder-callback.patch +asoc-s3c24xx-use-const-snd_soc_component_driver-pointer.patch +asoc-rt5640-correct-the-digital-interface-data-select.patch +efi-fix-out-of-bounds-read-in-variable_matches.patch +workqueue-fix-ghost-pending-flag-while-doing-mq-io.patch diff --git a/queue-3.14/workqueue-fix-ghost-pending-flag-while-doing-mq-io.patch b/queue-3.14/workqueue-fix-ghost-pending-flag-while-doing-mq-io.patch new file mode 100644 index 00000000000..53c436bc25f --- /dev/null +++ b/queue-3.14/workqueue-fix-ghost-pending-flag-while-doing-mq-io.patch @@ -0,0 +1,163 @@ +From 346c09f80459a3ad97df1816d6d606169a51001a Mon Sep 17 00:00:00 2001 +From: Roman Pen +Date: Tue, 26 Apr 2016 13:15:35 +0200 +Subject: workqueue: fix ghost PENDING flag while doing MQ IO + +From: Roman Pen + +commit 346c09f80459a3ad97df1816d6d606169a51001a upstream. + +The bug in a workqueue leads to a stalled IO request in MQ ctx->rq_list +with the following backtrace: + +[ 601.347452] INFO: task kworker/u129:5:1636 blocked for more than 120 seconds. +[ 601.347574] Tainted: G O 4.4.5-1-storage+ #6 +[ 601.347651] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 601.348142] kworker/u129:5 D ffff880803077988 0 1636 2 0x00000000 +[ 601.348519] Workqueue: ibnbd_server_fileio_wq ibnbd_dev_file_submit_io_worker [ibnbd_server] +[ 601.348999] ffff880803077988 ffff88080466b900 ffff8808033f9c80 ffff880803078000 +[ 601.349662] ffff880807c95000 7fffffffffffffff ffffffff815b0920 ffff880803077ad0 +[ 601.350333] ffff8808030779a0 ffffffff815b01d5 0000000000000000 ffff880803077a38 +[ 601.350965] Call Trace: +[ 601.351203] [] ? bit_wait+0x60/0x60 +[ 601.351444] [] schedule+0x35/0x80 +[ 601.351709] [] schedule_timeout+0x192/0x230 +[ 601.351958] [] ? blk_flush_plug_list+0xc7/0x220 +[ 601.352208] [] ? ktime_get+0x37/0xa0 +[ 601.352446] [] ? bit_wait+0x60/0x60 +[ 601.352688] [] io_schedule_timeout+0xa4/0x110 +[ 601.352951] [] ? _raw_spin_unlock_irqrestore+0xe/0x10 +[ 601.353196] [] bit_wait_io+0x1b/0x70 +[ 601.353440] [] __wait_on_bit+0x5d/0x90 +[ 601.353689] [] wait_on_page_bit+0xc0/0xd0 +[ 601.353958] [] ? autoremove_wake_function+0x40/0x40 +[ 601.354200] [] __filemap_fdatawait_range+0xe4/0x140 +[ 601.354441] [] filemap_fdatawait_range+0x14/0x30 +[ 601.354688] [] filemap_write_and_wait_range+0x3f/0x70 +[ 601.354932] [] blkdev_fsync+0x1b/0x50 +[ 601.355193] [] vfs_fsync_range+0x49/0xa0 +[ 601.355432] [] blkdev_write_iter+0xca/0x100 +[ 601.355679] [] __vfs_write+0xaa/0xe0 +[ 601.355925] [] vfs_write+0xa9/0x1a0 +[ 601.356164] [] kernel_write+0x38/0x50 + +The underlying device is a null_blk, with default parameters: + + queue_mode = MQ + submit_queues = 1 + +Verification that nullb0 has something inflight: + +root@pserver8:~# cat /sys/block/nullb0/inflight + 0 1 +root@pserver8:~# find /sys/block/nullb0/mq/0/cpu* -name rq_list -print -exec cat {} \; +... +/sys/block/nullb0/mq/0/cpu2/rq_list +CTX pending: + ffff8838038e2400 +... + +During debug it became clear that stalled request is always inserted in +the rq_list from the following path: + + save_stack_trace_tsk + 34 + blk_mq_insert_requests + 231 + blk_mq_flush_plug_list + 281 + blk_flush_plug_list + 199 + wait_on_page_bit + 192 + __filemap_fdatawait_range + 228 + filemap_fdatawait_range + 20 + filemap_write_and_wait_range + 63 + blkdev_fsync + 27 + vfs_fsync_range + 73 + blkdev_write_iter + 202 + __vfs_write + 170 + vfs_write + 169 + kernel_write + 56 + +So blk_flush_plug_list() was called with from_schedule == true. + +If from_schedule is true, that means that finally blk_mq_insert_requests() +offloads execution of __blk_mq_run_hw_queue() and uses kblockd workqueue, +i.e. it calls kblockd_schedule_delayed_work_on(). + +That means, that we race with another CPU, which is about to execute +__blk_mq_run_hw_queue() work. + +Further debugging shows the following traces from different CPUs: + + CPU#0 CPU#1 + ---------------------------------- ------------------------------- + reqeust A inserted + STORE hctx->ctx_map[0] bit marked + kblockd_schedule...() returns 1 + + request B inserted + STORE hctx->ctx_map[1] bit marked + kblockd_schedule...() returns 0 + *** WORK PENDING bit is cleared *** + flush_busy_ctxs() is executed, but + bit 1, set by CPU#1, is not observed + +As a result request B pended forever. + +This behaviour can be explained by speculative LOAD of hctx->ctx_map on +CPU#0, which is reordered with clear of PENDING bit and executed _before_ +actual STORE of bit 1 on CPU#1. + +The proper fix is an explicit full barrier , which guarantees +that clear of PENDING bit is to be executed before all possible +speculative LOADS or STORES inside actual work function. + +Signed-off-by: Roman Pen +Cc: Gioh Kim +Cc: Michael Wang +Cc: Tejun Heo +Cc: Jens Axboe +Cc: linux-block@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Tejun Heo +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/workqueue.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -629,6 +629,35 @@ static void set_work_pool_and_clear_pend + */ + smp_wmb(); + set_work_data(work, (unsigned long)pool_id << WORK_OFFQ_POOL_SHIFT, 0); ++ /* ++ * The following mb guarantees that previous clear of a PENDING bit ++ * will not be reordered with any speculative LOADS or STORES from ++ * work->current_func, which is executed afterwards. This possible ++ * reordering can lead to a missed execution on attempt to qeueue ++ * the same @work. E.g. consider this case: ++ * ++ * CPU#0 CPU#1 ++ * ---------------------------- -------------------------------- ++ * ++ * 1 STORE event_indicated ++ * 2 queue_work_on() { ++ * 3 test_and_set_bit(PENDING) ++ * 4 } set_..._and_clear_pending() { ++ * 5 set_work_data() # clear bit ++ * 6 smp_mb() ++ * 7 work->current_func() { ++ * 8 LOAD event_indicated ++ * } ++ * ++ * Without an explicit full barrier speculative LOAD on line 8 can ++ * be executed before CPU#0 does STORE on line 1. If that happens, ++ * CPU#0 observes the PENDING bit is still set and new execution of ++ * a @work is not queued in a hope, that CPU#1 will eventually ++ * finish the queued @work. Meanwhile CPU#1 does not see ++ * event_indicated is set, because speculative LOAD was executed ++ * before actual STORE. ++ */ ++ smp_mb(); + } + + static void clear_work_data(struct work_struct *work)