]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ipmi:ssif: Add a timer between request retries
authorCorey Minyard <cminyard@mvista.com>
Wed, 25 Jan 2023 16:34:47 +0000 (10:34 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Mar 2023 07:32:49 +0000 (08:32 +0100)
[ Upstream commit 00bb7e763ec9f384cb382455cb6ba5588b5375cf ]

The IPMI spec has a time (T6) specified between request retries.  Add
the handling for that.

Reported by: Tony Camuso <tcamuso@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Corey Minyard <cminyard@mvista.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/char/ipmi/ipmi_ssif.c

index 02ca0d9a0d8cb192ddcc6abf861be596a7b7b8a6..d5f068a10a5a01380989da5cbbe46432ad39ced2 100644 (file)
@@ -79,7 +79,8 @@
 /*
  * Timer values
  */
-#define SSIF_MSG_USEC          60000   /* 60ms between message tries. */
+#define SSIF_MSG_USEC          60000   /* 60ms between message tries (T3). */
+#define SSIF_REQ_RETRY_USEC    60000   /* 60ms between send retries (T6). */
 #define SSIF_MSG_PART_USEC     5000    /* 5ms for a message part */
 
 /* How many times to we retry sending/receiving the message. */
@@ -87,7 +88,9 @@
 #define        SSIF_RECV_RETRIES       250
 
 #define SSIF_MSG_MSEC          (SSIF_MSG_USEC / 1000)
+#define SSIF_REQ_RETRY_MSEC    (SSIF_REQ_RETRY_USEC / 1000)
 #define SSIF_MSG_JIFFIES       ((SSIF_MSG_USEC * 1000) / TICK_NSEC)
+#define SSIF_REQ_RETRY_JIFFIES ((SSIF_REQ_RETRY_USEC * 1000) / TICK_NSEC)
 #define SSIF_MSG_PART_JIFFIES  ((SSIF_MSG_PART_USEC * 1000) / TICK_NSEC)
 
 /*
@@ -236,6 +239,9 @@ struct ssif_info {
        bool                got_alert;
        bool                waiting_alert;
 
+       /* Used to inform the timeout that it should do a resend. */
+       bool                do_resend;
+
        /*
         * If set to true, this will request events the next time the
         * state machine is idle.
@@ -536,22 +542,28 @@ static void start_get(struct ssif_info *ssif_info)
                  ssif_info->recv, I2C_SMBUS_BLOCK_DATA);
 }
 
+static void start_resend(struct ssif_info *ssif_info);
+
 static void retry_timeout(struct timer_list *t)
 {
        struct ssif_info *ssif_info = from_timer(ssif_info, t, retry_timer);
        unsigned long oflags, *flags;
-       bool waiting;
+       bool waiting, resend;
 
        if (ssif_info->stopping)
                return;
 
        flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+       resend = ssif_info->do_resend;
+       ssif_info->do_resend = false;
        waiting = ssif_info->waiting_alert;
        ssif_info->waiting_alert = false;
        ipmi_ssif_unlock_cond(ssif_info, flags);
 
        if (waiting)
                start_get(ssif_info);
+       if (resend)
+               start_resend(ssif_info);
 }
 
 static void watch_timeout(struct timer_list *t)
@@ -600,8 +612,6 @@ static void ssif_alert(struct i2c_client *client, enum i2c_alert_protocol type,
                start_get(ssif_info);
 }
 
-static void start_resend(struct ssif_info *ssif_info);
-
 static void msg_done_handler(struct ssif_info *ssif_info, int result,
                             unsigned char *data, unsigned int len)
 {
@@ -906,7 +916,13 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result,
        if (result < 0) {
                ssif_info->retries_left--;
                if (ssif_info->retries_left > 0) {
-                       start_resend(ssif_info);
+                       /*
+                        * Wait the retry timeout time per the spec,
+                        * then redo the send.
+                        */
+                       ssif_info->do_resend = true;
+                       mod_timer(&ssif_info->retry_timer,
+                                 jiffies + SSIF_REQ_RETRY_JIFFIES);
                        return;
                }
 
@@ -1318,8 +1334,10 @@ static int do_cmd(struct i2c_client *client, int len, unsigned char *msg,
        ret = i2c_smbus_write_block_data(client, SSIF_IPMI_REQUEST, len, msg);
        if (ret) {
                retry_cnt--;
-               if (retry_cnt > 0)
+               if (retry_cnt > 0) {
+                       msleep(SSIF_REQ_RETRY_MSEC);
                        goto retry1;
+               }
                return -ENODEV;
        }
 
@@ -1459,8 +1477,10 @@ retry_write:
                                         32, msg);
        if (ret) {
                retry_cnt--;
-               if (retry_cnt > 0)
+               if (retry_cnt > 0) {
+                       msleep(SSIF_REQ_RETRY_MSEC);
                        goto retry_write;
+               }
                dev_err(&client->dev, "Could not write multi-part start, though the BMC said it could handle it.  Just limit sends to one part.\n");
                return ret;
        }