aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2008-07-14 16:38:29 -0400
committerJean Delvare <khali@mahadeva.delvare>2008-07-14 16:38:29 -0400
commit1b4dff9cd37d430bc76112396e92bb3552f37ccd (patch)
tree30bc7e5816a5d68bb0e2a202e4b54e1d776c2348 /drivers/i2c
parentd4653bf946a5856a17342cd47c47d10b16b1cc22 (diff)
i2c/eeprom: Fall back to SMBus read word transactions
When I2C block reads are not supported by the underlying adapter, use SMBus read word transactions instead of consecutive byte reads. Reasons for this change are: * The consecutive byte read approach is not safe on multi-master buses. * While consecutive byte reads have less overhead if you only count the bytes on the bus, it takes more than twice as many transactions as with SMBus read word transactions, and each transaction has a cost: taking and releasing the adapter mutex, and for polling drivers, waiting for the transaction to complete. This change yields a significant performance boost at HZ=250 with EEPROMs on an Intel 82801 bus (basically twice as fast.) SMBus read word transactions are widely supported so I don't expect compatibility issues. Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/chips/eeprom.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index 213a9f98decc..9a81252a7218 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -78,7 +78,7 @@ static struct i2c_driver eeprom_driver = {
78static void eeprom_update_client(struct i2c_client *client, u8 slice) 78static void eeprom_update_client(struct i2c_client *client, u8 slice)
79{ 79{
80 struct eeprom_data *data = i2c_get_clientdata(client); 80 struct eeprom_data *data = i2c_get_clientdata(client);
81 int i, j; 81 int i;
82 82
83 mutex_lock(&data->update_lock); 83 mutex_lock(&data->update_lock);
84 84
@@ -93,15 +93,12 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
93 != 32) 93 != 32)
94 goto exit; 94 goto exit;
95 } else { 95 } else {
96 if (i2c_smbus_write_byte(client, slice << 5)) { 96 for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
97 dev_dbg(&client->dev, "eeprom read start has failed!\n"); 97 int word = i2c_smbus_read_word_data(client, i);
98 goto exit; 98 if (word < 0)
99 }
100 for (i = slice << 5; i < (slice + 1) << 5; i++) {
101 j = i2c_smbus_read_byte(client);
102 if (j < 0)
103 goto exit; 99 goto exit;
104 data->data[i] = (u8) j; 100 data->data[i] = word & 0xff;
101 data->data[i + 1] = word >> 8;
105 } 102 }
106 } 103 }
107 data->last_updated[slice] = jiffies; 104 data->last_updated[slice] = jiffies;
@@ -177,14 +174,15 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
177 if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51) 174 if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51)
178 goto exit; 175 goto exit;
179 176
180 /* There are three ways we can read the EEPROM data: 177 /* There are four ways we can read the EEPROM data:
181 (1) I2C block reads (faster, but unsupported by most adapters) 178 (1) I2C block reads (faster, but unsupported by most adapters)
182 (2) Consecutive byte reads (100% overhead) 179 (2) Word reads (128% overhead)
183 (3) Regular byte data reads (200% overhead) 180 (3) Consecutive byte reads (88% overhead, unsafe)
184 The third method is not implemented by this driver because all 181 (4) Regular byte data reads (265% overhead)
185 known adapters support at least the second. */ 182 The third and fourth methods are not implemented by this driver
186 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA 183 because all known adapters support one of the first two. */
187 | I2C_FUNC_SMBUS_BYTE)) 184 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
185 && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
188 goto exit; 186 goto exit;
189 187
190 if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { 188 if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
@@ -212,13 +210,14 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
212 210
213 /* Detect the Vaio nature of EEPROMs. 211 /* Detect the Vaio nature of EEPROMs.
214 We use the "PCG-" or "VGN-" prefix as the signature. */ 212 We use the "PCG-" or "VGN-" prefix as the signature. */
215 if (address == 0x57) { 213 if (address == 0x57
214 && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
216 char name[4]; 215 char name[4];
217 216
218 name[0] = i2c_smbus_read_byte_data(new_client, 0x80); 217 name[0] = i2c_smbus_read_byte_data(new_client, 0x80);
219 name[1] = i2c_smbus_read_byte(new_client); 218 name[1] = i2c_smbus_read_byte_data(new_client, 0x81);
220 name[2] = i2c_smbus_read_byte(new_client); 219 name[2] = i2c_smbus_read_byte_data(new_client, 0x82);
221 name[3] = i2c_smbus_read_byte(new_client); 220 name[3] = i2c_smbus_read_byte_data(new_client, 0x83);
222 221
223 if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { 222 if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
224 dev_info(&new_client->dev, "Vaio EEPROM detected, " 223 dev_info(&new_client->dev, "Vaio EEPROM detected, "