Commit 24a5bb7b authored by David Brownell's avatar David Brownell Committed by Jean Delvare

i2c-core: Return -Errno, not -1

More updates to the I2C stack's fault reporting:  make the core stop
returning "-1" (usually "-EPERM") for all faults.  Instead, pass lower
level fault code up the stack, or return some appropriate errno.

This patch happens to touch almost exclusively SMBus calls.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 75415490
...@@ -598,10 +598,10 @@ be added back later if needed: ...@@ -598,10 +598,10 @@ be added back later if needed:
u8 command, u8 length, u8 command, u8 length,
u8 *values) u8 *values)
All these transactions return -1 on failure. The 'write' transactions All these transactions return a negative errno value on failure. The 'write'
return 0 on success; the 'read' transactions return the read value, except transactions return 0 on success; the 'read' transactions return the read
for read_block, which returns the number of values read. The block buffers value, except for block transactions, which return the number of values
need not be longer than 32 bytes. read. The block buffers need not be longer than 32 bytes.
You can read the file `smbus-protocol' for more information about the You can read the file `smbus-protocol' for more information about the
actual SMBus protocol. actual SMBus protocol.
......
...@@ -974,7 +974,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) ...@@ -974,7 +974,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
return ret; return ret;
} else { } else {
dev_dbg(&adap->dev, "I2C level transfers not supported\n"); dev_dbg(&adap->dev, "I2C level transfers not supported\n");
return -ENOSYS; return -EOPNOTSUPP;
} }
} }
EXPORT_SYMBOL(i2c_transfer); EXPORT_SYMBOL(i2c_transfer);
...@@ -1106,7 +1106,7 @@ int i2c_probe(struct i2c_adapter *adapter, ...@@ -1106,7 +1106,7 @@ int i2c_probe(struct i2c_adapter *adapter,
dev_warn(&adapter->dev, "SMBus Quick command not supported, " dev_warn(&adapter->dev, "SMBus Quick command not supported, "
"can't probe for chips\n"); "can't probe for chips\n");
return -1; return -EOPNOTSUPP;
} }
/* Probe entries are done second, and are not affected by ignore /* Probe entries are done second, and are not affected by ignore
...@@ -1298,7 +1298,7 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) ...@@ -1298,7 +1298,7 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
if (rpec != cpec) { if (rpec != cpec) {
pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n", pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
rpec, cpec); rpec, cpec);
return -1; return -EBADMSG;
} }
return 0; return 0;
} }
...@@ -1313,11 +1313,12 @@ EXPORT_SYMBOL(i2c_smbus_write_quick); ...@@ -1313,11 +1313,12 @@ EXPORT_SYMBOL(i2c_smbus_write_quick);
s32 i2c_smbus_read_byte(struct i2c_client *client) s32 i2c_smbus_read_byte(struct i2c_client *client)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, int status;
I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
return -1; status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
else I2C_SMBUS_READ, 0,
return data.byte; I2C_SMBUS_BYTE, &data);
return (status < 0) ? status : data.byte;
} }
EXPORT_SYMBOL(i2c_smbus_read_byte); EXPORT_SYMBOL(i2c_smbus_read_byte);
...@@ -1331,11 +1332,12 @@ EXPORT_SYMBOL(i2c_smbus_write_byte); ...@@ -1331,11 +1332,12 @@ EXPORT_SYMBOL(i2c_smbus_write_byte);
s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, int status;
I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
return -1; status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
else I2C_SMBUS_READ, command,
return data.byte; I2C_SMBUS_BYTE_DATA, &data);
return (status < 0) ? status : data.byte;
} }
EXPORT_SYMBOL(i2c_smbus_read_byte_data); EXPORT_SYMBOL(i2c_smbus_read_byte_data);
...@@ -1352,11 +1354,12 @@ EXPORT_SYMBOL(i2c_smbus_write_byte_data); ...@@ -1352,11 +1354,12 @@ EXPORT_SYMBOL(i2c_smbus_write_byte_data);
s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command) s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, int status;
I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
return -1; status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
else I2C_SMBUS_READ, command,
return data.word; I2C_SMBUS_WORD_DATA, &data);
return (status < 0) ? status : data.word;
} }
EXPORT_SYMBOL(i2c_smbus_read_word_data); EXPORT_SYMBOL(i2c_smbus_read_word_data);
...@@ -1390,11 +1393,13 @@ s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, ...@@ -1390,11 +1393,13 @@ s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command,
u8 *values) u8 *values)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
int status;
if (i2c_smbus_xfer(client->adapter, client->addr, client->flags, status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
I2C_SMBUS_READ, command, I2C_SMBUS_READ, command,
I2C_SMBUS_BLOCK_DATA, &data)) I2C_SMBUS_BLOCK_DATA, &data);
return -1; if (status)
return status;
memcpy(values, &data.block[1], data.block[0]); memcpy(values, &data.block[1], data.block[0]);
return data.block[0]; return data.block[0];
...@@ -1421,14 +1426,16 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, ...@@ -1421,14 +1426,16 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
u8 length, u8 *values) u8 length, u8 *values)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
int status;
if (length > I2C_SMBUS_BLOCK_MAX) if (length > I2C_SMBUS_BLOCK_MAX)
length = I2C_SMBUS_BLOCK_MAX; length = I2C_SMBUS_BLOCK_MAX;
data.block[0] = length; data.block[0] = length;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
I2C_SMBUS_READ,command, I2C_SMBUS_READ, command,
I2C_SMBUS_I2C_BLOCK_DATA,&data)) I2C_SMBUS_I2C_BLOCK_DATA, &data);
return -1; if (status < 0)
return status;
memcpy(values, &data.block[1], data.block[0]); memcpy(values, &data.block[1], data.block[0]);
return data.block[0]; return data.block[0];
...@@ -1469,6 +1476,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, ...@@ -1469,6 +1476,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
}; };
int i; int i;
u8 partial_pec = 0; u8 partial_pec = 0;
int status;
msgbuf0[0] = command; msgbuf0[0] = command;
switch(size) { switch(size) {
...@@ -1518,10 +1526,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, ...@@ -1518,10 +1526,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
} else { } else {
msg[0].len = data->block[0] + 2; msg[0].len = data->block[0] + 2;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
dev_err(&adapter->dev, "smbus_access called with " dev_err(&adapter->dev,
"invalid block write size (%d)\n", "Invalid block write size %d\n",
data->block[0]); data->block[0]);
return -1; return -EINVAL;
} }
for (i = 1; i < msg[0].len; i++) for (i = 1; i < msg[0].len; i++)
msgbuf0[i] = data->block[i-1]; msgbuf0[i] = data->block[i-1];
...@@ -1531,10 +1539,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, ...@@ -1531,10 +1539,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
num = 2; /* Another special case */ num = 2; /* Another special case */
read_write = I2C_SMBUS_READ; read_write = I2C_SMBUS_READ;
if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
dev_err(&adapter->dev, "%s called with invalid " dev_err(&adapter->dev,
"block proc call size (%d)\n", __func__, "Invalid block write size %d\n",
data->block[0]); data->block[0]);
return -1; return -EINVAL;
} }
msg[0].len = data->block[0] + 2; msg[0].len = data->block[0] + 2;
for (i = 1; i < msg[0].len; i++) for (i = 1; i < msg[0].len; i++)
...@@ -1549,19 +1557,18 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, ...@@ -1549,19 +1557,18 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
} else { } else {
msg[0].len = data->block[0] + 1; msg[0].len = data->block[0] + 1;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with " dev_err(&adapter->dev,
"invalid block write size (%d)\n", "Invalid block write size %d\n",
data->block[0]); data->block[0]);
return -1; return -EINVAL;
} }
for (i = 1; i <= data->block[0]; i++) for (i = 1; i <= data->block[0]; i++)
msgbuf0[i] = data->block[i]; msgbuf0[i] = data->block[i];
} }
break; break;
default: default:
dev_err(&adapter->dev, "smbus_access called with invalid size (%d)\n", dev_err(&adapter->dev, "Unsupported transaction %d\n", size);
size); return -EOPNOTSUPP;
return -1;
} }
i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
...@@ -1579,13 +1586,15 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, ...@@ -1579,13 +1586,15 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
msg[num-1].len++; msg[num-1].len++;
} }
if (i2c_transfer(adapter, msg, num) < 0) status = i2c_transfer(adapter, msg, num);
return -1; if (status < 0)
return status;
/* Check PEC if last message is a read */ /* Check PEC if last message is a read */
if (i && (msg[num-1].flags & I2C_M_RD)) { if (i && (msg[num-1].flags & I2C_M_RD)) {
if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0) status = i2c_smbus_check_pec(partial_pec, &msg[num-1]);
return -1; if (status < 0)
return status;
} }
if (read_write == I2C_SMBUS_READ) if (read_write == I2C_SMBUS_READ)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment