Skip to content

Commit

Permalink
ipmi:ssif: Add a timer between request retries
Browse files Browse the repository at this point in the history
The IPMI spec has a time (T6) specified between request retries.  Add
the handling for that.

Reported by: Tony Camuso <[email protected]>
Cc: [email protected]
Signed-off-by: Corey Minyard <[email protected]>
  • Loading branch information
cminyard committed Feb 10, 2023
1 parent 9e8b899 commit 00bb7e7
Showing 1 changed file with 27 additions and 7 deletions.
34 changes: 27 additions & 7 deletions drivers/char/ipmi/ipmi_ssif.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,18 @@
/*
* 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. */
#define SSIF_SEND_RETRIES 5
#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)

/*
Expand Down Expand Up @@ -229,6 +232,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.
Expand Down Expand Up @@ -531,22 +537,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)
Expand Down Expand Up @@ -595,8 +607,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)
{
Expand Down Expand Up @@ -901,7 +911,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;
}

Expand Down Expand Up @@ -1311,8 +1327,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;
}

Expand Down Expand Up @@ -1453,8 +1471,10 @@ static int start_multipart_test(struct i2c_client *client,
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;
}
Expand Down

0 comments on commit 00bb7e7

Please sign in to comment.