From: Greg Kroah-Hartman Date: Sun, 5 Feb 2017 10:26:52 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v3.18.48~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a66a2f0926c39ed69189df9badcf429464ff8c57;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: firmware-fix-null-pointer-dereference-in-__fw_load_abort.patch iio-adc-palmas_gpadc-retrieve-a-valid-iio_dev-in-suspend-resume.patch iio-dht11-use-usleep_range-instead-of-msleep-for-start-signal.patch iio-health-afe4403-retrieve-a-valid-iio_dev-in-suspend-resume.patch iio-health-afe4404-retrieve-a-valid-iio_dev-in-suspend-resume.patch iio-health-max30100-fixed-parenthesis-around-fifo-count-check.patch irqdomain-avoid-activating-interrupts-more-than-once.patch staging-greybus-timesync-validate-platform-state-callback.patch usb-gadget-f_fs-assorted-buffer-overflow-checks.patch usb-musb-fix-host-mode-error-71-regression.patch usb-serial-option-add-device-id-for-hp-lt2523-novatel-e371.patch x86-irq-make-irq-activate-operations-symmetric.patch --- diff --git a/queue-4.9/firmware-fix-null-pointer-dereference-in-__fw_load_abort.patch b/queue-4.9/firmware-fix-null-pointer-dereference-in-__fw_load_abort.patch new file mode 100644 index 00000000000..2d6bc4bbb31 --- /dev/null +++ b/queue-4.9/firmware-fix-null-pointer-dereference-in-__fw_load_abort.patch @@ -0,0 +1,152 @@ +From 191e885a2e130e639bb0c8ee350d7047294f2ce6 Mon Sep 17 00:00:00 2001 +From: "Luis R. Rodriguez" +Date: Wed, 25 Jan 2017 10:31:52 -0800 +Subject: firmware: fix NULL pointer dereference in __fw_load_abort() + +From: Luis R. Rodriguez + +commit 191e885a2e130e639bb0c8ee350d7047294f2ce6 upstream. + +Since commit 5d47ec02c37ea6 ("firmware: Correct handling of +fw_state_wait() return value") fw_load_abort() could be called twice and +lead us to a kernel crash. This happens only when the firmware fallback +mechanism (regular or custom) is used. The fallback mechanism exposes a +sysfs interface for userspace to upload a file and notify the kernel +when the file is loaded and ready, or to cancel an upload by echo'ing -1 +into on the loading file: + +echo -n "-1" > /sys/$DEVPATH/loading + +This will call fw_load_abort(). Some distributions actually have a udev +rule in place to *always* immediately cancel all firmware fallback +mechanism requests (Debian), they have: + + $ cat /lib/udev/rules.d/50-firmware.rules + # stub for immediately telling the kernel that userspace firmware loading + # failed; necessary to avoid long timeouts with CONFIG_FW_LOADER_USER_HELPER=y + SUBSYSTEM=="firmware", ACTION=="add", ATTR{loading}="-1 + +Distributions with this udev rule would run into this crash only if the +fallback mechanism is used. Since most distributions disable by default +using the fallback mechanism (CONFIG_FW_LOADER_USER_HELPER_FALLBACK), +this would typicaly mean only 2 drivers which *require* the fallback +mechanism could typically incur a crash: drivers/firmware/dell_rbu.c and +the drivers/leds/leds-lp55xx-common.c driver. Distributions enabling +CONFIG_FW_LOADER_USER_HELPER_FALLBACK by default are obviously more +exposed to this crash. + +The crash happens because after commit 5b029624948d ("firmware: do not +use fw_lock for fw_state protection") and subsequent fix commit +5d47ec02c37ea6 ("firmware: Correct handling of fw_state_wait() return +value") a race can happen between this cancelation and the firmware +fw_state_wait_timeout() being woken up after a state change with which +fw_load_abort() as that calls swake_up(). Upon error +fw_state_wait_timeout() will also again call fw_load_abort() and trigger +a null reference. + +At first glance we could just fix this with a !buf check on +fw_load_abort() before accessing buf->fw_st, however there is a logical +issue in having a state machine used for the fallback mechanism and +preventing access from it once we abort as its inside the buf +(buf->fw_st). + +The firmware_class.c code is setting the buf to NULL to annotate an +abort has occurred. Replace this mechanism by simply using the state +check instead. All the other code in place already uses similar checks +for aborting as well so no further changes are needed. + +An oops can be reproduced with the new fw_fallback.sh fallback mechanism +cancellation test. Either cancelling the fallback mechanism or the +custom fallback mechanism triggers a crash. + +mcgrof@piggy ~/linux-next/tools/testing/selftests/firmware +(git::20170111-fw-fixes)$ sudo ./fw_fallback.sh + +./fw_fallback.sh: timeout works +./fw_fallback.sh: firmware comparison works +./fw_fallback.sh: fallback mechanism works + +[ this then sits here when it is trying the cancellation test ] + +Kernel log: + +test_firmware: loading 'nope-test-firmware.bin' +misc test_firmware: Direct firmware load for nope-test-firmware.bin failed with error -2 +misc test_firmware: Falling back to user helper +BUG: unable to handle kernel NULL pointer dereference at 0000000000000038 +IP: _request_firmware+0xa27/0xad0 +PGD 0 + +Oops: 0000 [#1] SMP +Modules linked in: test_firmware(E) ... etc ... +CPU: 1 PID: 1396 Comm: fw_fallback.sh Tainted: G W E 4.10.0-rc3-next-20170111+ #30 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.10.1-0-g8891697-prebuilt.qemu-project.org 04/01/2014 +task: ffff9740b27f4340 task.stack: ffffbb15c0bc8000 +RIP: 0010:_request_firmware+0xa27/0xad0 +RSP: 0018:ffffbb15c0bcbd10 EFLAGS: 00010246 +RAX: 00000000fffffffe RBX: ffff9740afe5aa80 RCX: 0000000000000000 +RDX: ffff9740b27f4340 RSI: 0000000000000283 RDI: 0000000000000000 +RBP: ffffbb15c0bcbd90 R08: ffffbb15c0bcbcd8 R09: 0000000000000000 +R10: 0000000894a0d4b1 R11: 000000000000008c R12: ffffffffc0312480 +R13: 0000000000000005 R14: ffff9740b1c32400 R15: 00000000000003e8 +FS: 00007f8604422700(0000) GS:ffff9740bfc80000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000000038 CR3: 000000012164c000 CR4: 00000000000006e0 +Call Trace: + request_firmware+0x37/0x50 + trigger_request_store+0x79/0xd0 [test_firmware] + dev_attr_store+0x18/0x30 + sysfs_kf_write+0x37/0x40 + kernfs_fop_write+0x110/0x1a0 + __vfs_write+0x37/0x160 + ? _cond_resched+0x1a/0x50 + vfs_write+0xb5/0x1a0 + SyS_write+0x55/0xc0 + ? trace_do_page_fault+0x37/0xd0 + entry_SYSCALL_64_fastpath+0x1e/0xad +RIP: 0033:0x7f8603f49620 +RSP: 002b:00007fff6287b788 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 +RAX: ffffffffffffffda RBX: 000055c307b110a0 RCX: 00007f8603f49620 +RDX: 0000000000000016 RSI: 000055c3084d8a90 RDI: 0000000000000001 +RBP: 0000000000000016 R08: 000000000000c0ff R09: 000055c3084d6336 +R10: 000055c307b108b0 R11: 0000000000000246 R12: 000055c307b13c80 +R13: 000055c3084d6320 R14: 0000000000000000 R15: 00007fff6287b950 +Code: 9f 64 84 e8 9c 61 fe ff b8 f4 ff ff ff e9 6b f9 ff +ff 48 c7 c7 40 6b 8d 84 89 45 a8 e8 43 84 18 00 49 8b be 00 03 00 00 8b +45 a8 <83> 7f 38 02 74 08 e8 6e ec ff ff 8b 45 a8 49 c7 86 00 03 00 00 +RIP: _request_firmware+0xa27/0xad0 RSP: ffffbb15c0bcbd10 +CR2: 0000000000000038 +---[ end trace 6d94ac339c133e6f ]--- + +Fixes: 5d47ec02c37e ("firmware: Correct handling of fw_state_wait() return value") +Reported-and-Tested-by: Jakub Kicinski +Reported-and-Tested-by: Patrick Bruenn +Reported-by: Chris Wilson +Signed-off-by: Luis R. Rodriguez +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/firmware_class.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/base/firmware_class.c ++++ b/drivers/base/firmware_class.c +@@ -491,9 +491,6 @@ static void fw_load_abort(struct firmwar + struct firmware_buf *buf = fw_priv->buf; + + __fw_load_abort(buf); +- +- /* avoid user action after loading abort */ +- fw_priv->buf = NULL; + } + + #define is_fw_load_aborted(buf) \ +@@ -647,7 +644,7 @@ static ssize_t firmware_loading_store(st + + mutex_lock(&fw_lock); + fw_buf = fw_priv->buf; +- if (!fw_buf) ++ if (fw_state_is_aborted(&fw_buf->fw_st)) + goto out; + + switch (loading) { diff --git a/queue-4.9/iio-adc-palmas_gpadc-retrieve-a-valid-iio_dev-in-suspend-resume.patch b/queue-4.9/iio-adc-palmas_gpadc-retrieve-a-valid-iio_dev-in-suspend-resume.patch new file mode 100644 index 00000000000..80b32564c0b --- /dev/null +++ b/queue-4.9/iio-adc-palmas_gpadc-retrieve-a-valid-iio_dev-in-suspend-resume.patch @@ -0,0 +1,41 @@ +From d1aaf20ee655888c227d5137b7a63551f8d15416 Mon Sep 17 00:00:00 2001 +From: Alison Schofield +Date: Mon, 16 Jan 2017 11:27:52 -0800 +Subject: iio: adc: palmas_gpadc: retrieve a valid iio_dev in suspend/resume + +From: Alison Schofield + +commit d1aaf20ee655888c227d5137b7a63551f8d15416 upstream. + +The suspend/resume functions were using dev_to_iio_dev() to get +the iio_dev. That only works on IIO dev's. Use dev_get_drvdata() +for a platform device to get the correct iio_dev. + +Signed-off-by: Alison Schofield +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/adc/palmas_gpadc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/iio/adc/palmas_gpadc.c ++++ b/drivers/iio/adc/palmas_gpadc.c +@@ -775,7 +775,7 @@ static int palmas_adc_wakeup_reset(struc + + static int palmas_gpadc_suspend(struct device *dev) + { +- struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct palmas_gpadc *adc = iio_priv(indio_dev); + int wakeup = adc->wakeup1_enable || adc->wakeup2_enable; + int ret; +@@ -798,7 +798,7 @@ static int palmas_gpadc_suspend(struct d + + static int palmas_gpadc_resume(struct device *dev) + { +- struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct palmas_gpadc *adc = iio_priv(indio_dev); + int wakeup = adc->wakeup1_enable || adc->wakeup2_enable; + int ret; diff --git a/queue-4.9/iio-dht11-use-usleep_range-instead-of-msleep-for-start-signal.patch b/queue-4.9/iio-dht11-use-usleep_range-instead-of-msleep-for-start-signal.patch new file mode 100644 index 00000000000..21229fe2a9f --- /dev/null +++ b/queue-4.9/iio-dht11-use-usleep_range-instead-of-msleep-for-start-signal.patch @@ -0,0 +1,80 @@ +From 5c113b5e0082e90d2e1c7b12e96a7b8cf0623e27 Mon Sep 17 00:00:00 2001 +From: John Brooks +Date: Wed, 18 Jan 2017 21:50:39 +0000 +Subject: iio: dht11: Use usleep_range instead of msleep for start signal + +From: John Brooks + +commit 5c113b5e0082e90d2e1c7b12e96a7b8cf0623e27 upstream. + +The DHT22 (AM2302) datasheet specifies that the LOW start pulse should not +exceed 20ms. However, observations with an oscilloscope of an RPi Model 2B +(rev 1.1) communicating with a DHT22 sensor showed that the driver was +consistently sending start pulses longer than 20ms: + +Kernel 4.7.10-v7+ (n=132): + Minimum pulse length: 20.20ms + Maximum: 29.84ms + Mean: 24.96ms + StDev: 2.82ms + Sensor response rate: 100% + Read success rate: 76% + +On kernel 4.8, the start pulse was so long that the sensor would not even +respond 97% of the time: + +Kernel 4.8.16-v7+ (n=100): + Minimum pulse length: 30.4ms + Maximum: 74.4ms + Mean: 39.3ms + StDev: 10.2ms + Sensor response rate: 3% + Read success rate: 3% + +The driver would return ETIMEDOUT and write log messages like this: + +[ 51.430987] dht11 dht11@0: Only 1 signal edges detected +[ 66.311019] dht11 dht11@0: Only 0 signal edges detected + +Replacing msleep(18) with usleep_range(18000, 20000) made the pulse length +sane again and restored responsiveness: + +Kernel 4.8.16-v7+ with usleep_range (n=123): + Minimum pulse length: 18.16ms + Maximum: 20.20ms + Mean: 19.85ms + StDev: 0.51ms + Sensor response rate: 100% + Read success rate: 84% + +Signed-off-by: John Brooks +Reviewed-by: Harald Geyer +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/humidity/dht11.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/iio/humidity/dht11.c ++++ b/drivers/iio/humidity/dht11.c +@@ -71,7 +71,8 @@ + * a) select an implementation using busy loop polling on those systems + * b) use the checksum to do some probabilistic decoding + */ +-#define DHT11_START_TRANSMISSION 18 /* ms */ ++#define DHT11_START_TRANSMISSION_MIN 18000 /* us */ ++#define DHT11_START_TRANSMISSION_MAX 20000 /* us */ + #define DHT11_MIN_TIMERES 34000 /* ns */ + #define DHT11_THRESHOLD 49000 /* ns */ + #define DHT11_AMBIG_LOW 23000 /* ns */ +@@ -228,7 +229,8 @@ static int dht11_read_raw(struct iio_dev + ret = gpio_direction_output(dht11->gpio, 0); + if (ret) + goto err; +- msleep(DHT11_START_TRANSMISSION); ++ usleep_range(DHT11_START_TRANSMISSION_MIN, ++ DHT11_START_TRANSMISSION_MAX); + ret = gpio_direction_input(dht11->gpio); + if (ret) + goto err; diff --git a/queue-4.9/iio-health-afe4403-retrieve-a-valid-iio_dev-in-suspend-resume.patch b/queue-4.9/iio-health-afe4403-retrieve-a-valid-iio_dev-in-suspend-resume.patch new file mode 100644 index 00000000000..35e2f57d9a1 --- /dev/null +++ b/queue-4.9/iio-health-afe4403-retrieve-a-valid-iio_dev-in-suspend-resume.patch @@ -0,0 +1,42 @@ +From a5badd1e97e6caeca78ad74191f12fc923c403a8 Mon Sep 17 00:00:00 2001 +From: Alison Schofield +Date: Sat, 14 Jan 2017 19:51:52 -0800 +Subject: iio: health: afe4403: retrieve a valid iio_dev in suspend/resume + +From: Alison Schofield + +commit a5badd1e97e6caeca78ad74191f12fc923c403a8 upstream. + +The suspend/resume functions were using dev_to_iio_dev() to get +the iio_dev. That only works on IIO dev's. Replace it with spi +functions to get the correct iio_dev. + +Signed-off-by: Alison Schofield +Acked-by: Andrew F. Davis +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/health/afe4403.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/iio/health/afe4403.c ++++ b/drivers/iio/health/afe4403.c +@@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, afe4403_of_match + + static int __maybe_unused afe4403_suspend(struct device *dev) + { +- struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev)); + struct afe4403_data *afe = iio_priv(indio_dev); + int ret; + +@@ -443,7 +443,7 @@ static int __maybe_unused afe4403_suspen + + static int __maybe_unused afe4403_resume(struct device *dev) + { +- struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev)); + struct afe4403_data *afe = iio_priv(indio_dev); + int ret; + diff --git a/queue-4.9/iio-health-afe4404-retrieve-a-valid-iio_dev-in-suspend-resume.patch b/queue-4.9/iio-health-afe4404-retrieve-a-valid-iio_dev-in-suspend-resume.patch new file mode 100644 index 00000000000..78f6a6a2411 --- /dev/null +++ b/queue-4.9/iio-health-afe4404-retrieve-a-valid-iio_dev-in-suspend-resume.patch @@ -0,0 +1,42 @@ +From 802ecfc113df1e15af1d028427cbbe785ae9cc4a Mon Sep 17 00:00:00 2001 +From: Alison Schofield +Date: Sat, 14 Jan 2017 19:52:50 -0800 +Subject: iio: health: afe4404: retrieve a valid iio_dev in suspend/resume + +From: Alison Schofield + +commit 802ecfc113df1e15af1d028427cbbe785ae9cc4a upstream. + +The suspend/resume functions were using dev_to_iio_dev() to get +the iio_dev. That only works on IIO dev's. Replace it with i2c +functions to get the correct iio_dev. + +Signed-off-by: Alison Schofield +Acked-by: Andrew F. Davis +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/health/afe4404.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/iio/health/afe4404.c ++++ b/drivers/iio/health/afe4404.c +@@ -428,7 +428,7 @@ MODULE_DEVICE_TABLE(of, afe4404_of_match + + static int __maybe_unused afe4404_suspend(struct device *dev) + { +- struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct afe4404_data *afe = iio_priv(indio_dev); + int ret; + +@@ -449,7 +449,7 @@ static int __maybe_unused afe4404_suspen + + static int __maybe_unused afe4404_resume(struct device *dev) + { +- struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct afe4404_data *afe = iio_priv(indio_dev); + int ret; + diff --git a/queue-4.9/iio-health-max30100-fixed-parenthesis-around-fifo-count-check.patch b/queue-4.9/iio-health-max30100-fixed-parenthesis-around-fifo-count-check.patch new file mode 100644 index 00000000000..5c790958983 --- /dev/null +++ b/queue-4.9/iio-health-max30100-fixed-parenthesis-around-fifo-count-check.patch @@ -0,0 +1,37 @@ +From 828f84ee8f84710ea1818b3565add268bcb824c8 Mon Sep 17 00:00:00 2001 +From: Matt Ranostay +Date: Mon, 16 Jan 2017 18:04:18 -0800 +Subject: iio: health: max30100: fixed parenthesis around FIFO count check + +From: Matt Ranostay + +commit 828f84ee8f84710ea1818b3565add268bcb824c8 upstream. + +FIFO was being read every sample after the "almost full" state was +reached. This was due to an incorrect placement of the parenthesis +in the while condition check. + +Note - the fixes tag is not actually correct, but the fix in this patch +would also be needed for it to function correctly so we'll go with that +one. Backports should pick up both. + +Signed-off-by: Matt Ranostay +Fixes: b74fccad7 ("iio: health: max30100: correct FIFO check condition") +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/health/max30100.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iio/health/max30100.c ++++ b/drivers/iio/health/max30100.c +@@ -238,7 +238,7 @@ static irqreturn_t max30100_interrupt_ha + + mutex_lock(&data->lock); + +- while (cnt || (cnt = max30100_fifo_count(data) > 0)) { ++ while (cnt || (cnt = max30100_fifo_count(data)) > 0) { + ret = max30100_read_measurement(data); + if (ret) + break; diff --git a/queue-4.9/irqdomain-avoid-activating-interrupts-more-than-once.patch b/queue-4.9/irqdomain-avoid-activating-interrupts-more-than-once.patch new file mode 100644 index 00000000000..d9d9a8922bd --- /dev/null +++ b/queue-4.9/irqdomain-avoid-activating-interrupts-more-than-once.patch @@ -0,0 +1,144 @@ +From 08d85f3ea99f1eeafc4e8507936190e86a16ee8c Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Tue, 17 Jan 2017 16:00:48 +0000 +Subject: irqdomain: Avoid activating interrupts more than once + +From: Marc Zyngier + +commit 08d85f3ea99f1eeafc4e8507936190e86a16ee8c upstream. + +Since commit f3b0946d629c ("genirq/msi: Make sure PCI MSIs are +activated early"), we can end-up activating a PCI/MSI twice (once +at allocation time, and once at startup time). + +This is normally of no consequences, except that there is some +HW out there that may misbehave if activate is used more than once +(the GICv3 ITS, for example, uses the activate callback +to issue the MAPVI command, and the architecture spec says that +"If there is an existing mapping for the EventID-DeviceID +combination, behavior is UNPREDICTABLE"). + +While this could be worked around in each individual driver, it may +make more sense to tackle the issue at the core level. In order to +avoid getting in that situation, let's have a per-interrupt flag +to remember if we have already activated that interrupt or not. + +Fixes: f3b0946d629c ("genirq/msi: Make sure PCI MSIs are activated early") +Reported-and-tested-by: Andre Przywara +Signed-off-by: Marc Zyngier +Link: http://lkml.kernel.org/r/1484668848-24361-1-git-send-email-marc.zyngier@arm.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/irq.h | 17 +++++++++++++++++ + kernel/irq/irqdomain.c | 44 ++++++++++++++++++++++++++++++-------------- + 2 files changed, 47 insertions(+), 14 deletions(-) + +--- a/include/linux/irq.h ++++ b/include/linux/irq.h +@@ -184,6 +184,7 @@ struct irq_data { + * + * IRQD_TRIGGER_MASK - Mask for the trigger type bits + * IRQD_SETAFFINITY_PENDING - Affinity setting is pending ++ * IRQD_ACTIVATED - Interrupt has already been activated + * IRQD_NO_BALANCING - Balancing disabled for this IRQ + * IRQD_PER_CPU - Interrupt is per cpu + * IRQD_AFFINITY_SET - Interrupt affinity was set +@@ -202,6 +203,7 @@ struct irq_data { + enum { + IRQD_TRIGGER_MASK = 0xf, + IRQD_SETAFFINITY_PENDING = (1 << 8), ++ IRQD_ACTIVATED = (1 << 9), + IRQD_NO_BALANCING = (1 << 10), + IRQD_PER_CPU = (1 << 11), + IRQD_AFFINITY_SET = (1 << 12), +@@ -312,6 +314,21 @@ static inline bool irqd_affinity_is_mana + return __irqd_to_state(d) & IRQD_AFFINITY_MANAGED; + } + ++static inline bool irqd_is_activated(struct irq_data *d) ++{ ++ return __irqd_to_state(d) & IRQD_ACTIVATED; ++} ++ ++static inline void irqd_set_activated(struct irq_data *d) ++{ ++ __irqd_to_state(d) |= IRQD_ACTIVATED; ++} ++ ++static inline void irqd_clr_activated(struct irq_data *d) ++{ ++ __irqd_to_state(d) &= ~IRQD_ACTIVATED; ++} ++ + #undef __irqd_to_state + + static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -1346,6 +1346,30 @@ void irq_domain_free_irqs_parent(struct + } + EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent); + ++static void __irq_domain_activate_irq(struct irq_data *irq_data) ++{ ++ if (irq_data && irq_data->domain) { ++ struct irq_domain *domain = irq_data->domain; ++ ++ if (irq_data->parent_data) ++ __irq_domain_activate_irq(irq_data->parent_data); ++ if (domain->ops->activate) ++ domain->ops->activate(domain, irq_data); ++ } ++} ++ ++static void __irq_domain_deactivate_irq(struct irq_data *irq_data) ++{ ++ if (irq_data && irq_data->domain) { ++ struct irq_domain *domain = irq_data->domain; ++ ++ if (domain->ops->deactivate) ++ domain->ops->deactivate(domain, irq_data); ++ if (irq_data->parent_data) ++ __irq_domain_deactivate_irq(irq_data->parent_data); ++ } ++} ++ + /** + * irq_domain_activate_irq - Call domain_ops->activate recursively to activate + * interrupt +@@ -1356,13 +1380,9 @@ EXPORT_SYMBOL_GPL(irq_domain_free_irqs_p + */ + void irq_domain_activate_irq(struct irq_data *irq_data) + { +- if (irq_data && irq_data->domain) { +- struct irq_domain *domain = irq_data->domain; +- +- if (irq_data->parent_data) +- irq_domain_activate_irq(irq_data->parent_data); +- if (domain->ops->activate) +- domain->ops->activate(domain, irq_data); ++ if (!irqd_is_activated(irq_data)) { ++ __irq_domain_activate_irq(irq_data); ++ irqd_set_activated(irq_data); + } + } + +@@ -1376,13 +1396,9 @@ void irq_domain_activate_irq(struct irq_ + */ + void irq_domain_deactivate_irq(struct irq_data *irq_data) + { +- if (irq_data && irq_data->domain) { +- struct irq_domain *domain = irq_data->domain; +- +- if (domain->ops->deactivate) +- domain->ops->deactivate(domain, irq_data); +- if (irq_data->parent_data) +- irq_domain_deactivate_irq(irq_data->parent_data); ++ if (irqd_is_activated(irq_data)) { ++ __irq_domain_deactivate_irq(irq_data); ++ irqd_clr_activated(irq_data); + } + } + diff --git a/queue-4.9/series b/queue-4.9/series index f2f4fde8815..8867256584b 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -50,3 +50,15 @@ kvm-x86-do-not-save-guest-unsupported-xsave-state.patch usb-serial-qcserial-add-dell-dw5570-qdl.patch usb-serial-pl2303-add-aten-device-id.patch usb-add-quirk-for-worlde-easykey.25-midi-keyboard.patch +usb-musb-fix-host-mode-error-71-regression.patch +usb-gadget-f_fs-assorted-buffer-overflow-checks.patch +usb-serial-option-add-device-id-for-hp-lt2523-novatel-e371.patch +staging-greybus-timesync-validate-platform-state-callback.patch +iio-adc-palmas_gpadc-retrieve-a-valid-iio_dev-in-suspend-resume.patch +iio-health-afe4404-retrieve-a-valid-iio_dev-in-suspend-resume.patch +iio-health-afe4403-retrieve-a-valid-iio_dev-in-suspend-resume.patch +iio-dht11-use-usleep_range-instead-of-msleep-for-start-signal.patch +iio-health-max30100-fixed-parenthesis-around-fifo-count-check.patch +irqdomain-avoid-activating-interrupts-more-than-once.patch +x86-irq-make-irq-activate-operations-symmetric.patch +firmware-fix-null-pointer-dereference-in-__fw_load_abort.patch diff --git a/queue-4.9/staging-greybus-timesync-validate-platform-state-callback.patch b/queue-4.9/staging-greybus-timesync-validate-platform-state-callback.patch new file mode 100644 index 00000000000..ba2e3ea43a6 --- /dev/null +++ b/queue-4.9/staging-greybus-timesync-validate-platform-state-callback.patch @@ -0,0 +1,68 @@ +From b17c1bba9cec1727451b906d9a0c209774624873 Mon Sep 17 00:00:00 2001 +From: Rui Miguel Silva +Date: Mon, 23 Jan 2017 16:32:57 +0000 +Subject: staging: greybus: timesync: validate platform state callback + +From: Rui Miguel Silva + +commit b17c1bba9cec1727451b906d9a0c209774624873 upstream. + +When tearingdown timesync, and not in arche platform, the state platform +callback is not initialized. That will trigger the following NULL +dereferencing. +CallTrace: + + ? gb_timesync_platform_unlock_bus+0x11/0x20 [greybus] + gb_timesync_teardown+0x85/0xc0 [greybus] + gb_timesync_svc_remove+0xab/0x190 [greybus] + gb_svc_del+0x29/0x110 [greybus] + gb_hd_del+0x14/0x20 [greybus] + ap_disconnect+0x24/0x60 [gb_es2] + usb_unbind_interface+0x7a/0x2c0 + __device_release_driver+0x96/0x150 + device_release_driver+0x1e/0x30 + bus_remove_device+0xe7/0x130 + device_del+0x116/0x230 + usb_disable_device+0x97/0x1f0 + usb_disconnect+0x80/0x260 + hub_event+0x5ca/0x10e0 + process_one_work+0x126/0x3b0 + worker_thread+0x55/0x4c0 + ? process_one_work+0x3b0/0x3b0 + kthread+0xc4/0xe0 + ? kthread_park+0xb0/0xb0 + ret_from_fork+0x22/0x30 + +So, fix that by adding checks before use the callback. + +Fixes: 970dc85bd95d ("greybus: timesync: Add timesync core driver") +Signed-off-by: Rui Miguel Silva +Reviewed-by: Viresh Kumar +Reviewed-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/greybus/timesync_platform.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/staging/greybus/timesync_platform.c ++++ b/drivers/staging/greybus/timesync_platform.c +@@ -45,12 +45,18 @@ u32 gb_timesync_platform_get_clock_rate( + + int gb_timesync_platform_lock_bus(struct gb_timesync_svc *pdata) + { ++ if (!arche_platform_change_state_cb) ++ return 0; ++ + return arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_TIME_SYNC, + pdata); + } + + void gb_timesync_platform_unlock_bus(void) + { ++ if (!arche_platform_change_state_cb) ++ return; ++ + arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_ACTIVE, NULL); + } + diff --git a/queue-4.9/usb-gadget-f_fs-assorted-buffer-overflow-checks.patch b/queue-4.9/usb-gadget-f_fs-assorted-buffer-overflow-checks.patch new file mode 100644 index 00000000000..44f3140c2e2 --- /dev/null +++ b/queue-4.9/usb-gadget-f_fs-assorted-buffer-overflow-checks.patch @@ -0,0 +1,66 @@ +From 83e526f2a2fa4b2e82b6bd3ddbb26b70acfa8947 Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +Date: Wed, 18 Jan 2017 00:57:44 +0000 +Subject: usb: gadget: f_fs: Assorted buffer overflow checks. + +From: Vincent Pelletier + +commit 83e526f2a2fa4b2e82b6bd3ddbb26b70acfa8947 upstream. + +OS descriptor head, when flagged as provided, is accessed without +checking if it fits in provided buffer. Verify length before access. +Also, there are other places where buffer length it checked +after accessing offsets which are potentially past the end. Check +buffer length before as well to fail cleanly. + +Signed-off-by: Vincent Pelletier +Acked-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/function/f_fs.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -2269,6 +2269,8 @@ static int __ffs_data_do_os_desc(enum ff + if (len < sizeof(*d) || h->interface >= ffs->interfaces_count) + return -EINVAL; + length = le32_to_cpu(d->dwSize); ++ if (len < length) ++ return -EINVAL; + type = le32_to_cpu(d->dwPropertyDataType); + if (type < USB_EXT_PROP_UNICODE || + type > USB_EXT_PROP_UNICODE_MULTI) { +@@ -2277,6 +2279,11 @@ static int __ffs_data_do_os_desc(enum ff + return -EINVAL; + } + pnl = le16_to_cpu(d->wPropertyNameLength); ++ if (length < 14 + pnl) { ++ pr_vdebug("invalid os descriptor length: %d pnl:%d (descriptor %d)\n", ++ length, pnl, type); ++ return -EINVAL; ++ } + pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl)); + if (length != 14 + pnl + pdl) { + pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n", +@@ -2363,6 +2370,9 @@ static int __ffs_data_got_descs(struct f + } + } + if (flags & (1 << i)) { ++ if (len < 4) { ++ goto error; ++ } + os_descs_count = get_unaligned_le32(data); + data += 4; + len -= 4; +@@ -2435,7 +2445,8 @@ static int __ffs_data_got_strings(struct + + ENTER(); + +- if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC || ++ if (unlikely(len < 16 || ++ get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC || + get_unaligned_le32(data + 4) != len)) + goto error; + str_count = get_unaligned_le32(data + 8); diff --git a/queue-4.9/usb-musb-fix-host-mode-error-71-regression.patch b/queue-4.9/usb-musb-fix-host-mode-error-71-regression.patch new file mode 100644 index 00000000000..8b22b6105e8 --- /dev/null +++ b/queue-4.9/usb-musb-fix-host-mode-error-71-regression.patch @@ -0,0 +1,97 @@ +From 407788b51db6f6aab499d02420082f436abf3238 Mon Sep 17 00:00:00 2001 +From: Tony Lindgren +Date: Tue, 24 Jan 2017 09:18:57 -0600 +Subject: usb: musb: Fix host mode error -71 regression + +From: Tony Lindgren + +commit 407788b51db6f6aab499d02420082f436abf3238 upstream. + +Commit 467d5c980709 ("usb: musb: Implement session bit based runtime PM for +musb-core") started implementing musb generic runtime PM support by +introducing devctl register session bit based state control. + +This caused a regression where if a USB mass storage device is connected +to a USB hub, we can get: + +usb 1-1: reset high-speed USB device number 2 using musb-hdrc +usb 1-1: device descriptor read/64, error -71 +usb 1-1.1: new high-speed USB device number 4 using musb-hdrc + +This is because before the USB storage device is connected, musb is +in OTG_STATE_A_SUSPEND. And we currently only set need_finish_resume +in musb_stage0_irq() and the related code calling finish_resume_work +in musb_resume() and musb_runtime_resume() never gets called. + +To fix the issue, we can call schedule_delayed_work() directly in +musb_stage0_irq() to have finish_resume_work run. + +And we should no longer never get interrupts when when suspended. +We have changed musb to no longer need pm_runtime_irqsafe(). +The need_finish_resume flag was added in commit 9298b4aad37e ("usb: +musb: fix device hotplug behind hub") and no longer applies as far +as I can tell. So let's just remove the earlier code that no longer +is needed. + +Fixes: 467d5c980709 ("usb: musb: Implement session bit based runtime PM for musb-core") +Reported-by: Bin Liu +Signed-off-by: Tony Lindgren +Signed-off-by: Bin Liu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/musb/musb_core.c | 15 ++------------- + drivers/usb/musb/musb_core.h | 1 - + 2 files changed, 2 insertions(+), 14 deletions(-) + +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -578,11 +578,11 @@ static irqreturn_t musb_stage0_irq(struc + | MUSB_PORT_STAT_RESUME; + musb->rh_timer = jiffies + + msecs_to_jiffies(USB_RESUME_TIMEOUT); +- musb->need_finish_resume = 1; +- + musb->xceiv->otg->state = OTG_STATE_A_HOST; + musb->is_active = 1; + musb_host_resume_root_hub(musb); ++ schedule_delayed_work(&musb->finish_resume_work, ++ msecs_to_jiffies(USB_RESUME_TIMEOUT)); + break; + case OTG_STATE_B_WAIT_ACON: + musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; +@@ -2691,11 +2691,6 @@ static int musb_resume(struct device *de + mask = MUSB_DEVCTL_BDEVICE | MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV; + if ((devctl & mask) != (musb->context.devctl & mask)) + musb->port1_status = 0; +- if (musb->need_finish_resume) { +- musb->need_finish_resume = 0; +- schedule_delayed_work(&musb->finish_resume_work, +- msecs_to_jiffies(USB_RESUME_TIMEOUT)); +- } + + /* + * The USB HUB code expects the device to be in RPM_ACTIVE once it came +@@ -2747,12 +2742,6 @@ static int musb_runtime_resume(struct de + + musb_restore_context(musb); + +- if (musb->need_finish_resume) { +- musb->need_finish_resume = 0; +- schedule_delayed_work(&musb->finish_resume_work, +- msecs_to_jiffies(USB_RESUME_TIMEOUT)); +- } +- + spin_lock_irqsave(&musb->lock, flags); + error = musb_run_resume_work(musb); + if (error) +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -410,7 +410,6 @@ struct musb { + + /* is_suspended means USB B_PERIPHERAL suspend */ + unsigned is_suspended:1; +- unsigned need_finish_resume :1; + + /* may_wakeup means remote wakeup is enabled */ + unsigned may_wakeup:1; diff --git a/queue-4.9/usb-serial-option-add-device-id-for-hp-lt2523-novatel-e371.patch b/queue-4.9/usb-serial-option-add-device-id-for-hp-lt2523-novatel-e371.patch new file mode 100644 index 00000000000..c54ac67fd42 --- /dev/null +++ b/queue-4.9/usb-serial-option-add-device-id-for-hp-lt2523-novatel-e371.patch @@ -0,0 +1,32 @@ +From 5d03a2fd2292e71936c4235885c35ccc3c94695b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Tue, 24 Jan 2017 10:31:18 +0100 +Subject: USB: serial: option: add device ID for HP lt2523 (Novatel E371) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bjørn Mork + +commit 5d03a2fd2292e71936c4235885c35ccc3c94695b upstream. + +Yet another laptop vendor rebranded Novatel E371. + +Signed-off-by: Bjørn Mork +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -2007,6 +2007,7 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_6802, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD300, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, 0xff, 0xff, 0xff) }, /* HP lt2523 (Novatel E371) */ + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/queue-4.9/x86-irq-make-irq-activate-operations-symmetric.patch b/queue-4.9/x86-irq-make-irq-activate-operations-symmetric.patch new file mode 100644 index 00000000000..c7af0219e50 --- /dev/null +++ b/queue-4.9/x86-irq-make-irq-activate-operations-symmetric.patch @@ -0,0 +1,58 @@ +From aaaec6fc755447a1d056765b11b24d8ff2b81366 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Tue, 31 Jan 2017 19:03:21 +0100 +Subject: x86/irq: Make irq activate operations symmetric + +From: Thomas Gleixner + +commit aaaec6fc755447a1d056765b11b24d8ff2b81366 upstream. + +The recent commit which prevents double activation of interrupts unearthed +interesting code in x86. The code (ab)uses irq_domain_activate_irq() to +reconfigure an already activated interrupt. That trips over the prevention +code now. + +Fix it by deactivating the interrupt before activating the new configuration. + +Fixes: 08d85f3ea99f1 "irqdomain: Avoid activating interrupts more than once" +Reported-and-tested-by: Mike Galbraith +Reported-and-tested-by: Borislav Petkov +Signed-off-by: Thomas Gleixner +Cc: Andrey Ryabinin +Cc: Marc Zyngier +Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1701311901580.3457@nanos +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/apic/io_apic.c | 2 ++ + arch/x86/kernel/hpet.c | 1 + + 2 files changed, 3 insertions(+) + +--- a/arch/x86/kernel/apic/io_apic.c ++++ b/arch/x86/kernel/apic/io_apic.c +@@ -2118,6 +2118,7 @@ static inline void __init check_timer(vo + if (idx != -1 && irq_trigger(idx)) + unmask_ioapic_irq(irq_get_chip_data(0)); + } ++ irq_domain_deactivate_irq(irq_data); + irq_domain_activate_irq(irq_data); + if (timer_irq_works()) { + if (disable_timer_pin_1 > 0) +@@ -2139,6 +2140,7 @@ static inline void __init check_timer(vo + * legacy devices should be connected to IO APIC #0 + */ + replace_pin_at_irq_node(data, node, apic1, pin1, apic2, pin2); ++ irq_domain_deactivate_irq(irq_data); + irq_domain_activate_irq(irq_data); + legacy_pic->unmask(0); + if (timer_irq_works()) { +--- a/arch/x86/kernel/hpet.c ++++ b/arch/x86/kernel/hpet.c +@@ -352,6 +352,7 @@ static int hpet_resume(struct clock_even + } else { + struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt); + ++ irq_domain_deactivate_irq(irq_get_irq_data(hdev->irq)); + irq_domain_activate_irq(irq_get_irq_data(hdev->irq)); + disable_irq(hdev->irq); + irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));