]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 5 Feb 2017 10:26:52 +0000 (11:26 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 5 Feb 2017 10:26:52 +0000 (11:26 +0100)
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

13 files changed:
queue-4.9/firmware-fix-null-pointer-dereference-in-__fw_load_abort.patch [new file with mode: 0644]
queue-4.9/iio-adc-palmas_gpadc-retrieve-a-valid-iio_dev-in-suspend-resume.patch [new file with mode: 0644]
queue-4.9/iio-dht11-use-usleep_range-instead-of-msleep-for-start-signal.patch [new file with mode: 0644]
queue-4.9/iio-health-afe4403-retrieve-a-valid-iio_dev-in-suspend-resume.patch [new file with mode: 0644]
queue-4.9/iio-health-afe4404-retrieve-a-valid-iio_dev-in-suspend-resume.patch [new file with mode: 0644]
queue-4.9/iio-health-max30100-fixed-parenthesis-around-fifo-count-check.patch [new file with mode: 0644]
queue-4.9/irqdomain-avoid-activating-interrupts-more-than-once.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/staging-greybus-timesync-validate-platform-state-callback.patch [new file with mode: 0644]
queue-4.9/usb-gadget-f_fs-assorted-buffer-overflow-checks.patch [new file with mode: 0644]
queue-4.9/usb-musb-fix-host-mode-error-71-regression.patch [new file with mode: 0644]
queue-4.9/usb-serial-option-add-device-id-for-hp-lt2523-novatel-e371.patch [new file with mode: 0644]
queue-4.9/x86-irq-make-irq-activate-operations-symmetric.patch [new file with mode: 0644]

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 (file)
index 0000000..2d6bc4b
--- /dev/null
@@ -0,0 +1,152 @@
+From 191e885a2e130e639bb0c8ee350d7047294f2ce6 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Wed, 25 Jan 2017 10:31:52 -0800
+Subject: firmware: fix NULL pointer dereference in __fw_load_abort()
+
+From: Luis R. Rodriguez <mcgrof@kernel.org>
+
+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 <jakub.kicinski@netronome.com>
+Reported-and-Tested-by: Patrick Bruenn <p.bruenn@beckhoff.com>
+Reported-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..80b3256
--- /dev/null
@@ -0,0 +1,41 @@
+From d1aaf20ee655888c227d5137b7a63551f8d15416 Mon Sep 17 00:00:00 2001
+From: Alison Schofield <amsfield22@gmail.com>
+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 <amsfield22@gmail.com>
+
+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 <amsfield22@gmail.com>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..21229fe
--- /dev/null
@@ -0,0 +1,80 @@
+From 5c113b5e0082e90d2e1c7b12e96a7b8cf0623e27 Mon Sep 17 00:00:00 2001
+From: John Brooks <john@fastquake.com>
+Date: Wed, 18 Jan 2017 21:50:39 +0000
+Subject: iio: dht11: Use usleep_range instead of msleep for start signal
+
+From: John Brooks <john@fastquake.com>
+
+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 <john@fastquake.com>
+Reviewed-by: Harald Geyer <harald@ccbib.org>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..35e2f57
--- /dev/null
@@ -0,0 +1,42 @@
+From a5badd1e97e6caeca78ad74191f12fc923c403a8 Mon Sep 17 00:00:00 2001
+From: Alison Schofield <amsfield22@gmail.com>
+Date: Sat, 14 Jan 2017 19:51:52 -0800
+Subject: iio: health: afe4403: retrieve a valid iio_dev in suspend/resume
+
+From: Alison Schofield <amsfield22@gmail.com>
+
+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 <amsfield22@gmail.com>
+Acked-by: Andrew F. Davis <afd@ti.com>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..78f6a6a
--- /dev/null
@@ -0,0 +1,42 @@
+From 802ecfc113df1e15af1d028427cbbe785ae9cc4a Mon Sep 17 00:00:00 2001
+From: Alison Schofield <amsfield22@gmail.com>
+Date: Sat, 14 Jan 2017 19:52:50 -0800
+Subject: iio: health: afe4404: retrieve a valid iio_dev in suspend/resume
+
+From: Alison Schofield <amsfield22@gmail.com>
+
+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 <amsfield22@gmail.com>
+Acked-by: Andrew F. Davis <afd@ti.com>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..5c79095
--- /dev/null
@@ -0,0 +1,37 @@
+From 828f84ee8f84710ea1818b3565add268bcb824c8 Mon Sep 17 00:00:00 2001
+From: Matt Ranostay <matt@ranostay.consulting>
+Date: Mon, 16 Jan 2017 18:04:18 -0800
+Subject: iio: health: max30100: fixed parenthesis around FIFO count check
+
+From: Matt Ranostay <matt@ranostay.consulting>
+
+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 <matt@ranostay.consulting>
+Fixes: b74fccad7 ("iio: health: max30100: correct FIFO check condition")
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..d9d9a89
--- /dev/null
@@ -0,0 +1,144 @@
+From 08d85f3ea99f1eeafc4e8507936190e86a16ee8c Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier@arm.com>
+Date: Tue, 17 Jan 2017 16:00:48 +0000
+Subject: irqdomain: Avoid activating interrupts more than once
+
+From: Marc Zyngier <marc.zyngier@arm.com>
+
+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 <andre.przywara@arm.com>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+Link: http://lkml.kernel.org/r/1484668848-24361-1-git-send-email-marc.zyngier@arm.com
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
+       }
+ }
index f2f4fde88153389753c2a2f28ecca6ce6b83914c..8867256584b1210b4be2ed80f880873b4e6742d7 100644 (file)
@@ -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 (file)
index 0000000..ba2e3ea
--- /dev/null
@@ -0,0 +1,68 @@
+From b17c1bba9cec1727451b906d9a0c209774624873 Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rmfrfs@gmail.com>
+Date: Mon, 23 Jan 2017 16:32:57 +0000
+Subject: staging: greybus: timesync: validate platform state callback
+
+From: Rui Miguel Silva <rmfrfs@gmail.com>
+
+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 <rmfrfs@gmail.com>
+Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
+Reviewed-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..44f3140
--- /dev/null
@@ -0,0 +1,66 @@
+From 83e526f2a2fa4b2e82b6bd3ddbb26b70acfa8947 Mon Sep 17 00:00:00 2001
+From: Vincent Pelletier <plr.vincent@gmail.com>
+Date: Wed, 18 Jan 2017 00:57:44 +0000
+Subject: usb: gadget: f_fs: Assorted buffer overflow checks.
+
+From: Vincent Pelletier <plr.vincent@gmail.com>
+
+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 <plr.vincent@gmail.com>
+Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..8b22b61
--- /dev/null
@@ -0,0 +1,97 @@
+From 407788b51db6f6aab499d02420082f436abf3238 Mon Sep 17 00:00:00 2001
+From: Tony Lindgren <tony@atomide.com>
+Date: Tue, 24 Jan 2017 09:18:57 -0600
+Subject: usb: musb: Fix host mode error -71 regression
+
+From: Tony Lindgren <tony@atomide.com>
+
+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 <b-liu@ti.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Bin Liu <b-liu@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..c54ac67
--- /dev/null
@@ -0,0 +1,32 @@
+From 5d03a2fd2292e71936c4235885c35ccc3c94695b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+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 <bjorn@mork.no>
+
+commit 5d03a2fd2292e71936c4235885c35ccc3c94695b upstream.
+
+Yet another laptop vendor rebranded Novatel E371.
+
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..c7af021
--- /dev/null
@@ -0,0 +1,58 @@
+From aaaec6fc755447a1d056765b11b24d8ff2b81366 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 31 Jan 2017 19:03:21 +0100
+Subject: x86/irq: Make irq activate operations symmetric
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+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 <efault@gmx.de>
+Reported-and-tested-by: Borislav Petkov <bp@alien8.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
+Cc: Marc Zyngier <marc.zyngier@arm.com>
+Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1701311901580.3457@nanos
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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));