Add "eeprom-nc" sysfs attribute to provide non-cached read access to EEPROM data. This is needed because some EEPROM-like devices contain constantly changing real-time diagnostic data that cannot be cached in kernel memory. Signed-off-by: Petri Gynther <pgynther@xxxxxxxxxx> --- drivers/misc/eeprom/eeprom.c | 30 +++++++++++++++++++++++++++--- 1 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c index 2c27193..101260b 100644 --- a/drivers/misc/eeprom/eeprom.c +++ b/drivers/misc/eeprom/eeprom.c @@ -39,6 +39,10 @@ I2C_CLIENT_INSMOD_1(eeprom); /* Size of EEPROM in bytes */ #define EEPROM_SIZE 256 +/* EEPROM read modes */ +#define EEPROM_READ_CACHED 0 +#define EEPROM_READ_NONCACHED 1 + /* possible types of eeprom devices */ enum eeprom_nature { UNKNOWN, @@ -55,14 +59,16 @@ struct eeprom_data { }; -static void eeprom_update_client(struct i2c_client *client, u8 slice) +static void eeprom_update_client(struct i2c_client *client, u8 slice, + int eeprom_read_mode) { struct eeprom_data *data = i2c_get_clientdata(client); int i; mutex_lock(&data->update_lock); - if (!(data->valid & (1 << slice)) || + if (eeprom_read_mode == EEPROM_READ_NONCACHED || + !(data->valid & (1 << slice)) || time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); @@ -102,7 +108,7 @@ static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, /* Only refresh slices which contain requested bytes */ for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++) - eeprom_update_client(client, slice); + eeprom_update_client(client, slice, (int)bin_attr->private); /* Hide Vaio private settings to regular users: - BIOS passwords: bytes 0x00 to 0x0f @@ -132,6 +138,17 @@ static struct bin_attribute eeprom_attr = { }, .size = EEPROM_SIZE, .read = eeprom_read, + .private = (void *)EEPROM_READ_CACHED, +}; + +static struct bin_attribute eeprom_nc_attr = { + .attr = { + .name = "eeprom-nc", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = eeprom_read, + .private = (void *)EEPROM_READ_NONCACHED, }; /* Return 0 if detection is successful, -ENODEV otherwise */ @@ -202,8 +219,14 @@ static int eeprom_probe(struct i2c_client *client, if (err) goto exit_kfree; + err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_nc_attr); + if (err) + goto exit_sysfs_clean; + return 0; +exit_sysfs_clean: + sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); exit_kfree: kfree(data); exit: @@ -212,6 +235,7 @@ exit: static int eeprom_remove(struct i2c_client *client) { + sysfs_remove_bin_file(&client->dev.kobj, &eeprom_nc_attr); sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); kfree(i2c_get_clientdata(client)); -- 1.5.4.3 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html