linux-gbmc: support retry for ENXIO error

In rare cases, i2c-ast2600.c will return ENXIO error during sending of
MCTP packets in i2c multi-master mode. Here we supported limited retry
for ENXIO error.

Tested:
Still pass with nvmesensor single-worker-mode:
https://paste.googleplex.com/5948322238169088

Fusion-Link:
https://fusion2.corp.google.com/69214948-c3c6-3e47-8fab-32e83ffb9835
Google-Bug-Id: 286397121
Change-Id: Ib2ebbfaa6dba25c4571ca2afa714d01cf7e5e726
Signed-off-by: Jinliang Wang <jinliangw@google.com>
diff --git a/recipes-kernel/linux/files/0001-mctp-i2c-add-MCTP-retry-mechanism.patch b/recipes-kernel/linux/files/0001-mctp-i2c-add-MCTP-retry-mechanism.patch
index 2a6db1d..ae4d838 100644
--- a/recipes-kernel/linux/files/0001-mctp-i2c-add-MCTP-retry-mechanism.patch
+++ b/recipes-kernel/linux/files/0001-mctp-i2c-add-MCTP-retry-mechanism.patch
@@ -1,4 +1,4 @@
-From 5be710bf888d8ed9f10d12cd5db5faf8b3fd65e4 Mon Sep 17 00:00:00 2001
+From 9e2ff138c053f809c1d994d4d013ef8c35bddc89 Mon Sep 17 00:00:00 2001
 From: Jinliang Wang <jinliangw@google.com>
 Date: Mon, 22 Apr 2024 15:50:24 -0700
 Subject: [PATCH] mctp-i2c: add MCTP retry mechanism
@@ -17,41 +17,49 @@
 Google-Bug-Id: 286397121
 Signed-off-by: Jinliang Wang <jinliangw@google.com>
 ---
- drivers/net/mctp/mctp-i2c.c | 32 ++++++++++++++++++++++++++++++--
+ drivers/net/mctp/mctp-i2c.c | 40 +++++++++++++++++++++++++++++++++++--
  include/uapi/linux/i2c.h    |  2 ++
- 2 files changed, 32 insertions(+), 2 deletions(-)
+ 2 files changed, 40 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c
-index baf7afac7857..1d8296b0c0c2 100644
+index baf7afac7857..820e6f61b7f9 100644
 --- a/drivers/net/mctp/mctp-i2c.c
 +++ b/drivers/net/mctp/mctp-i2c.c
-@@ -435,6 +435,34 @@ static void mctp_i2c_unlock_reset(struct mctp_i2c_dev *midev)
+@@ -435,6 +435,42 @@ static void mctp_i2c_unlock_reset(struct mctp_i2c_dev *midev)
  		i2c_unlock_bus(midev->adapter, I2C_LOCK_SEGMENT);
  }
  
 +#define RETRY_TIME_MS 2000
 +#define RETRY_INVERVAL_MS 20
 +#define RETRY_CNT (RETRY_TIME_MS / RETRY_INVERVAL_MS)
++#define ENXIO_RETRY_LIMIT 5
 +
 +static int mctp_i2c_transfer_with_retry(struct i2c_adapter *adap,
 +					struct i2c_msg *msg)
 +{
 +	int rc = 0;
-+	int retry = 0;
++	int retry = 0; /* General retry count */
++	int enxio_retry = 0; /* Special retry count for ENXIO error */
 +	msg->flags = I2C_M_IS_MCTP;
 +	while (retry < RETRY_CNT) {
 +		retry++;
 +		rc = __i2c_transfer(adap, msg, 1);
-+		if (rc == -EBUSY || rc == -EAGAIN || rc == -EPROTO) {
++		if (rc == -ENXIO) {
++			enxio_retry++;
++			if (enxio_retry >= ENXIO_RETRY_LIMIT) {
++				/* Jump out if we accumulate enough ENXIO error */
++				break;
++			}
++		} else if (rc == -EBUSY || rc == -EAGAIN || rc == -EPROTO) {
 +			if (retry >= (RETRY_CNT - 1)) {
-+				/* set last retry flag */
++				/* Set last retry flag so i2c driver layer may perform necessary recovery */
 +				msg->flags |= I2C_M_LAST_RETRY;
 +			}
-+			msleep_interruptible(RETRY_INVERVAL_MS);
-+			/* continue to retry */
 +		} else {
 +			break;
 +		}
++		msleep_interruptible(RETRY_INVERVAL_MS);
++		/* Continue to retry */
 +	}
 +
 +	return rc;
@@ -60,7 +68,7 @@
  static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb)
  {
  	struct net_device_stats *stats = &midev->ndev->stats;
-@@ -478,7 +506,7 @@ static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb)
+@@ -478,7 +514,7 @@ static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb)
  		/* no flow: full lock & unlock */
  		mctp_i2c_lock_nest(midev);
  		mctp_i2c_device_select(midev->client, midev);
@@ -69,7 +77,7 @@
  		mctp_i2c_unlock_nest(midev);
  		break;
  
-@@ -492,7 +520,7 @@ static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb)
+@@ -492,7 +528,7 @@ static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb)
  
  	case MCTP_I2C_TX_FLOW_EXISTING:
  		/* existing flow: we already have the lock; just tx */