--- /dev/null
+From 7235fe0ab22d32e7800a3651c63974be4f19a4cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 May 2018 12:33:32 +0200
+Subject: ALSA: usb-audio: Clean up mixer element list traverse
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 8c558076c740e8009a96c6fdc3d4245dde62be77 ]
+
+Introduce a new macro for iterating over mixer element list for
+avoiding the open codes in many places. Also the open-coded
+container_of() and the forced cast to struct usb_mixer_elem_info are
+replaced with another simple macro, too.
+
+No functional changes but just readability improvement.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer.c | 20 +++++++++-----------
+ sound/usb/mixer.h | 6 ++++++
+ sound/usb/mixer_quirks.c | 2 +-
+ sound/usb/mixer_scarlett.c | 6 ++----
+ 4 files changed, 18 insertions(+), 16 deletions(-)
+
+diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
+index 33deb5ec8b7a1..1a8d706491e65 100644
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -2403,9 +2403,9 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
+ {
+ struct usb_mixer_elem_list *list;
+
+- for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {
++ for_each_mixer_elem(list, mixer, unitid) {
+ struct usb_mixer_elem_info *info =
+- (struct usb_mixer_elem_info *)list;
++ mixer_elem_list_to_info(list);
+ /* invalidate cache, so the value is read from the device */
+ info->cached = 0;
+ snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+@@ -2416,7 +2416,7 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
+ static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
+ struct usb_mixer_elem_list *list)
+ {
+- struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
++ struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
+ static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",
+ "S8", "U8", "S16", "U16"};
+ snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
+@@ -2442,8 +2442,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
+ mixer->ignore_ctl_error);
+ snd_iprintf(buffer, "Card: %s\n", chip->card->longname);
+ for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {
+- for (list = mixer->id_elems[unitid]; list;
+- list = list->next_id_elem) {
++ for_each_mixer_elem(list, mixer, unitid) {
+ snd_iprintf(buffer, " Unit: %i\n", list->id);
+ if (list->kctl)
+ snd_iprintf(buffer,
+@@ -2473,19 +2472,19 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
+ return;
+ }
+
+- for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem)
++ for_each_mixer_elem(list, mixer, unitid)
+ count++;
+
+ if (count == 0)
+ return;
+
+- for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {
++ for_each_mixer_elem(list, mixer, unitid) {
+ struct usb_mixer_elem_info *info;
+
+ if (!list->kctl)
+ continue;
+
+- info = (struct usb_mixer_elem_info *)list;
++ info = mixer_elem_list_to_info(list);
+ if (count > 1 && info->control != control)
+ continue;
+
+@@ -2705,7 +2704,7 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer)
+
+ static int restore_mixer_value(struct usb_mixer_elem_list *list)
+ {
+- struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
++ struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
+ int c, err, idx;
+
+ if (cval->cmask) {
+@@ -2741,8 +2740,7 @@ int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
+ if (reset_resume) {
+ /* restore cached mixer values */
+ for (id = 0; id < MAX_ID_ELEMS; id++) {
+- for (list = mixer->id_elems[id]; list;
+- list = list->next_id_elem) {
++ for_each_mixer_elem(list, mixer, id) {
+ if (list->resume) {
+ err = list->resume(list);
+ if (err < 0)
+diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
+index ba27f7ade670e..e02653465e292 100644
+--- a/sound/usb/mixer.h
++++ b/sound/usb/mixer.h
+@@ -53,6 +53,12 @@ struct usb_mixer_elem_list {
+ usb_mixer_elem_resume_func_t resume;
+ };
+
++/* iterate over mixer element list of the given unit id */
++#define for_each_mixer_elem(list, mixer, id) \
++ for ((list) = (mixer)->id_elems[id]; (list); (list) = (list)->next_id_elem)
++#define mixer_elem_list_to_info(list) \
++ container_of(list, struct usb_mixer_elem_info, head)
++
+ struct usb_mixer_elem_info {
+ struct usb_mixer_elem_list head;
+ unsigned int control; /* CS or ICN (high byte) */
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index b9ea4a42aee4e..ead0456a747c2 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -1171,7 +1171,7 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
+ int unitid = 12; /* SamleRate ExtensionUnit ID */
+
+ list_for_each_entry(mixer, &chip->mixer_list, list) {
+- cval = (struct usb_mixer_elem_info *)mixer->id_elems[unitid];
++ cval = mixer_elem_list_to_info(mixer->id_elems[unitid]);
+ if (cval) {
+ snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
+ cval->control << 8,
+diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
+index c33e2378089d5..4aeb9488a0c99 100644
+--- a/sound/usb/mixer_scarlett.c
++++ b/sound/usb/mixer_scarlett.c
+@@ -287,8 +287,7 @@ static int scarlett_ctl_switch_put(struct snd_kcontrol *kctl,
+
+ static int scarlett_ctl_resume(struct usb_mixer_elem_list *list)
+ {
+- struct usb_mixer_elem_info *elem =
+- container_of(list, struct usb_mixer_elem_info, head);
++ struct usb_mixer_elem_info *elem = mixer_elem_list_to_info(list);
+ int i;
+
+ for (i = 0; i < elem->channels; i++)
+@@ -447,8 +446,7 @@ static int scarlett_ctl_enum_put(struct snd_kcontrol *kctl,
+
+ static int scarlett_ctl_enum_resume(struct usb_mixer_elem_list *list)
+ {
+- struct usb_mixer_elem_info *elem =
+- container_of(list, struct usb_mixer_elem_info, head);
++ struct usb_mixer_elem_info *elem = mixer_elem_list_to_info(list);
+
+ if (elem->cached)
+ snd_usb_set_cur_mix_value(elem, 0, 0, *elem->cache_val);
+--
+2.25.1
+
--- /dev/null
+From 399b8d1ccab2d3084f198ac8873381a5e8ac32e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2020 14:23:40 +0200
+Subject: ALSA: usb-audio: Fix OOB access of mixer element list
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 220345e98f1cdc768eeb6e3364a0fa7ab9647fe7 ]
+
+The USB-audio mixer code holds a linked list of usb_mixer_elem_list,
+and several operations are performed for each mixer element. A few of
+them (snd_usb_mixer_notify_id() and snd_usb_mixer_interrupt_v2())
+assume each mixer element being a usb_mixer_elem_info object that is a
+subclass of usb_mixer_elem_list, cast via container_of() and access it
+members. This may result in an out-of-bound access when a
+non-standard list element has been added, as spotted by syzkaller
+recently.
+
+This patch adds a new field, is_std_info, in usb_mixer_elem_list to
+indicate that the element is the usb_mixer_elem_info type or not, and
+skip the access to such an element if needed.
+
+Reported-by: syzbot+fb14314433463ad51625@syzkaller.appspotmail.com
+Reported-by: syzbot+2405ca3401e943c538b5@syzkaller.appspotmail.com
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200624122340.9615-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer.c | 15 +++++++++++----
+ sound/usb/mixer.h | 9 +++++++--
+ sound/usb/mixer_quirks.c | 3 ++-
+ 3 files changed, 20 insertions(+), 7 deletions(-)
+
+diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
+index 1a8d706491e65..b29a3546ab6af 100644
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -591,8 +591,9 @@ static int check_matrix_bitmap(unsigned char *bmap,
+ * if failed, give up and free the control instance.
+ */
+
+-int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
+- struct snd_kcontrol *kctl)
++int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list,
++ struct snd_kcontrol *kctl,
++ bool is_std_info)
+ {
+ struct usb_mixer_interface *mixer = list->mixer;
+ int err;
+@@ -605,6 +606,7 @@ int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
+ return err;
+ }
+ list->kctl = kctl;
++ list->is_std_info = is_std_info;
+ list->next_id_elem = mixer->id_elems[list->id];
+ mixer->id_elems[list->id] = list;
+ return 0;
+@@ -2404,8 +2406,11 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
+ struct usb_mixer_elem_list *list;
+
+ for_each_mixer_elem(list, mixer, unitid) {
+- struct usb_mixer_elem_info *info =
+- mixer_elem_list_to_info(list);
++ struct usb_mixer_elem_info *info;
++
++ if (!list->is_std_info)
++ continue;
++ info = mixer_elem_list_to_info(list);
+ /* invalidate cache, so the value is read from the device */
+ info->cached = 0;
+ snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+@@ -2483,6 +2488,8 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
+
+ if (!list->kctl)
+ continue;
++ if (!list->is_std_info)
++ continue;
+
+ info = mixer_elem_list_to_info(list);
+ if (count > 1 && info->control != control)
+diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
+index e02653465e292..7c824a44589b0 100644
+--- a/sound/usb/mixer.h
++++ b/sound/usb/mixer.h
+@@ -49,6 +49,7 @@ struct usb_mixer_elem_list {
+ struct usb_mixer_elem_list *next_id_elem; /* list of controls with same id */
+ struct snd_kcontrol *kctl;
+ unsigned int id;
++ bool is_std_info;
+ usb_mixer_elem_dump_func_t dump;
+ usb_mixer_elem_resume_func_t resume;
+ };
+@@ -86,8 +87,12 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
+ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
+ int request, int validx, int value_set);
+
+-int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
+- struct snd_kcontrol *kctl);
++int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list,
++ struct snd_kcontrol *kctl,
++ bool is_std_info);
++
++#define snd_usb_mixer_add_control(list, kctl) \
++ snd_usb_mixer_add_list(list, kctl, true)
+
+ void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
+ struct usb_mixer_interface *mixer,
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index ead0456a747c2..5604cce30a582 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -169,7 +169,8 @@ static int add_single_ctl_with_resume(struct usb_mixer_interface *mixer,
+ return -ENOMEM;
+ }
+ kctl->private_free = snd_usb_mixer_elem_free;
+- return snd_usb_mixer_add_control(list, kctl);
++ /* don't use snd_usb_mixer_add_control() here, this is a special list element */
++ return snd_usb_mixer_add_list(list, kctl, false);
+ }
+
+ /*
+--
+2.25.1
+
--- /dev/null
+From 84a08162da3de7ac2f682a77bee58a8b9e4bf036 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Nov 2017 17:35:17 +0100
+Subject: ALSA: usb-audio: uac1: Invalidate ctl on interrupt
+
+From: Julian Scheel <julian@jusst.de>
+
+[ Upstream commit b2500b584cfd228d67e1e43daf27c8af865b499e ]
+
+When an interrupt occurs, the value of at least one of the belonging
+controls should have changed. To make sure they get re-read from device
+on the next read, invalidate the cache. This was correctly implemented
+for uac2 already, but missing for uac1.
+
+Signed-off-by: Julian Scheel <julian@jusst.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
+index dbbc5609b453b..33deb5ec8b7a1 100644
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -2403,9 +2403,14 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
+ {
+ struct usb_mixer_elem_list *list;
+
+- for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem)
++ for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {
++ struct usb_mixer_elem_info *info =
++ (struct usb_mixer_elem_info *)list;
++ /* invalidate cache, so the value is read from the device */
++ info->cached = 0;
+ snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &list->kctl->id);
++ }
+ }
+
+ static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
+--
+2.25.1
+
--- /dev/null
+From 86dfa1cf0b1bae628c603bdb0bb0985cfb56a2c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jun 2020 07:31:53 -0400
+Subject: cifs/smb3: Fix data inconsistent when punch hole
+
+From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+
+[ Upstream commit acc91c2d8de4ef46ed751c5f9df99ed9a109b100 ]
+
+When punch hole success, we also can read old data from file:
+ # strace -e trace=pread64,fallocate xfs_io -f -c "pread 20 40" \
+ -c "fpunch 20 40" -c"pread 20 40" file
+ pread64(3, " version 5.8.0-rc1+"..., 40, 20) = 40
+ fallocate(3, FALLOC_FL_KEEP_SIZE|FALLOC_FL_PUNCH_HOLE, 20, 40) = 0
+ pread64(3, " version 5.8.0-rc1+"..., 40, 20) = 40
+
+CIFS implements the fallocate(FALLOCATE_FL_PUNCH_HOLE) with send SMB
+ioctl(FSCTL_SET_ZERO_DATA) to server. It just set the range of the
+remote file to zero, but local page caches not updated, then the
+local page caches inconsistent with server.
+
+Also can be found by xfstests generic/316.
+
+So, we need to remove the page caches before send the SMB
+ioctl(FSCTL_SET_ZERO_DATA) to server.
+
+Fixes: 31742c5a33176 ("enable fallocate punch hole ("fallocate -p") for SMB3")
+Suggested-by: Pavel Shilovsky <pshilov@microsoft.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+Cc: stable@vger.kernel.org # v3.17
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/smb2ops.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
+index 951c444d83e7b..61ea429e1210b 100644
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -1824,6 +1824,12 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
+ return rc;
+ }
+
++ /*
++ * We implement the punch hole through ioctl, so we need remove the page
++ * caches first, otherwise the data may be inconsistent with the server.
++ */
++ truncate_pagecache_range(inode, offset, offset + len - 1);
++
+ cifs_dbg(FYI, "offset %lld len %lld", offset, len);
+
+ fsctl_buf.FileOffset = cpu_to_le64(offset);
+--
+2.25.1
+
--- /dev/null
+From a94c42f513bb2098c480ac5aeb7ea72cc2832a21 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jun 2020 07:31:54 -0400
+Subject: cifs/smb3: Fix data inconsistent when zero file range
+
+From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+
+[ Upstream commit 6b69040247e14b43419a520f841f2b3052833df9 ]
+
+CIFS implements the fallocate(FALLOC_FL_ZERO_RANGE) with send SMB
+ioctl(FSCTL_SET_ZERO_DATA) to server. It just set the range of the
+remote file to zero, but local page cache not update, then the data
+inconsistent with server, which leads the xfstest generic/008 failed.
+
+So we need to remove the local page caches before send SMB
+ioctl(FSCTL_SET_ZERO_DATA) to server. After next read, it will
+re-cache it.
+
+Fixes: 30175628bf7f5 ("[SMB3] Enable fallocate -z support for SMB3 mounts")
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Cc: stable@vger.kernel.org # v3.17
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/smb2ops.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
+index 61ea429e1210b..b46fdb2b8d349 100644
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -1755,6 +1755,12 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
+ inode = d_inode(cfile->dentry);
+ cifsi = CIFS_I(inode);
+
++ /*
++ * We zero the range through ioctl, so we need remove the page caches
++ * first, otherwise the data may be inconsistent with the server.
++ */
++ truncate_pagecache_range(inode, offset, offset + len - 1);
++
+ /* if file not oplocked can't be sure whether asking to extend size */
+ if (!CIFS_CACHE_READ(cifsi))
+ if (keep_size == false) {
+--
+2.25.1
+
xhci-fix-incorrect-ep_state_mask.patch
xhci-fix-enumeration-issue-when-setting-max-packet-size-for-fs-devices.patch
cdc-acm-add-disable_echo-quirk-for-microchip-smsc-chip.patch
+alsa-usb-audio-uac1-invalidate-ctl-on-interrupt.patch
+alsa-usb-audio-clean-up-mixer-element-list-traverse.patch
+alsa-usb-audio-fix-oob-access-of-mixer-element-list.patch
+xhci-poll-for-u0-after-disabling-usb2-lpm.patch
+cifs-smb3-fix-data-inconsistent-when-punch-hole.patch
+cifs-smb3-fix-data-inconsistent-when-zero-file-range.patch
--- /dev/null
+From 34ce3bf9cc3665aa79988b9c6be0589b7d310acc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jun 2020 16:59:49 +0300
+Subject: xhci: Poll for U0 after disabling USB2 LPM
+
+From: Kai-Heng Feng <kai.heng.feng@canonical.com>
+
+[ Upstream commit b3d71abd135e6919ca0b6cab463738472653ddfb ]
+
+USB2 devices with LPM enabled may interrupt the system suspend:
+[ 932.510475] usb 1-7: usb suspend, wakeup 0
+[ 932.510549] hub 1-0:1.0: hub_suspend
+[ 932.510581] usb usb1: bus suspend, wakeup 0
+[ 932.510590] xhci_hcd 0000:00:14.0: port 9 not suspended
+[ 932.510593] xhci_hcd 0000:00:14.0: port 8 not suspended
+..
+[ 932.520323] xhci_hcd 0000:00:14.0: Port change event, 1-7, id 7, portsc: 0x400e03
+..
+[ 932.591405] PM: pci_pm_suspend(): hcd_pci_suspend+0x0/0x30 returns -16
+[ 932.591414] PM: dpm_run_callback(): pci_pm_suspend+0x0/0x160 returns -16
+[ 932.591418] PM: Device 0000:00:14.0 failed to suspend async: error -16
+
+During system suspend, USB core will let HC suspends the device if it
+doesn't have remote wakeup enabled and doesn't have any children.
+However, from the log above we can see that the usb 1-7 doesn't get bus
+suspended due to not in U0. After a while the port finished U2 -> U0
+transition, interrupts the suspend process.
+
+The observation is that after disabling LPM, port doesn't transit to U0
+immediately and can linger in U2. xHCI spec 4.23.5.2 states that the
+maximum exit latency for USB2 LPM should be BESL + 10us. The BESL for
+the affected device is advertised as 400us, which is still not enough
+based on my testing result.
+
+So let's use the maximum permitted latency, 10000, to poll for U0
+status to solve the issue.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20200624135949.22611-6-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index d727cbbad44a2..cdf1c91554035 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -4226,6 +4226,9 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
+ mutex_lock(hcd->bandwidth_mutex);
+ xhci_change_max_exit_latency(xhci, udev, 0);
+ mutex_unlock(hcd->bandwidth_mutex);
++ readl_poll_timeout(port_array[port_num], pm_val,
++ (pm_val & PORT_PLS_MASK) == XDEV_U0,
++ 100, 10000);
+ return 0;
+ }
+ }
+--
+2.25.1
+