From: Greg Kroah-Hartman Date: Sun, 10 Apr 2016 00:41:03 +0000 (-0700) Subject: 4.5-stable patches X-Git-Tag: v4.5.1~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9209750dae3092bcbde6fd72305e4044ac6e4275;p=thirdparty%2Fkernel%2Fstable-queue.git 4.5-stable patches added patches: 8250-use-callbacks-to-access-uart_dll-uart_dlm.patch adv7511-tx_edid_present-is-still-1-after-a-disconnect.patch bttv-width-must-be-a-multiple-of-16-when-capturing-planar-formats.patch coda-fix-first-encoded-frame-payload.patch hid-fix-hid_ignore_special_drivers-module-parameter.patch hid-i2c-hid-fix-oob-write-in-i2c_hid_set_or_send_report.patch hid-logitech-fix-dual-action-gamepad-support.patch hid-multitouch-force-retrieving-of-win8-signature-blob.patch media-v4l2-compat-ioctl32-fix-missing-length-copy-in-put_v4l2_buffer32.patch mtip32xx-avoid-issuing-standby-immediate-cmd-during-ftl-rebuild.patch mtip32xx-cleanup-queued-requests-after-surprise-removal.patch mtip32xx-fix-broken-service-thread-handling.patch mtip32xx-fix-for-rmmod-crash-when-drive-is-in-ftl-rebuild.patch mtip32xx-handle-ftl-rebuild-failure-state-during-device-initialization.patch mtip32xx-handle-safe-removal-during-io.patch mtip32xx-implement-timeout-handler.patch mtip32xx-print-exact-time-when-an-internal-command-is-interrupted.patch mtip32xx-remove-unwanted-code-from-taskfile-error-handler.patch net-irda-fix-use-after-free-in-irtty_open.patch saa7134-fix-bytesperline-not-being-set-correctly-for-planar-formats.patch staging-android-ion_test-fix-check-of-platform_device_register_simple-error-code.patch staging-comedi-ni_mio_common-fix-the-ni_write-functions.patch staging-comedi-ni_tiocmd-change-mistaken-use-of-start_src-for-start_arg.patch tpm-fix-the-cleanup-of-struct-tpm_chip.patch tpm-fix-the-rollback-in-tpm_chip_register.patch tpm_crb-tpm2_shutdown-must-be-called-before-tpm_chip_unregister.patch tpm_eventlog.c-fix-binary_bios_measurements.patch tty-fix-gpf-in-flush_to_ldisc-part-2.patch --- diff --git a/queue-4.5/8250-use-callbacks-to-access-uart_dll-uart_dlm.patch b/queue-4.5/8250-use-callbacks-to-access-uart_dll-uart_dlm.patch new file mode 100644 index 00000000000..c3cd7c5133c --- /dev/null +++ b/queue-4.5/8250-use-callbacks-to-access-uart_dll-uart_dlm.patch @@ -0,0 +1,54 @@ +From 0b41ce991052022c030fd868e03877700220b090 Mon Sep 17 00:00:00 2001 +From: Sebastian Frias +Date: Fri, 18 Dec 2015 17:40:05 +0100 +Subject: 8250: use callbacks to access UART_DLL/UART_DLM + +From: Sebastian Frias + +commit 0b41ce991052022c030fd868e03877700220b090 upstream. + +Some UART HW has a single register combining UART_DLL/UART_DLM +(this was probably forgotten in the change that introduced the +callbacks, commit b32b19b8ffc05cbd3bf91c65e205f6a912ca15d9) + +Fixes: b32b19b8ffc0 ("[SERIAL] 8250: set divisor register correctly ...") + +Signed-off-by: Sebastian Frias +Reviewed-by: Peter Hurley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/8250/8250_port.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -731,22 +731,16 @@ static int size_fifo(struct uart_8250_po + */ + static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p) + { +- unsigned char old_dll, old_dlm, old_lcr; +- unsigned int id; ++ unsigned char old_lcr; ++ unsigned int id, old_dl; + + old_lcr = serial_in(p, UART_LCR); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A); ++ old_dl = serial_dl_read(p); ++ serial_dl_write(p, 0); ++ id = serial_dl_read(p); ++ serial_dl_write(p, old_dl); + +- old_dll = serial_in(p, UART_DLL); +- old_dlm = serial_in(p, UART_DLM); +- +- serial_out(p, UART_DLL, 0); +- serial_out(p, UART_DLM, 0); +- +- id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8; +- +- serial_out(p, UART_DLL, old_dll); +- serial_out(p, UART_DLM, old_dlm); + serial_out(p, UART_LCR, old_lcr); + + return id; diff --git a/queue-4.5/adv7511-tx_edid_present-is-still-1-after-a-disconnect.patch b/queue-4.5/adv7511-tx_edid_present-is-still-1-after-a-disconnect.patch new file mode 100644 index 00000000000..d9b8b794569 --- /dev/null +++ b/queue-4.5/adv7511-tx_edid_present-is-still-1-after-a-disconnect.patch @@ -0,0 +1,93 @@ +From b339a72e04a62f0b1882c43492fc712f1176b3e6 Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Wed, 10 Feb 2016 09:32:25 -0200 +Subject: [media] adv7511: TX_EDID_PRESENT is still 1 after a disconnect + +From: Hans Verkuil + +commit b339a72e04a62f0b1882c43492fc712f1176b3e6 upstream. + +The V4L2_CID_TX_EDID_PRESENT control reports if an EDID is present. +The adv7511 however still reported the EDID present after disconnecting +the HDMI cable. Fix the logic regarding this control. And when the EDID +is disconnected also call ADV7511_EDID_DETECT to notify the bridge driver. +This was also missing. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/i2c/adv7511.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +--- a/drivers/media/i2c/adv7511.c ++++ b/drivers/media/i2c/adv7511.c +@@ -1161,12 +1161,23 @@ static void adv7511_dbg_dump_edid(int lv + } + } + ++static void adv7511_notify_no_edid(struct v4l2_subdev *sd) ++{ ++ struct adv7511_state *state = get_adv7511_state(sd); ++ struct adv7511_edid_detect ed; ++ ++ /* We failed to read the EDID, so send an event for this. */ ++ ed.present = false; ++ ed.segment = adv7511_rd(sd, 0xc4); ++ v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); ++ v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0); ++} ++ + static void adv7511_edid_handler(struct work_struct *work) + { + struct delayed_work *dwork = to_delayed_work(work); + struct adv7511_state *state = container_of(dwork, struct adv7511_state, edid_handler); + struct v4l2_subdev *sd = &state->sd; +- struct adv7511_edid_detect ed; + + v4l2_dbg(1, debug, sd, "%s:\n", __func__); + +@@ -1191,9 +1202,7 @@ static void adv7511_edid_handler(struct + } + + /* We failed to read the EDID, so send an event for this. */ +- ed.present = false; +- ed.segment = adv7511_rd(sd, 0xc4); +- v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); ++ adv7511_notify_no_edid(sd); + v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__); + } + +@@ -1264,7 +1273,6 @@ static void adv7511_check_monitor_presen + /* update read only ctrls */ + v4l2_ctrl_s_ctrl(state->hotplug_ctrl, adv7511_have_hotplug(sd) ? 0x1 : 0x0); + v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, adv7511_have_rx_sense(sd) ? 0x1 : 0x0); +- v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); + + if ((status & MASK_ADV7511_HPD_DETECT) && ((status & MASK_ADV7511_MSEN_DETECT) || state->edid.segments)) { + v4l2_dbg(1, debug, sd, "%s: hotplug and (rx-sense or edid)\n", __func__); +@@ -1294,6 +1302,7 @@ static void adv7511_check_monitor_presen + } + adv7511_s_power(sd, false); + memset(&state->edid, 0, sizeof(struct adv7511_state_edid)); ++ adv7511_notify_no_edid(sd); + } + } + +@@ -1370,6 +1379,7 @@ static bool adv7511_check_edid_status(st + } + /* one more segment read ok */ + state->edid.segments = segment + 1; ++ v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x1); + if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) { + /* Request next EDID segment */ + v4l2_dbg(1, debug, sd, "%s: request segment %d\n", __func__, state->edid.segments); +@@ -1389,7 +1399,6 @@ static bool adv7511_check_edid_status(st + ed.present = true; + ed.segment = 0; + state->edid_detect_counter++; +- v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); + v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); + return ed.present; + } diff --git a/queue-4.5/bttv-width-must-be-a-multiple-of-16-when-capturing-planar-formats.patch b/queue-4.5/bttv-width-must-be-a-multiple-of-16-when-capturing-planar-formats.patch new file mode 100644 index 00000000000..aab3125319a --- /dev/null +++ b/queue-4.5/bttv-width-must-be-a-multiple-of-16-when-capturing-planar-formats.patch @@ -0,0 +1,102 @@ +From 5c915c68763889f0183a1cc61c84bb228b60124a Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 7 Feb 2016 09:24:29 -0200 +Subject: [media] bttv: Width must be a multiple of 16 when capturing planar formats + +From: Hans de Goede + +commit 5c915c68763889f0183a1cc61c84bb228b60124a upstream. + +On my bttv card "Hauppauge WinTV [card=10]" capturing in YV12 fmt at max +size results in a solid green rectangle being captured (all colors 0 in +YUV). + +This turns out to be caused by max-width (924) not being a multiple of 16. + +We've likely never hit this problem before since normally xawtv / tvtime, +etc. will prefer packed pixel formats. But when using a video card which +is using xf86-video-modesetting + glamor, only planar XVideo fmts are +available, and xawtv will chose a matching capture format to avoid needing +to do conversion, triggering the solid green window problem. + +Signed-off-by: Hans de Goede +Acked-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/pci/bt8xx/bttv-driver.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +--- a/drivers/media/pci/bt8xx/bttv-driver.c ++++ b/drivers/media/pci/bt8xx/bttv-driver.c +@@ -2334,6 +2334,19 @@ static int bttv_g_fmt_vid_overlay(struct + return 0; + } + ++static void bttv_get_width_mask_vid_cap(const struct bttv_format *fmt, ++ unsigned int *width_mask, ++ unsigned int *width_bias) ++{ ++ if (fmt->flags & FORMAT_FLAGS_PLANAR) { ++ *width_mask = ~15; /* width must be a multiple of 16 pixels */ ++ *width_bias = 8; /* nearest */ ++ } else { ++ *width_mask = ~3; /* width must be a multiple of 4 pixels */ ++ *width_bias = 2; /* nearest */ ++ } ++} ++ + static int bttv_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) + { +@@ -2343,6 +2356,7 @@ static int bttv_try_fmt_vid_cap(struct f + enum v4l2_field field; + __s32 width, height; + __s32 height2; ++ unsigned int width_mask, width_bias; + int rc; + + fmt = format_by_fourcc(f->fmt.pix.pixelformat); +@@ -2375,9 +2389,9 @@ static int bttv_try_fmt_vid_cap(struct f + width = f->fmt.pix.width; + height = f->fmt.pix.height; + ++ bttv_get_width_mask_vid_cap(fmt, &width_mask, &width_bias); + rc = limit_scaled_size_lock(fh, &width, &height, field, +- /* width_mask: 4 pixels */ ~3, +- /* width_bias: nearest */ 2, ++ width_mask, width_bias, + /* adjust_size */ 1, + /* adjust_crop */ 0); + if (0 != rc) +@@ -2410,6 +2424,7 @@ static int bttv_s_fmt_vid_cap(struct fil + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + __s32 width, height; ++ unsigned int width_mask, width_bias; + enum v4l2_field field; + + retval = bttv_switch_type(fh, f->type); +@@ -2424,9 +2439,10 @@ static int bttv_s_fmt_vid_cap(struct fil + height = f->fmt.pix.height; + field = f->fmt.pix.field; + ++ fmt = format_by_fourcc(f->fmt.pix.pixelformat); ++ bttv_get_width_mask_vid_cap(fmt, &width_mask, &width_bias); + retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field, +- /* width_mask: 4 pixels */ ~3, +- /* width_bias: nearest */ 2, ++ width_mask, width_bias, + /* adjust_size */ 1, + /* adjust_crop */ 1); + if (0 != retval) +@@ -2434,8 +2450,6 @@ static int bttv_s_fmt_vid_cap(struct fil + + f->fmt.pix.field = field; + +- fmt = format_by_fourcc(f->fmt.pix.pixelformat); +- + /* update our state informations */ + fh->fmt = fmt; + fh->cap.field = f->fmt.pix.field; diff --git a/queue-4.5/coda-fix-first-encoded-frame-payload.patch b/queue-4.5/coda-fix-first-encoded-frame-payload.patch new file mode 100644 index 00000000000..46a7460586d --- /dev/null +++ b/queue-4.5/coda-fix-first-encoded-frame-payload.patch @@ -0,0 +1,38 @@ +From 74dc385cb450089b28c28be2c8a0baca296b95f9 Mon Sep 17 00:00:00 2001 +From: Philipp Zabel +Date: Mon, 4 Jan 2016 17:30:09 -0200 +Subject: [media] coda: fix first encoded frame payload + +From: Philipp Zabel + +commit 74dc385cb450089b28c28be2c8a0baca296b95f9 upstream. + +During the recent vb2_buffer restructuring, the calculation of the +buffer payload reported to userspace was accidentally broken for the +first encoded frame, counting only the length of the headers. +This patch re-adds the length of the actual frame data. + +Fixes: 2d7007153f0c ("[media] media: videobuf2: Restructure vb2_buffer") + +Reported-by: Michael Olbrich +Signed-off-by: Philipp Zabel +Tested-by: Jan Luebbe +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/platform/coda/coda-bit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/platform/coda/coda-bit.c ++++ b/drivers/media/platform/coda/coda-bit.c +@@ -1342,7 +1342,7 @@ static void coda_finish_encode(struct co + + /* Calculate bytesused field */ + if (dst_buf->sequence == 0) { +- vb2_set_plane_payload(&dst_buf->vb2_buf, 0, ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr + + ctx->vpu_header_size[0] + + ctx->vpu_header_size[1] + + ctx->vpu_header_size[2]); diff --git a/queue-4.5/hid-fix-hid_ignore_special_drivers-module-parameter.patch b/queue-4.5/hid-fix-hid_ignore_special_drivers-module-parameter.patch new file mode 100644 index 00000000000..93c33a9c795 --- /dev/null +++ b/queue-4.5/hid-fix-hid_ignore_special_drivers-module-parameter.patch @@ -0,0 +1,43 @@ +From 4392bf333388cabdad5afe5b1500002d7b9c318e Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Fri, 12 Feb 2016 17:10:37 +0100 +Subject: HID: fix hid_ignore_special_drivers module parameter + +From: Benjamin Tissoires + +commit 4392bf333388cabdad5afe5b1500002d7b9c318e upstream. + +hid_ignore_special_drivers works fine until hid_scan_report autodetects and +reassign devices (for hid-multitouch, hid-microsoft and hid-rmi). + +Simplify the handling of the parameter: if it is there, use hid-generic, no +matter what, and if not, scan the device or rely on the hid_have_special_driver +table. + +This was detected while trying to disable hid-multitouch on a Surface Pro cover +which prevented to use the keyboard. + +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-core.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -2616,9 +2616,10 @@ int hid_add_device(struct hid_device *hd + /* + * Scan generic devices for group information + */ +- if (hid_ignore_special_drivers || +- (!hdev->group && +- !hid_match_id(hdev, hid_have_special_driver))) { ++ if (hid_ignore_special_drivers) { ++ hdev->group = HID_GROUP_GENERIC; ++ } else if (!hdev->group && ++ !hid_match_id(hdev, hid_have_special_driver)) { + ret = hid_scan_report(hdev); + if (ret) + hid_warn(hdev, "bad device descriptor (%d)\n", ret); diff --git a/queue-4.5/hid-i2c-hid-fix-oob-write-in-i2c_hid_set_or_send_report.patch b/queue-4.5/hid-i2c-hid-fix-oob-write-in-i2c_hid_set_or_send_report.patch new file mode 100644 index 00000000000..ae8a7427b1d --- /dev/null +++ b/queue-4.5/hid-i2c-hid-fix-oob-write-in-i2c_hid_set_or_send_report.patch @@ -0,0 +1,86 @@ +From 3b654288b196ceaa156029d9457ccbded0489b98 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov +Date: Mon, 14 Mar 2016 15:21:04 -0700 +Subject: HID: i2c-hid: fix OOB write in i2c_hid_set_or_send_report() + +From: Dmitry Torokhov + +commit 3b654288b196ceaa156029d9457ccbded0489b98 upstream. + +Even though hid_hw_* checks that passed in data_len is less than +HID_MAX_BUFFER_SIZE it is not enough, as i2c-hid does not necessarily +allocate buffers of HID_MAX_BUFFER_SIZE but rather checks all device +reports and select largest size. In-kernel users normally just send as much +data as report needs, so there is no problem, but hidraw users can do +whatever they please: + +BUG: KASAN: slab-out-of-bounds in memcpy+0x34/0x54 at addr ffffffc07135ea80 +Write of size 4101 by task syz-executor/8747 +CPU: 2 PID: 8747 Comm: syz-executor Tainted: G BU 3.18.0 #37 +Hardware name: Google Tegra210 Smaug Rev 1,3+ (DT) +Call trace: +[] dump_backtrace+0x0/0x258 arch/arm64/kernel/traps.c:83 +[] show_stack+0x1c/0x2c arch/arm64/kernel/traps.c:172 +[< inline >] __dump_stack lib/dump_stack.c:15 +[] dump_stack+0x90/0x140 lib/dump_stack.c:50 +[< inline >] print_error_description mm/kasan/report.c:97 +[< inline >] kasan_report_error mm/kasan/report.c:278 +[] kasan_report+0x268/0x530 mm/kasan/report.c:305 +[] __asan_storeN+0x20/0x150 mm/kasan/kasan.c:718 +[] memcpy+0x30/0x54 mm/kasan/kasan.c:299 +[] __i2c_hid_command+0x2b0/0x7b4 drivers/hid/i2c-hid/i2c-hid.c:178 +[< inline >] i2c_hid_set_or_send_report drivers/hid/i2c-hid/i2c-hid.c:321 +[] i2c_hid_output_raw_report.isra.2+0x3d4/0x4b8 drivers/hid/i2c-hid/i2c-hid.c:589 +[] i2c_hid_output_report+0x54/0x68 drivers/hid/i2c-hid/i2c-hid.c:602 +[< inline >] hid_hw_output_report include/linux/hid.h:1039 +[] hidraw_send_report+0x400/0x414 drivers/hid/hidraw.c:154 +[] hidraw_write+0x40/0x64 drivers/hid/hidraw.c:177 +[] vfs_write+0x1d4/0x3cc fs/read_write.c:534 +[< inline >] SYSC_pwrite64 fs/read_write.c:627 +[] SyS_pwrite64+0xec/0x144 fs/read_write.c:614 +Object at ffffffc07135ea80, in cache kmalloc-512 +Object allocated with size 268 bytes. + +Let's check data length against the buffer size before attempting to copy +data over. + +Reported-by: Alexander Potapenko +Signed-off-by: Dmitry Torokhov +Reviewed-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/i2c-hid/i2c-hid.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/hid/i2c-hid/i2c-hid.c ++++ b/drivers/hid/i2c-hid/i2c-hid.c +@@ -283,17 +283,21 @@ static int i2c_hid_set_or_send_report(st + u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister); + u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister); + u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength); ++ u16 size; ++ int args_len; ++ int index = 0; ++ ++ i2c_hid_dbg(ihid, "%s\n", __func__); ++ ++ if (data_len > ihid->bufsize) ++ return -EINVAL; + +- /* hid_hw_* already checked that data_len < HID_MAX_BUFFER_SIZE */ +- u16 size = 2 /* size */ + ++ size = 2 /* size */ + + (reportID ? 1 : 0) /* reportID */ + + data_len /* buf */; +- int args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ + ++ args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ + + 2 /* dataRegister */ + + size /* args */; +- int index = 0; +- +- i2c_hid_dbg(ihid, "%s\n", __func__); + + if (!use_data && maxOutputLength == 0) + return -ENOSYS; diff --git a/queue-4.5/hid-logitech-fix-dual-action-gamepad-support.patch b/queue-4.5/hid-logitech-fix-dual-action-gamepad-support.patch new file mode 100644 index 00000000000..9a1117e8d7d --- /dev/null +++ b/queue-4.5/hid-logitech-fix-dual-action-gamepad-support.patch @@ -0,0 +1,35 @@ +From 5d74325a2201376a95520a4a38a1ce2c65761c49 Mon Sep 17 00:00:00 2001 +From: Grazvydas Ignotas +Date: Sat, 13 Feb 2016 22:41:51 +0200 +Subject: HID: logitech: fix Dual Action gamepad support + +From: Grazvydas Ignotas + +commit 5d74325a2201376a95520a4a38a1ce2c65761c49 upstream. + +The patch that added Logitech Dual Action gamepad support forgot to +update the special driver list for the device. This caused the logitech +driver not to probe unless kernel module load order was favorable. +Update the special driver list to fix it. Thanks to Simon Wood for the +idea. + +Cc: Vitaly Katraew +Fixes: 56d0c8b7c8fb ("HID: add support for Logitech Dual Action gamepads") +Signed-off-by: Grazvydas Ignotas +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1891,6 +1891,7 @@ static const struct hid_device_id hid_ha + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, diff --git a/queue-4.5/hid-multitouch-force-retrieving-of-win8-signature-blob.patch b/queue-4.5/hid-multitouch-force-retrieving-of-win8-signature-blob.patch new file mode 100644 index 00000000000..09b3121d8c7 --- /dev/null +++ b/queue-4.5/hid-multitouch-force-retrieving-of-win8-signature-blob.patch @@ -0,0 +1,40 @@ +From 45c5c6828214605eaefa6755c47bd1a2c7eb203e Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Mon, 7 Mar 2016 11:02:38 +0100 +Subject: HID: multitouch: force retrieving of Win8 signature blob + +From: Benjamin Tissoires + +commit 45c5c6828214605eaefa6755c47bd1a2c7eb203e upstream. + +The Synaptics 0x11e5 over I2C found in the Asus T100-CHI requires to +fetch the signature blob to actually start sending events. + +With this patch, we should be close enough to the Windows driver which +checks the content of the blob at plugin to validate or not the +touchscreen. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=113481 +Fixes: 6d4f5440 ("HID: multitouch: Fetch feature reports on demand for Win8 devices") +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-multitouch.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -396,6 +396,11 @@ static void mt_feature_mapping(struct hi + td->is_buttonpad = true; + + break; ++ case 0xff0000c5: ++ /* Retrieve the Win8 blob once to enable some devices */ ++ if (usage->usage_index == 0) ++ mt_get_feature(hdev, field->report); ++ break; + } + } + diff --git a/queue-4.5/media-v4l2-compat-ioctl32-fix-missing-length-copy-in-put_v4l2_buffer32.patch b/queue-4.5/media-v4l2-compat-ioctl32-fix-missing-length-copy-in-put_v4l2_buffer32.patch new file mode 100644 index 00000000000..6c2b2980a6b --- /dev/null +++ b/queue-4.5/media-v4l2-compat-ioctl32-fix-missing-length-copy-in-put_v4l2_buffer32.patch @@ -0,0 +1,90 @@ +From 7df5ab8774aa383c6d2bff00688d004585d96dfd Mon Sep 17 00:00:00 2001 +From: Tiffany Lin +Date: Tue, 19 Jan 2016 05:56:50 -0200 +Subject: [media] media: v4l2-compat-ioctl32: fix missing length copy in put_v4l2_buffer32 + +From: Tiffany Lin + +commit 7df5ab8774aa383c6d2bff00688d004585d96dfd upstream. + +In v4l2-compliance utility, test QUERYBUF required correct length +value to go through each planar to check planar's length in +multi-planar buffer type + +Signed-off-by: Tiffany Lin +Reviewed-by: Laurent Pinchart +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +@@ -415,7 +415,8 @@ static int get_v4l2_buffer32(struct v4l2 + get_user(kp->index, &up->index) || + get_user(kp->type, &up->type) || + get_user(kp->flags, &up->flags) || +- get_user(kp->memory, &up->memory)) ++ get_user(kp->memory, &up->memory) || ++ get_user(kp->length, &up->length)) + return -EFAULT; + + if (V4L2_TYPE_IS_OUTPUT(kp->type)) +@@ -427,9 +428,6 @@ static int get_v4l2_buffer32(struct v4l2 + return -EFAULT; + + if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { +- if (get_user(kp->length, &up->length)) +- return -EFAULT; +- + num_planes = kp->length; + if (num_planes == 0) { + kp->m.planes = NULL; +@@ -462,16 +460,14 @@ static int get_v4l2_buffer32(struct v4l2 + } else { + switch (kp->memory) { + case V4L2_MEMORY_MMAP: +- if (get_user(kp->length, &up->length) || +- get_user(kp->m.offset, &up->m.offset)) ++ if (get_user(kp->m.offset, &up->m.offset)) + return -EFAULT; + break; + case V4L2_MEMORY_USERPTR: + { + compat_long_t tmp; + +- if (get_user(kp->length, &up->length) || +- get_user(tmp, &up->m.userptr)) ++ if (get_user(tmp, &up->m.userptr)) + return -EFAULT; + + kp->m.userptr = (unsigned long)compat_ptr(tmp); +@@ -513,7 +509,8 @@ static int put_v4l2_buffer32(struct v4l2 + copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || + put_user(kp->sequence, &up->sequence) || + put_user(kp->reserved2, &up->reserved2) || +- put_user(kp->reserved, &up->reserved)) ++ put_user(kp->reserved, &up->reserved) || ++ put_user(kp->length, &up->length)) + return -EFAULT; + + if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { +@@ -536,13 +533,11 @@ static int put_v4l2_buffer32(struct v4l2 + } else { + switch (kp->memory) { + case V4L2_MEMORY_MMAP: +- if (put_user(kp->length, &up->length) || +- put_user(kp->m.offset, &up->m.offset)) ++ if (put_user(kp->m.offset, &up->m.offset)) + return -EFAULT; + break; + case V4L2_MEMORY_USERPTR: +- if (put_user(kp->length, &up->length) || +- put_user(kp->m.userptr, &up->m.userptr)) ++ if (put_user(kp->m.userptr, &up->m.userptr)) + return -EFAULT; + break; + case V4L2_MEMORY_OVERLAY: diff --git a/queue-4.5/mtip32xx-avoid-issuing-standby-immediate-cmd-during-ftl-rebuild.patch b/queue-4.5/mtip32xx-avoid-issuing-standby-immediate-cmd-during-ftl-rebuild.patch new file mode 100644 index 00000000000..046e53c705c --- /dev/null +++ b/queue-4.5/mtip32xx-avoid-issuing-standby-immediate-cmd-during-ftl-rebuild.patch @@ -0,0 +1,74 @@ +From d8a18d2d8f5de55666c6011ed175939d22c8e3d8 Mon Sep 17 00:00:00 2001 +From: Asai Thambi SP +Date: Wed, 24 Feb 2016 21:17:32 -0800 +Subject: mtip32xx: Avoid issuing standby immediate cmd during FTL rebuild + +From: Asai Thambi SP + +commit d8a18d2d8f5de55666c6011ed175939d22c8e3d8 upstream. + +Prevent standby immediate command from being issued in remove, +suspend and shutdown paths, while drive is in FTL rebuild process. + +Signed-off-by: Selvan Mani +Signed-off-by: Vignesh Gunasekaran +Signed-off-by: Asai Thambi S P +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/mtip32xx/mtip32xx.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -3263,20 +3263,25 @@ out1: + return rv; + } + +-static void mtip_standby_drive(struct driver_data *dd) ++static int mtip_standby_drive(struct driver_data *dd) + { +- if (dd->sr) +- return; ++ int rv = 0; + ++ if (dd->sr || !dd->port) ++ return -ENODEV; + /* + * Send standby immediate (E0h) to the drive so that it + * saves its state. + */ + if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags) && +- !test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) +- if (mtip_standby_immediate(dd->port)) ++ !test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag) && ++ !test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) { ++ rv = mtip_standby_immediate(dd->port); ++ if (rv) + dev_warn(&dd->pdev->dev, + "STANDBY IMMEDIATE failed\n"); ++ } ++ return rv; + } + + /* +@@ -3334,8 +3339,7 @@ static int mtip_hw_shutdown(struct drive + * Send standby immediate (E0h) to the drive so that it + * saves its state. + */ +- if (!dd->sr && dd->port) +- mtip_standby_immediate(dd->port); ++ mtip_standby_drive(dd); + + return 0; + } +@@ -3358,7 +3362,7 @@ static int mtip_hw_suspend(struct driver + * Send standby immediate (E0h) to the drive + * so that it saves its state. + */ +- if (mtip_standby_immediate(dd->port) != 0) { ++ if (mtip_standby_drive(dd) != 0) { + dev_err(&dd->pdev->dev, + "Failed standby-immediate command\n"); + return -EFAULT; diff --git a/queue-4.5/mtip32xx-cleanup-queued-requests-after-surprise-removal.patch b/queue-4.5/mtip32xx-cleanup-queued-requests-after-surprise-removal.patch new file mode 100644 index 00000000000..7738efa7d64 --- /dev/null +++ b/queue-4.5/mtip32xx-cleanup-queued-requests-after-surprise-removal.patch @@ -0,0 +1,208 @@ +From 008e56d200225321371748d95908e6222436f06d Mon Sep 17 00:00:00 2001 +From: Asai Thambi SP +Date: Wed, 24 Feb 2016 21:21:20 -0800 +Subject: mtip32xx: Cleanup queued requests after surprise removal + +From: Asai Thambi SP + +commit 008e56d200225321371748d95908e6222436f06d upstream. + +Fail all pending requests after surprise removal of a drive. + +Signed-off-by: Vignesh Gunasekaran +Signed-off-by: Selvan Mani +Signed-off-by: Asai Thambi S P +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/mtip32xx/mtip32xx.c | 78 +++++++++++++++++++++++++++++--------- + 1 file changed, 60 insertions(+), 18 deletions(-) + +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -173,7 +173,13 @@ static struct mtip_cmd *mtip_get_int_com + { + struct request *rq; + ++ if (mtip_check_surprise_removal(dd->pdev)) ++ return NULL; ++ + rq = blk_mq_alloc_request(dd->queue, 0, BLK_MQ_REQ_RESERVED); ++ if (IS_ERR(rq)) ++ return NULL; ++ + return blk_mq_rq_to_pdu(rq); + } + +@@ -575,6 +581,8 @@ static void mtip_completion(struct mtip_ + dev_warn(&port->dd->pdev->dev, + "Internal command %d completed with TFE\n", tag); + ++ command->comp_func = NULL; ++ command->comp_data = NULL; + complete(waiting); + } + +@@ -1009,12 +1017,14 @@ static bool mtip_pause_ncq(struct mtip_p + * + * @port Pointer to port data structure + * @timeout Max duration to wait (ms) ++ * @atomic gfp_t flag to indicate blockable context or not + * + * return value + * 0 Success + * -EBUSY Commands still active + */ +-static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) ++static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout, ++ gfp_t atomic) + { + unsigned long to; + unsigned int n; +@@ -1025,16 +1035,21 @@ static int mtip_quiesce_io(struct mtip_p + to = jiffies + msecs_to_jiffies(timeout); + do { + if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) && +- test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { ++ test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags) && ++ atomic == GFP_KERNEL) { + msleep(20); + continue; /* svc thd is actively issuing commands */ + } + +- msleep(100); ++ if (atomic == GFP_KERNEL) ++ msleep(100); ++ else { ++ cpu_relax(); ++ udelay(100); ++ } ++ + if (mtip_check_surprise_removal(port->dd->pdev)) + goto err_fault; +- if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) +- goto err_fault; + + /* + * Ignore s_active bit 0 of array element 0. +@@ -1096,6 +1111,10 @@ static int mtip_exec_internal_command(st + } + + int_cmd = mtip_get_int_command(dd); ++ if (!int_cmd) { ++ dbg_printk(MTIP_DRV_NAME "Unable to allocate tag for PIO cmd\n"); ++ return -EFAULT; ++ } + + set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); + +@@ -1108,7 +1127,7 @@ static int mtip_exec_internal_command(st + if (fis->command != ATA_CMD_STANDBYNOW1) { + /* wait for io to complete if non atomic */ + if (mtip_quiesce_io(port, +- MTIP_QUIESCE_IO_TIMEOUT_MS) < 0) { ++ MTIP_QUIESCE_IO_TIMEOUT_MS, atomic) < 0) { + dev_warn(&dd->pdev->dev, + "Failed to quiesce IO\n"); + mtip_put_int_command(dd, int_cmd); +@@ -3347,10 +3366,6 @@ static int mtip_standby_drive(struct dri + */ + static int mtip_hw_exit(struct driver_data *dd) + { +- /* +- * Send standby immediate (E0h) to the drive so that it +- * saves its state. +- */ + if (!dd->sr) { + /* de-initialize the port. */ + mtip_deinit_port(dd->port); +@@ -3967,7 +3982,7 @@ static int mtip_block_initialize(struct + if (rv) { + dev_err(&dd->pdev->dev, + "Unable to allocate request queue\n"); +- goto block_queue_alloc_init_error; ++ goto block_queue_alloc_tag_error; + } + + /* Allocate the request queue. */ +@@ -4079,8 +4094,9 @@ kthread_run_error: + read_capacity_error: + init_hw_cmds_error: + blk_cleanup_queue(dd->queue); +- blk_mq_free_tag_set(&dd->tags); + block_queue_alloc_init_error: ++ blk_mq_free_tag_set(&dd->tags); ++block_queue_alloc_tag_error: + mtip_hw_debugfs_exit(dd); + disk_index_error: + spin_lock(&rssd_index_lock); +@@ -4097,6 +4113,22 @@ protocol_init_error: + return rv; + } + ++static void mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv) ++{ ++ struct driver_data *dd = (struct driver_data *)data; ++ struct mtip_cmd *cmd; ++ ++ if (likely(!reserv)) ++ blk_mq_complete_request(rq, -ENODEV); ++ else if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &dd->port->flags)) { ++ ++ cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL); ++ if (cmd->comp_func) ++ cmd->comp_func(dd->port, MTIP_TAG_INTERNAL, ++ cmd, -ENODEV); ++ } ++} ++ + /* + * Block layer deinitialization function. + * +@@ -4128,12 +4160,23 @@ static int mtip_block_remove(struct driv + } + } + +- if (!dd->sr) +- mtip_standby_drive(dd); ++ if (!dd->sr) { ++ /* ++ * Explicitly wait here for IOs to quiesce, ++ * as mtip_standby_drive usually won't wait for IOs. ++ */ ++ if (!mtip_quiesce_io(dd->port, MTIP_QUIESCE_IO_TIMEOUT_MS, ++ GFP_KERNEL)) ++ mtip_standby_drive(dd); ++ } + else + dev_info(&dd->pdev->dev, "device %s surprise removal\n", + dd->disk->disk_name); + ++ blk_mq_freeze_queue_start(dd->queue); ++ blk_mq_stop_hw_queues(dd->queue); ++ blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd); ++ + /* + * Delete our gendisk structure. This also removes the device + * from /dev +@@ -4548,16 +4591,15 @@ static void mtip_pci_remove(struct pci_d + } while (atomic_read(&dd->irq_workers_active) != 0 && + time_before(jiffies, to)); + +- fsync_bdev(dd->bdev); ++ if (!dd->sr) ++ fsync_bdev(dd->bdev); + + if (atomic_read(&dd->irq_workers_active) != 0) { + dev_warn(&dd->pdev->dev, + "Completion workers still active!\n"); + } + +- if (dd->sr) +- blk_mq_stop_hw_queues(dd->queue); +- ++ blk_set_queue_dying(dd->queue); + set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); + + /* Clean up the block layer. */ diff --git a/queue-4.5/mtip32xx-fix-broken-service-thread-handling.patch b/queue-4.5/mtip32xx-fix-broken-service-thread-handling.patch new file mode 100644 index 00000000000..175c8840d46 --- /dev/null +++ b/queue-4.5/mtip32xx-fix-broken-service-thread-handling.patch @@ -0,0 +1,58 @@ +From cfc05bd31384c4898bf2437a4de5557f3cf9803a Mon Sep 17 00:00:00 2001 +From: Asai Thambi SP +Date: Wed, 24 Feb 2016 21:16:00 -0800 +Subject: mtip32xx: Fix broken service thread handling + +From: Asai Thambi SP + +commit cfc05bd31384c4898bf2437a4de5557f3cf9803a upstream. + +Service thread does not detect the need for taskfile error hanlding. Fixed the +flag condition to process taskfile error. + +Signed-off-by: Selvan Mani +Signed-off-by: Asai Thambi S P +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/mtip32xx/mtip32xx.c | 6 +++--- + drivers/block/mtip32xx/mtip32xx.h | 5 +++++ + 2 files changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -2917,9 +2917,7 @@ static int mtip_service_thread(void *dat + * is in progress nor error handling is active + */ + wait_event_interruptible(port->svc_wait, (port->flags) && +- !(port->flags & MTIP_PF_PAUSE_IO)); +- +- set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); ++ (port->flags & MTIP_PF_SVC_THD_WORK)); + + if (kthread_should_stop() || + test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags)) +@@ -2929,6 +2927,8 @@ static int mtip_service_thread(void *dat + &dd->dd_flag))) + goto st_out; + ++ set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); ++ + restart_eh: + /* Demux bits: start with error handling */ + if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) { +--- a/drivers/block/mtip32xx/mtip32xx.h ++++ b/drivers/block/mtip32xx/mtip32xx.h +@@ -144,6 +144,11 @@ enum { + MTIP_PF_REBUILD_BIT = 6, + MTIP_PF_SVC_THD_STOP_BIT = 8, + ++ MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) | ++ (1 << MTIP_PF_ISSUE_CMDS_BIT) | ++ (1 << MTIP_PF_REBUILD_BIT) | ++ (1 << MTIP_PF_SVC_THD_STOP_BIT)), ++ + /* below are bit numbers in 'dd_flag' defined in driver_data */ + MTIP_DDF_SEC_LOCK_BIT = 0, + MTIP_DDF_REMOVE_PENDING_BIT = 1, diff --git a/queue-4.5/mtip32xx-fix-for-rmmod-crash-when-drive-is-in-ftl-rebuild.patch b/queue-4.5/mtip32xx-fix-for-rmmod-crash-when-drive-is-in-ftl-rebuild.patch new file mode 100644 index 00000000000..78c89e9e33e --- /dev/null +++ b/queue-4.5/mtip32xx-fix-for-rmmod-crash-when-drive-is-in-ftl-rebuild.patch @@ -0,0 +1,74 @@ +From 59cf70e236c96594d9f1e065755d8fce9df5356b Mon Sep 17 00:00:00 2001 +From: Asai Thambi SP +Date: Wed, 24 Feb 2016 21:17:47 -0800 +Subject: mtip32xx: Fix for rmmod crash when drive is in FTL rebuild + +From: Asai Thambi SP + +commit 59cf70e236c96594d9f1e065755d8fce9df5356b upstream. + +When FTL rebuild is in progress, alloc_disk() initializes the disk +but device node will be created by add_disk() only after successful +completion of FTL rebuild. So, skip deletion of device node in +removal path when FTL rebuild is in progress. + +Signed-off-by: Selvan Mani +Signed-off-by: Asai Thambi S P +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/mtip32xx/mtip32xx.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -2968,10 +2968,8 @@ restart_eh: + } + + if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) { +- if (mtip_ftl_rebuild_poll(dd) < 0) +- set_bit(MTIP_DDF_REBUILD_FAILED_BIT, +- &dd->dd_flag); +- clear_bit(MTIP_PF_REBUILD_BIT, &port->flags); ++ if (mtip_ftl_rebuild_poll(dd) == 0) ++ clear_bit(MTIP_PF_REBUILD_BIT, &port->flags); + } + } + +@@ -3851,7 +3849,6 @@ static int mtip_block_initialize(struct + + mtip_hw_debugfs_init(dd); + +-skip_create_disk: + memset(&dd->tags, 0, sizeof(dd->tags)); + dd->tags.ops = &mtip_mq_ops; + dd->tags.nr_hw_queues = 1; +@@ -3881,6 +3878,7 @@ skip_create_disk: + dd->disk->queue = dd->queue; + dd->queue->queuedata = dd; + ++skip_create_disk: + /* Initialize the protocol layer. */ + wait_for_rebuild = mtip_hw_get_identify(dd); + if (wait_for_rebuild < 0) { +@@ -4041,7 +4039,8 @@ static int mtip_block_remove(struct driv + dd->bdev = NULL; + } + if (dd->disk) { +- del_gendisk(dd->disk); ++ if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) ++ del_gendisk(dd->disk); + if (dd->disk->queue) { + blk_cleanup_queue(dd->queue); + blk_mq_free_tag_set(&dd->tags); +@@ -4082,7 +4081,8 @@ static int mtip_block_shutdown(struct dr + dev_info(&dd->pdev->dev, + "Shutting down %s ...\n", dd->disk->disk_name); + +- del_gendisk(dd->disk); ++ if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) ++ del_gendisk(dd->disk); + if (dd->disk->queue) { + blk_cleanup_queue(dd->queue); + blk_mq_free_tag_set(&dd->tags); diff --git a/queue-4.5/mtip32xx-handle-ftl-rebuild-failure-state-during-device-initialization.patch b/queue-4.5/mtip32xx-handle-ftl-rebuild-failure-state-during-device-initialization.patch new file mode 100644 index 00000000000..5f2d0e1fb65 --- /dev/null +++ b/queue-4.5/mtip32xx-handle-ftl-rebuild-failure-state-during-device-initialization.patch @@ -0,0 +1,72 @@ +From aae4a033868c496adae86fc6f9c3e0c405bbf360 Mon Sep 17 00:00:00 2001 +From: Asai Thambi SP +Date: Wed, 24 Feb 2016 21:18:20 -0800 +Subject: mtip32xx: Handle FTL rebuild failure state during device initialization + +From: Asai Thambi SP + +commit aae4a033868c496adae86fc6f9c3e0c405bbf360 upstream. + +Allow device initialization to finish gracefully when it is in +FTL rebuild failure state. Also, recover device out of this state +after successfully secure erasing it. + +Signed-off-by: Selvan Mani +Signed-off-by: Vignesh Gunasekaran +Signed-off-by: Asai Thambi S P +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/mtip32xx/mtip32xx.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -699,7 +699,7 @@ static void mtip_handle_tfe(struct drive + fail_reason = "thermal shutdown"; + } + if (buf[288] == 0xBF) { +- set_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag); ++ set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag); + dev_info(&dd->pdev->dev, + "Drive indicates rebuild has failed. Secure erase required.\n"); + fail_all_ncq_cmds = 1; +@@ -1000,6 +1000,7 @@ static bool mtip_pause_ncq(struct mtip_p + (fis->features == 0x27 || fis->features == 0x72 || + fis->features == 0x62 || fis->features == 0x26))) { + clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag); ++ clear_bit(MTIP_DDF_REBUILD_FAILED_BIT, &port->dd->dd_flag); + /* Com reset after secure erase or lowlevel format */ + mtip_restart_port(port); + clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); +@@ -1166,6 +1167,7 @@ static int mtip_exec_internal_command(st + if ((rv = wait_for_completion_interruptible_timeout( + &wait, + msecs_to_jiffies(timeout))) <= 0) { ++ + if (rv == -ERESTARTSYS) { /* interrupted */ + dev_err(&dd->pdev->dev, + "Internal command [%02X] was interrupted after %u ms\n", +@@ -3084,7 +3086,7 @@ static int mtip_hw_get_identify(struct d + if (buf[288] == 0xBF) { + dev_info(&dd->pdev->dev, + "Drive indicates rebuild has failed.\n"); +- /* TODO */ ++ set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag); + } + } + +@@ -3687,10 +3689,9 @@ static int mtip_submit_request(struct bl + rq_data_dir(rq))) { + return -ENODATA; + } +- if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))) ++ if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag) || ++ test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag))) + return -ENODATA; +- if (test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)) +- return -ENXIO; + } + + if (rq->cmd_flags & REQ_DISCARD) { diff --git a/queue-4.5/mtip32xx-handle-safe-removal-during-io.patch b/queue-4.5/mtip32xx-handle-safe-removal-during-io.patch new file mode 100644 index 00000000000..97038e67a2d --- /dev/null +++ b/queue-4.5/mtip32xx-handle-safe-removal-during-io.patch @@ -0,0 +1,102 @@ +From 51c6570eb922146470c2fe660c34585414679bd6 Mon Sep 17 00:00:00 2001 +From: Asai Thambi SP +Date: Wed, 24 Feb 2016 21:18:10 -0800 +Subject: mtip32xx: Handle safe removal during IO + +From: Asai Thambi SP + +commit 51c6570eb922146470c2fe660c34585414679bd6 upstream. + +Flush inflight IOs using fsync_bdev() when the device is safely +removed. Also, block further IOs in device open function. + +Signed-off-by: Selvan Mani +Signed-off-by: Rajesh Kumar Sambandam +Signed-off-by: Asai Thambi S P +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/mtip32xx/mtip32xx.c | 34 ++++++++++++++++++++++++++++++++-- + drivers/block/mtip32xx/mtip32xx.h | 1 + + 2 files changed, 33 insertions(+), 2 deletions(-) + +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -3595,6 +3595,28 @@ static int mtip_block_getgeo(struct bloc + return 0; + } + ++static int mtip_block_open(struct block_device *dev, fmode_t mode) ++{ ++ struct driver_data *dd; ++ ++ if (dev && dev->bd_disk) { ++ dd = (struct driver_data *) dev->bd_disk->private_data; ++ ++ if (dd) { ++ if (test_bit(MTIP_DDF_REMOVAL_BIT, ++ &dd->dd_flag)) { ++ return -ENODEV; ++ } ++ return 0; ++ } ++ } ++ return -ENODEV; ++} ++ ++void mtip_block_release(struct gendisk *disk, fmode_t mode) ++{ ++} ++ + /* + * Block device operation function. + * +@@ -3602,6 +3624,8 @@ static int mtip_block_getgeo(struct bloc + * layer. + */ + static const struct block_device_operations mtip_block_ops = { ++ .open = mtip_block_open, ++ .release = mtip_block_release, + .ioctl = mtip_block_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = mtip_block_compat_ioctl, +@@ -4427,7 +4451,7 @@ static void mtip_pci_remove(struct pci_d + struct driver_data *dd = pci_get_drvdata(pdev); + unsigned long flags, to; + +- set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); ++ set_bit(MTIP_DDF_REMOVAL_BIT, &dd->dd_flag); + + spin_lock_irqsave(&dev_lock, flags); + list_del_init(&dd->online_list); +@@ -4444,12 +4468,18 @@ static void mtip_pci_remove(struct pci_d + } while (atomic_read(&dd->irq_workers_active) != 0 && + time_before(jiffies, to)); + ++ fsync_bdev(dd->bdev); ++ + if (atomic_read(&dd->irq_workers_active) != 0) { + dev_warn(&dd->pdev->dev, + "Completion workers still active!\n"); + } + +- blk_mq_stop_hw_queues(dd->queue); ++ if (dd->sr) ++ blk_mq_stop_hw_queues(dd->queue); ++ ++ set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); ++ + /* Clean up the block layer. */ + mtip_block_remove(dd); + +--- a/drivers/block/mtip32xx/mtip32xx.h ++++ b/drivers/block/mtip32xx/mtip32xx.h +@@ -158,6 +158,7 @@ enum { + MTIP_DDF_RESUME_BIT = 6, + MTIP_DDF_INIT_DONE_BIT = 7, + MTIP_DDF_REBUILD_FAILED_BIT = 8, ++ MTIP_DDF_REMOVAL_BIT = 9, + + MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | + (1 << MTIP_DDF_SEC_LOCK_BIT) | diff --git a/queue-4.5/mtip32xx-implement-timeout-handler.patch b/queue-4.5/mtip32xx-implement-timeout-handler.patch new file mode 100644 index 00000000000..8475e44a20a --- /dev/null +++ b/queue-4.5/mtip32xx-implement-timeout-handler.patch @@ -0,0 +1,195 @@ +From abb0ccd185c9e31847709b86192e6c815d1f57ad Mon Sep 17 00:00:00 2001 +From: Asai Thambi SP +Date: Wed, 24 Feb 2016 21:21:13 -0800 +Subject: mtip32xx: Implement timeout handler + +From: Asai Thambi SP + +commit abb0ccd185c9e31847709b86192e6c815d1f57ad upstream. + +Added timeout handler. Replaced blk_mq_end_request() with +blk_mq_complete_request() to avoid double completion of a request. + +Signed-off-by: Selvan Mani +Signed-off-by: Rajesh Kumar Sambandam +Signed-off-by: Asai Thambi S P +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/mtip32xx/mtip32xx.c | 95 ++++++++++++++++++++++++++++++++++---- + drivers/block/mtip32xx/mtip32xx.h | 7 ++ + 2 files changed, 92 insertions(+), 10 deletions(-) + +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -233,15 +233,9 @@ static void mtip_async_complete(struct m + "Command tag %d failed due to TFE\n", tag); + } + +- /* Unmap the DMA scatter list entries */ +- dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, cmd->direction); +- + rq = mtip_rq_from_tag(dd, tag); + +- if (unlikely(cmd->unaligned)) +- up(&port->cmd_slot_unal); +- +- blk_mq_end_request(rq, status ? -EIO : 0); ++ blk_mq_complete_request(rq, status); + } + + /* +@@ -2889,6 +2883,42 @@ static int mtip_ftl_rebuild_poll(struct + return -EFAULT; + } + ++static void mtip_softirq_done_fn(struct request *rq) ++{ ++ struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq); ++ struct driver_data *dd = rq->q->queuedata; ++ ++ /* Unmap the DMA scatter list entries */ ++ dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, ++ cmd->direction); ++ ++ if (unlikely(cmd->unaligned)) ++ up(&dd->port->cmd_slot_unal); ++ ++ blk_mq_end_request(rq, rq->errors); ++} ++ ++static void mtip_abort_cmd(struct request *req, void *data, ++ bool reserved) ++{ ++ struct driver_data *dd = data; ++ ++ dbg_printk(MTIP_DRV_NAME " Aborting request, tag = %d\n", req->tag); ++ ++ clear_bit(req->tag, dd->port->cmds_to_issue); ++ req->errors = -EIO; ++ mtip_softirq_done_fn(req); ++} ++ ++static void mtip_queue_cmd(struct request *req, void *data, ++ bool reserved) ++{ ++ struct driver_data *dd = data; ++ ++ set_bit(req->tag, dd->port->cmds_to_issue); ++ blk_abort_request(req); ++} ++ + /* + * service thread to issue queued commands + * +@@ -2901,7 +2931,7 @@ static int mtip_ftl_rebuild_poll(struct + static int mtip_service_thread(void *data) + { + struct driver_data *dd = (struct driver_data *)data; +- unsigned long slot, slot_start, slot_wrap; ++ unsigned long slot, slot_start, slot_wrap, to; + unsigned int num_cmd_slots = dd->slot_groups * 32; + struct mtip_port *port = dd->port; + +@@ -2938,6 +2968,32 @@ restart_eh: + if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) + goto restart_eh; + ++ if (test_bit(MTIP_PF_TO_ACTIVE_BIT, &port->flags)) { ++ to = jiffies + msecs_to_jiffies(5000); ++ ++ do { ++ mdelay(100); ++ } while (atomic_read(&dd->irq_workers_active) != 0 && ++ time_before(jiffies, to)); ++ ++ if (atomic_read(&dd->irq_workers_active) != 0) ++ dev_warn(&dd->pdev->dev, ++ "Completion workers still active!"); ++ ++ spin_lock(dd->queue->queue_lock); ++ blk_mq_all_tag_busy_iter(*dd->tags.tags, ++ mtip_queue_cmd, dd); ++ spin_unlock(dd->queue->queue_lock); ++ ++ set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags); ++ ++ if (mtip_device_reset(dd)) ++ blk_mq_all_tag_busy_iter(*dd->tags.tags, ++ mtip_abort_cmd, dd); ++ ++ clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags); ++ } ++ + if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { + slot = 1; + /* used to restrict the loop to one iteration */ +@@ -3803,11 +3859,33 @@ static int mtip_init_cmd(void *data, str + return 0; + } + ++static enum blk_eh_timer_return mtip_cmd_timeout(struct request *req, ++ bool reserved) ++{ ++ struct driver_data *dd = req->q->queuedata; ++ int ret = BLK_EH_RESET_TIMER; ++ ++ if (reserved) ++ goto exit_handler; ++ ++ if (test_bit(req->tag, dd->port->cmds_to_issue)) ++ goto exit_handler; ++ ++ if (test_and_set_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags)) ++ goto exit_handler; ++ ++ wake_up_interruptible(&dd->port->svc_wait); ++exit_handler: ++ return ret; ++} ++ + static struct blk_mq_ops mtip_mq_ops = { + .queue_rq = mtip_queue_rq, + .map_queue = blk_mq_map_queue, + .init_request = mtip_init_cmd, + .exit_request = mtip_free_cmd, ++ .complete = mtip_softirq_done_fn, ++ .timeout = mtip_cmd_timeout, + }; + + /* +@@ -3883,6 +3961,7 @@ static int mtip_block_initialize(struct + dd->tags.numa_node = dd->numa_node; + dd->tags.flags = BLK_MQ_F_SHOULD_MERGE; + dd->tags.driver_data = dd; ++ dd->tags.timeout = MTIP_NCQ_CMD_TIMEOUT_MS; + + rv = blk_mq_alloc_tag_set(&dd->tags); + if (rv) { +--- a/drivers/block/mtip32xx/mtip32xx.h ++++ b/drivers/block/mtip32xx/mtip32xx.h +@@ -134,10 +134,12 @@ enum { + MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */ + MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */ + MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */ ++ MTIP_PF_TO_ACTIVE_BIT = 9, /* timeout handling */ + MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) | + (1 << MTIP_PF_EH_ACTIVE_BIT) | + (1 << MTIP_PF_SE_ACTIVE_BIT) | +- (1 << MTIP_PF_DM_ACTIVE_BIT)), ++ (1 << MTIP_PF_DM_ACTIVE_BIT) | ++ (1 << MTIP_PF_TO_ACTIVE_BIT)), + + MTIP_PF_SVC_THD_ACTIVE_BIT = 4, + MTIP_PF_ISSUE_CMDS_BIT = 5, +@@ -147,7 +149,8 @@ enum { + MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) | + (1 << MTIP_PF_ISSUE_CMDS_BIT) | + (1 << MTIP_PF_REBUILD_BIT) | +- (1 << MTIP_PF_SVC_THD_STOP_BIT)), ++ (1 << MTIP_PF_SVC_THD_STOP_BIT) | ++ (1 << MTIP_PF_TO_ACTIVE_BIT)), + + /* below are bit numbers in 'dd_flag' defined in driver_data */ + MTIP_DDF_SEC_LOCK_BIT = 0, diff --git a/queue-4.5/mtip32xx-print-exact-time-when-an-internal-command-is-interrupted.patch b/queue-4.5/mtip32xx-print-exact-time-when-an-internal-command-is-interrupted.patch new file mode 100644 index 00000000000..45023c4b228 --- /dev/null +++ b/queue-4.5/mtip32xx-print-exact-time-when-an-internal-command-is-interrupted.patch @@ -0,0 +1,52 @@ +From 5b7e0a8ac85e2dfd83830dc9e0b3554d153a37e3 Mon Sep 17 00:00:00 2001 +From: Asai Thambi SP +Date: Wed, 24 Feb 2016 21:16:38 -0800 +Subject: mtip32xx: Print exact time when an internal command is interrupted + +From: Asai Thambi SP + +commit 5b7e0a8ac85e2dfd83830dc9e0b3554d153a37e3 upstream. + +Print exact time when an internal command is interrupted. + +Signed-off-by: Selvan Mani +Signed-off-by: Rajesh Kumar Sambandam +Signed-off-by: Asai Thambi S P +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/mtip32xx/mtip32xx.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -1092,6 +1092,7 @@ static int mtip_exec_internal_command(st + struct mtip_cmd *int_cmd; + struct driver_data *dd = port->dd; + int rv = 0; ++ unsigned long start; + + /* Make sure the buffer is 8 byte aligned. This is asic specific. */ + if (buffer & 0x00000007) { +@@ -1155,6 +1156,8 @@ static int mtip_exec_internal_command(st + /* Populate the command header */ + int_cmd->command_header->byte_count = 0; + ++ start = jiffies; ++ + /* Issue the command to the hardware */ + mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL); + +@@ -1165,8 +1168,9 @@ static int mtip_exec_internal_command(st + msecs_to_jiffies(timeout))) <= 0) { + if (rv == -ERESTARTSYS) { /* interrupted */ + dev_err(&dd->pdev->dev, +- "Internal command [%02X] was interrupted after %lu ms\n", +- fis->command, timeout); ++ "Internal command [%02X] was interrupted after %u ms\n", ++ fis->command, ++ jiffies_to_msecs(jiffies - start)); + rv = -EINTR; + goto exec_ic_exit; + } else if (rv == 0) /* timeout */ diff --git a/queue-4.5/mtip32xx-remove-unwanted-code-from-taskfile-error-handler.patch b/queue-4.5/mtip32xx-remove-unwanted-code-from-taskfile-error-handler.patch new file mode 100644 index 00000000000..2e42f386961 --- /dev/null +++ b/queue-4.5/mtip32xx-remove-unwanted-code-from-taskfile-error-handler.patch @@ -0,0 +1,56 @@ +From e35b94738a2f7caa12017f69ef385cb6b8028965 Mon Sep 17 00:00:00 2001 +From: Asai Thambi SP +Date: Wed, 24 Feb 2016 21:16:21 -0800 +Subject: mtip32xx: Remove unwanted code from taskfile error handler + +From: Asai Thambi SP + +commit e35b94738a2f7caa12017f69ef385cb6b8028965 upstream. + +Remove setting and clearing MTIP_PF_EH_ACTIVE_BIT flag in +mtip_handle_tfe() as they are redundant. Also avoid waking +up service thread from mtip_handle_tfe() because it is +already woken up in case of taskfile error. + +Signed-off-by: Selvan Mani +Signed-off-by: Rajesh Kumar Sambandam +Signed-off-by: Asai Thambi S P +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/mtip32xx/mtip32xx.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -618,8 +618,6 @@ static void mtip_handle_tfe(struct drive + + port = dd->port; + +- set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); +- + if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { + cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL); + dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n"); +@@ -628,7 +626,7 @@ static void mtip_handle_tfe(struct drive + cmd->comp_func(port, MTIP_TAG_INTERNAL, + cmd, PORT_IRQ_TF_ERR); + } +- goto handle_tfe_exit; ++ return; + } + + /* clear the tag accumulator */ +@@ -771,11 +769,6 @@ static void mtip_handle_tfe(struct drive + } + } + print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt); +- +-handle_tfe_exit: +- /* clear eh_active */ +- clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); +- wake_up_interruptible(&port->svc_wait); + } + + /* diff --git a/queue-4.5/net-irda-fix-use-after-free-in-irtty_open.patch b/queue-4.5/net-irda-fix-use-after-free-in-irtty_open.patch new file mode 100644 index 00000000000..d45c24be50e --- /dev/null +++ b/queue-4.5/net-irda-fix-use-after-free-in-irtty_open.patch @@ -0,0 +1,65 @@ +From 401879c57f01cbf2da204ad2e8db910525c6dbea Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Sat, 9 Jan 2016 17:48:45 -0800 +Subject: net: irda: Fix use-after-free in irtty_open() + +From: Peter Hurley + +commit 401879c57f01cbf2da204ad2e8db910525c6dbea upstream. + +The N_IRDA line discipline may access the previous line discipline's closed +and already-fre private data on open [1]. + +The tty->disc_data field _never_ refers to valid data on entry to the +line discipline's open() method. Rather, the ldisc is expected to +initialize that field for its own use for the lifetime of the instance +(ie. from open() to close() only). + +[1] + ================================================================== + BUG: KASAN: use-after-free in irtty_open+0x422/0x550 at addr ffff8800331dd068 + Read of size 4 by task a.out/13960 + ============================================================================= + BUG kmalloc-512 (Tainted: G B ): kasan: bad access detected + ----------------------------------------------------------------------------- + ... + Call Trace: + [] __asan_report_load4_noabort+0x3e/0x40 mm/kasan/report.c:279 + [] irtty_open+0x422/0x550 drivers/net/irda/irtty-sir.c:436 + [] tty_ldisc_open.isra.2+0x60/0xa0 drivers/tty/tty_ldisc.c:447 + [] tty_set_ldisc+0x1a0/0x940 drivers/tty/tty_ldisc.c:567 + [< inline >] tiocsetd drivers/tty/tty_io.c:2650 + [] tty_ioctl+0xace/0x1fd0 drivers/tty/tty_io.c:2883 + [< inline >] vfs_ioctl fs/ioctl.c:43 + [] do_vfs_ioctl+0x57c/0xe60 fs/ioctl.c:607 + [< inline >] SYSC_ioctl fs/ioctl.c:622 + [] SyS_ioctl+0x74/0x80 fs/ioctl.c:613 + [] entry_SYSCALL_64_fastpath+0x16/0x7a + +Reported-and-tested-by: Dmitry Vyukov +Signed-off-by: Peter Hurley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/irda/irtty-sir.c | 10 ---------- + 1 file changed, 10 deletions(-) + +--- a/drivers/net/irda/irtty-sir.c ++++ b/drivers/net/irda/irtty-sir.c +@@ -430,16 +430,6 @@ static int irtty_open(struct tty_struct + + /* Module stuff handled via irda_ldisc.owner - Jean II */ + +- /* First make sure we're not already connected. */ +- if (tty->disc_data != NULL) { +- priv = tty->disc_data; +- if (priv && priv->magic == IRTTY_MAGIC) { +- ret = -EEXIST; +- goto out; +- } +- tty->disc_data = NULL; /* ### */ +- } +- + /* stop the underlying driver */ + irtty_stop_receiver(tty, TRUE); + if (tty->ops->stop) diff --git a/queue-4.5/saa7134-fix-bytesperline-not-being-set-correctly-for-planar-formats.patch b/queue-4.5/saa7134-fix-bytesperline-not-being-set-correctly-for-planar-formats.patch new file mode 100644 index 00000000000..5f5eddc5c3f --- /dev/null +++ b/queue-4.5/saa7134-fix-bytesperline-not-being-set-correctly-for-planar-formats.patch @@ -0,0 +1,62 @@ +From 3e71da19f9dc22e39a755d6ae9678661abb66adc Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 14 Feb 2016 17:51:37 -0200 +Subject: [media] saa7134: Fix bytesperline not being set correctly for planar formats + +From: Hans de Goede + +commit 3e71da19f9dc22e39a755d6ae9678661abb66adc upstream. + +bytesperline should be the bytesperline for the first plane for planar +formats, not that of all planes combined. + +This fixes a crash in xawtv caused by the wrong bpl. + +BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1305389 +Reported-and-tested-by: Stas Sergeev + +Signed-off-by: Hans de Goede +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/pci/saa7134/saa7134-video.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/drivers/media/pci/saa7134/saa7134-video.c ++++ b/drivers/media/pci/saa7134/saa7134-video.c +@@ -1219,10 +1219,13 @@ static int saa7134_g_fmt_vid_cap(struct + f->fmt.pix.height = dev->height; + f->fmt.pix.field = dev->field; + f->fmt.pix.pixelformat = dev->fmt->fourcc; +- f->fmt.pix.bytesperline = +- (f->fmt.pix.width * dev->fmt->depth) >> 3; ++ if (dev->fmt->planar) ++ f->fmt.pix.bytesperline = f->fmt.pix.width; ++ else ++ f->fmt.pix.bytesperline = ++ (f->fmt.pix.width * dev->fmt->depth) / 8; + f->fmt.pix.sizeimage = +- f->fmt.pix.height * f->fmt.pix.bytesperline; ++ (f->fmt.pix.height * f->fmt.pix.width * dev->fmt->depth) / 8; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + return 0; + } +@@ -1298,10 +1301,13 @@ static int saa7134_try_fmt_vid_cap(struc + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; + f->fmt.pix.width &= ~0x03; +- f->fmt.pix.bytesperline = +- (f->fmt.pix.width * fmt->depth) >> 3; ++ if (fmt->planar) ++ f->fmt.pix.bytesperline = f->fmt.pix.width; ++ else ++ f->fmt.pix.bytesperline = ++ (f->fmt.pix.width * fmt->depth) / 8; + f->fmt.pix.sizeimage = +- f->fmt.pix.height * f->fmt.pix.bytesperline; ++ (f->fmt.pix.height * f->fmt.pix.width * fmt->depth) / 8; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + + return 0; diff --git a/queue-4.5/series b/queue-4.5/series index 78c9ab7d95b..ed07f4efd7a 100644 --- a/queue-4.5/series +++ b/queue-4.5/series @@ -84,3 +84,31 @@ crypto-ux500-fix-checks-of-error-code-returned-by-devm_ioremap_resource.patch crypto-marvell-cesa-forward-devm_ioremap_resource-error-code.patch x.509-fix-leap-year-handling-again.patch mei-bus-check-if-the-device-is-enabled-before-data-transfer.patch +tpm-fix-the-rollback-in-tpm_chip_register.patch +tpm_crb-tpm2_shutdown-must-be-called-before-tpm_chip_unregister.patch +tpm_eventlog.c-fix-binary_bios_measurements.patch +tpm-fix-the-cleanup-of-struct-tpm_chip.patch +hid-logitech-fix-dual-action-gamepad-support.patch +hid-i2c-hid-fix-oob-write-in-i2c_hid_set_or_send_report.patch +hid-multitouch-force-retrieving-of-win8-signature-blob.patch +hid-fix-hid_ignore_special_drivers-module-parameter.patch +staging-comedi-ni_tiocmd-change-mistaken-use-of-start_src-for-start_arg.patch +staging-android-ion_test-fix-check-of-platform_device_register_simple-error-code.patch +staging-comedi-ni_mio_common-fix-the-ni_write-functions.patch +tty-fix-gpf-in-flush_to_ldisc-part-2.patch +net-irda-fix-use-after-free-in-irtty_open.patch +8250-use-callbacks-to-access-uart_dll-uart_dlm.patch +saa7134-fix-bytesperline-not-being-set-correctly-for-planar-formats.patch +adv7511-tx_edid_present-is-still-1-after-a-disconnect.patch +bttv-width-must-be-a-multiple-of-16-when-capturing-planar-formats.patch +coda-fix-first-encoded-frame-payload.patch +media-v4l2-compat-ioctl32-fix-missing-length-copy-in-put_v4l2_buffer32.patch +mtip32xx-avoid-issuing-standby-immediate-cmd-during-ftl-rebuild.patch +mtip32xx-fix-broken-service-thread-handling.patch +mtip32xx-remove-unwanted-code-from-taskfile-error-handler.patch +mtip32xx-print-exact-time-when-an-internal-command-is-interrupted.patch +mtip32xx-fix-for-rmmod-crash-when-drive-is-in-ftl-rebuild.patch +mtip32xx-handle-safe-removal-during-io.patch +mtip32xx-handle-ftl-rebuild-failure-state-during-device-initialization.patch +mtip32xx-implement-timeout-handler.patch +mtip32xx-cleanup-queued-requests-after-surprise-removal.patch diff --git a/queue-4.5/staging-android-ion_test-fix-check-of-platform_device_register_simple-error-code.patch b/queue-4.5/staging-android-ion_test-fix-check-of-platform_device_register_simple-error-code.patch new file mode 100644 index 00000000000..628b94a45ac --- /dev/null +++ b/queue-4.5/staging-android-ion_test-fix-check-of-platform_device_register_simple-error-code.patch @@ -0,0 +1,34 @@ +From ccbc2a9e7878ff09bcaed4893c2a2d3adbb797e2 Mon Sep 17 00:00:00 2001 +From: Vladimir Zapolskiy +Date: Wed, 23 Mar 2016 00:38:43 +0200 +Subject: staging: android: ion_test: fix check of platform_device_register_simple() error code + +From: Vladimir Zapolskiy + +commit ccbc2a9e7878ff09bcaed4893c2a2d3adbb797e2 upstream. + +On error platform_device_register_simple() returns ERR_PTR() value, +check for NULL always fails. The change corrects the check itself and +propagates the returned error upwards. + +Fixes: 81fb0b901397 ("staging: android: ion_test: unregister the platform device") +Signed-off-by: Vladimir Zapolskiy +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/android/ion/ion_test.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/staging/android/ion/ion_test.c ++++ b/drivers/staging/android/ion/ion_test.c +@@ -285,8 +285,8 @@ static int __init ion_test_init(void) + { + ion_test_pdev = platform_device_register_simple("ion-test", + -1, NULL, 0); +- if (!ion_test_pdev) +- return -ENODEV; ++ if (IS_ERR(ion_test_pdev)) ++ return PTR_ERR(ion_test_pdev); + + return platform_driver_probe(&ion_test_platform_driver, ion_test_probe); + } diff --git a/queue-4.5/staging-comedi-ni_mio_common-fix-the-ni_write-functions.patch b/queue-4.5/staging-comedi-ni_mio_common-fix-the-ni_write-functions.patch new file mode 100644 index 00000000000..63cbd406cba --- /dev/null +++ b/queue-4.5/staging-comedi-ni_mio_common-fix-the-ni_write-functions.patch @@ -0,0 +1,54 @@ +From bd3a3cd6c27b117fb9a43a38c8072c95332beecc Mon Sep 17 00:00:00 2001 +From: H Hartley Sweeten +Date: Tue, 22 Mar 2016 10:04:48 -0700 +Subject: staging: comedi: ni_mio_common: fix the ni_write[blw]() functions + +From: H Hartley Sweeten + +commit bd3a3cd6c27b117fb9a43a38c8072c95332beecc upstream. + +Memory mapped io (dev->mmio) should not also be writing to the ioport +(dev->iobase) registers. Add the missing 'else' to these functions. + +Fixes: 0953ee4acca0 ("staging: comedi: ni_mio_common: checkpatch.pl cleanup (else not useful)") +Signed-off-by: H Hartley Sweeten +Reviewed-by: Ian Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/drivers/ni_mio_common.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/staging/comedi/drivers/ni_mio_common.c ++++ b/drivers/staging/comedi/drivers/ni_mio_common.c +@@ -246,24 +246,24 @@ static void ni_writel(struct comedi_devi + { + if (dev->mmio) + writel(data, dev->mmio + reg); +- +- outl(data, dev->iobase + reg); ++ else ++ outl(data, dev->iobase + reg); + } + + static void ni_writew(struct comedi_device *dev, uint16_t data, int reg) + { + if (dev->mmio) + writew(data, dev->mmio + reg); +- +- outw(data, dev->iobase + reg); ++ else ++ outw(data, dev->iobase + reg); + } + + static void ni_writeb(struct comedi_device *dev, uint8_t data, int reg) + { + if (dev->mmio) + writeb(data, dev->mmio + reg); +- +- outb(data, dev->iobase + reg); ++ else ++ outb(data, dev->iobase + reg); + } + + static uint32_t ni_readl(struct comedi_device *dev, int reg) diff --git a/queue-4.5/staging-comedi-ni_tiocmd-change-mistaken-use-of-start_src-for-start_arg.patch b/queue-4.5/staging-comedi-ni_tiocmd-change-mistaken-use-of-start_src-for-start_arg.patch new file mode 100644 index 00000000000..cb28b416b8b --- /dev/null +++ b/queue-4.5/staging-comedi-ni_tiocmd-change-mistaken-use-of-start_src-for-start_arg.patch @@ -0,0 +1,32 @@ +From 1fd24a4702d2af0ea4d5845126cf57d4d1796216 Mon Sep 17 00:00:00 2001 +From: "Spencer E. Olson" +Date: Tue, 12 Jan 2016 10:33:18 -0700 +Subject: staging: comedi: ni_tiocmd: change mistaken use of start_src for start_arg + +From: Spencer E. Olson + +commit 1fd24a4702d2af0ea4d5845126cf57d4d1796216 upstream. + +This fixes a bug in function ni_tio_input_inttrig(). The trigger number +should be compared to cmd->start_arg, not cmd->start_src. + +Fixes: 6a760394d7eb ("staging: comedi: ni_tiocmd: clarify the cmd->start_arg validation and use") +Signed-off-by: Spencer E. Olson +Reviewed-by: Ian Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/drivers/ni_tiocmd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/comedi/drivers/ni_tiocmd.c ++++ b/drivers/staging/comedi/drivers/ni_tiocmd.c +@@ -92,7 +92,7 @@ static int ni_tio_input_inttrig(struct c + unsigned long flags; + int ret = 0; + +- if (trig_num != cmd->start_src) ++ if (trig_num != cmd->start_arg) + return -EINVAL; + + spin_lock_irqsave(&counter->lock, flags); diff --git a/queue-4.5/tpm-fix-the-cleanup-of-struct-tpm_chip.patch b/queue-4.5/tpm-fix-the-cleanup-of-struct-tpm_chip.patch new file mode 100644 index 00000000000..f64841ae501 --- /dev/null +++ b/queue-4.5/tpm-fix-the-cleanup-of-struct-tpm_chip.patch @@ -0,0 +1,43 @@ +From 8e0ee3c9faed7ca68807ea45141775856c438ac0 Mon Sep 17 00:00:00 2001 +From: Jarkko Sakkinen +Date: Mon, 8 Feb 2016 22:31:08 +0200 +Subject: tpm: fix the cleanup of struct tpm_chip + +From: Jarkko Sakkinen + +commit 8e0ee3c9faed7ca68807ea45141775856c438ac0 upstream. + +If the initialization fails before tpm_chip_register(), put_device() +will be not called, which causes release callback not to be called. +This patch fixes the issue by adding put_device() to devres list of +the parent device. + +Fixes: 313d21eeab ("tpm: device class for tpm") +Signed-off-by: Jarkko Sakkinen +Reviewed-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tpm/tpm-chip.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/char/tpm/tpm-chip.c ++++ b/drivers/char/tpm/tpm-chip.c +@@ -136,6 +136,8 @@ struct tpm_chip *tpmm_chip_alloc(struct + chip->cdev.owner = chip->pdev->driver->owner; + chip->cdev.kobj.parent = &chip->dev.kobj; + ++ devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev); ++ + return chip; + } + EXPORT_SYMBOL_GPL(tpmm_chip_alloc); +@@ -171,7 +173,7 @@ static int tpm_add_char_device(struct tp + static void tpm_del_char_device(struct tpm_chip *chip) + { + cdev_del(&chip->cdev); +- device_unregister(&chip->dev); ++ device_del(&chip->dev); + } + + static int tpm1_chip_register(struct tpm_chip *chip) diff --git a/queue-4.5/tpm-fix-the-rollback-in-tpm_chip_register.patch b/queue-4.5/tpm-fix-the-rollback-in-tpm_chip_register.patch new file mode 100644 index 00000000000..3d1fd016eff --- /dev/null +++ b/queue-4.5/tpm-fix-the-rollback-in-tpm_chip_register.patch @@ -0,0 +1,73 @@ +From 72c91ce8523ae5828fe5e4417ae0aaab53707a08 Mon Sep 17 00:00:00 2001 +From: Jarkko Sakkinen +Date: Fri, 29 Jan 2016 09:47:22 -0800 +Subject: tpm: fix the rollback in tpm_chip_register() + +From: Jarkko Sakkinen + +commit 72c91ce8523ae5828fe5e4417ae0aaab53707a08 upstream. + +Fixed the rollback and gave more self-documenting names for the +functions. + +Fixes: d972b0523f ("tpm: fix call order in tpm-chip.c") +Signed-off-by: Jarkko Sakkinen +Reviewed-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tpm/tpm-chip.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/char/tpm/tpm-chip.c ++++ b/drivers/char/tpm/tpm-chip.c +@@ -140,7 +140,7 @@ struct tpm_chip *tpmm_chip_alloc(struct + } + EXPORT_SYMBOL_GPL(tpmm_chip_alloc); + +-static int tpm_dev_add_device(struct tpm_chip *chip) ++static int tpm_add_char_device(struct tpm_chip *chip) + { + int rc; + +@@ -151,7 +151,6 @@ static int tpm_dev_add_device(struct tpm + chip->devname, MAJOR(chip->dev.devt), + MINOR(chip->dev.devt), rc); + +- device_unregister(&chip->dev); + return rc; + } + +@@ -162,13 +161,14 @@ static int tpm_dev_add_device(struct tpm + chip->devname, MAJOR(chip->dev.devt), + MINOR(chip->dev.devt), rc); + ++ cdev_del(&chip->cdev); + return rc; + } + + return rc; + } + +-static void tpm_dev_del_device(struct tpm_chip *chip) ++static void tpm_del_char_device(struct tpm_chip *chip) + { + cdev_del(&chip->cdev); + device_unregister(&chip->dev); +@@ -222,7 +222,7 @@ int tpm_chip_register(struct tpm_chip *c + + tpm_add_ppi(chip); + +- rc = tpm_dev_add_device(chip); ++ rc = tpm_add_char_device(chip); + if (rc) + goto out_err; + +@@ -274,6 +274,6 @@ void tpm_chip_unregister(struct tpm_chip + sysfs_remove_link(&chip->pdev->kobj, "ppi"); + + tpm1_chip_unregister(chip); +- tpm_dev_del_device(chip); ++ tpm_del_char_device(chip); + } + EXPORT_SYMBOL_GPL(tpm_chip_unregister); diff --git a/queue-4.5/tpm_crb-tpm2_shutdown-must-be-called-before-tpm_chip_unregister.patch b/queue-4.5/tpm_crb-tpm2_shutdown-must-be-called-before-tpm_chip_unregister.patch new file mode 100644 index 00000000000..157f7effb80 --- /dev/null +++ b/queue-4.5/tpm_crb-tpm2_shutdown-must-be-called-before-tpm_chip_unregister.patch @@ -0,0 +1,36 @@ +From 99cda8cb4639de81cde785b5bab9bc52e916e594 Mon Sep 17 00:00:00 2001 +From: Jarkko Sakkinen +Date: Thu, 18 Feb 2016 22:11:29 +0200 +Subject: tpm_crb: tpm2_shutdown() must be called before tpm_chip_unregister() + +From: Jarkko Sakkinen + +commit 99cda8cb4639de81cde785b5bab9bc52e916e594 upstream. + +Wrong call order. + +Reported-by: Jason Gunthorpe +Fixes: 74d6b3ceaa17 +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tpm/tpm_crb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/char/tpm/tpm_crb.c ++++ b/drivers/char/tpm/tpm_crb.c +@@ -302,11 +302,11 @@ static int crb_acpi_remove(struct acpi_d + struct device *dev = &device->dev; + struct tpm_chip *chip = dev_get_drvdata(dev); + +- tpm_chip_unregister(chip); +- + if (chip->flags & TPM_CHIP_FLAG_TPM2) + tpm2_shutdown(chip, TPM2_SU_CLEAR); + ++ tpm_chip_unregister(chip); ++ + return 0; + } + diff --git a/queue-4.5/tpm_eventlog.c-fix-binary_bios_measurements.patch b/queue-4.5/tpm_eventlog.c-fix-binary_bios_measurements.patch new file mode 100644 index 00000000000..0c369204a75 --- /dev/null +++ b/queue-4.5/tpm_eventlog.c-fix-binary_bios_measurements.patch @@ -0,0 +1,58 @@ +From 186d124f07da193a8f47e491af85cb695d415f2f Mon Sep 17 00:00:00 2001 +From: Harald Hoyer +Date: Sat, 6 Feb 2016 15:44:42 +0100 +Subject: tpm_eventlog.c: fix binary_bios_measurements + +From: Harald Hoyer + +commit 186d124f07da193a8f47e491af85cb695d415f2f upstream. + +The commit 0cc698af36ff ("vTPM: support little endian guests") copied +the event, but without the event data, did an endian conversion on the +size and tried to output the event data from the copied version, which +has only have one byte of the data, resulting in garbage event data. + +[jarkko.sakkinen@linux.intel.com: fixed minor coding style issues and + renamed the local variable tempPtr as temp_ptr now that there is an + excuse to do this.] + +Signed-off-by: Harald Hoyer +Fixes: 0cc698af36ff ("vTPM: support little endian guests") +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tpm/tpm_eventlog.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/char/tpm/tpm_eventlog.c ++++ b/drivers/char/tpm/tpm_eventlog.c +@@ -232,7 +232,7 @@ static int tpm_binary_bios_measurements_ + { + struct tcpa_event *event = v; + struct tcpa_event temp_event; +- char *tempPtr; ++ char *temp_ptr; + int i; + + memcpy(&temp_event, event, sizeof(struct tcpa_event)); +@@ -242,10 +242,16 @@ static int tpm_binary_bios_measurements_ + temp_event.event_type = do_endian_conversion(event->event_type); + temp_event.event_size = do_endian_conversion(event->event_size); + +- tempPtr = (char *)&temp_event; ++ temp_ptr = (char *) &temp_event; + +- for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++) +- seq_putc(m, tempPtr[i]); ++ for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++) ++ seq_putc(m, temp_ptr[i]); ++ ++ temp_ptr = (char *) v; ++ ++ for (i = (sizeof(struct tcpa_event) - 1); ++ i < (sizeof(struct tcpa_event) + temp_event.event_size); i++) ++ seq_putc(m, temp_ptr[i]); + + return 0; + diff --git a/queue-4.5/tty-fix-gpf-in-flush_to_ldisc-part-2.patch b/queue-4.5/tty-fix-gpf-in-flush_to_ldisc-part-2.patch new file mode 100644 index 00000000000..a500089e4a2 --- /dev/null +++ b/queue-4.5/tty-fix-gpf-in-flush_to_ldisc-part-2.patch @@ -0,0 +1,35 @@ +From f33798deecbd59a2955f40ac0ae2bc7dff54c069 Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Sun, 10 Jan 2016 20:36:12 -0800 +Subject: tty: Fix GPF in flush_to_ldisc(), part 2 + +From: Peter Hurley + +commit f33798deecbd59a2955f40ac0ae2bc7dff54c069 upstream. + +commit 9ce119f318ba ("tty: Fix GPF in flush_to_ldisc()") fixed a +GPF caused by a line discipline which does not define a receive_buf() +method. + +However, the vt driver (and speakup driver also) pushes selection +data directly to the line discipline receive_buf() method via +tty_ldisc_receive_buf(). Fix the same problem in tty_ldisc_receive_buf(). + +Signed-off-by: Peter Hurley +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/tty.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/tty.h ++++ b/include/linux/tty.h +@@ -589,7 +589,7 @@ static inline int tty_ldisc_receive_buf( + count = ld->ops->receive_buf2(ld->tty, p, f, count); + else { + count = min_t(int, count, ld->tty->receive_room); +- if (count) ++ if (count && ld->ops->receive_buf) + ld->ops->receive_buf(ld->tty, p, f, count); + } + return count;