From: Greg Kroah-Hartman Date: Sun, 19 Jan 2020 13:49:00 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v4.4.211~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a713a68fe5fcad309ad9bbda9ac5e455f7e11607;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: iio-adc-ad7124-fix-dt-channel-configuration.patch iio-buffer-align-the-size-of-scan-bytes-to-size-of-the-largest-element.patch iio-chemical-pms7003-fix-unmet-triggered-buffer-dependency.patch iio-imu-st_lsm6dsx-fix-selection-of-st_lsm6ds3_id.patch iio-light-vcnl4000-fix-scale-for-vcnl4040.patch perf-correctly-handle-failed-perf_get_aux_event.patch scsi-fnic-fix-invalid-stack-access.patch scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch staging-comedi-ni_routes-allow-partial-routing-information.patch staging-comedi-ni_routes-fix-null-dereference-in-ni_find_route_source.patch usb-serial-ch341-handle-unbound-port-at-reset_resume.patch usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch usb-serial-io_edgeport-handle-unbound-ports-on-urb-completion.patch usb-serial-keyspan-handle-unbound-ports.patch usb-serial-opticon-fix-control-message-timeouts.patch usb-serial-option-add-support-for-quectel-rm500q-in-qdl-mode.patch usb-serial-option-add-support-for-quectel-rm500q.patch usb-serial-quatech2-handle-unbound-ports.patch usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch usb-serial-suppress-driver-bind-attributes.patch --- diff --git a/queue-5.4/iio-adc-ad7124-fix-dt-channel-configuration.patch b/queue-5.4/iio-adc-ad7124-fix-dt-channel-configuration.patch new file mode 100644 index 00000000000..28b60bdbeaf --- /dev/null +++ b/queue-5.4/iio-adc-ad7124-fix-dt-channel-configuration.patch @@ -0,0 +1,68 @@ +From d7857e4ee1ba69732b16c73b2f2dde83ecd78ee4 Mon Sep 17 00:00:00 2001 +From: Alexandru Tachici +Date: Fri, 20 Dec 2019 12:07:19 +0200 +Subject: iio: adc: ad7124: Fix DT channel configuration + +From: Alexandru Tachici + +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 +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-5.4/iio-buffer-align-the-size-of-scan-bytes-to-size-of-the-largest-element.patch b/queue-5.4/iio-buffer-align-the-size-of-scan-bytes-to-size-of-the-largest-element.patch new file mode 100644 index 00000000000..2820fc74ed0 --- /dev/null +++ b/queue-5.4/iio-buffer-align-the-size-of-scan-bytes-to-size-of-the-largest-element.patch @@ -0,0 +1,61 @@ +From 883f616530692d81cb70f8a32d85c0d2afc05f69 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lars=20M=C3=B6llendorf?= +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 + +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 +Reviewed-by: Lars-Peter Clausen +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } + diff --git a/queue-5.4/iio-chemical-pms7003-fix-unmet-triggered-buffer-dependency.patch b/queue-5.4/iio-chemical-pms7003-fix-unmet-triggered-buffer-dependency.patch new file mode 100644 index 00000000000..6cd29424b39 --- /dev/null +++ b/queue-5.4/iio-chemical-pms7003-fix-unmet-triggered-buffer-dependency.patch @@ -0,0 +1,37 @@ +From 217afe63ccf445fc220e5ef480683607b05c0aa5 Mon Sep 17 00:00:00 2001 +From: Tomasz Duszynski +Date: Fri, 13 Dec 2019 22:38:08 +0100 +Subject: iio: chemical: pms7003: fix unmet triggered buffer dependency + +From: Tomasz Duszynski + +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 +Fixes: a1d642266c14 ("iio: chemical: add support for Plantower PMS7003 sensor") +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + 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 diff --git a/queue-5.4/iio-imu-st_lsm6dsx-fix-selection-of-st_lsm6ds3_id.patch b/queue-5.4/iio-imu-st_lsm6dsx-fix-selection-of-st_lsm6ds3_id.patch new file mode 100644 index 00000000000..c3acbb379bb --- /dev/null +++ b/queue-5.4/iio-imu-st_lsm6dsx-fix-selection-of-st_lsm6ds3_id.patch @@ -0,0 +1,52 @@ +From fb4fbc8904e786537e29329d791147389e1465a2 Mon Sep 17 00:00:00 2001 +From: Stephan Gerhold +Date: Mon, 16 Dec 2019 13:41:20 +0100 +Subject: iio: imu: st_lsm6dsx: Fix selection of ST_LSM6DS3_ID + +From: Stephan Gerhold + +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: # 5.4 +Acked-by: Lorenzo Bianconi +Signed-off-by: Stephan Gerhold +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-5.4/iio-light-vcnl4000-fix-scale-for-vcnl4040.patch b/queue-5.4/iio-light-vcnl4000-fix-scale-for-vcnl4040.patch new file mode 100644 index 00000000000..6473eb4fb5b --- /dev/null +++ b/queue-5.4/iio-light-vcnl4000-fix-scale-for-vcnl4040.patch @@ -0,0 +1,54 @@ +From bc80573ea25bb033a58da81b3ce27205b97c088e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Guido=20G=C3=BCnther?= +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 + +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 +Reviewed-by: Marco Felsch +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-5.4/perf-correctly-handle-failed-perf_get_aux_event.patch b/queue-5.4/perf-correctly-handle-failed-perf_get_aux_event.patch new file mode 100644 index 00000000000..7cc3fe6ae83 --- /dev/null +++ b/queue-5.4/perf-correctly-handle-failed-perf_get_aux_event.patch @@ -0,0 +1,61 @@ +From da9ec3d3dd0f1240a48920be063448a2242dbd90 Mon Sep 17 00:00:00 2001 +From: Mark Rutland +Date: Mon, 6 Jan 2020 12:03:39 +0000 +Subject: perf: Correctly handle failed perf_get_aux_event() + +From: Mark Rutland + +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 +Signed-off-by: Mark Rutland +Signed-off-by: Peter Zijlstra (Intel) +Signed-off-by: Ingo Molnar +Acked-by: Alexander Shishkin +Tested-by: Vince Weaver +Signed-off-by: Greg Kroah-Hartman + +--- + 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(), diff --git a/queue-5.4/scsi-fnic-fix-invalid-stack-access.patch b/queue-5.4/scsi-fnic-fix-invalid-stack-access.patch new file mode 100644 index 00000000000..1e4f191371e --- /dev/null +++ b/queue-5.4/scsi-fnic-fix-invalid-stack-access.patch @@ -0,0 +1,122 @@ +From 42ec15ceaea74b5f7a621fc6686cbf69ca66c4cf Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Tue, 7 Jan 2020 21:15:49 +0100 +Subject: scsi: fnic: fix invalid stack access + +From: Arnd Bergmann + +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 +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } diff --git a/queue-5.4/scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch b/queue-5.4/scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch new file mode 100644 index 00000000000..fd99e163c9a --- /dev/null +++ b/queue-5.4/scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch @@ -0,0 +1,577 @@ +From 28d76df18f0ad5bcf5fa48510b225f0ed262a99b Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 14 Jan 2020 15:34:14 +0300 +Subject: scsi: mptfusion: Fix double fetch bug in ioctl + +From: Dan Carpenter + +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 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Dan Carpenter +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-5.4/series b/queue-5.4/series index 81b38eef00f..6fc508855fc 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -34,3 +34,23 @@ io_uring-only-allow-submit-from-owning-task.patch 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 diff --git a/queue-5.4/staging-comedi-ni_routes-allow-partial-routing-information.patch b/queue-5.4/staging-comedi-ni_routes-allow-partial-routing-information.patch new file mode 100644 index 00000000000..714af4a7cb4 --- /dev/null +++ b/queue-5.4/staging-comedi-ni_routes-allow-partial-routing-information.patch @@ -0,0 +1,86 @@ +From 9fea3a40f6b07de977a2783270c8c3bc82544d45 Mon Sep 17 00:00:00 2001 +From: Ian Abbott +Date: Tue, 14 Jan 2020 18:25:32 +0000 +Subject: staging: comedi: ni_routes: allow partial routing information + +From: Ian Abbott + +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: # 4.20+ +Cc: Spencer E. Olson +Signed-off-by: Ian Abbott +Link: https://lore.kernel.org/r/20200114182532.132058-3-abbotti@mev.co.uk +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } + diff --git a/queue-5.4/staging-comedi-ni_routes-fix-null-dereference-in-ni_find_route_source.patch b/queue-5.4/staging-comedi-ni_routes-fix-null-dereference-in-ni_find_route_source.patch new file mode 100644 index 00000000000..0adb905ab8d --- /dev/null +++ b/queue-5.4/staging-comedi-ni_routes-fix-null-dereference-in-ni_find_route_source.patch @@ -0,0 +1,54 @@ +From 01e20b664f808a4f3048ca3f930911fd257209bd Mon Sep 17 00:00:00 2001 +From: Ian Abbott +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 + +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: # 4.20+ +Cc: Spencer E. Olson +Signed-off-by: Ian Abbott +Link: https://lore.kernel.org/r/20200114182532.132058-2-abbotti@mev.co.uk +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-5.4/usb-serial-ch341-handle-unbound-port-at-reset_resume.patch b/queue-5.4/usb-serial-ch341-handle-unbound-port-at-reset_resume.patch new file mode 100644 index 00000000000..62fa750ff0b --- /dev/null +++ b/queue-5.4/usb-serial-ch341-handle-unbound-port-at-reset_resume.patch @@ -0,0 +1,40 @@ +From 4d5ef53f75c22d28f490bcc5c771fcc610a9afa4 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 17 Jan 2020 10:50:22 +0100 +Subject: USB: serial: ch341: handle unbound port at reset_resume + +From: Johan Hovold + +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 # 2.6.30 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-5.4/usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch b/queue-5.4/usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch new file mode 100644 index 00000000000..c98f9bd6c5d --- /dev/null +++ b/queue-5.4/usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch @@ -0,0 +1,67 @@ +From 1568c58d11a7c851bd09341aeefd6a1c308ac40d Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 17 Jan 2020 10:50:24 +0100 +Subject: USB: serial: io_edgeport: add missing active-port sanity check + +From: Johan Hovold + +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 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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) { diff --git a/queue-5.4/usb-serial-io_edgeport-handle-unbound-ports-on-urb-completion.patch b/queue-5.4/usb-serial-io_edgeport-handle-unbound-ports-on-urb-completion.patch new file mode 100644 index 00000000000..ba58f4f440f --- /dev/null +++ b/queue-5.4/usb-serial-io_edgeport-handle-unbound-ports-on-urb-completion.patch @@ -0,0 +1,45 @@ +From e37d1aeda737a20b1846a91a3da3f8b0f00cf690 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 17 Jan 2020 10:50:23 +0100 +Subject: USB: serial: io_edgeport: handle unbound ports on URB completion + +From: Johan Hovold + +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 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-5.4/usb-serial-keyspan-handle-unbound-ports.patch b/queue-5.4/usb-serial-keyspan-handle-unbound-ports.patch new file mode 100644 index 00000000000..33a2a0d2774 --- /dev/null +++ b/queue-5.4/usb-serial-keyspan-handle-unbound-ports.patch @@ -0,0 +1,45 @@ +From 3018dd3fa114b13261e9599ddb5656ef97a1fa17 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 17 Jan 2020 10:50:25 +0100 +Subject: USB: serial: keyspan: handle unbound ports + +From: Johan Hovold + +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 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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__); diff --git a/queue-5.4/usb-serial-opticon-fix-control-message-timeouts.patch b/queue-5.4/usb-serial-opticon-fix-control-message-timeouts.patch new file mode 100644 index 00000000000..321531ab721 --- /dev/null +++ b/queue-5.4/usb-serial-opticon-fix-control-message-timeouts.patch @@ -0,0 +1,39 @@ +From 5e28055f340275a8616eee88ef19186631b4d136 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 13 Jan 2020 18:22:13 +0100 +Subject: USB: serial: opticon: fix control-message timeouts + +From: Johan Hovold + +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 # 2.6.39 +Cc: Martin Jansen +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-5.4/usb-serial-option-add-support-for-quectel-rm500q-in-qdl-mode.patch b/queue-5.4/usb-serial-option-add-support-for-quectel-rm500q-in-qdl-mode.patch new file mode 100644 index 00000000000..1c7dac28182 --- /dev/null +++ b/queue-5.4/usb-serial-option-add-support-for-quectel-rm500q-in-qdl-mode.patch @@ -0,0 +1,45 @@ +From f3eaabbfd093c93d791eb930cc68d9b15246a65e Mon Sep 17 00:00:00 2001 +From: Reinhard Speyerer +Date: Tue, 14 Jan 2020 14:29:23 +0100 +Subject: USB: serial: option: add support for Quectel RM500Q in QDL mode + +From: Reinhard Speyerer + +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 +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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) }, diff --git a/queue-5.4/usb-serial-option-add-support-for-quectel-rm500q.patch b/queue-5.4/usb-serial-option-add-support-for-quectel-rm500q.patch new file mode 100644 index 00000000000..d6760d4a50b --- /dev/null +++ b/queue-5.4/usb-serial-option-add-support-for-quectel-rm500q.patch @@ -0,0 +1,353 @@ +From accf227de4d211b52c830a58b2df00d5739f2389 Mon Sep 17 00:00:00 2001 +From: Kristian Evensen +Date: Mon, 13 Jan 2020 15:14:05 +0100 +Subject: USB: serial: option: Add support for Quectel RM500Q + +From: Kristian Evensen + +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 +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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), diff --git a/queue-5.4/usb-serial-quatech2-handle-unbound-ports.patch b/queue-5.4/usb-serial-quatech2-handle-unbound-ports.patch new file mode 100644 index 00000000000..0cff9ecc06e --- /dev/null +++ b/queue-5.4/usb-serial-quatech2-handle-unbound-ports.patch @@ -0,0 +1,52 @@ +From 9715a43eea77e42678a1002623f2d9a78f5b81a1 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 17 Jan 2020 15:35:26 +0100 +Subject: USB: serial: quatech2: handle unbound ports + +From: Johan Hovold + +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 # 3.5 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-5.4/usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch b/queue-5.4/usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch new file mode 100644 index 00000000000..36a972d10eb --- /dev/null +++ b/queue-5.4/usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch @@ -0,0 +1,211 @@ +From 260e41ac4dd3e5acb90be624c03ba7f019615b75 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jer=C3=B3nimo=20Borque?= +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 + +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 +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-5.4/usb-serial-suppress-driver-bind-attributes.patch b/queue-5.4/usb-serial-suppress-driver-bind-attributes.patch new file mode 100644 index 00000000000..26244ec249e --- /dev/null +++ b/queue-5.4/usb-serial-suppress-driver-bind-attributes.patch @@ -0,0 +1,41 @@ +From fdb838efa31e1ed9a13ae6ad0b64e30fdbd00570 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 16 Jan 2020 17:07:05 +0100 +Subject: USB: serial: suppress driver bind attributes + +From: Johan Hovold + +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 +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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 */