linux-gbmc: i2c-npcm7xx.c: add multi_master bus recoevery

The previous multi_master hack bypassed the npcm_i2c_recovery_tgclk.
Also, some NVMe-Mi device may reset their i2c module without notify
BMC i2c driver. In this case, the i2c-npcm7xx.c will enter a bad state
(bus_busy is false but bus->ber_state is true ) and it cannot send out
MCTP packet anymore.

Here we introduced the multi_master bus recovery mechanism:
When the accumulated bus->busy_cnt exceeds the adap->retries, we will
trigger npcm_i2c_reset and i2c_recover_bus.

Tested:
Before the fix, when stressing NVMe-Mi device i2c reset, we will
observe a lot of failure messages in kernel log:

Oct 30 23:17:18  kernel: i2c i2c-6: __i2c_transfer failed -11
Oct 30 23:17:18  kernel: i2c i2c-6: __i2c_transfer failed -11
Oct 30 23:17:18  kernel: i2c i2c-6: __i2c_transfer failed -11

After the fix, when stressing NVMe-Mi device i2c reset, there
is only a limited number of __i2c_transfer failed.

Google-Bug-Id: 297058513
Google-Bug-Id: 301615133
Google-Bug-Id: 305746801#comment11
Google-Bug-Id: 308495306

Change-Id: Ifeccfecc22f9ae92a7284975abea11e2593f1581
Signed-off-by: Jinliang Wang <jinliangw@google.com>
(cherry picked from commit 0dfc2659dbbb3ae4d8aac4a3bb70e40692af837c)
diff --git a/recipes-kernel/linux/files/0001-i2c-npcm-quirk-to-fix-multiple-master-xfer-failure.patch b/recipes-kernel/linux/files/0001-i2c-npcm-quirk-to-fix-multiple-master-xfer-failure.patch
index 4f5427e..6e3b124 100644
--- a/recipes-kernel/linux/files/0001-i2c-npcm-quirk-to-fix-multiple-master-xfer-failure.patch
+++ b/recipes-kernel/linux/files/0001-i2c-npcm-quirk-to-fix-multiple-master-xfer-failure.patch
@@ -1,4 +1,4 @@
-From 3d32e67d9488850502873ee61bd85666cf460873 Mon Sep 17 00:00:00 2001
+From 04e48856a6f899c821ea3578cf57a2e0c203fe55 Mon Sep 17 00:00:00 2001
 From: Jinliang Wang <jinliangw@google.com>
 Date: Tue, 28 Mar 2023 11:16:27 -0700
 Subject: [PATCH] i2c: npcm: quirk to fix multiple master xfer failure
@@ -10,32 +10,44 @@
 special handling. Nuvoton is still trying to find a more proper way to
 support multiple master mode in upstream i2c-npcm7xx.c.
 
-Signed-off-by: Jinliang Wang <jinliangw@google.com>
-
 Patch Tracking Bug: b/275108914
 Upstream info / review: N/A
 Upstream-Status: Pending
 Justification: The patch is upstreamable however Nuvoton is still
 working on more appropriate and general implementation
 
+Google-Bug-Id: 266723609
+Google-Bug-Id: 295580753
+Google-Bug-Id: 297058513
 Signed-off-by: William A. Kennington III <wak@google.com>
+Signed-off-by: Jinliang Wang <jinliangw@google.com>
 ---
- drivers/i2c/busses/i2c-npcm7xx.c | 69 +++++++++++++++++++++++++-------
- 1 file changed, 54 insertions(+), 15 deletions(-)
+ drivers/i2c/busses/i2c-npcm7xx.c | 81 +++++++++++++++++++++++++++-----
+ 1 file changed, 68 insertions(+), 13 deletions(-)
 
 diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
-index bfef6ae45988..a255d152734f 100644
+index bfef6ae45988..d193efbb33b1 100644
 --- a/drivers/i2c/busses/i2c-npcm7xx.c
 +++ b/drivers/i2c/busses/i2c-npcm7xx.c
-@@ -433,6 +433,7 @@ struct npcm_i2c {
+@@ -433,6 +433,8 @@ struct npcm_i2c {
  	bool read_block_use;
  	unsigned long int_time_stamp;
  	unsigned long bus_freq; /* in Hz */
 +	bool multi_master;
++	int busy_cnt;
  #if IS_ENABLED(CONFIG_I2C_SLAVE)
  	u8 own_slave_addr;
  	struct i2c_client *slave;
-@@ -1218,7 +1219,7 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
+@@ -800,6 +802,8 @@ static void npcm_i2c_reset(struct npcm_i2c *bus)
+ 	npcm_i2c_clear_master_status(bus);
+ 
+ 	bus->state = I2C_IDLE;
++	bus->busy_cnt = 0;
++	bus->multi_master = false;
+ }
+ 
+ static inline bool npcm_i2c_is_master(struct npcm_i2c *bus)
+@@ -1218,7 +1222,7 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
  		 * master ( for a channel which is master\slave switching)
  		 */
  		if (completion_done(&bus->cmd_complete) == false) {
@@ -44,7 +56,7 @@
  			complete(&bus->cmd_complete);
  		}
  		bus->own_slave_addr = 0xFF;
-@@ -1643,6 +1644,7 @@ static void npcm_i2c_irq_handle_ber(struct npcm_i2c *bus)
+@@ -1643,6 +1647,7 @@ static void npcm_i2c_irq_handle_ber(struct npcm_i2c *bus)
  	bus->stop_ind = I2C_BUS_ERR_IND;
  	if (npcm_i2c_is_master(bus)) {
  		npcm_i2c_master_abort(bus);
@@ -52,7 +64,7 @@
  	} else {
  		bus->ber_state = true;
  		npcm_i2c_clear_master_status(bus);
-@@ -1788,6 +1790,14 @@ static int npcm_i2c_int_master_handler(struct npcm_i2c *bus)
+@@ -1788,6 +1793,14 @@ static int npcm_i2c_int_master_handler(struct npcm_i2c *bus)
  	    (FIELD_GET(NPCM_I2CCST3_EO_BUSY,
  		       ioread8(bus->reg + NPCM_I2CCST3)))) {
  		npcm_i2c_irq_handle_eob(bus);
@@ -67,7 +79,7 @@
  		return 0;
  	}
  
-@@ -1819,11 +1829,16 @@ static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
+@@ -1819,11 +1832,16 @@ static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
  	/* Allow 3 bytes (27 toggles) to be read from the slave: */
  	int              iter = 27;
  
@@ -85,7 +97,7 @@
  		return 0;
  	}
  
-@@ -1888,7 +1903,6 @@ static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
+@@ -1888,7 +1906,6 @@ static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
  		if (bus->rec_succ_cnt < ULLONG_MAX)
  			bus->rec_succ_cnt++;
  	}
@@ -93,7 +105,7 @@
  	return status;
  }
  
-@@ -2107,7 +2121,7 @@ static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus,
+@@ -2107,7 +2124,7 @@ static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus,
  				       bool use_PEC, bool use_read_block)
  {
  	if (bus->state != I2C_IDLE) {
@@ -102,7 +114,15 @@
  		return false;
  	}
  	bus->dest_addr = slave_addr << 1;
-@@ -2184,6 +2198,11 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+@@ -2165,6 +2182,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ 		return -EINVAL;
+ 	}
+ 
++	bus->multi_master = false;
+ 	msg0 = &msgs[0];
+ 	slave_addr = msg0->addr;
+ 	if (msg0->flags & I2C_M_RD) { /* read */
+@@ -2184,6 +2202,11 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
  		write_data = msg0->buf;
  		nread = 0;
  		read_data = NULL;
@@ -114,7 +134,7 @@
  		if (num == 2) {
  			msg1 = &msgs[1];
  			read_data = msg1->buf;
-@@ -2201,6 +2220,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+@@ -2201,6 +2224,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
  
  	if (nwrite >= 32 * 1024 || nread >= 32 * 1024) {
  		dev_err(bus->dev, "i2c%d buffer too big\n", bus->num);
@@ -122,7 +142,7 @@
  		return -EINVAL;
  	}
  
-@@ -2212,7 +2232,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+@@ -2212,7 +2236,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
  		 * entire while since it is too long.
  		 */
  		spin_lock_irqsave(&bus->lock, flags);
@@ -131,7 +151,7 @@
  #if IS_ENABLED(CONFIG_I2C_SLAVE)
  		if (!bus_busy && bus->slave)
  			iowrite8((bus->slave->addr & 0x7F),
-@@ -2220,20 +2240,29 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+@@ -2220,21 +2244,41 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
  #endif
  		spin_unlock_irqrestore(&bus->lock, flags);
  
@@ -146,14 +166,22 @@
  	bus->dest_addr = slave_addr << 1;
  	if (bus_busy || bus->ber_state) {
  		iowrite8(NPCM_I2CCST_BB, bus->reg + NPCM_I2CCST);
--		npcm_i2c_reset(bus);
--		i2c_recover_bus(adap);
--		return -EAGAIN;
-+		if(bus->multi_master == false)
-+		{
-+			npcm_i2c_reset(bus);
-+			i2c_recover_bus(adap);
++		if (bus->multi_master) {
++			bus->busy_cnt++;
++			if (bus->busy_cnt < adap->retries) {
++				/* skip recovery */
++				bus->cmd_err = -EAGAIN;
++				goto npcm_i2c_xfer_complete;
++			}
++
++			/* need recovery */
++			dev_err(bus->dev, "i2c%d multi_master busy recover\n",
++				bus->num);
 +		}
++
+ 		npcm_i2c_reset(bus);
+ 		i2c_recover_bus(adap);
+-		return -EAGAIN;
 +		bus->cmd_err = -EAGAIN;
 +		goto npcm_i2c_xfer_complete;
  	}
@@ -164,9 +192,11 @@
 -	bus->cmd_err = 0;
 +	bus->cmd_err = -EAGAIN;
  	bus->read_block_use = read_block;
++	bus->busy_cnt = 0;
  
  	reinit_completion(&bus->cmd_complete);
-@@ -2258,8 +2287,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ 
+@@ -2258,8 +2302,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
  			if (bus->timeout_cnt < ULLONG_MAX)
  				bus->timeout_cnt++;
  			if (bus->master_or_slave == I2C_MASTER) {
@@ -176,7 +206,7 @@
  				bus->state = I2C_IDLE;
  			}
  		}
-@@ -2267,7 +2295,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+@@ -2267,7 +2310,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
  
  	/* if there was BER, check if need to recover the bus: */
  	if (bus->cmd_err == -EAGAIN)
@@ -185,7 +215,7 @@
  
  	/*
  	 * After any type of error, check if LAST bit is still set,
-@@ -2282,6 +2310,15 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+@@ -2282,6 +2325,15 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
  	npcm_i2c_stall_after_start(bus, false);
  	npcm_i2c_eob_int(bus, false);
  
@@ -201,7 +231,7 @@
  #if IS_ENABLED(CONFIG_I2C_SLAVE)
  	/* reenable slave if it was enabled */
  	if (bus->slave)
-@@ -2423,8 +2460,10 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
+@@ -2423,8 +2475,11 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
  
  	adap = &bus->adap;
  	adap->owner = THIS_MODULE;
@@ -211,9 +241,10 @@
 +	adap->retries = 10;
 +	adap->timeout = msecs_to_jiffies(400) * adap->retries;
 +	bus->multi_master = false;
++	bus->busy_cnt = 0;
  	adap->algo = &npcm_i2c_algo;
  	adap->quirks = &npcm_i2c_quirks;
  	adap->algo_data = bus;
 -- 
-2.41.0.640.ga95def55d0-goog
+2.42.0.820.g83a721a137-goog