From fe300210de11548ace8f2ef6949e6853bf513ce7 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Wed, 30 Dec 2020 23:14:51 -0500 Subject: [PATCH] Fixes for 4.4 Signed-off-by: Sasha Levin --- ...ix-hanging-device-offline-processing.patch | 62 +++++++ ...-initial-cpu-reset-also-for-smt-sibl.patch | 59 +++++++ ...use-smp_get_base_cpu-helper-function.patch | 41 +++++ queue-4.4/series | 4 + ...acceleport-fix-write-wakeup-deadlock.patch | 160 ++++++++++++++++++ 5 files changed, 326 insertions(+) create mode 100644 queue-4.4/s390-dasd-fix-hanging-device-offline-processing.patch create mode 100644 queue-4.4/s390-smp-perform-initial-cpu-reset-also-for-smt-sibl.patch create mode 100644 queue-4.4/s390-smp-use-smp_get_base_cpu-helper-function.patch create mode 100644 queue-4.4/usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch diff --git a/queue-4.4/s390-dasd-fix-hanging-device-offline-processing.patch b/queue-4.4/s390-dasd-fix-hanging-device-offline-processing.patch new file mode 100644 index 00000000000..49de84a2a96 --- /dev/null +++ b/queue-4.4/s390-dasd-fix-hanging-device-offline-processing.patch @@ -0,0 +1,62 @@ +From 8ddf4d22cac7e4804ac1a7c11f4877a307944546 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Dec 2020 16:59:04 +0100 +Subject: s390/dasd: fix hanging device offline processing + +From: Stefan Haberland + +[ Upstream commit 658a337a606f48b7ebe451591f7681d383fa115e ] + +For an LCU update a read unit address configuration IO is required. +This is started using sleep_on(), which has early exit paths in case the +device is not usable for IO. For example when it is in offline processing. + +In those cases the LCU update should fail and not be retried. +Therefore lcu_update_work checks if EOPNOTSUPP is returned or not. + +Commit 41995342b40c ("s390/dasd: fix endless loop after read unit address configuration") +accidentally removed the EOPNOTSUPP return code from +read_unit_address_configuration(), which in turn might lead to an endless +loop of the LCU update in offline processing. + +Fix by returning EOPNOTSUPP again if the device is not able to perform the +request. + +Fixes: 41995342b40c ("s390/dasd: fix endless loop after read unit address configuration") +Cc: stable@vger.kernel.org #5.3 +Signed-off-by: Stefan Haberland +Reviewed-by: Jan Hoeppner +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/s390/block/dasd_alias.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c +index 89b708135000c..03543c0a2dd0f 100644 +--- a/drivers/s390/block/dasd_alias.c ++++ b/drivers/s390/block/dasd_alias.c +@@ -475,11 +475,19 @@ static int read_unit_address_configuration(struct dasd_device *device, + spin_unlock_irqrestore(&lcu->lock, flags); + + rc = dasd_sleep_on(cqr); +- if (rc && !suborder_not_supported(cqr)) { ++ if (!rc) ++ goto out; ++ ++ if (suborder_not_supported(cqr)) { ++ /* suborder not supported or device unusable for IO */ ++ rc = -EOPNOTSUPP; ++ } else { ++ /* IO failed but should be retried */ + spin_lock_irqsave(&lcu->lock, flags); + lcu->flags |= NEED_UAC_UPDATE; + spin_unlock_irqrestore(&lcu->lock, flags); + } ++out: + dasd_kfree_request(cqr, cqr->memdev); + return rc; + } +-- +2.27.0 + diff --git a/queue-4.4/s390-smp-perform-initial-cpu-reset-also-for-smt-sibl.patch b/queue-4.4/s390-smp-perform-initial-cpu-reset-also-for-smt-sibl.patch new file mode 100644 index 00000000000..1327f993dbc --- /dev/null +++ b/queue-4.4/s390-smp-perform-initial-cpu-reset-also-for-smt-sibl.patch @@ -0,0 +1,59 @@ +From ed8b681de2733104b61dda3d7d8a69166d405ee6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Dec 2020 07:35:21 +0100 +Subject: s390/smp: perform initial CPU reset also for SMT siblings + +From: Sven Schnelle + +[ Upstream commit b5e438ebd7e808d1d2435159ac4742e01a94b8da ] + +Not resetting the SMT siblings might leave them in unpredictable +state. One of the observed problems was that the CPU timer wasn't +reset and therefore large system time values where accounted during +CPU bringup. + +Cc: # 4.0 +Fixes: 10ad34bc76dfb ("s390: add SMT support") +Reviewed-by: Heiko Carstens +Signed-off-by: Sven Schnelle +Signed-off-by: Heiko Carstens +Signed-off-by: Sasha Levin +--- + arch/s390/kernel/smp.c | 18 +++--------------- + 1 file changed, 3 insertions(+), 15 deletions(-) + +diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c +index c941bd500765a..526927621369b 100644 +--- a/arch/s390/kernel/smp.c ++++ b/arch/s390/kernel/smp.c +@@ -843,24 +843,12 @@ static void smp_start_secondary(void *cpuvoid) + /* Upping and downing of CPUs */ + int __cpu_up(unsigned int cpu, struct task_struct *tidle) + { +- struct pcpu *pcpu; +- int base, i, rc; ++ struct pcpu *pcpu = pcpu_devices + cpu; ++ int rc; + +- pcpu = pcpu_devices + cpu; + if (pcpu->state != CPU_STATE_CONFIGURED) + return -EIO; +- base = smp_get_base_cpu(cpu); +- for (i = 0; i <= smp_cpu_mtid; i++) { +- if (base + i < nr_cpu_ids) +- if (cpu_online(base + i)) +- break; +- } +- /* +- * If this is the first CPU of the core to get online +- * do an initial CPU reset. +- */ +- if (i > smp_cpu_mtid && +- pcpu_sigp_retry(pcpu_devices + base, SIGP_INITIAL_CPU_RESET, 0) != ++ if (pcpu_sigp_retry(pcpu, SIGP_INITIAL_CPU_RESET, 0) != + SIGP_CC_ORDER_CODE_ACCEPTED) + return -EIO; + +-- +2.27.0 + diff --git a/queue-4.4/s390-smp-use-smp_get_base_cpu-helper-function.patch b/queue-4.4/s390-smp-use-smp_get_base_cpu-helper-function.patch new file mode 100644 index 00000000000..2f99202dbd9 --- /dev/null +++ b/queue-4.4/s390-smp-use-smp_get_base_cpu-helper-function.patch @@ -0,0 +1,41 @@ +From dbcde903799671b0c171e0450733faaf11dc66ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2016 21:18:58 +0100 +Subject: s390/smp: use smp_get_base_cpu() helper function + +From: Heiko Carstens + +[ Upstream commit 5423145f8c4e885c640d12adc35c421127ed015f ] + +Signed-off-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Sasha Levin +--- + arch/s390/kernel/smp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c +index f113fcd781d87..c941bd500765a 100644 +--- a/arch/s390/kernel/smp.c ++++ b/arch/s390/kernel/smp.c +@@ -849,7 +849,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) + pcpu = pcpu_devices + cpu; + if (pcpu->state != CPU_STATE_CONFIGURED) + return -EIO; +- base = cpu - (cpu % (smp_cpu_mtid + 1)); ++ base = smp_get_base_cpu(cpu); + for (i = 0; i <= smp_cpu_mtid; i++) { + if (base + i < nr_cpu_ids) + if (cpu_online(base + i)) +@@ -1018,7 +1018,7 @@ static ssize_t cpu_configure_store(struct device *dev, + rc = -EBUSY; + /* disallow configuration changes of online cpus and cpu 0 */ + cpu = dev->id; +- cpu -= cpu % (smp_cpu_mtid + 1); ++ cpu = smp_get_base_cpu(cpu); + if (cpu == 0) + goto out; + for (i = 0; i <= smp_cpu_mtid; i++) +-- +2.27.0 + diff --git a/queue-4.4/series b/queue-4.4/series index a6d38d7d489..d3c99afd7c7 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -4,3 +4,7 @@ alsa-usb-audio-fix-sync-ep-altsetting-sanity-check.patch alsa-hda-realtek-support-dell-headset-mode-for-alc3271.patch alsa-hda-fix-a-wrong-fixup-for-alc289-on-dell-machines.patch alsa-hda-realtek-dell-headphone-has-noise-on-unmute-for-alc236.patch +s390-smp-use-smp_get_base_cpu-helper-function.patch +s390-smp-perform-initial-cpu-reset-also-for-smt-sibl.patch +s390-dasd-fix-hanging-device-offline-processing.patch +usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch diff --git a/queue-4.4/usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch b/queue-4.4/usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch new file mode 100644 index 00000000000..6ef9d03a9b5 --- /dev/null +++ b/queue-4.4/usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch @@ -0,0 +1,160 @@ +From 0403535f41a8ea7e98d76c506e9425d357c670c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Oct 2020 11:43:06 +0100 +Subject: USB: serial: digi_acceleport: fix write-wakeup deadlocks + +From: Johan Hovold + +[ Upstream commit 5098e77962e7c8947f87bd8c5869c83e000a522a ] + +The driver must not call tty_wakeup() while holding its private lock as +line disciplines are allowed to call back into write() from +write_wakeup(), leading to a deadlock. + +Also remove the unneeded work struct that was used to defer wakeup in +order to work around a possible race in ancient times (see comment about +n_tty write_chan() in commit 14b54e39b412 ("USB: serial: remove +changelogs and old todo entries")). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/digi_acceleport.c | 45 ++++++++-------------------- + 1 file changed, 13 insertions(+), 32 deletions(-) + +diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c +index be93b9ff2d989..b630048c49883 100644 +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -23,7 +23,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -201,14 +200,12 @@ struct digi_port { + int dp_throttle_restart; + wait_queue_head_t dp_flush_wait; + wait_queue_head_t dp_close_wait; /* wait queue for close */ +- struct work_struct dp_wakeup_work; + struct usb_serial_port *dp_port; + }; + + + /* Local Function Declarations */ + +-static void digi_wakeup_write_lock(struct work_struct *work); + static int digi_write_oob_command(struct usb_serial_port *port, + unsigned char *buf, int count, int interruptible); + static int digi_write_inb_command(struct usb_serial_port *port, +@@ -355,26 +352,6 @@ __releases(lock) + return timeout; + } + +- +-/* +- * Digi Wakeup Write +- * +- * Wake up port, line discipline, and tty processes sleeping +- * on writes. +- */ +- +-static void digi_wakeup_write_lock(struct work_struct *work) +-{ +- struct digi_port *priv = +- container_of(work, struct digi_port, dp_wakeup_work); +- struct usb_serial_port *port = priv->dp_port; +- unsigned long flags; +- +- spin_lock_irqsave(&priv->dp_port_lock, flags); +- tty_port_tty_wakeup(&port->port); +- spin_unlock_irqrestore(&priv->dp_port_lock, flags); +-} +- + /* + * Digi Write OOB Command + * +@@ -986,6 +963,7 @@ static void digi_write_bulk_callback(struct urb *urb) + struct digi_serial *serial_priv; + int ret = 0; + int status = urb->status; ++ bool wakeup; + + /* port and serial sanity check */ + if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { +@@ -1012,6 +990,7 @@ static void digi_write_bulk_callback(struct urb *urb) + } + + /* try to send any buffered data on this port */ ++ wakeup = true; + spin_lock(&priv->dp_port_lock); + priv->dp_write_urb_in_use = 0; + if (priv->dp_out_buf_len > 0) { +@@ -1027,19 +1006,18 @@ static void digi_write_bulk_callback(struct urb *urb) + if (ret == 0) { + priv->dp_write_urb_in_use = 1; + priv->dp_out_buf_len = 0; ++ wakeup = false; + } + } +- /* wake up processes sleeping on writes immediately */ +- tty_port_tty_wakeup(&port->port); +- /* also queue up a wakeup at scheduler time, in case we */ +- /* lost the race in write_chan(). */ +- schedule_work(&priv->dp_wakeup_work); +- + spin_unlock(&priv->dp_port_lock); ++ + if (ret && ret != -EPERM) + dev_err_console(port, + "%s: usb_submit_urb failed, ret=%d, port=%d\n", + __func__, ret, priv->dp_port_num); ++ ++ if (wakeup) ++ tty_port_tty_wakeup(&port->port); + } + + static int digi_write_room(struct tty_struct *tty) +@@ -1239,7 +1217,6 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) + init_waitqueue_head(&priv->dp_transmit_idle_wait); + init_waitqueue_head(&priv->dp_flush_wait); + init_waitqueue_head(&priv->dp_close_wait); +- INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); + priv->dp_port = port; + + init_waitqueue_head(&port->write_wait); +@@ -1525,13 +1502,14 @@ static int digi_read_oob_callback(struct urb *urb) + rts = tty->termios.c_cflag & CRTSCTS; + + if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) { ++ bool wakeup = false; ++ + spin_lock(&priv->dp_port_lock); + /* convert from digi flags to termiox flags */ + if (val & DIGI_READ_INPUT_SIGNALS_CTS) { + priv->dp_modem_signals |= TIOCM_CTS; +- /* port must be open to use tty struct */ + if (rts) +- tty_port_tty_wakeup(&port->port); ++ wakeup = true; + } else { + priv->dp_modem_signals &= ~TIOCM_CTS; + /* port must be open to use tty struct */ +@@ -1550,6 +1528,9 @@ static int digi_read_oob_callback(struct urb *urb) + priv->dp_modem_signals &= ~TIOCM_CD; + + spin_unlock(&priv->dp_port_lock); ++ ++ if (wakeup) ++ tty_port_tty_wakeup(&port->port); + } else if (opcode == DIGI_CMD_TRANSMIT_IDLE) { + spin_lock(&priv->dp_port_lock); + priv->dp_transmit_idle = 1; +-- +2.27.0 + -- 2.47.3