]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Jan 2023 09:29:47 +0000 (10:29 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Jan 2023 09:29:47 +0000 (10:29 +0100)
added patches:
i2c-mv64xxx-add-atomic_xfer-method-to-driver.patch
i2c-mv64xxx-remove-shutdown-method-from-driver.patch

queue-5.15/i2c-mv64xxx-add-atomic_xfer-method-to-driver.patch [new file with mode: 0644]
queue-5.15/i2c-mv64xxx-remove-shutdown-method-from-driver.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/i2c-mv64xxx-add-atomic_xfer-method-to-driver.patch b/queue-5.15/i2c-mv64xxx-add-atomic_xfer-method-to-driver.patch
new file mode 100644 (file)
index 0000000..822f733
--- /dev/null
@@ -0,0 +1,146 @@
+From 544a8d75f3d6e60e160cd92dc56321484598a993 Mon Sep 17 00:00:00 2001
+From: Chris Morgan <macromorgan@hotmail.com>
+Date: Wed, 30 Mar 2022 12:16:57 -0500
+Subject: i2c: mv64xxx: Add atomic_xfer method to driver
+
+From: Chris Morgan <macromorgan@hotmail.com>
+
+commit 544a8d75f3d6e60e160cd92dc56321484598a993 upstream.
+
+Add an atomic_xfer method to the driver so that it behaves correctly
+when controlling a PMIC that is responsible for device shutdown.
+
+The atomic_xfer method added is similar to the one from the i2c-rk3x
+driver. When running an atomic_xfer a bool flag in the driver data is
+set, the interrupt is not unmasked on transfer start, and the IRQ
+handler is manually invoked while waiting for pending transfers to
+complete.
+
+Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
+Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Tong Zhang <ztong0001@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-mv64xxx.c |   52 ++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 46 insertions(+), 6 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-mv64xxx.c
++++ b/drivers/i2c/busses/i2c-mv64xxx.c
+@@ -150,6 +150,7 @@ struct mv64xxx_i2c_data {
+       /* Clk div is 2 to the power n, not 2 to the power n + 1 */
+       bool                    clk_n_base_0;
+       struct i2c_bus_recovery_info    rinfo;
++      bool                    atomic;
+ };
+ static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
+@@ -179,7 +180,10 @@ mv64xxx_i2c_prepare_for_io(struct mv64xx
+       u32     dir = 0;
+       drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK |
+-              MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN;
++                            MV64XXX_I2C_REG_CONTROL_TWSIEN;
++
++      if (!drv_data->atomic)
++              drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_INTEN;
+       if (msg->flags & I2C_M_RD)
+               dir = 1;
+@@ -409,7 +413,8 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c
+       case MV64XXX_I2C_ACTION_RCV_DATA_STOP:
+               drv_data->msg->buf[drv_data->byte_posn++] =
+                       readl(drv_data->reg_base + drv_data->reg_offsets.data);
+-              drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
++              if (!drv_data->atomic)
++                      drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
+               writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
+                       drv_data->reg_base + drv_data->reg_offsets.control);
+               drv_data->block = 0;
+@@ -427,7 +432,8 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c
+               drv_data->rc = -EIO;
+               fallthrough;
+       case MV64XXX_I2C_ACTION_SEND_STOP:
+-              drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
++              if (!drv_data->atomic)
++                      drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
+               writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
+                       drv_data->reg_base + drv_data->reg_offsets.control);
+               drv_data->block = 0;
+@@ -575,6 +581,17 @@ mv64xxx_i2c_wait_for_completion(struct m
+               spin_unlock_irqrestore(&drv_data->lock, flags);
+ }
++static void mv64xxx_i2c_wait_polling(struct mv64xxx_i2c_data *drv_data)
++{
++      ktime_t timeout = ktime_add_ms(ktime_get(), drv_data->adapter.timeout);
++
++      while (READ_ONCE(drv_data->block) &&
++             ktime_compare(ktime_get(), timeout) < 0) {
++              udelay(5);
++              mv64xxx_i2c_intr(0, drv_data);
++      }
++}
++
+ static int
+ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,
+                               int is_last)
+@@ -590,7 +607,11 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i
+       mv64xxx_i2c_send_start(drv_data);
+       spin_unlock_irqrestore(&drv_data->lock, flags);
+-      mv64xxx_i2c_wait_for_completion(drv_data);
++      if (!drv_data->atomic)
++              mv64xxx_i2c_wait_for_completion(drv_data);
++      else
++              mv64xxx_i2c_wait_polling(drv_data);
++
+       return drv_data->rc;
+ }
+@@ -717,7 +738,7 @@ mv64xxx_i2c_functionality(struct i2c_ada
+ }
+ static int
+-mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
++mv64xxx_i2c_xfer_core(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+ {
+       struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
+       int rc, ret = num;
+@@ -730,7 +751,7 @@ mv64xxx_i2c_xfer(struct i2c_adapter *ada
+       drv_data->msgs = msgs;
+       drv_data->num_msgs = num;
+-      if (mv64xxx_i2c_can_offload(drv_data))
++      if (mv64xxx_i2c_can_offload(drv_data) && !drv_data->atomic)
+               rc = mv64xxx_i2c_offload_xfer(drv_data);
+       else
+               rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[0], num == 1);
+@@ -747,8 +768,27 @@ mv64xxx_i2c_xfer(struct i2c_adapter *ada
+       return ret;
+ }
++static int
++mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
++{
++      struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
++
++      drv_data->atomic = 0;
++      return mv64xxx_i2c_xfer_core(adap, msgs, num);
++}
++
++static int mv64xxx_i2c_xfer_atomic(struct i2c_adapter *adap,
++                                 struct i2c_msg msgs[], int num)
++{
++      struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
++
++      drv_data->atomic = 1;
++      return mv64xxx_i2c_xfer_core(adap, msgs, num);
++}
++
+ static const struct i2c_algorithm mv64xxx_i2c_algo = {
+       .master_xfer = mv64xxx_i2c_xfer,
++      .master_xfer_atomic = mv64xxx_i2c_xfer_atomic,
+       .functionality = mv64xxx_i2c_functionality,
+ };
diff --git a/queue-5.15/i2c-mv64xxx-remove-shutdown-method-from-driver.patch b/queue-5.15/i2c-mv64xxx-remove-shutdown-method-from-driver.patch
new file mode 100644 (file)
index 0000000..b194ba7
--- /dev/null
@@ -0,0 +1,57 @@
+From 09b343038e3470e4d0da45f0ee09fb42107e5314 Mon Sep 17 00:00:00 2001
+From: Chris Morgan <macromorgan@hotmail.com>
+Date: Fri, 25 Mar 2022 13:06:25 -0500
+Subject: i2c: mv64xxx: Remove shutdown method from driver
+
+From: Chris Morgan <macromorgan@hotmail.com>
+
+commit 09b343038e3470e4d0da45f0ee09fb42107e5314 upstream.
+
+When I attempt to shut down (or reboot) my R8 based NTC CHIP with this
+i2c driver I get the following error: "i2c i2c-0: mv64xxx: I2C bus
+locked, block: 1, time_left: 0". Reboots are successful but shutdowns
+freeze. If I comment out the shutdown routine the device both reboots
+and shuts down successfully without receiving this error (however it
+does receive a warning of missing atomic_xfer).
+
+It appears that very few i2c drivers have a shutdown method, I assume
+because these devices are often used to communicate with PMICs (such
+as in my case with the R8 based NTC CHIP). I'm proposing we simply
+remove this method so long as it doesn't cause trouble for others
+downstream. I'll work on an atomic_xfer method and submit that in
+a different patch.
+
+Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
+Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Tong Zhang <ztong0001@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-mv64xxx.c |    9 ---------
+ 1 file changed, 9 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-mv64xxx.c
++++ b/drivers/i2c/busses/i2c-mv64xxx.c
+@@ -1047,14 +1047,6 @@ mv64xxx_i2c_remove(struct platform_devic
+       return 0;
+ }
+-static void
+-mv64xxx_i2c_shutdown(struct platform_device *pd)
+-{
+-      pm_runtime_disable(&pd->dev);
+-      if (!pm_runtime_status_suspended(&pd->dev))
+-              mv64xxx_i2c_runtime_suspend(&pd->dev);
+-}
+-
+ static const struct dev_pm_ops mv64xxx_i2c_pm_ops = {
+       SET_RUNTIME_PM_OPS(mv64xxx_i2c_runtime_suspend,
+                          mv64xxx_i2c_runtime_resume, NULL)
+@@ -1065,7 +1057,6 @@ static const struct dev_pm_ops mv64xxx_i
+ static struct platform_driver mv64xxx_i2c_driver = {
+       .probe  = mv64xxx_i2c_probe,
+       .remove = mv64xxx_i2c_remove,
+-      .shutdown = mv64xxx_i2c_shutdown,
+       .driver = {
+               .name   = MV64XXX_I2C_CTLR_NAME,
+               .pm     = &mv64xxx_i2c_pm_ops,
index d971ea262cc3a9e3a0fade434138a8f36c6e84c1..b248c0c38ed0114a31c6de89b0378d8b7b85df28 100644 (file)
@@ -149,3 +149,5 @@ tracing-make-sure-trace_printk-can-output-as-soon-as-it-can-be-used.patch
 trace_events_hist-add-check-for-return-value-of-create_hist_field.patch
 ftrace-scripts-update-the-instructions-for-ftrace-bisect.sh.patch
 cifs-fix-oops-due-to-uncleared-server-smbd_conn-in-reconnect.patch
+i2c-mv64xxx-remove-shutdown-method-from-driver.patch
+i2c-mv64xxx-add-atomic_xfer-method-to-driver.patch