]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 2 Sep 2025 12:28:52 +0000 (14:28 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 2 Sep 2025 12:28:52 +0000 (14:28 +0200)
added patches:
hid-mcp2221-don-t-set-bus-speed-on-every-transfer.patch
hid-mcp2221-handle-reads-greater-than-60-bytes.patch
revert-drm-dp-change-aux-dpcd-probe-address-from-dpcd_rev-to-lane0_1_status.patch
xfs-do-not-propagate-enodata-disk-errors-into-xattr-code.patch

queue-6.6/hid-mcp2221-don-t-set-bus-speed-on-every-transfer.patch [new file with mode: 0644]
queue-6.6/hid-mcp2221-handle-reads-greater-than-60-bytes.patch [new file with mode: 0644]
queue-6.6/revert-drm-dp-change-aux-dpcd-probe-address-from-dpcd_rev-to-lane0_1_status.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/xfs-do-not-propagate-enodata-disk-errors-into-xattr-code.patch [new file with mode: 0644]

diff --git a/queue-6.6/hid-mcp2221-don-t-set-bus-speed-on-every-transfer.patch b/queue-6.6/hid-mcp2221-don-t-set-bus-speed-on-every-transfer.patch
new file mode 100644 (file)
index 0000000..aea73f3
--- /dev/null
@@ -0,0 +1,126 @@
+From 02a46753601a24e1673d9c28173121055e8e6cc9 Mon Sep 17 00:00:00 2001
+From: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
+Date: Wed, 25 Oct 2023 16:55:13 +1300
+Subject: HID: mcp2221: Don't set bus speed on every transfer
+
+From: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
+
+commit 02a46753601a24e1673d9c28173121055e8e6cc9 upstream.
+
+Since the initial commit of this driver the I2C bus speed has been
+reconfigured for every single transfer. This is despite the fact that we
+never change the speed and it is never "lost" by the chip.
+Upon investigation we find that what was really happening was that the
+setting of the bus speed had the side effect of cancelling a previous
+failed command if there was one, thereby freeing the bus. This is the
+part that was actually required to keep the bus operational in the face
+of failed commands.
+
+Instead of always setting the speed, we now correctly cancel any failed
+commands as they are detected. This means we can just set the bus speed
+at probe time and remove the previous speed sets on each transfer.
+This has the effect of improving performance and reducing the number of
+commands required to complete transfers.
+
+Signed-off-by: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Fixes: 67a95c21463d ("HID: mcp2221: add usb to i2c-smbus host bridge")
+[romain.sioen@microchip.com: backport to stable, up to 6.8. Add "Fixes" tag]
+Signed-off-by: Romain Sioen <romain.sioen@microchip.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-mcp2221.c |   41 +++++++++++++++++++++++++++--------------
+ 1 file changed, 27 insertions(+), 14 deletions(-)
+
+--- a/drivers/hid/hid-mcp2221.c
++++ b/drivers/hid/hid-mcp2221.c
+@@ -187,6 +187,25 @@ static int mcp_cancel_last_cmd(struct mc
+       return mcp_send_data_req_status(mcp, mcp->txbuf, 8);
+ }
++/* Check if the last command succeeded or failed and return the result.
++ * If the command did fail, cancel that command which will free the i2c bus.
++ */
++static int mcp_chk_last_cmd_status_free_bus(struct mcp2221 *mcp)
++{
++      int ret;
++
++      ret = mcp_chk_last_cmd_status(mcp);
++      if (ret) {
++              /* The last command was a failure.
++               * Send a cancel which will also free the bus.
++               */
++              usleep_range(980, 1000);
++              mcp_cancel_last_cmd(mcp);
++      }
++
++      return ret;
++}
++
+ static int mcp_set_i2c_speed(struct mcp2221 *mcp)
+ {
+       int ret;
+@@ -241,7 +260,7 @@ static int mcp_i2c_write(struct mcp2221
+               usleep_range(980, 1000);
+               if (last_status) {
+-                      ret = mcp_chk_last_cmd_status(mcp);
++                      ret = mcp_chk_last_cmd_status_free_bus(mcp);
+                       if (ret)
+                               return ret;
+               }
+@@ -308,7 +327,7 @@ static int mcp_i2c_smbus_read(struct mcp
+               if (ret)
+                       return ret;
+-              ret = mcp_chk_last_cmd_status(mcp);
++              ret = mcp_chk_last_cmd_status_free_bus(mcp);
+               if (ret)
+                       return ret;
+@@ -328,11 +347,6 @@ static int mcp_i2c_xfer(struct i2c_adapt
+       mutex_lock(&mcp->lock);
+-      /* Setting speed before every transaction is required for mcp2221 */
+-      ret = mcp_set_i2c_speed(mcp);
+-      if (ret)
+-              goto exit;
+-
+       if (num == 1) {
+               if (msgs->flags & I2C_M_RD) {
+                       ret = mcp_i2c_smbus_read(mcp, msgs, MCP2221_I2C_RD_DATA,
+@@ -417,9 +431,7 @@ static int mcp_smbus_write(struct mcp222
+       if (last_status) {
+               usleep_range(980, 1000);
+-              ret = mcp_chk_last_cmd_status(mcp);
+-              if (ret)
+-                      return ret;
++              ret = mcp_chk_last_cmd_status_free_bus(mcp);
+       }
+       return ret;
+@@ -437,10 +449,6 @@ static int mcp_smbus_xfer(struct i2c_ada
+       mutex_lock(&mcp->lock);
+-      ret = mcp_set_i2c_speed(mcp);
+-      if (ret)
+-              goto exit;
+-
+       switch (size) {
+       case I2C_SMBUS_QUICK:
+@@ -1152,6 +1160,11 @@ static int mcp2221_probe(struct hid_devi
+       if (i2c_clk_freq < 50)
+               i2c_clk_freq = 50;
+       mcp->cur_i2c_clk_div = (12000000 / (i2c_clk_freq * 1000)) - 3;
++      ret = mcp_set_i2c_speed(mcp);
++      if (ret) {
++              hid_err(hdev, "can't set i2c speed: %d\n", ret);
++              return ret;
++      }
+       mcp->adapter.owner = THIS_MODULE;
+       mcp->adapter.class = I2C_CLASS_HWMON;
diff --git a/queue-6.6/hid-mcp2221-handle-reads-greater-than-60-bytes.patch b/queue-6.6/hid-mcp2221-handle-reads-greater-than-60-bytes.patch
new file mode 100644 (file)
index 0000000..53d87be
--- /dev/null
@@ -0,0 +1,104 @@
+From 2682468671aa0b4d52ae09779b48212a80d71b91 Mon Sep 17 00:00:00 2001
+From: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
+Date: Wed, 25 Oct 2023 16:55:14 +1300
+Subject: HID: mcp2221: Handle reads greater than 60 bytes
+
+From: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
+
+commit 2682468671aa0b4d52ae09779b48212a80d71b91 upstream.
+
+When a user requests more than 60 bytes of data the MCP2221 must chunk
+the data in chunks up to 60 bytes long (see command/response code 0x40
+in the datasheet).
+In order to signal that the device has more data the (undocumented) byte
+at byte index 2 of the Get I2C Data response uses the value 0x54. This
+contrasts with the case for the final data chunk where the value
+returned is 0x55 (MCP2221_I2C_READ_COMPL). The fact that 0x55 was not
+returned in the response was interpreted by the driver as a failure
+meaning that all reads of more than 60 bytes would fail.
+
+Add support for reads that are split over multiple chunks by looking for
+the response code indicating that more data is expected and continuing
+the read as the code intended. Some timing delays are required to ensure
+the chip has time to refill its FIFO as data is read in from the I2C
+bus. This timing has been tested in my system when configured for bus
+speeds of 50KHz, 100KHz, and 400KHz and operates well.
+
+Signed-off-by: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Fixes: 67a95c21463d0 ("HID: mcp2221: add usb to i2c-smbus host bridge")
+[romain.sioen@microchip.com: backport to stable, up to 6.8. Add "Fixes" tag]
+Signed-off-by: Romain Sioen <romain.sioen@microchip.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-mcp2221.c |   32 +++++++++++++++++++++++---------
+ 1 file changed, 23 insertions(+), 9 deletions(-)
+
+--- a/drivers/hid/hid-mcp2221.c
++++ b/drivers/hid/hid-mcp2221.c
+@@ -49,6 +49,7 @@ enum {
+       MCP2221_I2C_MASK_ADDR_NACK = 0x40,
+       MCP2221_I2C_WRADDRL_SEND = 0x21,
+       MCP2221_I2C_ADDR_NACK = 0x25,
++      MCP2221_I2C_READ_PARTIAL = 0x54,
+       MCP2221_I2C_READ_COMPL = 0x55,
+       MCP2221_ALT_F_NOT_GPIOV = 0xEE,
+       MCP2221_ALT_F_NOT_GPIOD = 0xEF,
+@@ -297,6 +298,7 @@ static int mcp_i2c_smbus_read(struct mcp
+ {
+       int ret;
+       u16 total_len;
++      int retries = 0;
+       mcp->txbuf[0] = type;
+       if (msg) {
+@@ -320,20 +322,31 @@ static int mcp_i2c_smbus_read(struct mcp
+       mcp->rxbuf_idx = 0;
+       do {
++              /* Wait for the data to be read by the device */
++              usleep_range(980, 1000);
++
+               memset(mcp->txbuf, 0, 4);
+               mcp->txbuf[0] = MCP2221_I2C_GET_DATA;
+               ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
+-              if (ret)
+-                      return ret;
+-
+-              ret = mcp_chk_last_cmd_status_free_bus(mcp);
+-              if (ret)
+-                      return ret;
+-
+-              usleep_range(980, 1000);
++              if (ret) {
++                      if (retries < 5) {
++                              /* The data wasn't ready to read.
++                               * Wait a bit longer and try again.
++                               */
++                              usleep_range(90, 100);
++                              retries++;
++                      } else {
++                              return ret;
++                      }
++              } else {
++                      retries = 0;
++              }
+       } while (mcp->rxbuf_idx < total_len);
++      usleep_range(980, 1000);
++      ret = mcp_chk_last_cmd_status_free_bus(mcp);
++
+       return ret;
+ }
+@@ -799,7 +812,8 @@ static int mcp2221_raw_event(struct hid_
+                               mcp->status = -EIO;
+                               break;
+                       }
+-                      if (data[2] == MCP2221_I2C_READ_COMPL) {
++                      if (data[2] == MCP2221_I2C_READ_COMPL ||
++                          data[2] == MCP2221_I2C_READ_PARTIAL) {
+                               buf = mcp->rxbuf;
+                               memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]);
+                               mcp->rxbuf_idx = mcp->rxbuf_idx + data[3];
diff --git a/queue-6.6/revert-drm-dp-change-aux-dpcd-probe-address-from-dpcd_rev-to-lane0_1_status.patch b/queue-6.6/revert-drm-dp-change-aux-dpcd-probe-address-from-dpcd_rev-to-lane0_1_status.patch
new file mode 100644 (file)
index 0000000..934c1bf
--- /dev/null
@@ -0,0 +1,40 @@
+From imre.deak@intel.com  Tue Sep  2 13:50:59 2025
+From: Imre Deak <imre.deak@intel.com>
+Date: Thu, 28 Aug 2025 20:49:29 +0300
+Subject: Revert "drm/dp: Change AUX DPCD probe address from DPCD_REV to LANE0_1_STATUS"
+To: <stable@vger.kernel.org>
+Cc: <intel-gfx@lists.freedesktop.org>, <dri-devel@lists.freedesktop.org>, Sasha Levin <sashal@kernel.org>
+
+From: Imre Deak <imre.deak@intel.com>
+
+This reverts commit 65e46aeaf84aa88539bcff6b8077e05fbd0700da which is
+commit a40c5d727b8111b5db424a1e43e14a1dcce1e77f upstream.
+
+The upstream commit a40c5d727b8111b5db424a1e43e14a1dcce1e77f ("drm/dp:
+Change AUX DPCD probe address from DPCD_REV to LANE0_1_STATUS") the
+reverted commit backported causes a regression, on one eDP panel at
+least resulting in display flickering, described in detail at the Link:
+below. The issue fixed by the upstream commit will need a different
+solution, revert the backport for now.
+
+Cc: intel-gfx@lists.freedesktop.org
+Cc: dri-devel@lists.freedesktop.org
+Cc: Sasha Levin <sashal@kernel.org>
+Link: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14558
+Signed-off-by: Imre Deak <imre.deak@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/display/drm_dp_helper.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/display/drm_dp_helper.c
++++ b/drivers/gpu/drm/display/drm_dp_helper.c
+@@ -663,7 +663,7 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_a
+        * monitor doesn't power down exactly after the throw away read.
+        */
+       if (!aux->is_remote) {
+-              ret = drm_dp_dpcd_probe(aux, DP_LANE0_1_STATUS);
++              ret = drm_dp_dpcd_probe(aux, DP_DPCD_REV);
+               if (ret < 0)
+                       return ret;
+       }
index 8719f41e741f12e4dd5c1de1121f56278360e281..b8be5cee26801185fa74144092f53bceeb59f817 100644 (file)
@@ -69,3 +69,7 @@ smb3-client-fix-return-code-mapping-of-remap_file_range.patch
 drm-nouveau-disp-always-accept-linear-modifier.patch
 net-rose-fix-a-typo-in-rose_clear_routes.patch
 net-mlx5-sf-fix-add-port-error-handling.patch
+hid-mcp2221-don-t-set-bus-speed-on-every-transfer.patch
+hid-mcp2221-handle-reads-greater-than-60-bytes.patch
+revert-drm-dp-change-aux-dpcd-probe-address-from-dpcd_rev-to-lane0_1_status.patch
+xfs-do-not-propagate-enodata-disk-errors-into-xattr-code.patch
diff --git a/queue-6.6/xfs-do-not-propagate-enodata-disk-errors-into-xattr-code.patch b/queue-6.6/xfs-do-not-propagate-enodata-disk-errors-into-xattr-code.patch
new file mode 100644 (file)
index 0000000..13ea340
--- /dev/null
@@ -0,0 +1,83 @@
+From ae668cd567a6a7622bc813ee0bb61c42bed61ba7 Mon Sep 17 00:00:00 2001
+From: Eric Sandeen <sandeen@redhat.com>
+Date: Fri, 22 Aug 2025 12:55:56 -0500
+Subject: xfs: do not propagate ENODATA disk errors into xattr code
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+commit ae668cd567a6a7622bc813ee0bb61c42bed61ba7 upstream.
+
+ENODATA (aka ENOATTR) has a very specific meaning in the xfs xattr code;
+namely, that the requested attribute name could not be found.
+
+However, a medium error from disk may also return ENODATA. At best,
+this medium error may escape to userspace as "attribute not found"
+when in fact it's an IO (disk) error.
+
+At worst, we may oops in xfs_attr_leaf_get() when we do:
+
+       error = xfs_attr_leaf_hasname(args, &bp);
+       if (error == -ENOATTR)  {
+               xfs_trans_brelse(args->trans, bp);
+               return error;
+       }
+
+because an ENODATA/ENOATTR error from disk leaves us with a null bp,
+and the xfs_trans_brelse will then null-deref it.
+
+As discussed on the list, we really need to modify the lower level
+IO functions to trap all disk errors and ensure that we don't let
+unique errors like this leak up into higher xfs functions - many
+like this should be remapped to EIO.
+
+However, this patch directly addresses a reported bug in the xattr
+code, and should be safe to backport to stable kernels. A larger-scope
+patch to handle more unique errors at lower levels can follow later.
+
+(Note, prior to 07120f1abdff we did not oops, but we did return the
+wrong error code to userspace.)
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Fixes: 07120f1abdff ("xfs: Add xfs_has_attr and subroutines")
+Cc: stable@vger.kernel.org # v5.9+
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+[ Adjust context: removed metadata health tracking calls ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_attr_remote.c |    7 +++++++
+ fs/xfs/libxfs/xfs_da_btree.c    |    6 ++++++
+ 2 files changed, 13 insertions(+)
+
+--- a/fs/xfs/libxfs/xfs_attr_remote.c
++++ b/fs/xfs/libxfs/xfs_attr_remote.c
+@@ -418,6 +418,13 @@ xfs_attr_rmtval_get(
+                       dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
+                       error = xfs_buf_read(mp->m_ddev_targp, dblkno, dblkcnt,
+                                       0, &bp, &xfs_attr3_rmt_buf_ops);
++                      /*
++                       * ENODATA from disk implies a disk medium failure;
++                       * ENODATA for xattrs means attribute not found, so
++                       * disambiguate that here.
++                       */
++                      if (error == -ENODATA)
++                              error = -EIO;
+                       if (error)
+                               return error;
+--- a/fs/xfs/libxfs/xfs_da_btree.c
++++ b/fs/xfs/libxfs/xfs_da_btree.c
+@@ -2649,6 +2649,12 @@ xfs_da_read_buf(
+       error = xfs_trans_read_buf_map(mp, tp, mp->m_ddev_targp, mapp, nmap, 0,
+                       &bp, ops);
++      /*
++       * ENODATA from disk implies a disk medium failure; ENODATA for
++       * xattrs means attribute not found, so disambiguate that here.
++       */
++      if (error == -ENODATA && whichfork == XFS_ATTR_FORK)
++              error = -EIO;
+       if (error)
+               goto out_free;