--- /dev/null
+From d7857e4ee1ba69732b16c73b2f2dde83ecd78ee4 Mon Sep 17 00:00:00 2001
+From: Alexandru Tachici <alexandru.tachici@analog.com>
+Date: Fri, 20 Dec 2019 12:07:19 +0200
+Subject: iio: adc: ad7124: Fix DT channel configuration
+
+From: Alexandru Tachici <alexandru.tachici@analog.com>
+
+commit d7857e4ee1ba69732b16c73b2f2dde83ecd78ee4 upstream.
+
+This patch fixes device tree channel configuration.
+
+ad7124 driver reads channels configuration from the device tree.
+It expects to find channel specifications as child nodes.
+Before this patch ad7124 driver assumed that the child nodes are parsed
+by for_each_available_child_of_node in the order 0,1,2,3...
+
+This is wrong and the real order of the children can be seen by running:
+dtc -I fs /sys/firmware/devicetree/base on the machine.
+
+For example, running this on an rpi 3B+ yields the real
+children order: 4,2,0,7,5,3,1,6
+
+Before this patch the driver assigned the channel configuration
+like this:
+ - 0 <- 4
+ - 1 <- 2
+ - 2 <- 0
+ ........
+For example, the symptoms can be observed by connecting the 4th channel
+to a 1V tension and then reading the in_voltage0-voltage19_raw sysfs
+(multiplied of course by the scale) one would see that channel 0
+measures 1V and channel 4 measures only noise.
+
+Now the driver uses the reg property of each child in order to
+correctly identify to which channel the parsed configuration
+belongs to.
+
+Fixes b3af341bbd966: ("iio: adc: Add ad7124 support")
+Signed-off-by: Alexandru Tachici <alexandru.tachici@analog.com>
+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/adc/ad7124.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/iio/adc/ad7124.c
++++ b/drivers/iio/adc/ad7124.c
+@@ -494,13 +494,11 @@ static int ad7124_of_parse_channel_confi
+ st->channel_config[channel].buf_negative =
+ of_property_read_bool(child, "adi,buffered-negative");
+
+- *chan = ad7124_channel_template;
+- chan->address = channel;
+- chan->scan_index = channel;
+- chan->channel = ain[0];
+- chan->channel2 = ain[1];
+-
+- chan++;
++ chan[channel] = ad7124_channel_template;
++ chan[channel].address = channel;
++ chan[channel].scan_index = channel;
++ chan[channel].channel = ain[0];
++ chan[channel].channel2 = ain[1];
+ }
+
+ return 0;
--- /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
+@@ -566,7 +566,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,
+@@ -574,13 +574,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 217afe63ccf445fc220e5ef480683607b05c0aa5 Mon Sep 17 00:00:00 2001
+From: Tomasz Duszynski <tduszyns@gmail.com>
+Date: Fri, 13 Dec 2019 22:38:08 +0100
+Subject: iio: chemical: pms7003: fix unmet triggered buffer dependency
+
+From: Tomasz Duszynski <tduszyns@gmail.com>
+
+commit 217afe63ccf445fc220e5ef480683607b05c0aa5 upstream.
+
+IIO triggered buffer depends on IIO buffer which is missing from Kconfig
+file. This should go unnoticed most of the time because there's a
+chance something else has already enabled buffers. In some rare cases
+though one might experience kbuild warnings about unmet direct
+dependencies and build failures due to missing symbols.
+
+Fix this by selecting IIO_BUFFER explicitly.
+
+Signed-off-by: Tomasz Duszynski <tduszyns@gmail.com>
+Fixes: a1d642266c14 ("iio: chemical: add support for Plantower PMS7003 sensor")
+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/chemical/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/iio/chemical/Kconfig
++++ b/drivers/iio/chemical/Kconfig
+@@ -65,6 +65,7 @@ config IAQCORE
+ config PMS7003
+ tristate "Plantower PMS7003 particulate matter sensor"
+ depends on SERIAL_DEV_BUS
++ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say Y here to build support for the Plantower PMS7003 particulate
--- /dev/null
+From fb4fbc8904e786537e29329d791147389e1465a2 Mon Sep 17 00:00:00 2001
+From: Stephan Gerhold <stephan@gerhold.net>
+Date: Mon, 16 Dec 2019 13:41:20 +0100
+Subject: iio: imu: st_lsm6dsx: Fix selection of ST_LSM6DS3_ID
+
+From: Stephan Gerhold <stephan@gerhold.net>
+
+commit fb4fbc8904e786537e29329d791147389e1465a2 upstream.
+
+At the moment, attempting to probe a device with ST_LSM6DS3_ID
+(e.g. using the st,lsm6ds3 compatible) fails with:
+
+ st_lsm6dsx_i2c 1-006b: unsupported whoami [69]
+
+... even though 0x69 is the whoami listed for ST_LSM6DS3_ID.
+
+This happens because st_lsm6dsx_check_whoami() also attempts
+to match unspecified (zero-initialized) entries in the "id" array.
+ST_LSM6DS3_ID = 0 will therefore match any entry in
+st_lsm6dsx_sensor_settings (here: the first), because none of them
+actually have all 12 entries listed in the "id" array.
+
+Avoid this by additionally checking if "name" is set,
+which is only set for valid entries in the "id" array.
+
+Note: Although the problem was introduced earlier it did not surface until
+commit 52f4b1f19679 ("iio: imu: st_lsm6dsx: add support for accel/gyro unit of lsm9ds1")
+because ST_LSM6DS3_ID was the first entry in st_lsm6dsx_sensor_settings.
+
+Fixes: d068e4a0f921 ("iio: imu: st_lsm6dsx: add support to multiple devices with the same settings")
+Cc: <stable@vger.kernel.org> # 5.4
+Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+@@ -911,7 +911,8 @@ static int st_lsm6dsx_check_whoami(struc
+
+ for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
+ for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) {
+- if (id == st_lsm6dsx_sensor_settings[i].id[j].hw_id)
++ if (st_lsm6dsx_sensor_settings[i].id[j].name &&
++ id == st_lsm6dsx_sensor_settings[i].id[j].hw_id)
+ break;
+ }
+ if (j < ST_LSM6DSX_MAX_ID)
--- /dev/null
+From bc80573ea25bb033a58da81b3ce27205b97c088e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Fri, 27 Dec 2019 11:22:54 +0100
+Subject: iio: light: vcnl4000: Fix scale for vcnl4040
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guido Günther <agx@sigxcpu.org>
+
+commit bc80573ea25bb033a58da81b3ce27205b97c088e upstream.
+
+According to the data sheet the ambient sensor's scale is 0.12 lux/step
+(not 0.024 lux/step as used by vcnl4200) when the integration time is
+80ms. The integration time is currently hardcoded in the driver to that
+value.
+
+See p. 8 in https://www.vishay.com/docs/84307/designingvcnl4040.pdf
+
+Fixes: 5a441aade5b3 ("iio: light: vcnl4000 add support for the VCNL4040 proximity and light sensor")
+Signed-off-by: Guido Günther <agx@sigxcpu.org>
+Reviewed-by: Marco Felsch <m.felsch@pengutronix.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/light/vcnl4000.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/iio/light/vcnl4000.c
++++ b/drivers/iio/light/vcnl4000.c
+@@ -163,7 +163,6 @@ static int vcnl4200_init(struct vcnl4000
+ if (ret < 0)
+ return ret;
+
+- data->al_scale = 24000;
+ data->vcnl4200_al.reg = VCNL4200_AL_DATA;
+ data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
+ switch (id) {
+@@ -172,11 +171,13 @@ static int vcnl4200_init(struct vcnl4000
+ /* show 54ms in total. */
+ data->vcnl4200_al.sampling_rate = ktime_set(0, 54000 * 1000);
+ data->vcnl4200_ps.sampling_rate = ktime_set(0, 4200 * 1000);
++ data->al_scale = 24000;
+ break;
+ case VCNL4040_PROD_ID:
+ /* Integration time is 80ms, add 10ms. */
+ data->vcnl4200_al.sampling_rate = ktime_set(0, 100000 * 1000);
+ data->vcnl4200_ps.sampling_rate = ktime_set(0, 100000 * 1000);
++ data->al_scale = 120000;
+ break;
+ }
+ data->vcnl4200_al.last_measurement = ktime_set(0, 0);
--- /dev/null
+From da9ec3d3dd0f1240a48920be063448a2242dbd90 Mon Sep 17 00:00:00 2001
+From: Mark Rutland <mark.rutland@arm.com>
+Date: Mon, 6 Jan 2020 12:03:39 +0000
+Subject: perf: Correctly handle failed perf_get_aux_event()
+
+From: Mark Rutland <mark.rutland@arm.com>
+
+commit da9ec3d3dd0f1240a48920be063448a2242dbd90 upstream.
+
+Vince reports a worrying issue:
+
+| so I was tracking down some odd behavior in the perf_fuzzer which turns
+| out to be because perf_even_open() sometimes returns 0 (indicating a file
+| descriptor of 0) even though as far as I can tell stdin is still open.
+
+... and further the cause:
+
+| error is triggered if aux_sample_size has non-zero value.
+|
+| seems to be this line in kernel/events/core.c:
+|
+| if (perf_need_aux_event(event) && !perf_get_aux_event(event, group_leader))
+| goto err_locked;
+|
+| (note, err is never set)
+
+This seems to be a thinko in commit:
+
+ ab43762ef010967e ("perf: Allow normal events to output AUX data")
+
+... and we should probably return -EINVAL here, as this should only
+happen when the new event is mis-configured or does not have a
+compatible aux_event group leader.
+
+Fixes: ab43762ef010967e ("perf: Allow normal events to output AUX data")
+Reported-by: Vince Weaver <vincent.weaver@maine.edu>
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Tested-by: Vince Weaver <vincent.weaver@maine.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/events/core.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -11182,8 +11182,10 @@ SYSCALL_DEFINE5(perf_event_open,
+ }
+ }
+
+- if (event->attr.aux_output && !perf_get_aux_event(event, group_leader))
++ if (event->attr.aux_output && !perf_get_aux_event(event, group_leader)) {
++ err = -EINVAL;
+ goto err_locked;
++ }
+
+ /*
+ * Must be under the same ctx::mutex as perf_install_in_context(),
--- /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
+@@ -688,26 +688,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;
+ }
+@@ -732,30 +732,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));
+
+@@ -2659,15 +2554,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;
+@@ -2681,12 +2574,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",
+@@ -2854,7 +2741,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);
+
+@@ -2908,7 +2795,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);
+
cpuidle-teo-fix-intervals-array-indexing-bug.patch
arm-dts-am571x-idk-fix-gpios-property-to-have-the-correct-gpio-number.patch
arm-davinci-select-config_reset_controller.patch
+perf-correctly-handle-failed-perf_get_aux_event.patch
+iio-adc-ad7124-fix-dt-channel-configuration.patch
+iio-imu-st_lsm6dsx-fix-selection-of-st_lsm6ds3_id.patch
+iio-light-vcnl4000-fix-scale-for-vcnl4040.patch
+iio-chemical-pms7003-fix-unmet-triggered-buffer-dependency.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-handle-unbound-ports-on-urb-completion.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
+staging-comedi-ni_routes-fix-null-dereference-in-ni_find_route_source.patch
+staging-comedi-ni_routes-allow-partial-routing-information.patch
+scsi-fnic-fix-invalid-stack-access.patch
+scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch
--- /dev/null
+From 9fea3a40f6b07de977a2783270c8c3bc82544d45 Mon Sep 17 00:00:00 2001
+From: Ian Abbott <abbotti@mev.co.uk>
+Date: Tue, 14 Jan 2020 18:25:32 +0000
+Subject: staging: comedi: ni_routes: allow partial routing information
+
+From: Ian Abbott <abbotti@mev.co.uk>
+
+commit 9fea3a40f6b07de977a2783270c8c3bc82544d45 upstream.
+
+This patch fixes a regression on setting up asynchronous commands to use
+external trigger sources when board-specific routing information is
+missing.
+
+`ni_find_device_routes()` (called via `ni_assign_device_routes()`) finds
+the table of register values for the device family and the set of valid
+routes for the specific board. If both are found,
+`tables->route_values` is set to point to the table of register values
+for the device family and `tables->valid_routes` is set to point to the
+list of valid routes for the specific board. If either is not found,
+both `tables->route_values` and `tables->valid_routes` are left set at
+their initial null values (initialized by `ni_assign_device_routes()`)
+and the function returns `-ENODATA`.
+
+Returning an error results in some routing functionality being disabled.
+Unfortunately, leaving `table->route_values` set to `NULL` also breaks
+the setting up of asynchronous commands that are configured to use
+external trigger sources. Calls to `ni_check_trigger_arg()` or
+`ni_check_trigger_arg_roffs()` while checking the asynchronous command
+set-up would result in a null pointer dereference if
+`table->route_values` is `NULL`. The null pointer dereference is fixed
+in another patch, but it now results in failure to set up the
+asynchronous command. That is a regression from the behavior prior to
+commit 347e244884c3 ("staging: comedi: tio: implement global tio/ctr
+routing") and commit 56d0b826d39f ("staging: comedi: ni_mio_common:
+implement new routing for TRIG_EXT").
+
+Change `ni_find_device_routes()` to set `tables->route_values` and/or
+`tables->valid_routes` to valid information even if the other one can
+only be set to `NULL` due to missing information. The function will
+still return an error in that case. This should result in
+`tables->valid_routes` being valid for all currently supported device
+families even if the board-specific routing information is missing.
+That should be enough to fix the regression on setting up asynchronous
+commands to use external triggers for boards with missing routing
+information.
+
+Fixes: 347e244884c3 ("staging: comedi: tio: implement global tio/ctr routing")
+Fixes: 56d0b826d39f ("staging: comedi: ni_mio_common: implement new routing for TRIG_EXT").
+Cc: <stable@vger.kernel.org> # 4.20+
+Cc: Spencer E. Olson <olsonse@umich.edu>
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Link: https://lore.kernel.org/r/20200114182532.132058-3-abbotti@mev.co.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/drivers/ni_routes.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/ni_routes.c
++++ b/drivers/staging/comedi/drivers/ni_routes.c
+@@ -74,9 +74,6 @@ static int ni_find_device_routes(const c
+ }
+ }
+
+- if (!rv)
+- return -ENODATA;
+-
+ /* Second, find the set of routes valid for this device. */
+ for (i = 0; ni_device_routes_list[i]; ++i) {
+ if (memcmp(ni_device_routes_list[i]->device, board_name,
+@@ -86,12 +83,12 @@ static int ni_find_device_routes(const c
+ }
+ }
+
+- if (!dr)
+- return -ENODATA;
+-
+ tables->route_values = rv;
+ tables->valid_routes = dr;
+
++ if (!rv || !dr)
++ return -ENODATA;
++
+ return 0;
+ }
+
--- /dev/null
+From 01e20b664f808a4f3048ca3f930911fd257209bd Mon Sep 17 00:00:00 2001
+From: Ian Abbott <abbotti@mev.co.uk>
+Date: Tue, 14 Jan 2020 18:25:31 +0000
+Subject: staging: comedi: ni_routes: fix null dereference in ni_find_route_source()
+
+From: Ian Abbott <abbotti@mev.co.uk>
+
+commit 01e20b664f808a4f3048ca3f930911fd257209bd upstream.
+
+In `ni_find_route_source()`, `tables->route_values` gets dereferenced.
+However it is possible that `tables->route_values` is `NULL`, leading to
+a null pointer dereference. `tables->route_values` will be `NULL` if
+the call to `ni_assign_device_routes()` during board initialization
+returned an error due to missing device family routing information or
+missing board-specific routing information. For example, there is
+currently no board-specific routing information provided for the
+PCIe-6251 board and several other boards, so those are affected by this
+bug.
+
+The bug is triggered when `ni_find_route_source()` is called via
+`ni_check_trigger_arg()` or `ni_check_trigger_arg_roffs()` when checking
+the arguments for setting up asynchronous commands. Fix it by returning
+`-EINVAL` if `tables->route_values` is `NULL`.
+
+Even with this fix, setting up asynchronous commands to use external
+trigger sources for boards with missing routing information will still
+fail gracefully. Since `ni_find_route_source()` only depends on the
+device family routing information, it would be better if that was made
+available even if the board-specific routing information is missing.
+That will be addressed by another patch.
+
+Fixes: 4bb90c87abbe ("staging: comedi: add interface to ni routing table information")
+Cc: <stable@vger.kernel.org> # 4.20+
+Cc: Spencer E. Olson <olsonse@umich.edu>
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Link: https://lore.kernel.org/r/20200114182532.132058-2-abbotti@mev.co.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/drivers/ni_routes.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/staging/comedi/drivers/ni_routes.c
++++ b/drivers/staging/comedi/drivers/ni_routes.c
+@@ -489,6 +489,9 @@ int ni_find_route_source(const u8 src_se
+ {
+ int src;
+
++ if (!tables->route_values)
++ return -EINVAL;
++
+ dest = B(dest); /* subtract NI names offset */
+ /* ensure we are not going to under/over run the route value table */
+ if (dest < 0 || dest >= NI_NUM_NAMES)
--- /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
+@@ -589,9 +589,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
+@@ -1725,7 +1725,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;
+@@ -1821,9 +1822,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 && edge_port->open) {
+ dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
+@@ -1833,8 +1833,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 */
+@@ -1869,6 +1869,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 e37d1aeda737a20b1846a91a3da3f8b0f00cf690 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 17 Jan 2020 10:50:23 +0100
+Subject: USB: serial: io_edgeport: handle unbound ports on URB completion
+
+From: Johan Hovold <johan@kernel.org>
+
+commit e37d1aeda737a20b1846a91a3da3f8b0f00cf690 upstream.
+
+Check for NULL port data in the shared interrupt and bulk completion
+callbacks to avoid dereferencing a NULL pointer in case a device sends
+data for a port device which isn't bound to a driver (e.g. due to a
+malicious device having unexpected endpoints or after an allocation
+failure on port probe).
+
+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 | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -716,7 +716,7 @@ static void edge_interrupt_callback(stru
+ if (txCredits) {
+ port = edge_serial->serial->port[portNumber];
+ edge_port = usb_get_serial_port_data(port);
+- if (edge_port->open) {
++ if (edge_port && edge_port->open) {
+ spin_lock_irqsave(&edge_port->ep_lock,
+ flags);
+ edge_port->txCredits += txCredits;
+@@ -1825,7 +1825,7 @@ static void process_rcvd_data(struct edg
+ port = edge_serial->serial->port[
+ edge_serial->rxPort];
+ edge_port = usb_get_serial_port_data(port);
+- if (edge_port->open) {
++ if (edge_port && edge_port->open) {
+ dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
+ __func__, rxLen,
+ edge_serial->rxPort);
--- /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
+@@ -1058,6 +1058,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__);
+@@ -1459,6 +1461,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
+@@ -113,7 +113,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
+@@ -1107,6 +1107,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
+@@ -248,6 +248,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
+@@ -1104,6 +1105,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
+@@ -841,7 +841,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;
+@@ -869,7 +872,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
+@@ -86,6 +86,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
+@@ -1317,6 +1317,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 */