]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Wed, 7 Jun 2023 01:39:46 +0000 (21:39 -0400)
committerSasha Levin <sashal@kernel.org>
Wed, 7 Jun 2023 01:39:46 +0000 (21:39 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.15/block-fix-revalidate-performance-regression.patch [new file with mode: 0644]
queue-5.15/block-pass-a-gendisk-to-blk_queue_clear_zone_setting.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/usb-cdns3-allocate-tx-fifo-size-according-to-composi.patch [new file with mode: 0644]
queue-5.15/usb-cdns3-fix-ncm-gadget-rx-speed-20x-slow-than-expe.patch [new file with mode: 0644]

diff --git a/queue-5.15/block-fix-revalidate-performance-regression.patch b/queue-5.15/block-fix-revalidate-performance-regression.patch
new file mode 100644 (file)
index 0000000..fa73864
--- /dev/null
@@ -0,0 +1,63 @@
+From 4c8caef3c9e2e4c90db8697ce768ecb05261942f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 May 2023 16:32:37 +0900
+Subject: block: fix revalidate performance regression
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit 47fe1c3064c6bc1bfa3c032ff78e603e5dd6e5bc ]
+
+The scsi driver function sd_read_block_characteristics() always calls
+disk_set_zoned() to a disk zoned model correctly, in case the device
+model changed. This is done even for regular disks to set the zoned
+model to BLK_ZONED_NONE and free any zone related resources if the drive
+previously was zoned.
+
+This behavior significantly impact the time it takes to revalidate disks
+on a large system as the call to disk_clear_zone_settings() done from
+disk_set_zoned() for the BLK_ZONED_NONE case results in the device
+request queued to be frozen, even if there are no zone resources to
+free.
+
+Avoid this overhead for non-zoned devices by not calling
+disk_clear_zone_settings() in disk_set_zoned() if the device model
+was already set to BLK_ZONED_NONE, which is always the case for regular
+devices.
+
+Reported by: Brian Bunker <brian@purestorage.com>
+
+Fixes: 508aebb80527 ("block: introduce blk_queue_clear_zone_settings()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Link: https://lore.kernel.org/r/20230529073237.1339862-1-dlemoal@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-settings.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/block/blk-settings.c b/block/blk-settings.c
+index 8b84b4f126966..b2dfbfd08cbbd 100644
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -875,6 +875,7 @@ static bool disk_has_partitions(struct gendisk *disk)
+ void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
+ {
+       struct request_queue *q = disk->queue;
++      unsigned int old_model = q->limits.zoned;
+       switch (model) {
+       case BLK_ZONED_HM:
+@@ -912,7 +913,7 @@ void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
+                */
+               blk_queue_zone_write_granularity(q,
+                                               queue_logical_block_size(q));
+-      } else {
++      } else if (old_model != BLK_ZONED_NONE) {
+               disk_clear_zone_settings(disk);
+       }
+ }
+-- 
+2.39.2
+
diff --git a/queue-5.15/block-pass-a-gendisk-to-blk_queue_clear_zone_setting.patch b/queue-5.15/block-pass-a-gendisk-to-blk_queue_clear_zone_setting.patch
new file mode 100644 (file)
index 0000000..4c6a0cc
--- /dev/null
@@ -0,0 +1,75 @@
+From 1011c6b47b0dfafc6fa92f182e76b1b713a14fee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Jul 2022 09:03:41 +0200
+Subject: block: pass a gendisk to blk_queue_clear_zone_settings
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit b3c72f8138b5f967a9fa527af84b35018897aba3 ]
+
+Switch to a gendisk based API in preparation for moving all zone related
+fields from the request_queue to the gendisk.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Link: https://lore.kernel.org/r/20220706070350.1703384-8-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Stable-dep-of: 47fe1c3064c6 ("block: fix revalidate performance regression")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-settings.c | 2 +-
+ block/blk-zoned.c    | 4 +++-
+ block/blk.h          | 4 ++--
+ 3 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/block/blk-settings.c b/block/blk-settings.c
+index b880c70e22e4e..8b84b4f126966 100644
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -913,7 +913,7 @@ void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
+               blk_queue_zone_write_granularity(q,
+                                               queue_logical_block_size(q));
+       } else {
+-              blk_queue_clear_zone_settings(q);
++              disk_clear_zone_settings(disk);
+       }
+ }
+ EXPORT_SYMBOL_GPL(blk_queue_set_zoned);
+diff --git a/block/blk-zoned.c b/block/blk-zoned.c
+index 774ecc598bee2..2629ec5d977b4 100644
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -630,8 +630,10 @@ int blk_revalidate_disk_zones(struct gendisk *disk,
+ }
+ EXPORT_SYMBOL_GPL(blk_revalidate_disk_zones);
+-void blk_queue_clear_zone_settings(struct request_queue *q)
++void disk_clear_zone_settings(struct gendisk *disk)
+ {
++      struct request_queue *q = disk->queue;
++
+       blk_mq_freeze_queue(q);
+       blk_queue_free_zone_bitmaps(q);
+diff --git a/block/blk.h b/block/blk.h
+index aab72194d2266..336bdb35466ee 100644
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -343,10 +343,10 @@ struct bio *blk_next_bio(struct bio *bio, unsigned int nr_pages, gfp_t gfp);
+ #ifdef CONFIG_BLK_DEV_ZONED
+ void blk_queue_free_zone_bitmaps(struct request_queue *q);
+-void blk_queue_clear_zone_settings(struct request_queue *q);
++void disk_clear_zone_settings(struct gendisk *disk);
+ #else
+ static inline void blk_queue_free_zone_bitmaps(struct request_queue *q) {}
+-static inline void blk_queue_clear_zone_settings(struct request_queue *q) {}
++static inline void disk_clear_zone_settings(struct gendisk *disk) {}
+ #endif
+ int blk_alloc_ext_minor(void);
+-- 
+2.39.2
+
index 03f25e833ef62c9a8e9c60b05340b0797f1b20e4..f54f5206740606ffe696ab4b22298d74d7e1c84f 100644 (file)
@@ -127,3 +127,7 @@ tty-serial-fsl_lpuart-use-uartctrl_txinv-to-send-break-instead-of-uartctrl_sbk.p
 btrfs-fix-csum_tree_block-page-iteration-to-avoid-tripping-on-werror-array-bounds.patch
 powerpc-iommu-limit-number-of-tces-to-512-for-h_stuff_tce-hcall.patch
 iommu-amd-fix-domain-flush-size-when-syncing-iotlb.patch
+usb-cdns3-allocate-tx-fifo-size-according-to-composi.patch
+usb-cdns3-fix-ncm-gadget-rx-speed-20x-slow-than-expe.patch
+block-pass-a-gendisk-to-blk_queue_clear_zone_setting.patch
+block-fix-revalidate-performance-regression.patch
diff --git a/queue-5.15/usb-cdns3-allocate-tx-fifo-size-according-to-composi.patch b/queue-5.15/usb-cdns3-allocate-tx-fifo-size-according-to-composi.patch
new file mode 100644 (file)
index 0000000..9298c74
--- /dev/null
@@ -0,0 +1,192 @@
+From 751a1dc41ef88fec04fc5566402bb984391891b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 11:40:55 -0500
+Subject: usb: cdns3: allocate TX FIFO size according to composite EP number
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit dce49449e04ff150838a31386ee65917beb9ebb5 ]
+
+Some devices have USB compositions which may require multiple endpoints.
+To get better performance, need bigger CDNS3_EP_BUF_SIZE.
+
+But bigger CDNS3_EP_BUF_SIZE may exceed total hardware FIFO size when
+multiple endpoints.
+
+By introducing the check_config() callback, calculate CDNS3_EP_BUF_SIZE.
+
+Move CDNS3_EP_BUF_SIZE into cnds3_device: ep_buf_size
+Combine CDNS3_EP_ISO_SS_BURST and CDNS3_EP_ISO_HS_MULT into
+cnds3_device:ep_iso_burst
+
+Using a simple algorithm to calculate ep_buf_size.
+ep_buf_size = ep_iso_burst = (onchip_buffers - 2k) / (number of IN EP +
+1).
+
+Test at 8qxp:
+
+       Gadget                  ep_buf_size
+
+       RNDIS:                          5
+       RNDIS+ACM:                      3
+       Mass Storage + NCM + ACM        2
+
+Previous CDNS3_EP_BUF_SIZE is 4, RNDIS + ACM will be failure because
+exceed FIFO memory.
+
+Acked-by: Peter Chen <peter.chen@kernel.org>
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20220509164055.1815081-1-Frank.Li@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: dbe678f6192f ("usb: cdns3: fix NCM gadget RX speed 20x slow than expection at iMX8QM")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/cdns3/cdns3-gadget.c | 47 +++++++++++++++++++++++++++++---
+ drivers/usb/cdns3/cdns3-gadget.h |  9 ++++--
+ 2 files changed, 49 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
+index 924c2793c7327..ccfaebca6faa7 100644
+--- a/drivers/usb/cdns3/cdns3-gadget.c
++++ b/drivers/usb/cdns3/cdns3-gadget.c
+@@ -2040,7 +2040,7 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
+       u8 mult = 0;
+       int ret;
+-      buffering = CDNS3_EP_BUF_SIZE - 1;
++      buffering = priv_dev->ep_buf_size - 1;
+       cdns3_configure_dmult(priv_dev, priv_ep);
+@@ -2059,7 +2059,7 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
+               break;
+       default:
+               ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC);
+-              mult = CDNS3_EP_ISO_HS_MULT - 1;
++              mult = priv_dev->ep_iso_burst - 1;
+               buffering = mult + 1;
+       }
+@@ -2075,14 +2075,14 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
+               mult = 0;
+               max_packet_size = 1024;
+               if (priv_ep->type == USB_ENDPOINT_XFER_ISOC) {
+-                      maxburst = CDNS3_EP_ISO_SS_BURST - 1;
++                      maxburst = priv_dev->ep_iso_burst - 1;
+                       buffering = (mult + 1) *
+                                   (maxburst + 1);
+                       if (priv_ep->interval > 1)
+                               buffering++;
+               } else {
+-                      maxburst = CDNS3_EP_BUF_SIZE - 1;
++                      maxburst = priv_dev->ep_buf_size - 1;
+               }
+               break;
+       default:
+@@ -2097,6 +2097,10 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
+       else
+               priv_ep->trb_burst_size = 16;
++      mult = min_t(u8, mult, EP_CFG_MULT_MAX);
++      buffering = min_t(u8, buffering, EP_CFG_BUFFERING_MAX);
++      maxburst = min_t(u8, maxburst, EP_CFG_MAXBURST_MAX);
++
+       /* onchip buffer is only allocated before configuration */
+       if (!priv_dev->hw_configured_flag) {
+               ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1,
+@@ -2982,6 +2986,40 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget)
+       return 0;
+ }
++/**
++ * cdns3_gadget_check_config - ensure cdns3 can support the USB configuration
++ * @gadget: pointer to the USB gadget
++ *
++ * Used to record the maximum number of endpoints being used in a USB composite
++ * device. (across all configurations)  This is to be used in the calculation
++ * of the TXFIFO sizes when resizing internal memory for individual endpoints.
++ * It will help ensured that the resizing logic reserves enough space for at
++ * least one max packet.
++ */
++static int cdns3_gadget_check_config(struct usb_gadget *gadget)
++{
++      struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
++      struct usb_ep *ep;
++      int n_in = 0;
++      int total;
++
++      list_for_each_entry(ep, &gadget->ep_list, ep_list) {
++              if (ep->claimed && (ep->address & USB_DIR_IN))
++                      n_in++;
++      }
++
++      /* 2KB are reserved for EP0, 1KB for out*/
++      total = 2 + n_in + 1;
++
++      if (total > priv_dev->onchip_buffers)
++              return -ENOMEM;
++
++      priv_dev->ep_buf_size = priv_dev->ep_iso_burst =
++                      (priv_dev->onchip_buffers - 2) / (n_in + 1);
++
++      return 0;
++}
++
+ static const struct usb_gadget_ops cdns3_gadget_ops = {
+       .get_frame = cdns3_gadget_get_frame,
+       .wakeup = cdns3_gadget_wakeup,
+@@ -2990,6 +3028,7 @@ static const struct usb_gadget_ops cdns3_gadget_ops = {
+       .udc_start = cdns3_gadget_udc_start,
+       .udc_stop = cdns3_gadget_udc_stop,
+       .match_ep = cdns3_gadget_match_ep,
++      .check_config = cdns3_gadget_check_config,
+ };
+ static void cdns3_free_all_eps(struct cdns3_device *priv_dev)
+diff --git a/drivers/usb/cdns3/cdns3-gadget.h b/drivers/usb/cdns3/cdns3-gadget.h
+index c5660f2c4293f..fbe4a8e3aa897 100644
+--- a/drivers/usb/cdns3/cdns3-gadget.h
++++ b/drivers/usb/cdns3/cdns3-gadget.h
+@@ -562,15 +562,18 @@ struct cdns3_usb_regs {
+ /* Max burst size (used only in SS mode). */
+ #define EP_CFG_MAXBURST_MASK  GENMASK(11, 8)
+ #define EP_CFG_MAXBURST(p)    (((p) << 8) & EP_CFG_MAXBURST_MASK)
++#define EP_CFG_MAXBURST_MAX   15
+ /* ISO max burst. */
+ #define EP_CFG_MULT_MASK      GENMASK(15, 14)
+ #define EP_CFG_MULT(p)                (((p) << 14) & EP_CFG_MULT_MASK)
++#define EP_CFG_MULT_MAX               2
+ /* ISO max burst. */
+ #define EP_CFG_MAXPKTSIZE_MASK        GENMASK(26, 16)
+ #define EP_CFG_MAXPKTSIZE(p)  (((p) << 16) & EP_CFG_MAXPKTSIZE_MASK)
+ /* Max number of buffered packets. */
+ #define EP_CFG_BUFFERING_MASK GENMASK(31, 27)
+ #define EP_CFG_BUFFERING(p)   (((p) << 27) & EP_CFG_BUFFERING_MASK)
++#define EP_CFG_BUFFERING_MAX  15
+ /* EP_CMD - bitmasks */
+ /* Endpoint reset. */
+@@ -1094,9 +1097,6 @@ struct cdns3_trb {
+ #define CDNS3_ENDPOINTS_MAX_COUNT     32
+ #define CDNS3_EP_ZLP_BUF_SIZE         1024
+-#define CDNS3_EP_BUF_SIZE             4       /* KB */
+-#define CDNS3_EP_ISO_HS_MULT          3
+-#define CDNS3_EP_ISO_SS_BURST         3
+ #define CDNS3_MAX_NUM_DESCMISS_BUF    32
+ #define CDNS3_DESCMIS_BUF_SIZE                2048    /* Bytes */
+ #define CDNS3_WA2_NUM_BUFFERS         128
+@@ -1333,6 +1333,9 @@ struct cdns3_device {
+       /*in KB */
+       u16                             onchip_buffers;
+       u16                             onchip_used_size;
++
++      u16                             ep_buf_size;
++      u16                             ep_iso_burst;
+ };
+ void cdns3_set_register_bit(void __iomem *ptr, u32 mask);
+-- 
+2.39.2
+
diff --git a/queue-5.15/usb-cdns3-fix-ncm-gadget-rx-speed-20x-slow-than-expe.patch b/queue-5.15/usb-cdns3-fix-ncm-gadget-rx-speed-20x-slow-than-expe.patch
new file mode 100644 (file)
index 0000000..5ba79f0
--- /dev/null
@@ -0,0 +1,63 @@
+From 3ddff533f7fa4e9d6434ac0e9d8f701d3e0d2107 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 May 2023 11:49:45 -0400
+Subject: usb: cdns3: fix NCM gadget RX speed 20x slow than expection at iMX8QM
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit dbe678f6192f27879ac9ff6bc7a1036aad85aae9 ]
+
+At iMX8QM platform, enable NCM gadget and run 'iperf3 -s'.
+At host, run 'iperf3 -V -c fe80::6863:98ff:feef:3e0%enxc6e147509498'
+
+[  5]   0.00-1.00   sec  1.55 MBytes  13.0 Mbits/sec   90   4.18 KBytes
+[  5]   1.00-2.00   sec  1.44 MBytes  12.0 Mbits/sec   75   4.18 KBytes
+[  5]   2.00-3.00   sec  1.48 MBytes  12.4 Mbits/sec   75   4.18 KBytes
+
+Expected speed should be bigger than 300Mbits/sec.
+
+The root cause of this performance drop was found to be data corruption
+happening at 4K borders in some Ethernet packets, leading to TCP
+checksum errors. This corruption occurs from the position
+(4K - (address & 0x7F)) to 4K. The u_ether function's allocation of
+skb_buff reserves 64B, meaning all RX addresses resemble 0xXXXX0040.
+
+Force trb_burst_size to 16 can fix this problem.
+
+Cc: stable@vger.kernel.org
+Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20230518154946.3666662-1-Frank.Li@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/cdns3/cdns3-gadget.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
+index ccfaebca6faa7..1dcadef933e3a 100644
+--- a/drivers/usb/cdns3/cdns3-gadget.c
++++ b/drivers/usb/cdns3/cdns3-gadget.c
+@@ -2097,6 +2097,19 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
+       else
+               priv_ep->trb_burst_size = 16;
++      /*
++       * In versions preceding DEV_VER_V2, for example, iMX8QM, there exit the bugs
++       * in the DMA. These bugs occur when the trb_burst_size exceeds 16 and the
++       * address is not aligned to 128 Bytes (which is a product of the 64-bit AXI
++       * and AXI maximum burst length of 16 or 0xF+1, dma_axi_ctrl0[3:0]). This
++       * results in data corruption when it crosses the 4K border. The corruption
++       * specifically occurs from the position (4K - (address & 0x7F)) to 4K.
++       *
++       * So force trb_burst_size to 16 at such platform.
++       */
++      if (priv_dev->dev_ver < DEV_VER_V2)
++              priv_ep->trb_burst_size = 16;
++
+       mult = min_t(u8, mult, EP_CFG_MULT_MAX);
+       buffering = min_t(u8, buffering, EP_CFG_BUFFERING_MAX);
+       maxburst = min_t(u8, maxburst, EP_CFG_MAXBURST_MAX);
+-- 
+2.39.2
+