Patch "i2c: smbus: Send alert notifications to all devices if source not found" has been added to the 4.19-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    i2c: smbus: Send alert notifications to all devices if source not found

to the 4.19-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     i2c-smbus-send-alert-notifications-to-all-devices-if.patch
and it can be found in the queue-4.19 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 39f0af3be24389b3a3f20a9beaa3051f58e5f9b9
Author: Guenter Roeck <linux@xxxxxxxxxxxx>
Date:   Tue Jul 30 07:19:41 2024 -0700

    i2c: smbus: Send alert notifications to all devices if source not found
    
    [ Upstream commit f6c29f710c1ff2590109f83be3e212b86c01e0f3 ]
    
    If a SMBus alert is received and the originating device is not found,
    the reason may be that the address reported on the SMBus alert address
    is corrupted, for example because multiple devices asserted alert and
    do not correctly implement SMBus arbitration.
    
    If this happens, call alert handlers on all devices connected to the
    given I2C bus, in the hope that this cleans up the situation.
    
    This change reliably fixed the problem on a system with multiple devices
    on a single bus. Example log where the device on address 0x18 (ADM1021)
    and on address 0x4c (ADT7461A) both had the alert line asserted:
    
    smbus_alert 3-000c: SMBALERT# from dev 0x0c, flag 0
    smbus_alert 3-000c: no driver alert()!
    smbus_alert 3-000c: SMBALERT# from dev 0x0c, flag 0
    smbus_alert 3-000c: no driver alert()!
    lm90 3-0018: temp1 out of range, please check!
    lm90 3-0018: Disabling ALERT#
    lm90 3-0029: Everything OK
    lm90 3-002a: Everything OK
    lm90 3-004c: temp1 out of range, please check!
    lm90 3-004c: temp2 out of range, please check!
    lm90 3-004c: Disabling ALERT#
    
    Fixes: b5527a7766f0 ("i2c: Add SMBus alert support")
    Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx>
    [wsa: fixed a typo in the commit message]
    Signed-off-by: Wolfram Sang <wsa+renesas@xxxxxxxxxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
index ac2a5c2a7f8d8..0e9c2943194c8 100644
--- a/drivers/i2c/i2c-smbus.c
+++ b/drivers/i2c/i2c-smbus.c
@@ -73,6 +73,32 @@ static int smbus_do_alert(struct device *dev, void *addrp)
 	return ret;
 }
 
+/* Same as above, but call back all drivers with alert handler */
+
+static int smbus_do_alert_force(struct device *dev, void *addrp)
+{
+	struct i2c_client *client = i2c_verify_client(dev);
+	struct alert_data *data = addrp;
+	struct i2c_driver *driver;
+
+	if (!client || (client->flags & I2C_CLIENT_TEN))
+		return 0;
+
+	/*
+	 * Drivers should either disable alerts, or provide at least
+	 * a minimal handler. Lock so the driver won't change.
+	 */
+	device_lock(dev);
+	if (client->dev.driver) {
+		driver = to_i2c_driver(client->dev.driver);
+		if (driver->alert)
+			driver->alert(client, data->type, data->data);
+	}
+	device_unlock(dev);
+
+	return 0;
+}
+
 /*
  * The alert IRQ handler needs to hand work off to a task which can issue
  * SMBus calls, because those sleeping calls can't be made in IRQ context.
@@ -114,13 +140,19 @@ static irqreturn_t smbus_alert(int irq, void *d)
 		/*
 		 * If we read the same address more than once, and the alert
 		 * was not handled by a driver, it won't do any good to repeat
-		 * the loop because it will never terminate.
-		 * Bail out in this case.
+		 * the loop because it will never terminate. Try again, this
+		 * time calling the alert handlers of all devices connected to
+		 * the bus, and abort the loop afterwards. If this helps, we
+		 * are all set. If it doesn't, there is nothing else we can do,
+		 * so we might as well abort the loop.
 		 * Note: This assumes that a driver with alert handler handles
 		 * the alert properly and clears it if necessary.
 		 */
-		if (data.addr == prev_addr && status != -EBUSY)
+		if (data.addr == prev_addr && status != -EBUSY) {
+			device_for_each_child(&ara->adapter->dev, &data,
+					      smbus_do_alert_force);
 			break;
+		}
 		prev_addr = data.addr;
 	}
 




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux