mirror of https://gitee.com/openkylin/linux.git
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
This commit is contained in:
commit
6b27354cca
|
@ -39,6 +39,7 @@ struct i2c_acpi_lookup {
|
||||||
int index;
|
int index;
|
||||||
u32 speed;
|
u32 speed;
|
||||||
u32 min_speed;
|
u32 min_speed;
|
||||||
|
u32 force_speed;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -285,6 +286,19 @@ i2c_acpi_match_device(const struct acpi_device_id *matches,
|
||||||
return acpi_match_device(matches, &client->dev);
|
return acpi_match_device(matches, &client->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct acpi_device_id i2c_acpi_force_400khz_device_ids[] = {
|
||||||
|
/*
|
||||||
|
* These Silead touchscreen controllers only work at 400KHz, for
|
||||||
|
* some reason they do not work at 100KHz. On some devices the ACPI
|
||||||
|
* tables list another device at their bus as only being capable
|
||||||
|
* of 100KHz, testing has shown that these other devices work fine
|
||||||
|
* at 400KHz (as can be expected of any recent i2c hw) so we force
|
||||||
|
* the speed of the bus to 400 KHz if a Silead device is present.
|
||||||
|
*/
|
||||||
|
{ "MSSL1680", 0 },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level,
|
static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level,
|
||||||
void *data, void **return_value)
|
void *data, void **return_value)
|
||||||
{
|
{
|
||||||
|
@ -303,6 +317,9 @@ static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level,
|
||||||
if (lookup->speed <= lookup->min_speed)
|
if (lookup->speed <= lookup->min_speed)
|
||||||
lookup->min_speed = lookup->speed;
|
lookup->min_speed = lookup->speed;
|
||||||
|
|
||||||
|
if (acpi_match_device_ids(adev, i2c_acpi_force_400khz_device_ids) == 0)
|
||||||
|
lookup->force_speed = 400000;
|
||||||
|
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +357,16 @@ u32 i2c_acpi_find_bus_speed(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lookup.min_speed != UINT_MAX ? lookup.min_speed : 0;
|
if (lookup.force_speed) {
|
||||||
|
if (lookup.force_speed != lookup.min_speed)
|
||||||
|
dev_warn(dev, FW_BUG "DSDT uses known not-working I2C bus speed %d, forcing it to %d\n",
|
||||||
|
lookup.min_speed, lookup.force_speed);
|
||||||
|
return lookup.force_speed;
|
||||||
|
} else if (lookup.min_speed != UINT_MAX) {
|
||||||
|
return lookup.min_speed;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed);
|
EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed);
|
||||||
|
|
||||||
|
|
|
@ -245,14 +245,14 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
|
||||||
}
|
}
|
||||||
|
|
||||||
client = of_i2c_register_device(adap, rd->dn);
|
client = of_i2c_register_device(adap, rd->dn);
|
||||||
put_device(&adap->dev);
|
|
||||||
|
|
||||||
if (IS_ERR(client)) {
|
if (IS_ERR(client)) {
|
||||||
dev_err(&adap->dev, "failed to create client for '%pOF'\n",
|
dev_err(&adap->dev, "failed to create client for '%pOF'\n",
|
||||||
rd->dn);
|
rd->dn);
|
||||||
|
put_device(&adap->dev);
|
||||||
of_node_clear_flag(rd->dn, OF_POPULATED);
|
of_node_clear_flag(rd->dn, OF_POPULATED);
|
||||||
return notifier_from_errno(PTR_ERR(client));
|
return notifier_from_errno(PTR_ERR(client));
|
||||||
}
|
}
|
||||||
|
put_device(&adap->dev);
|
||||||
break;
|
break;
|
||||||
case OF_RECONFIG_CHANGE_REMOVE:
|
case OF_RECONFIG_CHANGE_REMOVE:
|
||||||
/* already depopulated? */
|
/* already depopulated? */
|
||||||
|
|
Loading…
Reference in New Issue