mei: pxp: re-enable client on errors
authorAlexander Usyskin <alexander.usyskin@intel.com>
Wed, 11 Oct 2023 11:01:56 +0000 (14:01 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 18 Oct 2023 08:01:33 +0000 (10:01 +0200)
Disable and enable mei-pxp client on errors to clean the internal state.

Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Link: https://lore.kernel.org/r/20231011110157.247552-4-tomas.winkler@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/pxp/mei_pxp.c

index c6cdd6a47308ebcc72f34c3891b0b6daeb581cd4..9875d16445bb03efcfb31cd94583fd8c49e588de 100644 (file)
 
 #include "mei_pxp.h"
 
+static inline int mei_pxp_reenable(const struct device *dev, struct mei_cl_device *cldev)
+{
+       int ret;
+
+       dev_warn(dev, "Trying to reset the channel...\n");
+       ret = mei_cldev_disable(cldev);
+       if (ret < 0)
+               dev_warn(dev, "mei_cldev_disable failed. %d\n", ret);
+       /*
+        * Explicitly ignoring disable failure,
+        * enable may fix the states and succeed
+        */
+       ret = mei_cldev_enable(cldev);
+       if (ret < 0)
+               dev_err(dev, "mei_cldev_enable failed. %d\n", ret);
+       return ret;
+}
+
 /**
  * mei_pxp_send_message() - Sends a PXP message to ME FW.
  * @dev: device corresponding to the mei_cl_device
@@ -35,6 +53,7 @@ mei_pxp_send_message(struct device *dev, const void *message, size_t size)
 {
        struct mei_cl_device *cldev;
        ssize_t byte;
+       int ret;
 
        if (!dev || !message)
                return -EINVAL;
@@ -44,10 +63,20 @@ mei_pxp_send_message(struct device *dev, const void *message, size_t size)
        byte = mei_cldev_send(cldev, message, size);
        if (byte < 0) {
                dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
-               return byte;
+               switch (byte) {
+               case -ENOMEM:
+                       fallthrough;
+               case -ENODEV:
+                       fallthrough;
+               case -ETIME:
+                       ret = mei_pxp_reenable(dev, cldev);
+                       if (ret)
+                               byte = ret;
+                       break;
+               }
        }
 
-       return 0;
+       return byte;
 }
 
 /**
@@ -63,6 +92,7 @@ mei_pxp_receive_message(struct device *dev, void *buffer, size_t size)
        struct mei_cl_device *cldev;
        ssize_t byte;
        bool retry = false;
+       int ret;
 
        if (!dev || !buffer)
                return -EINVAL;
@@ -73,26 +103,22 @@ retry:
        byte = mei_cldev_recv(cldev, buffer, size);
        if (byte < 0) {
                dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
-               if (byte != -ENOMEM)
-                       return byte;
-
-               /* Retry the read when pages are reclaimed */
-               msleep(20);
-               if (!retry) {
-                       retry = true;
-                       goto retry;
-               } else {
-                       dev_warn(dev, "No memory on data receive after retry, trying to reset the channel...\n");
-                       byte = mei_cldev_disable(cldev);
-                       if (byte < 0)
-                               dev_warn(dev, "mei_cldev_disable failed. %zd\n", byte);
-                       /*
-                        * Explicitly ignoring disable failure,
-                        * enable may fix the states and succeed
-                        */
-                       byte = mei_cldev_enable(cldev);
-                       if (byte < 0)
-                               dev_err(dev, "mei_cldev_enable failed. %zd\n", byte);
+               switch (byte) {
+               case -ENOMEM:
+                       /* Retry the read when pages are reclaimed */
+                       msleep(20);
+                       if (!retry) {
+                               retry = true;
+                               goto retry;
+                       }
+                       fallthrough;
+               case -ENODEV:
+                       fallthrough;
+               case -ETIME:
+                       ret = mei_pxp_reenable(dev, cldev);
+                       if (ret)
+                               byte = ret;
+                       break;
                }
        }