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 branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
"An I2C core fix to prevent a use-after-free in a rare error path,
and an I2C ACPI addition to work around broken HW/firmware related
to touchscreens"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
i2c: core: fix use after free in of_i2c_notify
i2c: acpi: Force bus speed to 400KHz if a Silead touchscreen is present

+29 -3
+27 -1
drivers/i2c/i2c-core-acpi.c
··· 39 39 int index; 40 40 u32 speed; 41 41 u32 min_speed; 42 + u32 force_speed; 42 43 }; 43 44 44 45 /** ··· 286 285 return acpi_match_device(matches, &client->dev); 287 286 } 288 287 288 + static const struct acpi_device_id i2c_acpi_force_400khz_device_ids[] = { 289 + /* 290 + * These Silead touchscreen controllers only work at 400KHz, for 291 + * some reason they do not work at 100KHz. On some devices the ACPI 292 + * tables list another device at their bus as only being capable 293 + * of 100KHz, testing has shown that these other devices work fine 294 + * at 400KHz (as can be expected of any recent i2c hw) so we force 295 + * the speed of the bus to 400 KHz if a Silead device is present. 296 + */ 297 + { "MSSL1680", 0 }, 298 + {} 299 + }; 300 + 289 301 static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level, 290 302 void *data, void **return_value) 291 303 { ··· 316 302 317 303 if (lookup->speed <= lookup->min_speed) 318 304 lookup->min_speed = lookup->speed; 305 + 306 + if (acpi_match_device_ids(adev, i2c_acpi_force_400khz_device_ids) == 0) 307 + lookup->force_speed = 400000; 319 308 320 309 return AE_OK; 321 310 } ··· 357 340 return 0; 358 341 } 359 342 360 - return lookup.min_speed != UINT_MAX ? lookup.min_speed : 0; 343 + if (lookup.force_speed) { 344 + if (lookup.force_speed != lookup.min_speed) 345 + dev_warn(dev, FW_BUG "DSDT uses known not-working I2C bus speed %d, forcing it to %d\n", 346 + lookup.min_speed, lookup.force_speed); 347 + return lookup.force_speed; 348 + } else if (lookup.min_speed != UINT_MAX) { 349 + return lookup.min_speed; 350 + } else { 351 + return 0; 352 + } 361 353 } 362 354 EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed); 363 355
+2 -2
drivers/i2c/i2c-core-of.c
··· 245 245 } 246 246 247 247 client = of_i2c_register_device(adap, rd->dn); 248 - put_device(&adap->dev); 249 - 250 248 if (IS_ERR(client)) { 251 249 dev_err(&adap->dev, "failed to create client for '%pOF'\n", 252 250 rd->dn); 251 + put_device(&adap->dev); 253 252 of_node_clear_flag(rd->dn, OF_POPULATED); 254 253 return notifier_from_errno(PTR_ERR(client)); 255 254 } 255 + put_device(&adap->dev); 256 256 break; 257 257 case OF_RECONFIG_CHANGE_REMOVE: 258 258 /* already depopulated? */