]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.14
authorSasha Levin <sashal@kernel.org>
Thu, 31 Dec 2020 04:14:50 +0000 (23:14 -0500)
committerSasha Levin <sashal@kernel.org>
Thu, 31 Dec 2020 04:14:50 +0000 (23:14 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.14/powerpc-bitops-fix-possible-undefined-behaviour-with.patch [new file with mode: 0644]
queue-4.14/s390-dasd-fix-hanging-device-offline-processing.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch [new file with mode: 0644]
queue-4.14/vfio-pci-move-dummy_resources_list-init-in-vfio_pci_.patch [new file with mode: 0644]

diff --git a/queue-4.14/powerpc-bitops-fix-possible-undefined-behaviour-with.patch b/queue-4.14/powerpc-bitops-fix-possible-undefined-behaviour-with.patch
new file mode 100644 (file)
index 0000000..8ba441d
--- /dev/null
@@ -0,0 +1,122 @@
+From fe95acff763d8c5423d0a29719a104e0f5aecc94 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Oct 2020 14:05:46 +0000
+Subject: powerpc/bitops: Fix possible undefined behaviour with fls() and
+ fls64()
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+[ Upstream commit 1891ef21d92c4801ea082ee8ed478e304ddc6749 ]
+
+fls() and fls64() are using __builtin_ctz() and _builtin_ctzll().
+On powerpc, those builtins trivially use ctlzw and ctlzd power
+instructions.
+
+Allthough those instructions provide the expected result with
+input argument 0, __builtin_ctz() and __builtin_ctzll() are
+documented as undefined for value 0.
+
+The easiest fix would be to use fls() and fls64() functions
+defined in include/asm-generic/bitops/builtin-fls.h and
+include/asm-generic/bitops/fls64.h, but GCC output is not optimal:
+
+00000388 <testfls>:
+ 388:   2c 03 00 00     cmpwi   r3,0
+ 38c:   41 82 00 10     beq     39c <testfls+0x14>
+ 390:   7c 63 00 34     cntlzw  r3,r3
+ 394:   20 63 00 20     subfic  r3,r3,32
+ 398:   4e 80 00 20     blr
+ 39c:   38 60 00 00     li      r3,0
+ 3a0:   4e 80 00 20     blr
+
+000003b0 <testfls64>:
+ 3b0:   2c 03 00 00     cmpwi   r3,0
+ 3b4:   40 82 00 1c     bne     3d0 <testfls64+0x20>
+ 3b8:   2f 84 00 00     cmpwi   cr7,r4,0
+ 3bc:   38 60 00 00     li      r3,0
+ 3c0:   4d 9e 00 20     beqlr   cr7
+ 3c4:   7c 83 00 34     cntlzw  r3,r4
+ 3c8:   20 63 00 20     subfic  r3,r3,32
+ 3cc:   4e 80 00 20     blr
+ 3d0:   7c 63 00 34     cntlzw  r3,r3
+ 3d4:   20 63 00 40     subfic  r3,r3,64
+ 3d8:   4e 80 00 20     blr
+
+When the input of fls(x) is a constant, just check x for nullity and
+return either 0 or __builtin_clz(x). Otherwise, use cntlzw instruction
+directly.
+
+For fls64() on PPC64, do the same but with __builtin_clzll() and
+cntlzd instruction. On PPC32, lets take the generic fls64() which
+will use our fls(). The result is as expected:
+
+00000388 <testfls>:
+ 388:   7c 63 00 34     cntlzw  r3,r3
+ 38c:   20 63 00 20     subfic  r3,r3,32
+ 390:   4e 80 00 20     blr
+
+000003a0 <testfls64>:
+ 3a0:   2c 03 00 00     cmpwi   r3,0
+ 3a4:   40 82 00 10     bne     3b4 <testfls64+0x14>
+ 3a8:   7c 83 00 34     cntlzw  r3,r4
+ 3ac:   20 63 00 20     subfic  r3,r3,32
+ 3b0:   4e 80 00 20     blr
+ 3b4:   7c 63 00 34     cntlzw  r3,r3
+ 3b8:   20 63 00 40     subfic  r3,r3,64
+ 3bc:   4e 80 00 20     blr
+
+Fixes: 2fcff790dcb4 ("powerpc: Use builtin functions for fls()/__fls()/fls64()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Acked-by: Segher Boessenkool <segher@kernel.crashing.org>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/348c2d3f19ffcff8abe50d52513f989c4581d000.1603375524.git.christophe.leroy@csgroup.eu
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/bitops.h | 23 +++++++++++++++++++++--
+ 1 file changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
+index b750ffef83c7d..0ec93d940d12c 100644
+--- a/arch/powerpc/include/asm/bitops.h
++++ b/arch/powerpc/include/asm/bitops.h
+@@ -220,15 +220,34 @@ static __inline__ void __clear_bit_unlock(int nr, volatile unsigned long *addr)
+  */
+ static __inline__ int fls(unsigned int x)
+ {
+-      return 32 - __builtin_clz(x);
++      int lz;
++
++      if (__builtin_constant_p(x))
++              return x ? 32 - __builtin_clz(x) : 0;
++      asm("cntlzw %0,%1" : "=r" (lz) : "r" (x));
++      return 32 - lz;
+ }
+ #include <asm-generic/bitops/builtin-__fls.h>
++/*
++ * 64-bit can do this using one cntlzd (count leading zeroes doubleword)
++ * instruction; for 32-bit we use the generic version, which does two
++ * 32-bit fls calls.
++ */
++#ifdef CONFIG_PPC64
+ static __inline__ int fls64(__u64 x)
+ {
+-      return 64 - __builtin_clzll(x);
++      int lz;
++
++      if (__builtin_constant_p(x))
++              return x ? 64 - __builtin_clzll(x) : 0;
++      asm("cntlzd %0,%1" : "=r" (lz) : "r" (x));
++      return 64 - lz;
+ }
++#else
++#include <asm-generic/bitops/fls64.h>
++#endif
+ #ifdef CONFIG_PPC64
+ unsigned int __arch_hweight8(unsigned int w);
+-- 
+2.27.0
+
diff --git a/queue-4.14/s390-dasd-fix-hanging-device-offline-processing.patch b/queue-4.14/s390-dasd-fix-hanging-device-offline-processing.patch
new file mode 100644 (file)
index 0000000..8b3de30
--- /dev/null
@@ -0,0 +1,62 @@
+From aee4b627bc510664d799a70c1826eaee67b28e78 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Dec 2020 16:59:04 +0100
+Subject: s390/dasd: fix hanging device offline processing
+
+From: Stefan Haberland <sth@linux.ibm.com>
+
+[ 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 <sth@linux.ibm.com>
+Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 487b16ace0060..0f70cae1c01e3 100644
+--- a/drivers/s390/block/dasd_alias.c
++++ b/drivers/s390/block/dasd_alias.c
+@@ -462,11 +462,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
+
index 6ffa54076772b3db9d0cd0b99360ec2e284e7d8b..b891ae4d1642751115668a68a6a7ef1f61544143 100644 (file)
@@ -6,3 +6,7 @@ alsa-usb-audio-fix-sync-ep-altsetting-sanity-check.patch
 mm-memcontrol-eliminate-raw-access-to-stat-and-event-counters.patch
 mm-memcontrol-implement-lruvec-stat-functions-on-top-of-each-other.patch
 mm-memcontrol-fix-excessive-complexity-in-memory.stat-reporting.patch
+vfio-pci-move-dummy_resources_list-init-in-vfio_pci_.patch
+s390-dasd-fix-hanging-device-offline-processing.patch
+usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch
+powerpc-bitops-fix-possible-undefined-behaviour-with.patch
diff --git a/queue-4.14/usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch b/queue-4.14/usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch
new file mode 100644 (file)
index 0000000..2ed163c
--- /dev/null
@@ -0,0 +1,160 @@
+From 8eac8e4f2ee7251533844266f0589439ca1738ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Oct 2020 11:43:06 +0100
+Subject: USB: serial: digi_acceleport: fix write-wakeup deadlocks
+
+From: Johan Hovold <johan@kernel.org>
+
+[ 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 <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 2ce39af32cfa6..e494ffdc06bc9 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -23,7 +23,6 @@
+ #include <linux/tty_flip.h>
+ #include <linux/module.h>
+ #include <linux/spinlock.h>
+-#include <linux/workqueue.h>
+ #include <linux/uaccess.h>
+ #include <linux/usb.h>
+ #include <linux/wait.h>
+@@ -202,14 +201,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,
+@@ -360,26 +357,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
+  *
+@@ -990,6 +967,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) {
+@@ -1016,6 +994,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) {
+@@ -1031,19 +1010,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)
+@@ -1243,7 +1221,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);
+@@ -1510,13 +1487,14 @@ static int digi_read_oob_callback(struct urb *urb)
+                       rts = C_CRTSCTS(tty);
+               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 */
+@@ -1535,6 +1513,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
+
diff --git a/queue-4.14/vfio-pci-move-dummy_resources_list-init-in-vfio_pci_.patch b/queue-4.14/vfio-pci-move-dummy_resources_list-init-in-vfio_pci_.patch
new file mode 100644 (file)
index 0000000..246fca4
--- /dev/null
@@ -0,0 +1,49 @@
+From 6f2ebf2be85f3464c005eff7202fda93b76efe90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Nov 2020 18:52:02 +0100
+Subject: vfio/pci: Move dummy_resources_list init in vfio_pci_probe()
+
+From: Eric Auger <eric.auger@redhat.com>
+
+[ Upstream commit 16b8fe4caf499ae8e12d2ab1b1324497e36a7b83 ]
+
+In case an error occurs in vfio_pci_enable() before the call to
+vfio_pci_probe_mmaps(), vfio_pci_disable() will  try to iterate
+on an uninitialized list and cause a kernel panic.
+
+Lets move to the initialization to vfio_pci_probe() to fix the
+issue.
+
+Signed-off-by: Eric Auger <eric.auger@redhat.com>
+Fixes: 05f0c03fbac1 ("vfio-pci: Allow to mmap sub-page MMIO BARs if the mmio page is exclusive")
+CC: Stable <stable@vger.kernel.org> # v4.7+
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/pci/vfio_pci.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
+index 6fceefcab81db..dedc7edea5178 100644
+--- a/drivers/vfio/pci/vfio_pci.c
++++ b/drivers/vfio/pci/vfio_pci.c
+@@ -118,8 +118,6 @@ static void vfio_pci_probe_mmaps(struct vfio_pci_device *vdev)
+       int bar;
+       struct vfio_pci_dummy_resource *dummy_res;
+-      INIT_LIST_HEAD(&vdev->dummy_resources_list);
+-
+       for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) {
+               res = vdev->pdev->resource + bar;
+@@ -1524,6 +1522,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+       vdev->irq_type = VFIO_PCI_NUM_IRQS;
+       mutex_init(&vdev->igate);
+       spin_lock_init(&vdev->irqlock);
++      INIT_LIST_HEAD(&vdev->dummy_resources_list);
+       mutex_init(&vdev->vma_lock);
+       INIT_LIST_HEAD(&vdev->vma_list);
+       init_rwsem(&vdev->memory_lock);
+-- 
+2.27.0
+