struct i2c_client *client = i2c_verify_client(dev);
struct alert_data *data = addrp;
struct i2c_driver *driver;
+ int ret;
if (!client || client->addr != data->addr)
return 0;
device_lock(dev);
if (client->dev.driver) {
driver = to_i2c_driver(client->dev.driver);
- if (driver->alert)
+ if (driver->alert) {
+ /* Stop iterating after we find the device */
driver->alert(client, data->type, data->data);
- else
+ ret = -EBUSY;
+ } else {
dev_warn(&client->dev, "no driver alert()!\n");
- } else
+ ret = -EOPNOTSUPP;
+ }
+ } else {
dev_dbg(&client->dev, "alert with no driver\n");
+ ret = -ENODEV;
+ }
device_unlock(dev);
- /* Stop iterating after we find the device */
- return -EBUSY;
+ return ret;
}
/*
{
struct i2c_smbus_alert *alert = d;
struct i2c_client *ara;
+ unsigned short prev_addr = I2C_CLIENT_END; /* Not a valid address */
ara = alert->ara;
data.addr, data.data);
/* Notify driver for the device which issued the alert */
- device_for_each_child(&ara->adapter->dev, &data,
- smbus_do_alert);
+ status = device_for_each_child(&ara->adapter->dev, &data,
+ smbus_do_alert);
+ /*
+ * 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.
+ * 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)
+ break;
+ prev_addr = data.addr;
}
return IRQ_HANDLED;