--- /dev/null
+From 5fdb55c1ac9585eb23bb2541d5819224429e103d Mon Sep 17 00:00:00 2001
+From: Todd Kjos <tkjos@google.com>
+Date: Mon, 30 Aug 2021 12:51:46 -0700
+Subject: binder: make sure fd closes complete
+
+From: Todd Kjos <tkjos@google.com>
+
+commit 5fdb55c1ac9585eb23bb2541d5819224429e103d upstream.
+
+During BC_FREE_BUFFER processing, the BINDER_TYPE_FDA object
+cleanup may close 1 or more fds. The close operations are
+completed using the task work mechanism -- which means the thread
+needs to return to userspace or the file object may never be
+dereferenced -- which can lead to hung processes.
+
+Force the binder thread back to userspace if an fd is closed during
+BC_FREE_BUFFER handling.
+
+Fixes: 80cd795630d6 ("binder: fix use-after-free due to ksys_close() during fdget()")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Martijn Coenen <maco@android.com>
+Acked-by: Christian Brauner <christian.brauner@ubuntu.com>
+Signed-off-by: Todd Kjos <tkjos@google.com>
+Link: https://lore.kernel.org/r/20210830195146.587206-1-tkjos@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/android/binder.c | 23 +++++++++++++++++------
+ 1 file changed, 17 insertions(+), 6 deletions(-)
+
+--- a/drivers/android/binder.c
++++ b/drivers/android/binder.c
+@@ -2239,6 +2239,7 @@ static void binder_deferred_fd_close(int
+ }
+
+ static void binder_transaction_buffer_release(struct binder_proc *proc,
++ struct binder_thread *thread,
+ struct binder_buffer *buffer,
+ binder_size_t failed_at,
+ bool is_failure)
+@@ -2398,8 +2399,16 @@ static void binder_transaction_buffer_re
+ &proc->alloc, &fd, buffer,
+ offset, sizeof(fd));
+ WARN_ON(err);
+- if (!err)
++ if (!err) {
+ binder_deferred_fd_close(fd);
++ /*
++ * Need to make sure the thread goes
++ * back to userspace to complete the
++ * deferred close
++ */
++ if (thread)
++ thread->looper_need_return = true;
++ }
+ }
+ } break;
+ default:
+@@ -3469,7 +3478,7 @@ err_bad_parent:
+ err_copy_data_failed:
+ binder_free_txn_fixups(t);
+ trace_binder_transaction_failed_buffer_release(t->buffer);
+- binder_transaction_buffer_release(target_proc, t->buffer,
++ binder_transaction_buffer_release(target_proc, NULL, t->buffer,
+ buffer_offset, true);
+ if (target_node)
+ binder_dec_node_tmpref(target_node);
+@@ -3546,7 +3555,9 @@ err_invalid_target_handle:
+ * Cleanup buffer and free it.
+ */
+ static void
+-binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer)
++binder_free_buf(struct binder_proc *proc,
++ struct binder_thread *thread,
++ struct binder_buffer *buffer)
+ {
+ binder_inner_proc_lock(proc);
+ if (buffer->transaction) {
+@@ -3574,7 +3585,7 @@ binder_free_buf(struct binder_proc *proc
+ binder_node_inner_unlock(buf_node);
+ }
+ trace_binder_transaction_buffer_release(buffer);
+- binder_transaction_buffer_release(proc, buffer, 0, false);
++ binder_transaction_buffer_release(proc, thread, buffer, 0, false);
+ binder_alloc_free_buf(&proc->alloc, buffer);
+ }
+
+@@ -3775,7 +3786,7 @@ static int binder_thread_write(struct bi
+ proc->pid, thread->pid, (u64)data_ptr,
+ buffer->debug_id,
+ buffer->transaction ? "active" : "finished");
+- binder_free_buf(proc, buffer);
++ binder_free_buf(proc, thread, buffer);
+ break;
+ }
+
+@@ -4463,7 +4474,7 @@ retry:
+ buffer->transaction = NULL;
+ binder_cleanup_transaction(t, "fd fixups failed",
+ BR_FAILED_REPLY);
+- binder_free_buf(proc, buffer);
++ binder_free_buf(proc, thread, buffer);
+ binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+ "%d:%d %stransaction %d fd fixups failed %d/%d, line %d\n",
+ proc->pid, thread->pid,
--- /dev/null
+From 9ed38fd4a15417cac83967360cf20b853bfab9b6 Mon Sep 17 00:00:00 2001
+From: Steve French <stfrench@microsoft.com>
+Date: Thu, 23 Sep 2021 19:18:37 -0500
+Subject: cifs: fix incorrect check for null pointer in header_assemble
+
+From: Steve French <stfrench@microsoft.com>
+
+commit 9ed38fd4a15417cac83967360cf20b853bfab9b6 upstream.
+
+Although very unlikely that the tlink pointer would be null in this case,
+get_next_mid function can in theory return null (but not an error)
+so need to check for null (not for IS_ERR, which can not be returned
+here).
+
+Address warning:
+
+ fs/smbfs_client/connect.c:2392 cifs_match_super()
+ warn: 'tlink' isn't an ERR_PTR
+
+Pointed out by Dan Carpenter via smatch code analysis tool
+
+CC: stable@vger.kernel.org
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Acked-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cifs/connect.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -3691,9 +3691,10 @@ cifs_match_super(struct super_block *sb,
+ spin_lock(&cifs_tcp_ses_lock);
+ cifs_sb = CIFS_SB(sb);
+ tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
+- if (IS_ERR(tlink)) {
++ if (tlink == NULL) {
++ /* can not match superblock if tlink were ever null */
+ spin_unlock(&cifs_tcp_ses_lock);
+- return rc;
++ return 0;
+ }
+ tcon = tlink_tcon(tlink);
+ ses = tcon->ses;
--- /dev/null
+From ce1c42b4dacfe7d71c852d8bf3371067ccba865c Mon Sep 17 00:00:00 2001
+From: Julian Sikorski <belegdol@gmail.com>
+Date: Mon, 13 Sep 2021 20:14:55 +0200
+Subject: Re-enable UAS for LaCie Rugged USB3-FW with fk quirk
+
+From: Julian Sikorski <belegdol@gmail.com>
+
+commit ce1c42b4dacfe7d71c852d8bf3371067ccba865c upstream.
+
+Further testing has revealed that LaCie Rugged USB3-FW does work with
+uas as long as US_FL_NO_REPORT_OPCODES and US_FL_NO_SAME are enabled.
+
+Link: https://lore.kernel.org/linux-usb/2167ea48-e273-a336-a4e0-10a4e883e75e@redhat.com/
+Cc: stable <stable@vger.kernel.org>
+Suggested-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Julian Sikorski <belegdol+github@gmail.com>
+Link: https://lore.kernel.org/r/20210913181454.7365-1-belegdol+github@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/storage/unusual_uas.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/storage/unusual_uas.h
++++ b/drivers/usb/storage/unusual_uas.h
+@@ -50,7 +50,7 @@ UNUSUAL_DEV(0x059f, 0x1061, 0x0000, 0x99
+ "LaCie",
+ "Rugged USB3-FW",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+- US_FL_IGNORE_UAS),
++ US_FL_NO_REPORT_OPCODES | US_FL_NO_SAME),
+
+ /*
+ * Apricorn USB3 dongle sometimes returns "USBSUSBSUSBS" in response to SCSI
--- /dev/null
+From 25a1433216489de4abc889910f744e952cb6dbae Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Mon, 6 Sep 2021 21:35:48 +0900
+Subject: mcb: fix error handling in mcb_alloc_bus()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 25a1433216489de4abc889910f744e952cb6dbae upstream.
+
+There are two bugs:
+1) If ida_simple_get() fails then this code calls put_device(carrier)
+ but we haven't yet called get_device(carrier) and probably that
+ leads to a use after free.
+2) After device_initialize() then we need to use put_device() to
+ release the bus. This will free the internal resources tied to the
+ device and call mcb_free_bus() which will free the rest.
+
+Fixes: 5d9e2ab9fea4 ("mcb: Implement bus->dev.release callback")
+Fixes: 18d288198099 ("mcb: Correctly initialize the bus's device")
+Cc: stable@vger.kernel.org
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Johannes Thumshirn <jth@kernel.org>
+Link: https://lore.kernel.org/r/32e160cf6864ce77f9d62948338e24db9fd8ead9.1630931319.git.johannes.thumshirn@wdc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mcb/mcb-core.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/mcb/mcb-core.c
++++ b/drivers/mcb/mcb-core.c
+@@ -277,8 +277,8 @@ struct mcb_bus *mcb_alloc_bus(struct dev
+
+ bus_nr = ida_simple_get(&mcb_ida, 0, 0, GFP_KERNEL);
+ if (bus_nr < 0) {
+- rc = bus_nr;
+- goto err_free;
++ kfree(bus);
++ return ERR_PTR(bus_nr);
+ }
+
+ bus->bus_nr = bus_nr;
+@@ -293,12 +293,12 @@ struct mcb_bus *mcb_alloc_bus(struct dev
+ dev_set_name(&bus->dev, "mcb:%d", bus_nr);
+ rc = device_add(&bus->dev);
+ if (rc)
+- goto err_free;
++ goto err_put;
+
+ return bus;
+-err_free:
+- put_device(carrier);
+- kfree(bus);
++
++err_put:
++ put_device(&bus->dev);
+ return ERR_PTR(rc);
+ }
+ EXPORT_SYMBOL_GPL(mcb_alloc_bus);
--- /dev/null
+From 9c0f0a03e386f4e1df33db676401547e1b7800c6 Mon Sep 17 00:00:00 2001
+From: Wengang Wang <wen.gang.wang@oracle.com>
+Date: Fri, 24 Sep 2021 15:43:35 -0700
+Subject: ocfs2: drop acl cache for directories too
+
+From: Wengang Wang <wen.gang.wang@oracle.com>
+
+commit 9c0f0a03e386f4e1df33db676401547e1b7800c6 upstream.
+
+ocfs2_data_convert_worker() is currently dropping any cached acl info
+for FILE before down-converting meta lock. It should also drop for
+DIRECTORY. Otherwise the second acl lookup returns the cached one (from
+VFS layer) which could be already stale.
+
+The problem we are seeing is that the acl changes on one node doesn't
+get refreshed on other nodes in the following case:
+
+ Node 1 Node 2
+ -------------- ----------------
+ getfacl dir1
+
+ getfacl dir1 <-- this is OK
+
+ setfacl -m u:user1:rwX dir1
+ getfacl dir1 <-- see the change for user1
+
+ getfacl dir1 <-- can't see change for user1
+
+Link: https://lkml.kernel.org/r/20210903012631.6099-1-wen.gang.wang@oracle.com
+Signed-off-by: Wengang Wang <wen.gang.wang@oracle.com>
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Gang He <ghe@suse.com>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ocfs2/dlmglue.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/ocfs2/dlmglue.c
++++ b/fs/ocfs2/dlmglue.c
+@@ -3933,7 +3933,7 @@ static int ocfs2_data_convert_worker(str
+ oi = OCFS2_I(inode);
+ oi->ip_dir_lock_gen++;
+ mlog(0, "generation: %u\n", oi->ip_dir_lock_gen);
+- goto out;
++ goto out_forget;
+ }
+
+ if (!S_ISREG(inode->i_mode))
+@@ -3964,6 +3964,7 @@ static int ocfs2_data_convert_worker(str
+ filemap_fdatawait(mapping);
+ }
+
++out_forget:
+ forget_all_cached_acls(inode);
+
+ out:
--- /dev/null
+ocfs2-drop-acl-cache-for-directories-too.patch
+usb-gadget-r8a66597-fix-a-loop-in-set_feature.patch
+usb-dwc2-gadget-fix-isoc-flow-for-bdma-and-slave.patch
+usb-dwc2-gadget-fix-isoc-transfer-complete-handling-for-ddma.patch
+usb-musb-tusb6010-uninitialized-data-in-tusb_fifo_write_unaligned.patch
+cifs-fix-incorrect-check-for-null-pointer-in-header_assemble.patch
+xen-x86-fix-pv-trap-handling-on-secondary-processors.patch
+usb-storage-add-quirk-for-scanlogic-sl11r-ide-older-than-2.6c.patch
+usb-serial-cp210x-add-id-for-gw-instek-gdm-834x-digital-multimeter.patch
+usb-cdc-acm-fix-minor-number-release.patch
+binder-make-sure-fd-closes-complete.patch
+staging-greybus-uart-fix-tty-use-after-free.patch
+enable-uas-for-lacie-rugged-usb3-fw-with-fk-quirk.patch
+usb-core-hcd-add-support-for-deferring-roothub-registration.patch
+usb-serial-mos7840-remove-duplicated-0xac24-device-id.patch
+usb-serial-option-add-telit-ln920-compositions.patch
+usb-serial-option-remove-duplicate-usb-device-id.patch
+usb-serial-option-add-device-id-for-foxconn-t99w265.patch
+mcb-fix-error-handling-in-mcb_alloc_bus.patch
--- /dev/null
+From 92dc0b1f46e12cfabd28d709bb34f7a39431b44f Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 6 Sep 2021 14:45:38 +0200
+Subject: staging: greybus: uart: fix tty use after free
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 92dc0b1f46e12cfabd28d709bb34f7a39431b44f upstream.
+
+User space can hold a tty open indefinitely and tty drivers must not
+release the underlying structures until the last user is gone.
+
+Switch to using the tty-port reference counter to manage the life time
+of the greybus tty state to avoid use after free after a disconnect.
+
+Fixes: a18e15175708 ("greybus: more uart work")
+Cc: stable@vger.kernel.org # 4.9
+Reviewed-by: Alex Elder <elder@linaro.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://lore.kernel.org/r/20210906124538.22358-1-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/greybus/uart.c | 62 +++++++++++++++++++++--------------------
+ 1 file changed, 32 insertions(+), 30 deletions(-)
+
+--- a/drivers/staging/greybus/uart.c
++++ b/drivers/staging/greybus/uart.c
+@@ -789,6 +789,17 @@ out:
+ gbphy_runtime_put_autosuspend(gb_tty->gbphy_dev);
+ }
+
++static void gb_tty_port_destruct(struct tty_port *port)
++{
++ struct gb_tty *gb_tty = container_of(port, struct gb_tty, port);
++
++ if (gb_tty->minor != GB_NUM_MINORS)
++ release_minor(gb_tty);
++ kfifo_free(&gb_tty->write_fifo);
++ kfree(gb_tty->buffer);
++ kfree(gb_tty);
++}
++
+ static const struct tty_operations gb_ops = {
+ .install = gb_tty_install,
+ .open = gb_tty_open,
+@@ -814,6 +825,7 @@ static const struct tty_port_operations
+ .dtr_rts = gb_tty_dtr_rts,
+ .activate = gb_tty_port_activate,
+ .shutdown = gb_tty_port_shutdown,
++ .destruct = gb_tty_port_destruct,
+ };
+
+ static int gb_uart_probe(struct gbphy_device *gbphy_dev,
+@@ -826,17 +838,11 @@ static int gb_uart_probe(struct gbphy_de
+ int retval;
+ int minor;
+
+- gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL);
+- if (!gb_tty)
+- return -ENOMEM;
+-
+ connection = gb_connection_create(gbphy_dev->bundle,
+ le16_to_cpu(gbphy_dev->cport_desc->id),
+ gb_uart_request_handler);
+- if (IS_ERR(connection)) {
+- retval = PTR_ERR(connection);
+- goto exit_tty_free;
+- }
++ if (IS_ERR(connection))
++ return PTR_ERR(connection);
+
+ max_payload = gb_operation_get_payload_size_max(connection);
+ if (max_payload < sizeof(struct gb_uart_send_data_request)) {
+@@ -844,13 +850,23 @@ static int gb_uart_probe(struct gbphy_de
+ goto exit_connection_destroy;
+ }
+
++ gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL);
++ if (!gb_tty) {
++ retval = -ENOMEM;
++ goto exit_connection_destroy;
++ }
++
++ tty_port_init(&gb_tty->port);
++ gb_tty->port.ops = &gb_port_ops;
++ gb_tty->minor = GB_NUM_MINORS;
++
+ gb_tty->buffer_payload_max = max_payload -
+ sizeof(struct gb_uart_send_data_request);
+
+ gb_tty->buffer = kzalloc(gb_tty->buffer_payload_max, GFP_KERNEL);
+ if (!gb_tty->buffer) {
+ retval = -ENOMEM;
+- goto exit_connection_destroy;
++ goto exit_put_port;
+ }
+
+ INIT_WORK(&gb_tty->tx_work, gb_uart_tx_write_work);
+@@ -858,7 +874,7 @@ static int gb_uart_probe(struct gbphy_de
+ retval = kfifo_alloc(&gb_tty->write_fifo, GB_UART_WRITE_FIFO_SIZE,
+ GFP_KERNEL);
+ if (retval)
+- goto exit_buf_free;
++ goto exit_put_port;
+
+ gb_tty->credits = GB_UART_FIRMWARE_CREDITS;
+ init_completion(&gb_tty->credits_complete);
+@@ -872,7 +888,7 @@ static int gb_uart_probe(struct gbphy_de
+ } else {
+ retval = minor;
+ }
+- goto exit_kfifo_free;
++ goto exit_put_port;
+ }
+
+ gb_tty->minor = minor;
+@@ -881,9 +897,6 @@ static int gb_uart_probe(struct gbphy_de
+ init_waitqueue_head(&gb_tty->wioctl);
+ mutex_init(&gb_tty->mutex);
+
+- tty_port_init(&gb_tty->port);
+- gb_tty->port.ops = &gb_port_ops;
+-
+ gb_tty->connection = connection;
+ gb_tty->gbphy_dev = gbphy_dev;
+ gb_connection_set_data(connection, gb_tty);
+@@ -891,7 +904,7 @@ static int gb_uart_probe(struct gbphy_de
+
+ retval = gb_connection_enable_tx(connection);
+ if (retval)
+- goto exit_release_minor;
++ goto exit_put_port;
+
+ send_control(gb_tty, gb_tty->ctrlout);
+
+@@ -918,16 +931,10 @@ static int gb_uart_probe(struct gbphy_de
+
+ exit_connection_disable:
+ gb_connection_disable(connection);
+-exit_release_minor:
+- release_minor(gb_tty);
+-exit_kfifo_free:
+- kfifo_free(&gb_tty->write_fifo);
+-exit_buf_free:
+- kfree(gb_tty->buffer);
++exit_put_port:
++ tty_port_put(&gb_tty->port);
+ exit_connection_destroy:
+ gb_connection_destroy(connection);
+-exit_tty_free:
+- kfree(gb_tty);
+
+ return retval;
+ }
+@@ -958,15 +965,10 @@ static void gb_uart_remove(struct gbphy_
+ gb_connection_disable_rx(connection);
+ tty_unregister_device(gb_tty_driver, gb_tty->minor);
+
+- /* FIXME - free transmit / receive buffers */
+-
+ gb_connection_disable(connection);
+- tty_port_destroy(&gb_tty->port);
+ gb_connection_destroy(connection);
+- release_minor(gb_tty);
+- kfifo_free(&gb_tty->write_fifo);
+- kfree(gb_tty->buffer);
+- kfree(gb_tty);
++
++ tty_port_put(&gb_tty->port);
+ }
+
+ static int gb_tty_init(void)
--- /dev/null
+From 91fac0741d4817945c6ee0a17591421e7f5ecb86 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Tue, 7 Sep 2021 10:23:18 +0200
+Subject: USB: cdc-acm: fix minor-number release
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 91fac0741d4817945c6ee0a17591421e7f5ecb86 upstream.
+
+If the driver runs out of minor numbers it would release minor 0 and
+allow another device to claim the minor while still in use.
+
+Fortunately, registering the tty class device of the second device would
+fail (with a stack dump) due to the sysfs name collision so no memory is
+leaked.
+
+Fixes: cae2bc768d17 ("usb: cdc-acm: Decrement tty port's refcount if probe() fail")
+Cc: stable@vger.kernel.org # 4.19
+Cc: Jaejoong Kim <climbbb.kim@gmail.com>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://lore.kernel.org/r/20210907082318.7757-1-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/class/cdc-acm.c | 7 +++++--
+ drivers/usb/class/cdc-acm.h | 2 ++
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -725,7 +725,8 @@ static void acm_port_destruct(struct tty
+ {
+ struct acm *acm = container_of(port, struct acm, port);
+
+- acm_release_minor(acm);
++ if (acm->minor != ACM_MINOR_INVALID)
++ acm_release_minor(acm);
+ usb_put_intf(acm->control);
+ kfree(acm->country_codes);
+ kfree(acm);
+@@ -1356,8 +1357,10 @@ made_compressed_probe:
+ usb_get_intf(acm->control); /* undone in destruct() */
+
+ minor = acm_alloc_minor(acm);
+- if (minor < 0)
++ if (minor < 0) {
++ acm->minor = ACM_MINOR_INVALID;
+ goto alloc_fail1;
++ }
+
+ acm->minor = minor;
+ acm->dev = usb_dev;
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -22,6 +22,8 @@
+ #define ACM_TTY_MAJOR 166
+ #define ACM_TTY_MINORS 256
+
++#define ACM_MINOR_INVALID ACM_TTY_MINORS
++
+ /*
+ * Requests.
+ */
--- /dev/null
+From 58877b0824da15698bd85a0a9dbfa8c354e6ecb7 Mon Sep 17 00:00:00 2001
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Thu, 9 Sep 2021 12:11:58 +0530
+Subject: usb: core: hcd: Add support for deferring roothub registration
+
+From: Kishon Vijay Abraham I <kishon@ti.com>
+
+commit 58877b0824da15698bd85a0a9dbfa8c354e6ecb7 upstream.
+
+It has been observed with certain PCIe USB cards (like Inateck connected
+to AM64 EVM or J7200 EVM) that as soon as the primary roothub is
+registered, port status change is handled even before xHC is running
+leading to cold plug USB devices not detected. For such cases, registering
+both the root hubs along with the second HCD is required. Add support for
+deferring roothub registration in usb_add_hcd(), so that both primary and
+secondary roothubs are registered along with the second HCD.
+
+CC: stable@vger.kernel.org # 5.4+
+Suggested-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Tested-by: Chris Chiu <chris.chiu@canonical.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+Link: https://lore.kernel.org/r/20210909064200.16216-2-kishon@ti.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/hcd.c | 29 +++++++++++++++++++++++------
+ include/linux/usb/hcd.h | 2 ++
+ 2 files changed, 25 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2636,6 +2636,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ {
+ int retval;
+ struct usb_device *rhdev;
++ struct usb_hcd *shared_hcd;
+
+ if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
+ hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
+@@ -2792,13 +2793,26 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ goto err_hcd_driver_start;
+ }
+
++ /* starting here, usbcore will pay attention to the shared HCD roothub */
++ shared_hcd = hcd->shared_hcd;
++ if (!usb_hcd_is_primary_hcd(hcd) && shared_hcd && HCD_DEFER_RH_REGISTER(shared_hcd)) {
++ retval = register_root_hub(shared_hcd);
++ if (retval != 0)
++ goto err_register_root_hub;
++
++ if (shared_hcd->uses_new_polling && HCD_POLL_RH(shared_hcd))
++ usb_hcd_poll_rh_status(shared_hcd);
++ }
++
+ /* starting here, usbcore will pay attention to this root hub */
+- retval = register_root_hub(hcd);
+- if (retval != 0)
+- goto err_register_root_hub;
++ if (!HCD_DEFER_RH_REGISTER(hcd)) {
++ retval = register_root_hub(hcd);
++ if (retval != 0)
++ goto err_register_root_hub;
+
+- if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
+- usb_hcd_poll_rh_status(hcd);
++ if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
++ usb_hcd_poll_rh_status(hcd);
++ }
+
+ return retval;
+
+@@ -2841,6 +2855,7 @@ EXPORT_SYMBOL_GPL(usb_add_hcd);
+ void usb_remove_hcd(struct usb_hcd *hcd)
+ {
+ struct usb_device *rhdev = hcd->self.root_hub;
++ bool rh_registered;
+
+ dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
+
+@@ -2851,6 +2866,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+
+ dev_dbg(hcd->self.controller, "roothub graceful disconnect\n");
+ spin_lock_irq (&hcd_root_hub_lock);
++ rh_registered = hcd->rh_registered;
+ hcd->rh_registered = 0;
+ spin_unlock_irq (&hcd_root_hub_lock);
+
+@@ -2860,7 +2876,8 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ cancel_work_sync(&hcd->died_work);
+
+ mutex_lock(&usb_bus_idr_lock);
+- usb_disconnect(&rhdev); /* Sets rhdev to NULL */
++ if (rh_registered)
++ usb_disconnect(&rhdev); /* Sets rhdev to NULL */
+ mutex_unlock(&usb_bus_idr_lock);
+
+ /*
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -124,6 +124,7 @@ struct usb_hcd {
+ #define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */
+ #define HCD_FLAG_DEAD 6 /* controller has died? */
+ #define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */
++#define HCD_FLAG_DEFER_RH_REGISTER 8 /* Defer roothub registration */
+
+ /* The flags can be tested using these macros; they are likely to
+ * be slightly faster than test_bit().
+@@ -134,6 +135,7 @@ struct usb_hcd {
+ #define HCD_WAKEUP_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))
+ #define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING))
+ #define HCD_DEAD(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEAD))
++#define HCD_DEFER_RH_REGISTER(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEFER_RH_REGISTER))
+
+ /*
+ * Specifies if interfaces are authorized by default
--- /dev/null
+From 91bb163e1e4f88092f50dfaa5a816b658753e4b2 Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Date: Thu, 9 Sep 2021 14:45:15 +0400
+Subject: usb: dwc2: gadget: Fix ISOC flow for BDMA and Slave
+
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+
+commit 91bb163e1e4f88092f50dfaa5a816b658753e4b2 upstream.
+
+According USB spec each ISOC transaction should be performed in a
+designated for that transaction interval. On bus errors or delays
+in operating system scheduling of client software can result in no
+packet being transferred for a (micro)frame. An error indication
+should be returned as status to the client software in such a case.
+
+Current implementation in case of missed/dropped interval send same
+data in next possible interval instead of reporting missed isoc.
+
+This fix complete requests with -ENODATA if interval elapsed.
+
+HSOTG core in BDMA and Slave modes haven't HW support for
+(micro)frames tracking, this is why SW should care about tracking
+of (micro)frames. Because of that method and consider operating
+system scheduling delays, added few additional checking's of elapsed
+target (micro)frame:
+1. Immediately before enabling EP to start transfer.
+2. With any transfer completion interrupt.
+3. With incomplete isoc in/out interrupt.
+4. With EP disabled interrupt because of incomplete transfer.
+5. With OUT token received while EP disabled interrupt (for OUT
+transfers).
+6. With NAK replied to IN token interrupt (for IN transfers).
+
+As part of ISOC flow, additionally fixed 'current' and 'target' frame
+calculation functions. In HS mode SOF limits provided by DSTS register
+is 0x3fff, but in non HS mode this limit is 0x7ff.
+
+Tested by internal tool which also using for dwc3 testing.
+
+Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/95d1423adf4b0f68187c9894820c4b7e964a3f7f.1631175721.git.Minas.Harutyunyan@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/gadget.c | 189 +++++++++++++++++++++++++---------------------
+ 1 file changed, 106 insertions(+), 83 deletions(-)
+
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -115,10 +115,16 @@ static inline bool using_desc_dma(struct
+ */
+ static inline void dwc2_gadget_incr_frame_num(struct dwc2_hsotg_ep *hs_ep)
+ {
++ struct dwc2_hsotg *hsotg = hs_ep->parent;
++ u16 limit = DSTS_SOFFN_LIMIT;
++
++ if (hsotg->gadget.speed != USB_SPEED_HIGH)
++ limit >>= 3;
++
+ hs_ep->target_frame += hs_ep->interval;
+- if (hs_ep->target_frame > DSTS_SOFFN_LIMIT) {
++ if (hs_ep->target_frame > limit) {
+ hs_ep->frame_overrun = true;
+- hs_ep->target_frame &= DSTS_SOFFN_LIMIT;
++ hs_ep->target_frame &= limit;
+ } else {
+ hs_ep->frame_overrun = false;
+ }
+@@ -136,10 +142,16 @@ static inline void dwc2_gadget_incr_fram
+ */
+ static inline void dwc2_gadget_dec_frame_num_by_one(struct dwc2_hsotg_ep *hs_ep)
+ {
++ struct dwc2_hsotg *hsotg = hs_ep->parent;
++ u16 limit = DSTS_SOFFN_LIMIT;
++
++ if (hsotg->gadget.speed != USB_SPEED_HIGH)
++ limit >>= 3;
++
+ if (hs_ep->target_frame)
+ hs_ep->target_frame -= 1;
+ else
+- hs_ep->target_frame = DSTS_SOFFN_LIMIT;
++ hs_ep->target_frame = limit;
+ }
+
+ /**
+@@ -1018,6 +1030,12 @@ static void dwc2_gadget_start_isoc_ddma(
+ dwc2_writel(hsotg, ctrl, depctl);
+ }
+
++static bool dwc2_gadget_target_frame_elapsed(struct dwc2_hsotg_ep *hs_ep);
++static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg,
++ struct dwc2_hsotg_ep *hs_ep,
++ struct dwc2_hsotg_req *hs_req,
++ int result);
++
+ /**
+ * dwc2_hsotg_start_req - start a USB request from an endpoint's queue
+ * @hsotg: The controller state.
+@@ -1170,14 +1188,19 @@ static void dwc2_hsotg_start_req(struct
+ }
+ }
+
+- if (hs_ep->isochronous && hs_ep->interval == 1) {
+- hs_ep->target_frame = dwc2_hsotg_read_frameno(hsotg);
+- dwc2_gadget_incr_frame_num(hs_ep);
+-
+- if (hs_ep->target_frame & 0x1)
+- ctrl |= DXEPCTL_SETODDFR;
+- else
+- ctrl |= DXEPCTL_SETEVENFR;
++ if (hs_ep->isochronous) {
++ if (!dwc2_gadget_target_frame_elapsed(hs_ep)) {
++ if (hs_ep->interval == 1) {
++ if (hs_ep->target_frame & 0x1)
++ ctrl |= DXEPCTL_SETODDFR;
++ else
++ ctrl |= DXEPCTL_SETEVENFR;
++ }
++ ctrl |= DXEPCTL_CNAK;
++ } else {
++ dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, -ENODATA);
++ return;
++ }
+ }
+
+ ctrl |= DXEPCTL_EPENA; /* ensure ep enabled */
+@@ -1325,12 +1348,16 @@ static bool dwc2_gadget_target_frame_ela
+ u32 target_frame = hs_ep->target_frame;
+ u32 current_frame = hsotg->frame_number;
+ bool frame_overrun = hs_ep->frame_overrun;
++ u16 limit = DSTS_SOFFN_LIMIT;
++
++ if (hsotg->gadget.speed != USB_SPEED_HIGH)
++ limit >>= 3;
+
+ if (!frame_overrun && current_frame >= target_frame)
+ return true;
+
+ if (frame_overrun && current_frame >= target_frame &&
+- ((current_frame - target_frame) < DSTS_SOFFN_LIMIT / 2))
++ ((current_frame - target_frame) < limit / 2))
+ return true;
+
+ return false;
+@@ -1712,11 +1739,9 @@ static struct dwc2_hsotg_req *get_ep_hea
+ */
+ static void dwc2_gadget_start_next_request(struct dwc2_hsotg_ep *hs_ep)
+ {
+- u32 mask;
+ struct dwc2_hsotg *hsotg = hs_ep->parent;
+ int dir_in = hs_ep->dir_in;
+ struct dwc2_hsotg_req *hs_req;
+- u32 epmsk_reg = dir_in ? DIEPMSK : DOEPMSK;
+
+ if (!list_empty(&hs_ep->queue)) {
+ hs_req = get_ep_head(hs_ep);
+@@ -1732,9 +1757,6 @@ static void dwc2_gadget_start_next_reque
+ } else {
+ dev_dbg(hsotg->dev, "%s: No more ISOC-OUT requests\n",
+ __func__);
+- mask = dwc2_readl(hsotg, epmsk_reg);
+- mask |= DOEPMSK_OUTTKNEPDISMSK;
+- dwc2_writel(hsotg, mask, epmsk_reg);
+ }
+ }
+
+@@ -2304,19 +2326,6 @@ static void dwc2_hsotg_ep0_zlp(struct dw
+ dwc2_hsotg_program_zlp(hsotg, hsotg->eps_out[0]);
+ }
+
+-static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg,
+- u32 epctl_reg)
+-{
+- u32 ctrl;
+-
+- ctrl = dwc2_readl(hsotg, epctl_reg);
+- if (ctrl & DXEPCTL_EOFRNUM)
+- ctrl |= DXEPCTL_SETEVENFR;
+- else
+- ctrl |= DXEPCTL_SETODDFR;
+- dwc2_writel(hsotg, ctrl, epctl_reg);
+-}
+-
+ /*
+ * dwc2_gadget_get_xfersize_ddma - get transferred bytes amount from desc
+ * @hs_ep - The endpoint on which transfer went
+@@ -2437,20 +2446,11 @@ static void dwc2_hsotg_handle_outdone(st
+ dwc2_hsotg_ep0_zlp(hsotg, true);
+ }
+
+- /*
+- * Slave mode OUT transfers do not go through XferComplete so
+- * adjust the ISOC parity here.
+- */
+- if (!using_dma(hsotg)) {
+- if (hs_ep->isochronous && hs_ep->interval == 1)
+- dwc2_hsotg_change_ep_iso_parity(hsotg, DOEPCTL(epnum));
+- else if (hs_ep->isochronous && hs_ep->interval > 1)
+- dwc2_gadget_incr_frame_num(hs_ep);
+- }
+-
+ /* Set actual frame number for completed transfers */
+- if (!using_desc_dma(hsotg) && hs_ep->isochronous)
+- req->frame_number = hsotg->frame_number;
++ if (!using_desc_dma(hsotg) && hs_ep->isochronous) {
++ req->frame_number = hs_ep->target_frame;
++ dwc2_gadget_incr_frame_num(hs_ep);
++ }
+
+ dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
+ }
+@@ -2764,6 +2764,12 @@ static void dwc2_hsotg_complete_in(struc
+ return;
+ }
+
++ /* Set actual frame number for completed transfers */
++ if (!using_desc_dma(hsotg) && hs_ep->isochronous) {
++ hs_req->req.frame_number = hs_ep->target_frame;
++ dwc2_gadget_incr_frame_num(hs_ep);
++ }
++
+ dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
+ }
+
+@@ -2824,23 +2830,18 @@ static void dwc2_gadget_handle_ep_disabl
+
+ dwc2_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index);
+
+- if (hs_ep->isochronous) {
+- dwc2_hsotg_complete_in(hsotg, hs_ep);
+- return;
+- }
+-
+ if ((epctl & DXEPCTL_STALL) && (epctl & DXEPCTL_EPTYPE_BULK)) {
+ int dctl = dwc2_readl(hsotg, DCTL);
+
+ dctl |= DCTL_CGNPINNAK;
+ dwc2_writel(hsotg, dctl, DCTL);
+ }
+- return;
+- }
++ } else {
+
+- if (dctl & DCTL_GOUTNAKSTS) {
+- dctl |= DCTL_CGOUTNAK;
+- dwc2_writel(hsotg, dctl, DCTL);
++ if (dctl & DCTL_GOUTNAKSTS) {
++ dctl |= DCTL_CGOUTNAK;
++ dwc2_writel(hsotg, dctl, DCTL);
++ }
+ }
+
+ if (!hs_ep->isochronous)
+@@ -2861,8 +2862,6 @@ static void dwc2_gadget_handle_ep_disabl
+ /* Update current frame number value. */
+ hsotg->frame_number = dwc2_hsotg_read_frameno(hsotg);
+ } while (dwc2_gadget_target_frame_elapsed(hs_ep));
+-
+- dwc2_gadget_start_next_request(hs_ep);
+ }
+
+ /**
+@@ -2879,8 +2878,8 @@ static void dwc2_gadget_handle_ep_disabl
+ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep)
+ {
+ struct dwc2_hsotg *hsotg = ep->parent;
++ struct dwc2_hsotg_req *hs_req;
+ int dir_in = ep->dir_in;
+- u32 doepmsk;
+
+ if (dir_in || !ep->isochronous)
+ return;
+@@ -2894,28 +2893,39 @@ static void dwc2_gadget_handle_out_token
+ return;
+ }
+
+- if (ep->interval > 1 &&
+- ep->target_frame == TARGET_FRAME_INITIAL) {
++ if (ep->target_frame == TARGET_FRAME_INITIAL) {
+ u32 ctrl;
+
+ ep->target_frame = hsotg->frame_number;
+- dwc2_gadget_incr_frame_num(ep);
++ if (ep->interval > 1) {
++ ctrl = dwc2_readl(hsotg, DOEPCTL(ep->index));
++ if (ep->target_frame & 0x1)
++ ctrl |= DXEPCTL_SETODDFR;
++ else
++ ctrl |= DXEPCTL_SETEVENFR;
+
+- ctrl = dwc2_readl(hsotg, DOEPCTL(ep->index));
+- if (ep->target_frame & 0x1)
+- ctrl |= DXEPCTL_SETODDFR;
+- else
+- ctrl |= DXEPCTL_SETEVENFR;
++ dwc2_writel(hsotg, ctrl, DOEPCTL(ep->index));
++ }
++ }
++
++ while (dwc2_gadget_target_frame_elapsed(ep)) {
++ hs_req = get_ep_head(ep);
++ if (hs_req)
++ dwc2_hsotg_complete_request(hsotg, ep, hs_req, -ENODATA);
+
+- dwc2_writel(hsotg, ctrl, DOEPCTL(ep->index));
++ dwc2_gadget_incr_frame_num(ep);
++ /* Update current frame number value. */
++ hsotg->frame_number = dwc2_hsotg_read_frameno(hsotg);
+ }
+
+- dwc2_gadget_start_next_request(ep);
+- doepmsk = dwc2_readl(hsotg, DOEPMSK);
+- doepmsk &= ~DOEPMSK_OUTTKNEPDISMSK;
+- dwc2_writel(hsotg, doepmsk, DOEPMSK);
++ if (!ep->req)
++ dwc2_gadget_start_next_request(ep);
++
+ }
+
++static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
++ struct dwc2_hsotg_ep *hs_ep);
++
+ /**
+ * dwc2_gadget_handle_nak - handle NAK interrupt
+ * @hs_ep: The endpoint on which interrupt is asserted.
+@@ -2933,7 +2943,9 @@ static void dwc2_gadget_handle_out_token
+ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)
+ {
+ struct dwc2_hsotg *hsotg = hs_ep->parent;
++ struct dwc2_hsotg_req *hs_req;
+ int dir_in = hs_ep->dir_in;
++ u32 ctrl;
+
+ if (!dir_in || !hs_ep->isochronous)
+ return;
+@@ -2975,13 +2987,29 @@ static void dwc2_gadget_handle_nak(struc
+
+ dwc2_writel(hsotg, ctrl, DIEPCTL(hs_ep->index));
+ }
+-
+- dwc2_hsotg_complete_request(hsotg, hs_ep,
+- get_ep_head(hs_ep), 0);
+ }
+
+- if (!using_desc_dma(hsotg))
++ if (using_desc_dma(hsotg))
++ return;
++
++ ctrl = dwc2_readl(hsotg, DIEPCTL(hs_ep->index));
++ if (ctrl & DXEPCTL_EPENA)
++ dwc2_hsotg_ep_stop_xfr(hsotg, hs_ep);
++ else
++ dwc2_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index);
++
++ while (dwc2_gadget_target_frame_elapsed(hs_ep)) {
++ hs_req = get_ep_head(hs_ep);
++ if (hs_req)
++ dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, -ENODATA);
++
+ dwc2_gadget_incr_frame_num(hs_ep);
++ /* Update current frame number value. */
++ hsotg->frame_number = dwc2_hsotg_read_frameno(hsotg);
++ }
++
++ if (!hs_ep->req)
++ dwc2_gadget_start_next_request(hs_ep);
+ }
+
+ /**
+@@ -3048,12 +3076,8 @@ static void dwc2_hsotg_epint(struct dwc2
+ * need to look at completing IN requests here
+ * if operating slave mode
+ */
+- if (hs_ep->isochronous && hs_ep->interval > 1)
+- dwc2_gadget_incr_frame_num(hs_ep);
+-
+- dwc2_hsotg_complete_in(hsotg, hs_ep);
+- if (ints & DXEPINT_NAKINTRPT)
+- ints &= ~DXEPINT_NAKINTRPT;
++ if (!hs_ep->isochronous || !(ints & DXEPINT_NAKINTRPT))
++ dwc2_hsotg_complete_in(hsotg, hs_ep);
+
+ if (idx == 0 && !hs_ep->req)
+ dwc2_hsotg_enqueue_setup(hsotg);
+@@ -3062,10 +3086,8 @@ static void dwc2_hsotg_epint(struct dwc2
+ * We're using DMA, we need to fire an OutDone here
+ * as we ignore the RXFIFO.
+ */
+- if (hs_ep->isochronous && hs_ep->interval > 1)
+- dwc2_gadget_incr_frame_num(hs_ep);
+-
+- dwc2_hsotg_handle_outdone(hsotg, idx);
++ if (!hs_ep->isochronous || !(ints & DXEPINT_OUTTKNEPDIS))
++ dwc2_hsotg_handle_outdone(hsotg, idx);
+ }
+ }
+
+@@ -4055,6 +4077,7 @@ static int dwc2_hsotg_ep_enable(struct u
+ mask |= DIEPMSK_NAKMSK;
+ dwc2_writel(hsotg, mask, DIEPMSK);
+ } else {
++ epctrl |= DXEPCTL_SNAK;
+ mask = dwc2_readl(hsotg, DOEPMSK);
+ mask |= DOEPMSK_OUTTKNEPDISMSK;
+ dwc2_writel(hsotg, mask, DOEPMSK);
--- /dev/null
+From dbe2518b2d8eabffa74dbf7d9fdd7dacddab7fc0 Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Date: Sat, 11 Sep 2021 22:58:30 +0400
+Subject: usb: dwc2: gadget: Fix ISOC transfer complete handling for DDMA
+
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+
+commit dbe2518b2d8eabffa74dbf7d9fdd7dacddab7fc0 upstream.
+
+When last descriptor in a descriptor list completed with XferComplete
+interrupt, core switching to handle next descriptor and assert BNA
+interrupt. Both these interrupts are set while dwc2_hsotg_epint()
+handler called. Each interrupt should be handled separately: first
+XferComplete interrupt then BNA interrupt, otherwise last completed
+transfer will not be giveback to function driver as completed
+request.
+
+Fixes: 729cac693eec ("usb: dwc2: Change ISOC DDMA flow")
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Link: https://lore.kernel.org/r/a36981accc26cd674c5d8f8da6164344b94ec1fe.1631386531.git.Minas.Harutyunyan@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/gadget.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -3067,9 +3067,7 @@ static void dwc2_hsotg_epint(struct dwc2
+
+ /* In DDMA handle isochronous requests separately */
+ if (using_desc_dma(hsotg) && hs_ep->isochronous) {
+- /* XferCompl set along with BNA */
+- if (!(ints & DXEPINT_BNAINTR))
+- dwc2_gadget_complete_isoc_request_ddma(hs_ep);
++ dwc2_gadget_complete_isoc_request_ddma(hs_ep);
+ } else if (dir_in) {
+ /*
+ * We get OutDone from the FIFO, so we only
--- /dev/null
+From 17956b53ebff6a490baf580a836cbd3eae94892b Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Mon, 6 Sep 2021 12:42:21 +0300
+Subject: usb: gadget: r8a66597: fix a loop in set_feature()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 17956b53ebff6a490baf580a836cbd3eae94892b upstream.
+
+This loop is supposed to loop until if reads something other than
+CS_IDST or until it times out after 30,000 attempts. But because of
+the || vs && bug, it will never time out and instead it will loop a
+minimum of 30,000 times.
+
+This bug is quite old but the code is only used in USB_DEVICE_TEST_MODE
+so it probably doesn't affect regular usage.
+
+Fixes: 96fe53ef5498 ("usb: gadget: r8a66597-udc: add support for TEST_MODE")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Acked-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Link: https://lore.kernel.org/r/20210906094221.GA10957@kili
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/udc/r8a66597-udc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/udc/r8a66597-udc.c
++++ b/drivers/usb/gadget/udc/r8a66597-udc.c
+@@ -1250,7 +1250,7 @@ static void set_feature(struct r8a66597
+ do {
+ tmp = r8a66597_read(r8a66597, INTSTS0) & CTSQ;
+ udelay(1);
+- } while (tmp != CS_IDST || timeout-- > 0);
++ } while (tmp != CS_IDST && timeout-- > 0);
+
+ if (tmp == CS_IDST)
+ r8a66597_bset(r8a66597,
--- /dev/null
+From 517c7bf99bad3d6b9360558414aae634b7472d80 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Thu, 16 Sep 2021 16:57:37 +0300
+Subject: usb: musb: tusb6010: uninitialized data in tusb_fifo_write_unaligned()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 517c7bf99bad3d6b9360558414aae634b7472d80 upstream.
+
+This is writing to the first 1 - 3 bytes of "val" and then writing all
+four bytes to musb_writel(). The last byte is always going to be
+garbage. Zero out the last bytes instead.
+
+Fixes: 550a7375fe72 ("USB: Add MUSB and TUSB support")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210916135737.GI25094@kili
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/musb/tusb6010.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/musb/tusb6010.c
++++ b/drivers/usb/musb/tusb6010.c
+@@ -190,6 +190,7 @@ tusb_fifo_write_unaligned(void __iomem *
+ }
+ if (len > 0) {
+ /* Write the rest 1 - 3 bytes to FIFO */
++ val = 0;
+ memcpy(&val, buf, len);
+ musb_writel(fifo, 0, val);
+ }
--- /dev/null
+From 3bd18ba7d859eb1fbef3beb1e80c24f6f7d7596c Mon Sep 17 00:00:00 2001
+From: Uwe Brandt <uwe.brandt@gmail.com>
+Date: Tue, 21 Sep 2021 19:54:46 +0200
+Subject: USB: serial: cp210x: add ID for GW Instek GDM-834x Digital Multimeter
+
+From: Uwe Brandt <uwe.brandt@gmail.com>
+
+commit 3bd18ba7d859eb1fbef3beb1e80c24f6f7d7596c upstream.
+
+Add the USB serial device ID for the GW Instek GDM-834x Digital Multimeter.
+
+Signed-off-by: Uwe Brandt <uwe.brandt@gmail.com>
+Link: https://lore.kernel.org/r/YUxFl3YUCPGJZd8Y@hovoldconsulting.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/cp210x.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -234,6 +234,7 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */
+ { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */
+ { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */
++ { USB_DEVICE(0x2184, 0x0030) }, /* GW Instek GDM-834x Digital Multimeter */
+ { USB_DEVICE(0x2626, 0xEA60) }, /* Aruba Networks 7xxx USB Serial Console */
+ { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
+ { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
--- /dev/null
+From 211f323768a25b30c106fd38f15a0f62c7c2b5f4 Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+Date: Fri, 17 Sep 2021 11:18:47 +0200
+Subject: USB: serial: mos7840: remove duplicated 0xac24 device ID
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+commit 211f323768a25b30c106fd38f15a0f62c7c2b5f4 upstream.
+
+0xac24 device ID is already defined and used via
+BANDB_DEVICE_ID_USO9ML2_4. Remove the duplicate from the list.
+
+Fixes: 27f1281d5f72 ("USB: serial: Extra device/vendor ID for mos7840 driver")
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/mos7840.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -114,7 +114,6 @@
+ #define BANDB_DEVICE_ID_USOPTL4_2P 0xBC02
+ #define BANDB_DEVICE_ID_USOPTL4_4 0xAC44
+ #define BANDB_DEVICE_ID_USOPTL4_4P 0xBC03
+-#define BANDB_DEVICE_ID_USOPTL2_4 0xAC24
+
+ /* This driver also supports
+ * ATEN UC2324 device using Moschip MCS7840
+@@ -196,7 +195,6 @@ static const struct usb_device_id id_tab
+ {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)},
+ {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+ {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)},
+- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
+ {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
+ {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
+ {USB_DEVICE(USB_VENDOR_ID_MOXA, MOXA_DEVICE_ID_2210)},
--- /dev/null
+From 9e3eed534f8235a4a596a9dae5b8a6425d81ea1a Mon Sep 17 00:00:00 2001
+From: Slark Xiao <slark_xiao@163.com>
+Date: Fri, 17 Sep 2021 19:01:06 +0800
+Subject: USB: serial: option: add device id for Foxconn T99W265
+
+From: Slark Xiao <slark_xiao@163.com>
+
+commit 9e3eed534f8235a4a596a9dae5b8a6425d81ea1a upstream.
+
+Adding support for Foxconn device T99W265 for enumeration with
+PID 0xe0db.
+
+usb-devices output for 0xe0db
+T: Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 19 Spd=5000 MxCh= 0
+D: Ver= 3.20 Cls=ef(misc ) Sub=02 Prot=01 MxPS= 9 #Cfgs= 1
+P: Vendor=0489 ProdID=e0db Rev=05.04
+S: Manufacturer=Microsoft
+S: Product=Generic Mobile Broadband Adapter
+S: SerialNumber=6c50f452
+C: #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=896mA
+I: If#=0x0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim
+I: If#=0x1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim
+I: If#=0x2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option
+I: If#=0x3 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
+I: If#=0x4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option
+
+if0/1: MBIM, if2:Diag, if3:GNSS, if4: Modem
+
+Signed-off-by: Slark Xiao <slark_xiao@163.com>
+Link: https://lore.kernel.org/r/20210917110106.9852-1-slark_xiao@163.com
+[ johan: use USB_DEVICE_INTERFACE_CLASS(), amend comment ]
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/option.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -2075,6 +2075,8 @@ static const struct usb_device_id option
+ .driver_info = RSVD(0) | RSVD(1) | RSVD(6) },
+ { USB_DEVICE(0x0489, 0xe0b5), /* Foxconn T77W968 ESIM */
+ .driver_info = RSVD(0) | RSVD(1) | RSVD(6) },
++ { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0db, 0xff), /* Foxconn T99W265 MBIM */
++ .driver_info = RSVD(3) },
+ { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */
+ .driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
+ { USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */
--- /dev/null
+From 7bb057134d609b9c038a00b6876cf0d37d0118ce Mon Sep 17 00:00:00 2001
+From: Carlo Lobrano <c.lobrano@gmail.com>
+Date: Fri, 3 Sep 2021 14:39:13 +0200
+Subject: USB: serial: option: add Telit LN920 compositions
+
+From: Carlo Lobrano <c.lobrano@gmail.com>
+
+commit 7bb057134d609b9c038a00b6876cf0d37d0118ce upstream.
+
+This patch adds the following Telit LN920 compositions:
+
+0x1060: tty, adb, rmnet, tty, tty, tty, tty
+0x1061: tty, adb, mbim, tty, tty, tty, tty
+0x1062: rndis, tty, adb, tty, tty, tty, tty
+0x1063: tty, adb, ecm, tty, tty, tty, tty
+
+Signed-off-by: Carlo Lobrano <c.lobrano@gmail.com>
+Link: https://lore.kernel.org/r/20210903123913.1086513-1-c.lobrano@gmail.com
+Reviewed-by: Daniele Palmas <dnlplm@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/option.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1205,6 +1205,14 @@ static const struct usb_device_id option
+ .driver_info = NCTRL(0) | RSVD(1) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1056, 0xff), /* Telit FD980 */
+ .driver_info = NCTRL(2) | RSVD(3) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1060, 0xff), /* Telit LN920 (rmnet) */
++ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1061, 0xff), /* Telit LN920 (MBIM) */
++ .driver_info = NCTRL(0) | RSVD(1) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1062, 0xff), /* Telit LN920 (RNDIS) */
++ .driver_info = NCTRL(2) | RSVD(3) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */
++ .driver_info = NCTRL(0) | RSVD(1) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
+ .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
--- /dev/null
+From 1ca200a8c6f079950a04ea3c3380fe8cf78e95a2 Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+Date: Fri, 17 Sep 2021 11:18:48 +0200
+Subject: USB: serial: option: remove duplicate USB device ID
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+commit 1ca200a8c6f079950a04ea3c3380fe8cf78e95a2 upstream.
+
+The device ZTE 0x0094 is already on the list.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+Fixes: b9e44fe5ecda ("USB: option: cleanup zte 3g-dongle's pid in option.c")
+Cc: stable@vger.kernel.org
+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 deletion(-)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1658,7 +1658,6 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff),
+ .driver_info = RSVD(1) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff),
--- /dev/null
+From b55d37ef6b7db3eda9b4495a8d9b0a944ee8c67d Mon Sep 17 00:00:00 2001
+From: Ondrej Zary <linux@zary.sk>
+Date: Mon, 13 Sep 2021 23:01:06 +0200
+Subject: usb-storage: Add quirk for ScanLogic SL11R-IDE older than 2.6c
+
+From: Ondrej Zary <linux@zary.sk>
+
+commit b55d37ef6b7db3eda9b4495a8d9b0a944ee8c67d upstream.
+
+ScanLogic SL11R-IDE with firmware older than 2.6c (the latest one) has
+broken tag handling, preventing the device from working at all:
+usb 1-1: new full-speed USB device number 2 using uhci_hcd
+usb 1-1: New USB device found, idVendor=04ce, idProduct=0002, bcdDevice= 2.60
+usb 1-1: New USB device strings: Mfr=1, Product=1, SerialNumber=0
+usb 1-1: Product: USB Device
+usb 1-1: Manufacturer: USB Device
+usb-storage 1-1:1.0: USB Mass Storage device detected
+scsi host2: usb-storage 1-1:1.0
+usbcore: registered new interface driver usb-storage
+usb 1-1: reset full-speed USB device number 2 using uhci_hcd
+usb 1-1: reset full-speed USB device number 2 using uhci_hcd
+usb 1-1: reset full-speed USB device number 2 using uhci_hcd
+usb 1-1: reset full-speed USB device number 2 using uhci_hcd
+
+Add US_FL_BULK_IGNORE_TAG to fix it. Also update my e-mail address.
+
+2.6c is the only firmware that claims Linux compatibility.
+The firmware can be upgraded using ezotgdbg utility:
+https://github.com/asciilifeform/ezotgdbg
+
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Ondrej Zary <linux@zary.sk>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210913210106.12717-1-linux@zary.sk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/storage/unusual_devs.h | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -416,9 +416,16 @@ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x
+ USB_SC_UFI, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN),
+
+ /*
+- * Reported by Ondrej Zary <linux@rainbow-software.org>
++ * Reported by Ondrej Zary <linux@zary.sk>
+ * The device reports one sector more and breaks when that sector is accessed
++ * Firmwares older than 2.6c (the latest one and the only that claims Linux
++ * support) have also broken tag handling
+ */
++UNUSUAL_DEV( 0x04ce, 0x0002, 0x0000, 0x026b,
++ "ScanLogic",
++ "SL11R-IDE",
++ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++ US_FL_FIX_CAPACITY | US_FL_BULK_IGNORE_TAG),
+ UNUSUAL_DEV( 0x04ce, 0x0002, 0x026c, 0x026c,
+ "ScanLogic",
+ "SL11R-IDE",
--- /dev/null
+From 0594c58161b6e0f3da8efa9c6e3d4ba52b652717 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Mon, 20 Sep 2021 18:15:11 +0200
+Subject: xen/x86: fix PV trap handling on secondary processors
+
+From: Jan Beulich <jbeulich@suse.com>
+
+commit 0594c58161b6e0f3da8efa9c6e3d4ba52b652717 upstream.
+
+The initial observation was that in PV mode under Xen 32-bit user space
+didn't work anymore. Attempts of system calls ended in #GP(0x402). All
+of the sudden the vector 0x80 handler was not in place anymore. As it
+turns out up to 5.13 redundant initialization did occur: Once from
+cpu_initialize_context() (through its VCPUOP_initialise hypercall) and a
+2nd time while each CPU was brought fully up. This 2nd initialization is
+now gone, uncovering that the 1st one was flawed: Unlike for the
+set_trap_table hypercall, a full virtual IDT needs to be specified here;
+the "vector" fields of the individual entries are of no interest. With
+many (kernel) IDT entries still(?) (i.e. at that point at least) empty,
+the syscall vector 0x80 ended up in slot 0x20 of the virtual IDT, thus
+becoming the domain's handler for vector 0x20.
+
+Make xen_convert_trap_info() fit for either purpose, leveraging the fact
+that on the xen_copy_trap_info() path the table starts out zero-filled.
+This includes moving out the writing of the sentinel, which would also
+have lead to a buffer overrun in the xen_copy_trap_info() case if all
+(kernel) IDT entries were populated. Convert the writing of the sentinel
+to clearing of the entire table entry rather than just the address
+field.
+
+(I didn't bother trying to identify the commit which uncovered the issue
+in 5.14; the commit named below is the one which actually introduced the
+bad code.)
+
+Fixes: f87e4cac4f4e ("xen: SMP guest support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Link: https://lore.kernel.org/r/7a266932-092e-b68f-f2bb-1473b61adc6e@suse.com
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/xen/enlighten_pv.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/arch/x86/xen/enlighten_pv.c
++++ b/arch/x86/xen/enlighten_pv.c
+@@ -727,8 +727,8 @@ static void xen_write_idt_entry(gate_des
+ preempt_enable();
+ }
+
+-static void xen_convert_trap_info(const struct desc_ptr *desc,
+- struct trap_info *traps)
++static unsigned xen_convert_trap_info(const struct desc_ptr *desc,
++ struct trap_info *traps, bool full)
+ {
+ unsigned in, out, count;
+
+@@ -738,17 +738,18 @@ static void xen_convert_trap_info(const
+ for (in = out = 0; in < count; in++) {
+ gate_desc *entry = (gate_desc *)(desc->address) + in;
+
+- if (cvt_gate_to_trap(in, entry, &traps[out]))
++ if (cvt_gate_to_trap(in, entry, &traps[out]) || full)
+ out++;
+ }
+- traps[out].address = 0;
++
++ return out;
+ }
+
+ void xen_copy_trap_info(struct trap_info *traps)
+ {
+ const struct desc_ptr *desc = this_cpu_ptr(&idt_desc);
+
+- xen_convert_trap_info(desc, traps);
++ xen_convert_trap_info(desc, traps, true);
+ }
+
+ /* Load a new IDT into Xen. In principle this can be per-CPU, so we
+@@ -758,6 +759,7 @@ static void xen_load_idt(const struct de
+ {
+ static DEFINE_SPINLOCK(lock);
+ static struct trap_info traps[257];
++ unsigned out;
+
+ trace_xen_cpu_load_idt(desc);
+
+@@ -765,7 +767,8 @@ static void xen_load_idt(const struct de
+
+ memcpy(this_cpu_ptr(&idt_desc), desc, sizeof(idt_desc));
+
+- xen_convert_trap_info(desc, traps);
++ out = xen_convert_trap_info(desc, traps, false);
++ memset(&traps[out], 0, sizeof(traps[0]));
+
+ xen_mc_flush();
+ if (HYPERVISOR_set_trap_table(traps))