--- /dev/null
+From 883f616530692d81cb70f8a32d85c0d2afc05f69 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Lars=20M=C3=B6llendorf?= <lars.moellendorf@plating.de>
+Date: Fri, 13 Dec 2019 14:50:55 +0100
+Subject: iio: buffer: align the size of scan bytes to size of the largest element
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lars Möllendorf <lars.moellendorf@plating.de>
+
+commit 883f616530692d81cb70f8a32d85c0d2afc05f69 upstream.
+
+Previous versions of `iio_compute_scan_bytes` only aligned each element
+to its own length (i.e. its own natural alignment). Because multiple
+consecutive sets of scan elements are buffered this does not work in
+case the computed scan bytes do not align with the natural alignment of
+the first scan element in the set.
+
+This commit fixes this by aligning the scan bytes to the natural
+alignment of the largest scan element in the set.
+
+Fixes: 959d2952d124 ("staging:iio: make iio_sw_buffer_preenable much more general.")
+Signed-off-by: Lars Möllendorf <lars.moellendorf@plating.de>
+Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/industrialio-buffer.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/iio/industrialio-buffer.c
++++ b/drivers/iio/industrialio-buffer.c
+@@ -570,7 +570,7 @@ static int iio_compute_scan_bytes(struct
+ const unsigned long *mask, bool timestamp)
+ {
+ unsigned bytes = 0;
+- int length, i;
++ int length, i, largest = 0;
+
+ /* How much space will the demuxed element take? */
+ for_each_set_bit(i, mask,
+@@ -578,13 +578,17 @@ static int iio_compute_scan_bytes(struct
+ length = iio_storage_bytes_for_si(indio_dev, i);
+ bytes = ALIGN(bytes, length);
+ bytes += length;
++ largest = max(largest, length);
+ }
+
+ if (timestamp) {
+ length = iio_storage_bytes_for_timestamp(indio_dev);
+ bytes = ALIGN(bytes, length);
+ bytes += length;
++ largest = max(largest, length);
+ }
++
++ bytes = ALIGN(bytes, largest);
+ return bytes;
+ }
+
--- /dev/null
+From 42ec15ceaea74b5f7a621fc6686cbf69ca66c4cf Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Tue, 7 Jan 2020 21:15:49 +0100
+Subject: scsi: fnic: fix invalid stack access
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+commit 42ec15ceaea74b5f7a621fc6686cbf69ca66c4cf upstream.
+
+gcc -O3 warns that some local variables are not properly initialized:
+
+drivers/scsi/fnic/vnic_dev.c: In function 'fnic_dev_hang_notify':
+drivers/scsi/fnic/vnic_dev.c:511:16: error: 'a0' is used uninitialized in this function [-Werror=uninitialized]
+ vdev->args[0] = *a0;
+ ~~~~~~~~~~~~~~^~~~~
+drivers/scsi/fnic/vnic_dev.c:691:6: note: 'a0' was declared here
+ u64 a0, a1;
+ ^~
+drivers/scsi/fnic/vnic_dev.c:512:16: error: 'a1' is used uninitialized in this function [-Werror=uninitialized]
+ vdev->args[1] = *a1;
+ ~~~~~~~~~~~~~~^~~~~
+drivers/scsi/fnic/vnic_dev.c:691:10: note: 'a1' was declared here
+ u64 a0, a1;
+ ^~
+drivers/scsi/fnic/vnic_dev.c: In function 'fnic_dev_mac_addr':
+drivers/scsi/fnic/vnic_dev.c:512:16: error: 'a1' is used uninitialized in this function [-Werror=uninitialized]
+ vdev->args[1] = *a1;
+ ~~~~~~~~~~~~~~^~~~~
+drivers/scsi/fnic/vnic_dev.c:698:10: note: 'a1' was declared here
+ u64 a0, a1;
+ ^~
+
+Apparently the code relies on the local variables occupying adjacent memory
+locations in the same order, but this is of course not guaranteed.
+
+Use an array of two u64 variables where needed to make it work correctly.
+
+I suspect there is also an endianness bug here, but have not digged in deep
+enough to be sure.
+
+Fixes: 5df6d737dd4b ("[SCSI] fnic: Add new Cisco PCI-Express FCoE HBA")
+Fixes: mmtom ("init/Kconfig: enable -O3 for all arches")
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20200107201602.4096790-1-arnd@arndb.de
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/fnic/vnic_dev.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/scsi/fnic/vnic_dev.c
++++ b/drivers/scsi/fnic/vnic_dev.c
+@@ -445,26 +445,26 @@ int vnic_dev_soft_reset_done(struct vnic
+
+ int vnic_dev_hang_notify(struct vnic_dev *vdev)
+ {
+- u64 a0, a1;
++ u64 a0 = 0, a1 = 0;
+ int wait = 1000;
+ return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
+ }
+
+ int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
+ {
+- u64 a0, a1;
++ u64 a[2] = {};
+ int wait = 1000;
+ int err, i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ mac_addr[i] = 0;
+
+- err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
++ err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a[0], &a[1], wait);
+ if (err)
+ return err;
+
+ for (i = 0; i < ETH_ALEN; i++)
+- mac_addr[i] = ((u8 *)&a0)[i];
++ mac_addr[i] = ((u8 *)&a)[i];
+
+ return 0;
+ }
+@@ -489,30 +489,30 @@ void vnic_dev_packet_filter(struct vnic_
+
+ void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
+ {
+- u64 a0 = 0, a1 = 0;
++ u64 a[2] = {};
+ int wait = 1000;
+ int err;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+- ((u8 *)&a0)[i] = addr[i];
++ ((u8 *)&a)[i] = addr[i];
+
+- err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
++ err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a[0], &a[1], wait);
+ if (err)
+ pr_err("Can't add addr [%pM], %d\n", addr, err);
+ }
+
+ void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
+ {
+- u64 a0 = 0, a1 = 0;
++ u64 a[2] = {};
+ int wait = 1000;
+ int err;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+- ((u8 *)&a0)[i] = addr[i];
++ ((u8 *)&a)[i] = addr[i];
+
+- err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
++ err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a[0], &a[1], wait);
+ if (err)
+ pr_err("Can't del addr [%pM], %d\n", addr, err);
+ }
--- /dev/null
+From 28d76df18f0ad5bcf5fa48510b225f0ed262a99b Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 14 Jan 2020 15:34:14 +0300
+Subject: scsi: mptfusion: Fix double fetch bug in ioctl
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 28d76df18f0ad5bcf5fa48510b225f0ed262a99b upstream.
+
+Tom Hatskevich reported that we look up "iocp" then, in the called
+functions we do a second copy_from_user() and look it up again.
+The problem that could cause is:
+
+drivers/message/fusion/mptctl.c
+ 674 /* All of these commands require an interrupt or
+ 675 * are unknown/illegal.
+ 676 */
+ 677 if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
+ ^^^^
+We take this lock.
+
+ 678 return ret;
+ 679
+ 680 if (cmd == MPTFWDOWNLOAD)
+ 681 ret = mptctl_fw_download(arg);
+ ^^^
+Then the user memory changes and we look up "iocp" again but a different
+one so now we are holding the incorrect lock and have a race condition.
+
+ 682 else if (cmd == MPTCOMMAND)
+ 683 ret = mptctl_mpt_command(arg);
+
+The security impact of this bug is not as bad as it could have been
+because these operations are all privileged and root already has
+enormous destructive power. But it's still worth fixing.
+
+This patch passes the "iocp" pointer to the functions to avoid the
+second lookup. That deletes 100 lines of code from the driver so
+it's a nice clean up as well.
+
+Link: https://lore.kernel.org/r/20200114123414.GA7957@kadam
+Reported-by: Tom Hatskevich <tom2001tom.23@gmail.com>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/message/fusion/mptctl.c | 213 +++++++++-------------------------------
+ 1 file changed, 50 insertions(+), 163 deletions(-)
+
+--- a/drivers/message/fusion/mptctl.c
++++ b/drivers/message/fusion/mptctl.c
+@@ -100,19 +100,19 @@ struct buflist {
+ * Function prototypes. Called from OS entry point mptctl_ioctl.
+ * arg contents specific to function.
+ */
+-static int mptctl_fw_download(unsigned long arg);
+-static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
+-static int mptctl_gettargetinfo(unsigned long arg);
+-static int mptctl_readtest(unsigned long arg);
+-static int mptctl_mpt_command(unsigned long arg);
+-static int mptctl_eventquery(unsigned long arg);
+-static int mptctl_eventenable(unsigned long arg);
+-static int mptctl_eventreport(unsigned long arg);
+-static int mptctl_replace_fw(unsigned long arg);
+-
+-static int mptctl_do_reset(unsigned long arg);
+-static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
+-static int mptctl_hp_targetinfo(unsigned long arg);
++static int mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_getiocinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
++static int mptctl_gettargetinfo(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_readtest(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_mpt_command(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_eventquery(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_eventenable(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_eventreport(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_replace_fw(MPT_ADAPTER *iocp, unsigned long arg);
++
++static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_hp_hostinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
++static int mptctl_hp_targetinfo(MPT_ADAPTER *iocp, unsigned long arg);
+
+ static int mptctl_probe(struct pci_dev *, const struct pci_device_id *);
+ static void mptctl_remove(struct pci_dev *);
+@@ -123,8 +123,8 @@ static long compat_mpctl_ioctl(struct fi
+ /*
+ * Private function calls.
+ */
+-static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
+-static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
++static int mptctl_do_mpt_command(MPT_ADAPTER *iocp, struct mpt_ioctl_command karg, void __user *mfPtr);
++static int mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen);
+ static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
+ struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
+ static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
+@@ -656,19 +656,19 @@ __mptctl_ioctl(struct file *file, unsign
+ * by TM and FW reloads.
+ */
+ if ((cmd & ~IOCSIZE_MASK) == (MPTIOCINFO & ~IOCSIZE_MASK)) {
+- return mptctl_getiocinfo(arg, _IOC_SIZE(cmd));
++ return mptctl_getiocinfo(iocp, arg, _IOC_SIZE(cmd));
+ } else if (cmd == MPTTARGETINFO) {
+- return mptctl_gettargetinfo(arg);
++ return mptctl_gettargetinfo(iocp, arg);
+ } else if (cmd == MPTTEST) {
+- return mptctl_readtest(arg);
++ return mptctl_readtest(iocp, arg);
+ } else if (cmd == MPTEVENTQUERY) {
+- return mptctl_eventquery(arg);
++ return mptctl_eventquery(iocp, arg);
+ } else if (cmd == MPTEVENTENABLE) {
+- return mptctl_eventenable(arg);
++ return mptctl_eventenable(iocp, arg);
+ } else if (cmd == MPTEVENTREPORT) {
+- return mptctl_eventreport(arg);
++ return mptctl_eventreport(iocp, arg);
+ } else if (cmd == MPTFWREPLACE) {
+- return mptctl_replace_fw(arg);
++ return mptctl_replace_fw(iocp, arg);
+ }
+
+ /* All of these commands require an interrupt or
+@@ -678,15 +678,15 @@ __mptctl_ioctl(struct file *file, unsign
+ return ret;
+
+ if (cmd == MPTFWDOWNLOAD)
+- ret = mptctl_fw_download(arg);
++ ret = mptctl_fw_download(iocp, arg);
+ else if (cmd == MPTCOMMAND)
+- ret = mptctl_mpt_command(arg);
++ ret = mptctl_mpt_command(iocp, arg);
+ else if (cmd == MPTHARDRESET)
+- ret = mptctl_do_reset(arg);
++ ret = mptctl_do_reset(iocp, arg);
+ else if ((cmd & ~IOCSIZE_MASK) == (HP_GETHOSTINFO & ~IOCSIZE_MASK))
+- ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
++ ret = mptctl_hp_hostinfo(iocp, arg, _IOC_SIZE(cmd));
+ else if (cmd == HP_GETTARGETINFO)
+- ret = mptctl_hp_targetinfo(arg);
++ ret = mptctl_hp_targetinfo(iocp, arg);
+ else
+ ret = -EINVAL;
+
+@@ -705,11 +705,10 @@ mptctl_ioctl(struct file *file, unsigned
+ return ret;
+ }
+
+-static int mptctl_do_reset(unsigned long arg)
++static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg)
+ {
+ struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
+ struct mpt_ioctl_diag_reset krinfo;
+- MPT_ADAPTER *iocp;
+
+ if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
+ printk(KERN_ERR MYNAM "%s@%d::mptctl_do_reset - "
+@@ -718,12 +717,6 @@ static int mptctl_do_reset(unsigned long
+ return -EFAULT;
+ }
+
+- if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
+- printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n",
+- __FILE__, __LINE__, krinfo.hdr.iocnum);
+- return -ENODEV; /* (-6) No such device or address */
+- }
+-
+ dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "mptctl_do_reset called.\n",
+ iocp->name));
+
+@@ -754,7 +747,7 @@ static int mptctl_do_reset(unsigned long
+ * -ENOMSG if FW upload returned bad status
+ */
+ static int
+-mptctl_fw_download(unsigned long arg)
++mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg)
+ {
+ struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
+ struct mpt_fw_xfer kfwdl;
+@@ -766,7 +759,7 @@ mptctl_fw_download(unsigned long arg)
+ return -EFAULT;
+ }
+
+- return mptctl_do_fw_download(kfwdl.iocnum, kfwdl.bufp, kfwdl.fwlen);
++ return mptctl_do_fw_download(iocp, kfwdl.bufp, kfwdl.fwlen);
+ }
+
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -784,11 +777,10 @@ mptctl_fw_download(unsigned long arg)
+ * -ENOMSG if FW upload returned bad status
+ */
+ static int
+-mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
++mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen)
+ {
+ FWDownload_t *dlmsg;
+ MPT_FRAME_HDR *mf;
+- MPT_ADAPTER *iocp;
+ FWDownloadTCSGE_t *ptsge;
+ MptSge_t *sgl, *sgIn;
+ char *sgOut;
+@@ -808,17 +800,10 @@ mptctl_do_fw_download(int ioc, char __us
+ pFWDownloadReply_t ReplyMsg = NULL;
+ unsigned long timeleft;
+
+- if (mpt_verify_adapter(ioc, &iocp) < 0) {
+- printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
+- ioc);
+- return -ENODEV; /* (-6) No such device or address */
+- } else {
+-
+- /* Valid device. Get a message frame and construct the FW download message.
+- */
+- if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+- return -EAGAIN;
+- }
++ /* Valid device. Get a message frame and construct the FW download message.
++ */
++ if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
++ return -EAGAIN;
+
+ dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT
+ "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id));
+@@ -826,8 +811,6 @@ mptctl_do_fw_download(int ioc, char __us
+ iocp->name, ufwbuf));
+ dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n",
+ iocp->name, (int)fwlen));
+- dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.ioc = %04xh\n",
+- iocp->name, ioc));
+
+ dlmsg = (FWDownload_t*) mf;
+ ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
+@@ -1238,13 +1221,11 @@ kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_
+ * -ENODEV if no such device/adapter
+ */
+ static int
+-mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
++mptctl_getiocinfo (MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
+ {
+ struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
+ struct mpt_ioctl_iocinfo *karg;
+- MPT_ADAPTER *ioc;
+ struct pci_dev *pdev;
+- int iocnum;
+ unsigned int port;
+ int cim_rev;
+ struct scsi_device *sdev;
+@@ -1272,14 +1253,6 @@ mptctl_getiocinfo (unsigned long arg, un
+ return PTR_ERR(karg);
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- kfree(karg);
+- return -ENODEV;
+- }
+-
+ /* Verify the data transfer size is correct. */
+ if (karg->hdr.maxDataSize != data_size) {
+ printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
+@@ -1385,15 +1358,13 @@ mptctl_getiocinfo (unsigned long arg, un
+ * -ENODEV if no such device/adapter
+ */
+ static int
+-mptctl_gettargetinfo (unsigned long arg)
++mptctl_gettargetinfo (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+ struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
+ struct mpt_ioctl_targetinfo karg;
+- MPT_ADAPTER *ioc;
+ VirtDevice *vdevice;
+ char *pmem;
+ int *pdata;
+- int iocnum;
+ int numDevices = 0;
+ int lun;
+ int maxWordsLeft;
+@@ -1408,13 +1379,6 @@ mptctl_gettargetinfo (unsigned long arg)
+ return -EFAULT;
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+-
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_gettargetinfo called.\n",
+ ioc->name));
+ /* Get the port number and set the maximum number of bytes
+@@ -1510,12 +1474,10 @@ mptctl_gettargetinfo (unsigned long arg)
+ * -ENODEV if no such device/adapter
+ */
+ static int
+-mptctl_readtest (unsigned long arg)
++mptctl_readtest (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+ struct mpt_ioctl_test __user *uarg = (void __user *) arg;
+ struct mpt_ioctl_test karg;
+- MPT_ADAPTER *ioc;
+- int iocnum;
+
+ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
+ printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - "
+@@ -1524,13 +1486,6 @@ mptctl_readtest (unsigned long arg)
+ return -EFAULT;
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+-
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_readtest called.\n",
+ ioc->name));
+ /* Fill in the data and return the structure to the calling
+@@ -1571,12 +1526,10 @@ mptctl_readtest (unsigned long arg)
+ * -ENODEV if no such device/adapter
+ */
+ static int
+-mptctl_eventquery (unsigned long arg)
++mptctl_eventquery (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+ struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
+ struct mpt_ioctl_eventquery karg;
+- MPT_ADAPTER *ioc;
+- int iocnum;
+
+ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
+ printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - "
+@@ -1585,13 +1538,6 @@ mptctl_eventquery (unsigned long arg)
+ return -EFAULT;
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+-
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventquery called.\n",
+ ioc->name));
+ karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
+@@ -1610,12 +1556,10 @@ mptctl_eventquery (unsigned long arg)
+
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ static int
+-mptctl_eventenable (unsigned long arg)
++mptctl_eventenable (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+ struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
+ struct mpt_ioctl_eventenable karg;
+- MPT_ADAPTER *ioc;
+- int iocnum;
+
+ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
+ printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - "
+@@ -1624,13 +1568,6 @@ mptctl_eventenable (unsigned long arg)
+ return -EFAULT;
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+-
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventenable called.\n",
+ ioc->name));
+ if (ioc->events == NULL) {
+@@ -1658,12 +1595,10 @@ mptctl_eventenable (unsigned long arg)
+
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ static int
+-mptctl_eventreport (unsigned long arg)
++mptctl_eventreport (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+ struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
+ struct mpt_ioctl_eventreport karg;
+- MPT_ADAPTER *ioc;
+- int iocnum;
+ int numBytes, maxEvents, max;
+
+ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
+@@ -1673,12 +1608,6 @@ mptctl_eventreport (unsigned long arg)
+ return -EFAULT;
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n",
+ ioc->name));
+
+@@ -1712,12 +1641,10 @@ mptctl_eventreport (unsigned long arg)
+
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ static int
+-mptctl_replace_fw (unsigned long arg)
++mptctl_replace_fw (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+ struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
+ struct mpt_ioctl_replace_fw karg;
+- MPT_ADAPTER *ioc;
+- int iocnum;
+ int newFwSize;
+
+ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
+@@ -1727,13 +1654,6 @@ mptctl_replace_fw (unsigned long arg)
+ return -EFAULT;
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+-
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_replace_fw called.\n",
+ ioc->name));
+ /* If caching FW, Free the old FW image
+@@ -1780,12 +1700,10 @@ mptctl_replace_fw (unsigned long arg)
+ * -ENOMEM if memory allocation error
+ */
+ static int
+-mptctl_mpt_command (unsigned long arg)
++mptctl_mpt_command (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+ struct mpt_ioctl_command __user *uarg = (void __user *) arg;
+ struct mpt_ioctl_command karg;
+- MPT_ADAPTER *ioc;
+- int iocnum;
+ int rc;
+
+
+@@ -1796,14 +1714,7 @@ mptctl_mpt_command (unsigned long arg)
+ return -EFAULT;
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+-
+- rc = mptctl_do_mpt_command (karg, &uarg->MF);
++ rc = mptctl_do_mpt_command (ioc, karg, &uarg->MF);
+
+ return rc;
+ }
+@@ -1821,9 +1732,8 @@ mptctl_mpt_command (unsigned long arg)
+ * -EPERM if SCSI I/O and target is untagged
+ */
+ static int
+-mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
++mptctl_do_mpt_command (MPT_ADAPTER *ioc, struct mpt_ioctl_command karg, void __user *mfPtr)
+ {
+- MPT_ADAPTER *ioc;
+ MPT_FRAME_HDR *mf = NULL;
+ MPIHeader_t *hdr;
+ char *psge;
+@@ -1832,7 +1742,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ dma_addr_t dma_addr_in;
+ dma_addr_t dma_addr_out;
+ int sgSize = 0; /* Num SG elements */
+- int iocnum, flagsLength;
++ int flagsLength;
+ int sz, rc = 0;
+ int msgContext;
+ u16 req_idx;
+@@ -1847,13 +1757,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+ bufIn.kptr = bufOut.kptr = NULL;
+ bufIn.len = bufOut.len = 0;
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+-
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+ if (ioc->ioc_reset_in_progress) {
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+@@ -2418,17 +2321,15 @@ done_free_mem:
+ * -ENOMEM if memory allocation error
+ */
+ static int
+-mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
++mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
+ {
+ hp_host_info_t __user *uarg = (void __user *) arg;
+- MPT_ADAPTER *ioc;
+ struct pci_dev *pdev;
+ char *pbuf=NULL;
+ dma_addr_t buf_dma;
+ hp_host_info_t karg;
+ CONFIGPARMS cfg;
+ ConfigPageHeader_t hdr;
+- int iocnum;
+ int rc, cim_rev;
+ ToolboxIstwiReadWriteRequest_t *IstwiRWRequest;
+ MPT_FRAME_HDR *mf = NULL;
+@@ -2452,12 +2353,6 @@ mptctl_hp_hostinfo(unsigned long arg, un
+ return -EFAULT;
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n",
+ ioc->name));
+
+@@ -2670,15 +2565,13 @@ retry_wait:
+ * -ENOMEM if memory allocation error
+ */
+ static int
+-mptctl_hp_targetinfo(unsigned long arg)
++mptctl_hp_targetinfo(MPT_ADAPTER *ioc, unsigned long arg)
+ {
+ hp_target_info_t __user *uarg = (void __user *) arg;
+ SCSIDevicePage0_t *pg0_alloc;
+ SCSIDevicePage3_t *pg3_alloc;
+- MPT_ADAPTER *ioc;
+ MPT_SCSI_HOST *hd = NULL;
+ hp_target_info_t karg;
+- int iocnum;
+ int data_sz;
+ dma_addr_t page_dma;
+ CONFIGPARMS cfg;
+@@ -2692,12 +2585,6 @@ mptctl_hp_targetinfo(unsigned long arg)
+ return -EFAULT;
+ }
+
+- if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+- (ioc == NULL)) {
+- printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
+- __FILE__, __LINE__, iocnum);
+- return -ENODEV;
+- }
+ if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
+ return -EINVAL;
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
+@@ -2865,7 +2752,7 @@ compat_mptfwxfer_ioctl(struct file *filp
+ kfw.fwlen = kfw32.fwlen;
+ kfw.bufp = compat_ptr(kfw32.bufp);
+
+- ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
++ ret = mptctl_do_fw_download(iocp, kfw.bufp, kfw.fwlen);
+
+ mutex_unlock(&iocp->ioctl_cmds.mutex);
+
+@@ -2919,7 +2806,7 @@ compat_mpt_command(struct file *filp, un
+
+ /* Pass new structure to do_mpt_command
+ */
+- ret = mptctl_do_mpt_command (karg, &uarg->MF);
++ ret = mptctl_do_mpt_command (iocp, karg, &uarg->MF);
+
+ mutex_unlock(&iocp->ioctl_cmds.mutex);
+
fix-built-in-early-load-intel-microcode-alignment.patch
block-fix-an-integer-overflow-in-logical-block-size.patch
arm-dts-am571x-idk-fix-gpios-property-to-have-the-correct-gpio-number.patch
+iio-buffer-align-the-size-of-scan-bytes-to-size-of-the-largest-element.patch
+usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch
+usb-serial-option-add-support-for-quectel-rm500q.patch
+usb-serial-opticon-fix-control-message-timeouts.patch
+usb-serial-option-add-support-for-quectel-rm500q-in-qdl-mode.patch
+usb-serial-suppress-driver-bind-attributes.patch
+usb-serial-ch341-handle-unbound-port-at-reset_resume.patch
+usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch
+usb-serial-keyspan-handle-unbound-ports.patch
+usb-serial-quatech2-handle-unbound-ports.patch
+scsi-fnic-fix-invalid-stack-access.patch
+scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch
--- /dev/null
+From 4d5ef53f75c22d28f490bcc5c771fcc610a9afa4 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 17 Jan 2020 10:50:22 +0100
+Subject: USB: serial: ch341: handle unbound port at reset_resume
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 4d5ef53f75c22d28f490bcc5c771fcc610a9afa4 upstream.
+
+Check for NULL port data in reset_resume() to avoid dereferencing a NULL
+pointer in case the port device isn't bound to a driver (e.g. after a
+failed control request at port probe).
+
+Fixes: 1ded7ea47b88 ("USB: ch341 serial: fix port number changed after resume")
+Cc: stable <stable@vger.kernel.org> # 2.6.30
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ch341.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/ch341.c
++++ b/drivers/usb/serial/ch341.c
+@@ -592,9 +592,13 @@ static int ch341_tiocmget(struct tty_str
+ static int ch341_reset_resume(struct usb_serial *serial)
+ {
+ struct usb_serial_port *port = serial->port[0];
+- struct ch341_private *priv = usb_get_serial_port_data(port);
++ struct ch341_private *priv;
+ int ret;
+
++ priv = usb_get_serial_port_data(port);
++ if (!priv)
++ return 0;
++
+ /* reconfigure ch341 serial port after bus-reset */
+ ch341_configure(serial->dev, priv);
+
--- /dev/null
+From 1568c58d11a7c851bd09341aeefd6a1c308ac40d Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 17 Jan 2020 10:50:24 +0100
+Subject: USB: serial: io_edgeport: add missing active-port sanity check
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 1568c58d11a7c851bd09341aeefd6a1c308ac40d upstream.
+
+The driver receives the active port number from the device, but never
+made sure that the port number was valid. This could lead to a
+NULL-pointer dereference or memory corruption in case a device sends
+data for an invalid port.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/io_edgeport.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -1733,7 +1733,8 @@ static void edge_break(struct tty_struct
+ static void process_rcvd_data(struct edgeport_serial *edge_serial,
+ unsigned char *buffer, __u16 bufferLength)
+ {
+- struct device *dev = &edge_serial->serial->dev->dev;
++ struct usb_serial *serial = edge_serial->serial;
++ struct device *dev = &serial->dev->dev;
+ struct usb_serial_port *port;
+ struct edgeport_port *edge_port;
+ __u16 lastBufferLength;
+@@ -1838,9 +1839,8 @@ static void process_rcvd_data(struct edg
+
+ /* spit this data back into the tty driver if this
+ port is open */
+- if (rxLen) {
+- port = edge_serial->serial->port[
+- edge_serial->rxPort];
++ if (rxLen && edge_serial->rxPort < serial->num_ports) {
++ port = serial->port[edge_serial->rxPort];
+ edge_port = usb_get_serial_port_data(port);
+ if (edge_port->open) {
+ dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
+@@ -1850,8 +1850,8 @@ static void process_rcvd_data(struct edg
+ rxLen);
+ edge_port->port->icount.rx += rxLen;
+ }
+- buffer += rxLen;
+ }
++ buffer += rxLen;
+ break;
+
+ case EXPECT_HDR3: /* Expect 3rd byte of status header */
+@@ -1886,6 +1886,8 @@ static void process_rcvd_status(struct e
+ __u8 code = edge_serial->rxStatusCode;
+
+ /* switch the port pointer to the one being currently talked about */
++ if (edge_serial->rxPort >= edge_serial->serial->num_ports)
++ return;
+ port = edge_serial->serial->port[edge_serial->rxPort];
+ edge_port = usb_get_serial_port_data(port);
+ if (edge_port == NULL) {
--- /dev/null
+From 3018dd3fa114b13261e9599ddb5656ef97a1fa17 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 17 Jan 2020 10:50:25 +0100
+Subject: USB: serial: keyspan: handle unbound ports
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 3018dd3fa114b13261e9599ddb5656ef97a1fa17 upstream.
+
+Check for NULL port data in the control URB completion handlers to avoid
+dereferencing a NULL pointer in the unlikely case where a port device
+isn't bound to a driver (e.g. after an allocation failure on port
+probe()).
+
+Fixes: 0ca1268e109a ("USB Serial Keyspan: add support for USA-49WG & USA-28XG")
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/keyspan.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/serial/keyspan.c
++++ b/drivers/usb/serial/keyspan.c
+@@ -1062,6 +1062,8 @@ static void usa49_glocont_callback(struc
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ p_priv = usb_get_serial_port_data(port);
++ if (!p_priv)
++ continue;
+
+ if (p_priv->resend_cont) {
+ dev_dbg(&port->dev, "%s - sending setup\n", __func__);
+@@ -1463,6 +1465,8 @@ static void usa67_glocont_callback(struc
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ p_priv = usb_get_serial_port_data(port);
++ if (!p_priv)
++ continue;
+
+ if (p_priv->resend_cont) {
+ dev_dbg(&port->dev, "%s - sending setup\n", __func__);
--- /dev/null
+From 5e28055f340275a8616eee88ef19186631b4d136 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 13 Jan 2020 18:22:13 +0100
+Subject: USB: serial: opticon: fix control-message timeouts
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 5e28055f340275a8616eee88ef19186631b4d136 upstream.
+
+The driver was issuing synchronous uninterruptible control requests
+without using a timeout. This could lead to the driver hanging
+on open() or tiocmset() due to a malfunctioning (or malicious) device
+until the device is physically disconnected.
+
+The USB upper limit of five seconds per request should be more than
+enough.
+
+Fixes: 309a057932ab ("USB: opticon: add rts and cts support")
+Cc: stable <stable@vger.kernel.org> # 2.6.39
+Cc: Martin Jansen <martin.jansen@opticon.com>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/opticon.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/opticon.c
++++ b/drivers/usb/serial/opticon.c
+@@ -116,7 +116,7 @@ static int send_control_msg(struct usb_s
+ retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ requesttype,
+ USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+- 0, 0, buffer, 1, 0);
++ 0, 0, buffer, 1, USB_CTRL_SET_TIMEOUT);
+ kfree(buffer);
+
+ if (retval < 0)
--- /dev/null
+From f3eaabbfd093c93d791eb930cc68d9b15246a65e Mon Sep 17 00:00:00 2001
+From: Reinhard Speyerer <rspmn@arcor.de>
+Date: Tue, 14 Jan 2020 14:29:23 +0100
+Subject: USB: serial: option: add support for Quectel RM500Q in QDL mode
+
+From: Reinhard Speyerer <rspmn@arcor.de>
+
+commit f3eaabbfd093c93d791eb930cc68d9b15246a65e upstream.
+
+Add support for Quectel RM500Q in QDL mode.
+
+T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 24 Spd=480 MxCh= 0
+D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
+P: Vendor=2c7c ProdID=0800 Rev= 0.00
+S: Manufacturer=Qualcomm CDMA Technologies MSM
+S: Product=QUSB_BULK_SN:xxxxxxxx
+S: SerialNumber=xxxxxxxx
+C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 2mA
+I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=10 Driver=option
+E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+
+It is assumed that the ZLP flag required for other Qualcomm-based
+5G devices also applies to Quectel RM500Q.
+
+Signed-off-by: Reinhard Speyerer <rspmn@arcor.de>
+Cc: stable <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
+@@ -1110,6 +1110,8 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x30) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10),
++ .driver_info = ZLP },
+
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
--- /dev/null
+From accf227de4d211b52c830a58b2df00d5739f2389 Mon Sep 17 00:00:00 2001
+From: Kristian Evensen <kristian.evensen@gmail.com>
+Date: Mon, 13 Jan 2020 15:14:05 +0100
+Subject: USB: serial: option: Add support for Quectel RM500Q
+
+From: Kristian Evensen <kristian.evensen@gmail.com>
+
+commit accf227de4d211b52c830a58b2df00d5739f2389 upstream.
+
+RM500Q is a 5G module from Quectel, supporting both standalone and
+non-standalone modes. Unlike other recent Quectel modems, it is possible
+to identify the diagnostic interface (bInterfaceProtocol is unique).
+Thus, there is no need to check for the number of endpoints or reserve
+interfaces. The interface number is still dynamic though, so matching on
+interface number is not possible and two entries have to be added to the
+table.
+
+Output from usb-devices with all interfaces enabled (order is diag,
+nmea, at_port, modem, rmnet and adb):
+
+Bus 004 Device 007: ID 2c7c:0800 Quectel Wireless Solutions Co., Ltd.
+Device Descriptor:
+ bLength 18
+ bDescriptorType 1
+ bcdUSB 3.20
+ bDeviceClass 0 (Defined at Interface level)
+ bDeviceSubClass 0
+ bDeviceProtocol 0
+ bMaxPacketSize0 9
+ idVendor 0x2c7c Quectel Wireless Solutions Co., Ltd.
+ idProduct 0x0800
+ bcdDevice 4.14
+ iManufacturer 1 Quectel
+ iProduct 2 LTE-A Module
+ iSerial 3 40046d60
+ bNumConfigurations 1
+ Configuration Descriptor:
+ bLength 9
+ bDescriptorType 2
+ wTotalLength 328
+ bNumInterfaces 6
+ bConfigurationValue 1
+ iConfiguration 4 DIAG_SER_RMNET
+ bmAttributes 0xa0
+ (Bus Powered)
+ Remote Wakeup
+ MaxPower 224mA
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 0
+ bAlternateSetting 0
+ bNumEndpoints 2
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 255 Vendor Specific Subclass
+ bInterfaceProtocol 48
+ iInterface 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x81 EP 1 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x01 EP 1 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 1
+ bAlternateSetting 0
+ bNumEndpoints 3
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 0
+ bInterfaceProtocol 0
+ iInterface 0
+ ** UNRECOGNIZED: 05 24 00 10 01
+ ** UNRECOGNIZED: 05 24 01 00 00
+ ** UNRECOGNIZED: 04 24 02 02
+ ** UNRECOGNIZED: 05 24 06 00 00
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x83 EP 3 IN
+ bmAttributes 3
+ Transfer Type Interrupt
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x000a 1x 10 bytes
+ bInterval 9
+ bMaxBurst 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x82 EP 2 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x02 EP 2 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 2
+ bAlternateSetting 0
+ bNumEndpoints 3
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 0
+ bInterfaceProtocol 0
+ iInterface 0
+ ** UNRECOGNIZED: 05 24 00 10 01
+ ** UNRECOGNIZED: 05 24 01 00 00
+ ** UNRECOGNIZED: 04 24 02 02
+ ** UNRECOGNIZED: 05 24 06 00 00
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x85 EP 5 IN
+ bmAttributes 3
+ Transfer Type Interrupt
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x000a 1x 10 bytes
+ bInterval 9
+ bMaxBurst 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x84 EP 4 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x03 EP 3 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 3
+ bAlternateSetting 0
+ bNumEndpoints 3
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 0
+ bInterfaceProtocol 0
+ iInterface 0
+ ** UNRECOGNIZED: 05 24 00 10 01
+ ** UNRECOGNIZED: 05 24 01 00 00
+ ** UNRECOGNIZED: 04 24 02 02
+ ** UNRECOGNIZED: 05 24 06 00 00
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x87 EP 7 IN
+ bmAttributes 3
+ Transfer Type Interrupt
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x000a 1x 10 bytes
+ bInterval 9
+ bMaxBurst 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x86 EP 6 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x04 EP 4 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 4
+ bAlternateSetting 0
+ bNumEndpoints 3
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 255 Vendor Specific Subclass
+ bInterfaceProtocol 255 Vendor Specific Protocol
+ iInterface 5 CDEV Serial
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x88 EP 8 IN
+ bmAttributes 3
+ Transfer Type Interrupt
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0008 1x 8 bytes
+ bInterval 9
+ bMaxBurst 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x8e EP 14 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 6
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x0f EP 15 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 2
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 5
+ bAlternateSetting 0
+ bNumEndpoints 2
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 66
+ bInterfaceProtocol 1
+ iInterface 6 ADB Interface
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x05 EP 5 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x89 EP 9 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0400 1x 1024 bytes
+ bInterval 0
+ bMaxBurst 0
+Binary Object Store Descriptor:
+ bLength 5
+ bDescriptorType 15
+ wTotalLength 42
+ bNumDeviceCaps 3
+ USB 2.0 Extension Device Capability:
+ bLength 7
+ bDescriptorType 16
+ bDevCapabilityType 2
+ bmAttributes 0x00000006
+ Link Power Management (LPM) Supported
+ SuperSpeed USB Device Capability:
+ bLength 10
+ bDescriptorType 16
+ bDevCapabilityType 3
+ bmAttributes 0x00
+ wSpeedsSupported 0x000f
+ Device can operate at Low Speed (1Mbps)
+ Device can operate at Full Speed (12Mbps)
+ Device can operate at High Speed (480Mbps)
+ Device can operate at SuperSpeed (5Gbps)
+ bFunctionalitySupport 1
+ Lowest fully-functional device speed is Full Speed (12Mbps)
+ bU1DevExitLat 1 micro seconds
+ bU2DevExitLat 500 micro seconds
+ ** UNRECOGNIZED: 14 10 0a 00 01 00 00 00 00 11 00 00 30 40 0a 00 b0 40 0a 00
+Device Status: 0x0000
+ (Bus Powered)
+
+Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
+Cc: stable <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 | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -251,6 +251,7 @@ static void option_instat_callback(struc
+ #define QUECTEL_PRODUCT_BG96 0x0296
+ #define QUECTEL_PRODUCT_EP06 0x0306
+ #define QUECTEL_PRODUCT_EM12 0x0512
++#define QUECTEL_PRODUCT_RM500Q 0x0800
+
+ #define CMOTECH_VENDOR_ID 0x16d8
+ #define CMOTECH_PRODUCT_6001 0x6001
+@@ -1107,6 +1108,9 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff),
+ .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x30) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) },
++
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
--- /dev/null
+From 9715a43eea77e42678a1002623f2d9a78f5b81a1 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 17 Jan 2020 15:35:26 +0100
+Subject: USB: serial: quatech2: handle unbound ports
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 9715a43eea77e42678a1002623f2d9a78f5b81a1 upstream.
+
+Check for NULL port data in the modem- and line-status handlers to avoid
+dereferencing a NULL pointer in the unlikely case where a port device
+isn't bound to a driver (e.g. after an allocation failure on port
+probe).
+
+Note that the other (stubbed) event handlers qt2_process_xmit_empty()
+and qt2_process_flush() would need similar sanity checks in case they
+are ever implemented.
+
+Fixes: f7a33e608d9a ("USB: serial: add quatech2 usb to serial driver")
+Cc: stable <stable@vger.kernel.org> # 3.5
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/quatech2.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/usb/serial/quatech2.c
++++ b/drivers/usb/serial/quatech2.c
+@@ -867,7 +867,10 @@ static void qt2_update_msr(struct usb_se
+ u8 newMSR = (u8) *ch;
+ unsigned long flags;
+
++ /* May be called from qt2_process_read_urb() for an unbound port. */
+ port_priv = usb_get_serial_port_data(port);
++ if (!port_priv)
++ return;
+
+ spin_lock_irqsave(&port_priv->lock, flags);
+ port_priv->shadowMSR = newMSR;
+@@ -895,7 +898,10 @@ static void qt2_update_lsr(struct usb_se
+ unsigned long flags;
+ u8 newLSR = (u8) *ch;
+
++ /* May be called from qt2_process_read_urb() for an unbound port. */
+ port_priv = usb_get_serial_port_data(port);
++ if (!port_priv)
++ return;
+
+ if (newLSR & UART_LSR_BI)
+ newLSR &= (u8) (UART_LSR_OE | UART_LSR_BI);
--- /dev/null
+From 260e41ac4dd3e5acb90be624c03ba7f019615b75 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jer=C3=B3nimo=20Borque?= <jeronimo@borque.com.ar>
+Date: Thu, 9 Jan 2020 12:23:34 -0300
+Subject: USB: serial: simple: Add Motorola Solutions TETRA MTP3xxx and MTP85xx
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jerónimo Borque <jeronimo@borque.com.ar>
+
+commit 260e41ac4dd3e5acb90be624c03ba7f019615b75 upstream.
+
+Add device-ids for the Motorola Solutions TETRA radios MTP3xxx series
+and MTP85xx series
+
+$ lsusb -vd 0cad:
+
+Bus 001 Device 009: ID 0cad:9015 Motorola CGISS TETRA PEI interface
+Device Descriptor:
+ bLength 18
+ bDescriptorType 1
+ bcdUSB 2.00
+ bDeviceClass 0
+ bDeviceSubClass 0
+ bDeviceProtocol 0
+ bMaxPacketSize0 64
+ idVendor 0x0cad Motorola CGISS
+ idProduct 0x9015
+ bcdDevice 24.16
+ iManufacturer 1
+ iProduct 2
+ iSerial 0
+ bNumConfigurations 1
+ Configuration Descriptor:
+ bLength 9
+ bDescriptorType 2
+ wTotalLength 0x0037
+ bNumInterfaces 2
+ bConfigurationValue 1
+ iConfiguration 3
+ bmAttributes 0x80
+ (Bus Powered)
+ MaxPower 500mA
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 0
+ bAlternateSetting 0
+ bNumEndpoints 2
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 0
+ bInterfaceProtocol 0
+ iInterface 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x81 EP 1 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0040 1x 64 bytes
+ bInterval 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x01 EP 1 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0040 1x 64 bytes
+ bInterval 0
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 1
+ bAlternateSetting 0
+ bNumEndpoints 2
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 0
+ bInterfaceProtocol 0
+ iInterface 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x82 EP 2 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0040 1x 64 bytes
+ bInterval 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x02 EP 2 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0040 1x 64 bytes
+ bInterval 0
+
+Bus 001 Device 010: ID 0cad:9013 Motorola CGISS TETRA PEI interface
+Device Descriptor:
+ bLength 18
+ bDescriptorType 1
+ bcdUSB 2.00
+ bDeviceClass 0
+ bDeviceSubClass 0
+ bDeviceProtocol 0
+ bMaxPacketSize0 64
+ idVendor 0x0cad Motorola CGISS
+ idProduct 0x9013
+ bcdDevice 24.16
+ iManufacturer 1
+ iProduct 2
+ iSerial 0
+ bNumConfigurations 1
+ Configuration Descriptor:
+ bLength 9
+ bDescriptorType 2
+ wTotalLength 0x0037
+ bNumInterfaces 2
+ bConfigurationValue 1
+ iConfiguration 3
+ bmAttributes 0x80
+ (Bus Powered)
+ MaxPower 500mA
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 0
+ bAlternateSetting 0
+ bNumEndpoints 2
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 0
+ bInterfaceProtocol 0
+ iInterface 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x81 EP 1 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0200 1x 512 bytes
+ bInterval 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x01 EP 1 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0200 1x 512 bytes
+ bInterval 0
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 1
+ bAlternateSetting 0
+ bNumEndpoints 2
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 0
+ bInterfaceProtocol 0
+ iInterface 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x82 EP 2 IN
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0200 1x 512 bytes
+ bInterval 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x02 EP 2 OUT
+ bmAttributes 2
+ Transfer Type Bulk
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0200 1x 512 bytes
+ bInterval 0
+
+Signed-off-by: Jerónimo Borque <jeronimo@borque.com.ar>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/usb-serial-simple.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/usb-serial-simple.c
++++ b/drivers/usb/serial/usb-serial-simple.c
+@@ -89,6 +89,8 @@ DEVICE(moto_modem, MOTO_IDS);
+ #define MOTOROLA_TETRA_IDS() \
+ { USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \
+ { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \
++ { USB_DEVICE(0x0cad, 0x9013) }, /* MTP3xxx */ \
++ { USB_DEVICE(0x0cad, 0x9015) }, /* MTP85xx */ \
+ { USB_DEVICE(0x0cad, 0x9016) } /* TPG2200 */
+ DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
+
--- /dev/null
+From fdb838efa31e1ed9a13ae6ad0b64e30fdbd00570 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Thu, 16 Jan 2020 17:07:05 +0100
+Subject: USB: serial: suppress driver bind attributes
+
+From: Johan Hovold <johan@kernel.org>
+
+commit fdb838efa31e1ed9a13ae6ad0b64e30fdbd00570 upstream.
+
+USB-serial drivers must not be unbound from their ports before the
+corresponding USB driver is unbound from the parent interface so
+suppress the bind and unbind attributes.
+
+Unbinding a serial driver while it's port is open is a sure way to
+trigger a crash as any driver state is released on unbind while port
+hangup is handled on the parent USB interface level. Drivers for
+multiport devices where ports share a resource such as an interrupt
+endpoint also generally cannot handle individual ports going away.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/usb-serial.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -1332,6 +1332,9 @@ static int usb_serial_register(struct us
+ return -EINVAL;
+ }
+
++ /* Prevent individual ports from being unbound. */
++ driver->driver.suppress_bind_attrs = true;
++
+ usb_serial_operations_init(driver);
+
+ /* Add this device to our list of devices */