Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'i2c-for-6.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:

- Two fixes for SMBusAlert handling in the I2C core: one to avoid an
endless loop when scanning for handlers and one to make sure handlers
are always called even if HW has broken behaviour

- I2C header build fix for when ACPI is enabled but I2C isn't

- The testunit gets a rename in the code to match the documentation

- Two fixes for the Qualcomm GENI I2C controller are cleaning up the
error exit patch in the runtime_resume() function. The first is
disabling the clock, the second disables the icc on the way out

* tag 'i2c-for-6.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
i2c: testunit: match HostNotify test name with docs
i2c: qcom-geni: Add missing geni_icc_disable in geni_i2c_runtime_resume
i2c: qcom-geni: Add missing clk_disable_unprepare in geni_i2c_runtime_resume
i2c: Fix conditional for substituting empty ACPI functions
i2c: smbus: Send alert notifications to all devices if source not found
i2c: smbus: Improve handling of stuck alerts

+64 -11
+4 -1
drivers/i2c/busses/i2c-qcom-geni.c
··· 990 990 return ret; 991 991 992 992 ret = geni_se_resources_on(&gi2c->se); 993 - if (ret) 993 + if (ret) { 994 + clk_disable_unprepare(gi2c->core_clk); 995 + geni_icc_disable(&gi2c->se); 994 996 return ret; 997 + } 995 998 996 999 enable_irq(gi2c->irq); 997 1000 gi2c->suspended = 0;
+2 -2
drivers/i2c/i2c-slave-testunit.c
··· 18 18 19 19 enum testunit_cmds { 20 20 TU_CMD_READ_BYTES = 1, /* save 0 for ABORT, RESET or similar */ 21 - TU_CMD_HOST_NOTIFY, 21 + TU_CMD_SMBUS_HOST_NOTIFY, 22 22 TU_CMD_SMBUS_BLOCK_PROC_CALL, 23 23 TU_NUM_CMDS 24 24 }; ··· 60 60 msg.len = tu->regs[TU_REG_DATAH]; 61 61 break; 62 62 63 - case TU_CMD_HOST_NOTIFY: 63 + case TU_CMD_SMBUS_HOST_NOTIFY: 64 64 msg.addr = 0x08; 65 65 msg.flags = 0; 66 66 msg.len = 3;
+57 -7
drivers/i2c/i2c-smbus.c
··· 34 34 struct i2c_client *client = i2c_verify_client(dev); 35 35 struct alert_data *data = addrp; 36 36 struct i2c_driver *driver; 37 + int ret; 37 38 38 39 if (!client || client->addr != data->addr) 39 40 return 0; ··· 48 47 device_lock(dev); 49 48 if (client->dev.driver) { 50 49 driver = to_i2c_driver(client->dev.driver); 51 - if (driver->alert) 50 + if (driver->alert) { 51 + /* Stop iterating after we find the device */ 52 52 driver->alert(client, data->type, data->data); 53 - else 53 + ret = -EBUSY; 54 + } else { 54 55 dev_warn(&client->dev, "no driver alert()!\n"); 55 - } else 56 + ret = -EOPNOTSUPP; 57 + } 58 + } else { 56 59 dev_dbg(&client->dev, "alert with no driver\n"); 60 + ret = -ENODEV; 61 + } 57 62 device_unlock(dev); 58 63 59 - /* Stop iterating after we find the device */ 60 - return -EBUSY; 64 + return ret; 65 + } 66 + 67 + /* Same as above, but call back all drivers with alert handler */ 68 + 69 + static int smbus_do_alert_force(struct device *dev, void *addrp) 70 + { 71 + struct i2c_client *client = i2c_verify_client(dev); 72 + struct alert_data *data = addrp; 73 + struct i2c_driver *driver; 74 + 75 + if (!client || (client->flags & I2C_CLIENT_TEN)) 76 + return 0; 77 + 78 + /* 79 + * Drivers should either disable alerts, or provide at least 80 + * a minimal handler. Lock so the driver won't change. 81 + */ 82 + device_lock(dev); 83 + if (client->dev.driver) { 84 + driver = to_i2c_driver(client->dev.driver); 85 + if (driver->alert) 86 + driver->alert(client, data->type, data->data); 87 + } 88 + device_unlock(dev); 89 + 90 + return 0; 61 91 } 62 92 63 93 /* ··· 99 67 { 100 68 struct i2c_smbus_alert *alert = d; 101 69 struct i2c_client *ara; 70 + unsigned short prev_addr = I2C_CLIENT_END; /* Not a valid address */ 102 71 103 72 ara = alert->ara; 104 73 ··· 127 94 data.addr, data.data); 128 95 129 96 /* Notify driver for the device which issued the alert */ 130 - device_for_each_child(&ara->adapter->dev, &data, 131 - smbus_do_alert); 97 + status = device_for_each_child(&ara->adapter->dev, &data, 98 + smbus_do_alert); 99 + /* 100 + * If we read the same address more than once, and the alert 101 + * was not handled by a driver, it won't do any good to repeat 102 + * the loop because it will never terminate. Try again, this 103 + * time calling the alert handlers of all devices connected to 104 + * the bus, and abort the loop afterwards. If this helps, we 105 + * are all set. If it doesn't, there is nothing else we can do, 106 + * so we might as well abort the loop. 107 + * Note: This assumes that a driver with alert handler handles 108 + * the alert properly and clears it if necessary. 109 + */ 110 + if (data.addr == prev_addr && status != -EBUSY) { 111 + device_for_each_child(&ara->adapter->dev, &data, 112 + smbus_do_alert_force); 113 + break; 114 + } 115 + prev_addr = data.addr; 132 116 } 133 117 134 118 return IRQ_HANDLED;
+1 -1
include/linux/i2c.h
··· 1066 1066 struct acpi_resource; 1067 1067 struct acpi_resource_i2c_serialbus; 1068 1068 1069 - #if IS_ENABLED(CONFIG_ACPI) 1069 + #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_I2C) 1070 1070 bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, 1071 1071 struct acpi_resource_i2c_serialbus **i2c); 1072 1072 int i2c_acpi_client_count(struct acpi_device *adev);