Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 36c5682c authored by Corey Minyard's avatar Corey Minyard Committed by Greg Kroah-Hartman
Browse files

ipmi:ssif: Add a timer between request retries



[ 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: default avatarCorey Minyard <cminyard@mvista.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent e8ba1b69
Loading
Loading
Loading
Loading
+27 −7
Original line number Diff line number Diff line
@@ -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 @@ 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;
	}