aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJulia Lawall <julia@diku.dk>2010-10-24 12:16:58 -0400
committerJean Delvare <khali@endymion.delvare>2010-10-24 12:16:58 -0400
commit9cb2c2726e9ae212ccaeecd3eaadcd8d49ac7400 (patch)
treefb551cce7de62fc65c38beef7b014bb405362f61 /drivers/i2c
parentef9d9b8fb696850a95cd59ba2cd67991b6f722b3 (diff)
i2c-amd8111: Add proper error handling
The functions the functions amd_ec_wait_write and amd_ec_wait_read have an unsigned return type, but return a negative constant to indicate an error condition. A sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // <smpl> @exists@ identifier f; constant C; @@ unsigned f(...) { <+... * return -C; ...+> } // </smpl> Fixing amd_ec_wait_write and amd_ec_wait_read leads to the need to adjust the return type of the functions amd_ec_write and amd_ec_read, which are the only functions that call amd_ec_wait_write and amd_ec_wait_read. amd_ec_write and amd_ec_read, in turn, are only called from within the function amd8111_access, which already returns a signed typed value. Each of the calls to amd_ec_write and amd_ec_read are updated using the following semantic patch: // <smpl> @@ @@ + status = amd_ec_write - amd_ec_write (...); + if (status) return status; @@ @@ + status = amd_ec_read - amd_ec_read (...); + if (status) return status; // </smpl> The patch also adds the declaration of the status variable. Signed-off-by: Julia Lawall <julia@diku.dk> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c163
1 files changed, 113 insertions, 50 deletions
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index af1e5e254b7b..6b6a6b1d7025 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -69,7 +69,7 @@ static struct pci_driver amd8111_driver;
69 * ACPI 2.0 chapter 13 access of registers of the EC 69 * ACPI 2.0 chapter 13 access of registers of the EC
70 */ 70 */
71 71
72static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) 72static int amd_ec_wait_write(struct amd_smbus *smbus)
73{ 73{
74 int timeout = 500; 74 int timeout = 500;
75 75
@@ -85,7 +85,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
85 return 0; 85 return 0;
86} 86}
87 87
88static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) 88static int amd_ec_wait_read(struct amd_smbus *smbus)
89{ 89{
90 int timeout = 500; 90 int timeout = 500;
91 91
@@ -101,7 +101,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
101 return 0; 101 return 0;
102} 102}
103 103
104static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, 104static int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
105 unsigned char *data) 105 unsigned char *data)
106{ 106{
107 int status; 107 int status;
@@ -124,7 +124,7 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
124 return 0; 124 return 0;
125} 125}
126 126
127static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, 127static int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
128 unsigned char data) 128 unsigned char data)
129{ 129{
130 int status; 130 int status;
@@ -196,7 +196,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
196{ 196{
197 struct amd_smbus *smbus = adap->algo_data; 197 struct amd_smbus *smbus = adap->algo_data;
198 unsigned char protocol, len, pec, temp[2]; 198 unsigned char protocol, len, pec, temp[2];
199 int i; 199 int i, status;
200 200
201 protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ 201 protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ
202 : AMD_SMB_PRTCL_WRITE; 202 : AMD_SMB_PRTCL_WRITE;
@@ -209,38 +209,62 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
209 break; 209 break;
210 210
211 case I2C_SMBUS_BYTE: 211 case I2C_SMBUS_BYTE:
212 if (read_write == I2C_SMBUS_WRITE) 212 if (read_write == I2C_SMBUS_WRITE) {
213 amd_ec_write(smbus, AMD_SMB_CMD, command); 213 status = amd_ec_write(smbus, AMD_SMB_CMD,
214 command);
215 if (status)
216 return status;
217 }
214 protocol |= AMD_SMB_PRTCL_BYTE; 218 protocol |= AMD_SMB_PRTCL_BYTE;
215 break; 219 break;
216 220
217 case I2C_SMBUS_BYTE_DATA: 221 case I2C_SMBUS_BYTE_DATA:
218 amd_ec_write(smbus, AMD_SMB_CMD, command); 222 status = amd_ec_write(smbus, AMD_SMB_CMD, command);
219 if (read_write == I2C_SMBUS_WRITE) 223 if (status)
220 amd_ec_write(smbus, AMD_SMB_DATA, data->byte); 224 return status;
225 if (read_write == I2C_SMBUS_WRITE) {
226 status = amd_ec_write(smbus, AMD_SMB_DATA,
227 data->byte);
228 if (status)
229 return status;
230 }
221 protocol |= AMD_SMB_PRTCL_BYTE_DATA; 231 protocol |= AMD_SMB_PRTCL_BYTE_DATA;
222 break; 232 break;
223 233
224 case I2C_SMBUS_WORD_DATA: 234 case I2C_SMBUS_WORD_DATA:
225 amd_ec_write(smbus, AMD_SMB_CMD, command); 235 status = amd_ec_write(smbus, AMD_SMB_CMD, command);
236 if (status)
237 return status;
226 if (read_write == I2C_SMBUS_WRITE) { 238 if (read_write == I2C_SMBUS_WRITE) {
227 amd_ec_write(smbus, AMD_SMB_DATA, 239 status = amd_ec_write(smbus, AMD_SMB_DATA,
228 data->word & 0xff); 240 data->word & 0xff);
229 amd_ec_write(smbus, AMD_SMB_DATA + 1, 241 if (status)
230 data->word >> 8); 242 return status;
243 status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
244 data->word >> 8);
245 if (status)
246 return status;
231 } 247 }
232 protocol |= AMD_SMB_PRTCL_WORD_DATA | pec; 248 protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;
233 break; 249 break;
234 250
235 case I2C_SMBUS_BLOCK_DATA: 251 case I2C_SMBUS_BLOCK_DATA:
236 amd_ec_write(smbus, AMD_SMB_CMD, command); 252 status = amd_ec_write(smbus, AMD_SMB_CMD, command);
253 if (status)
254 return status;
237 if (read_write == I2C_SMBUS_WRITE) { 255 if (read_write == I2C_SMBUS_WRITE) {
238 len = min_t(u8, data->block[0], 256 len = min_t(u8, data->block[0],
239 I2C_SMBUS_BLOCK_MAX); 257 I2C_SMBUS_BLOCK_MAX);
240 amd_ec_write(smbus, AMD_SMB_BCNT, len); 258 status = amd_ec_write(smbus, AMD_SMB_BCNT, len);
241 for (i = 0; i < len; i++) 259 if (status)
242 amd_ec_write(smbus, AMD_SMB_DATA + i, 260 return status;
243 data->block[i + 1]); 261 for (i = 0; i < len; i++) {
262 status =
263 amd_ec_write(smbus, AMD_SMB_DATA + i,
264 data->block[i + 1]);
265 if (status)
266 return status;
267 }
244 } 268 }
245 protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec; 269 protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;
246 break; 270 break;
@@ -248,19 +272,35 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
248 case I2C_SMBUS_I2C_BLOCK_DATA: 272 case I2C_SMBUS_I2C_BLOCK_DATA:
249 len = min_t(u8, data->block[0], 273 len = min_t(u8, data->block[0],
250 I2C_SMBUS_BLOCK_MAX); 274 I2C_SMBUS_BLOCK_MAX);
251 amd_ec_write(smbus, AMD_SMB_CMD, command); 275 status = amd_ec_write(smbus, AMD_SMB_CMD, command);
252 amd_ec_write(smbus, AMD_SMB_BCNT, len); 276 if (status)
277 return status;
278 status = amd_ec_write(smbus, AMD_SMB_BCNT, len);
279 if (status)
280 return status;
253 if (read_write == I2C_SMBUS_WRITE) 281 if (read_write == I2C_SMBUS_WRITE)
254 for (i = 0; i < len; i++) 282 for (i = 0; i < len; i++) {
255 amd_ec_write(smbus, AMD_SMB_DATA + i, 283 status =
256 data->block[i + 1]); 284 amd_ec_write(smbus, AMD_SMB_DATA + i,
285 data->block[i + 1]);
286 if (status)
287 return status;
288 }
257 protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA; 289 protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;
258 break; 290 break;
259 291
260 case I2C_SMBUS_PROC_CALL: 292 case I2C_SMBUS_PROC_CALL:
261 amd_ec_write(smbus, AMD_SMB_CMD, command); 293 status = amd_ec_write(smbus, AMD_SMB_CMD, command);
262 amd_ec_write(smbus, AMD_SMB_DATA, data->word & 0xff); 294 if (status)
263 amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); 295 return status;
296 status = amd_ec_write(smbus, AMD_SMB_DATA,
297 data->word & 0xff);
298 if (status)
299 return status;
300 status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
301 data->word >> 8);
302 if (status)
303 return status;
264 protocol = AMD_SMB_PRTCL_PROC_CALL | pec; 304 protocol = AMD_SMB_PRTCL_PROC_CALL | pec;
265 read_write = I2C_SMBUS_READ; 305 read_write = I2C_SMBUS_READ;
266 break; 306 break;
@@ -268,11 +308,18 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
268 case I2C_SMBUS_BLOCK_PROC_CALL: 308 case I2C_SMBUS_BLOCK_PROC_CALL:
269 len = min_t(u8, data->block[0], 309 len = min_t(u8, data->block[0],
270 I2C_SMBUS_BLOCK_MAX - 1); 310 I2C_SMBUS_BLOCK_MAX - 1);
271 amd_ec_write(smbus, AMD_SMB_CMD, command); 311 status = amd_ec_write(smbus, AMD_SMB_CMD, command);
272 amd_ec_write(smbus, AMD_SMB_BCNT, len); 312 if (status)
273 for (i = 0; i < len; i++) 313 return status;
274 amd_ec_write(smbus, AMD_SMB_DATA + i, 314 status = amd_ec_write(smbus, AMD_SMB_BCNT, len);
275 data->block[i + 1]); 315 if (status)
316 return status;
317 for (i = 0; i < len; i++) {
318 status = amd_ec_write(smbus, AMD_SMB_DATA + i,
319 data->block[i + 1]);
320 if (status)
321 return status;
322 }
276 protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec; 323 protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec;
277 read_write = I2C_SMBUS_READ; 324 read_write = I2C_SMBUS_READ;
278 break; 325 break;
@@ -282,24 +329,29 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
282 return -EOPNOTSUPP; 329 return -EOPNOTSUPP;
283 } 330 }
284 331
285 amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); 332 status = amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
286 amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); 333 if (status)
334 return status;
335 status = amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
336 if (status)
337 return status;
287 338
288 /* FIXME this discards status from ec_read(); so temp[0] will 339 status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
289 * hold stack garbage ... the rest of this routine will act 340 if (status)
290 * nonsensically. Ignored ec_write() status might explain 341 return status;
291 * some such failures...
292 */
293 amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
294 342
295 if (~temp[0] & AMD_SMB_STS_DONE) { 343 if (~temp[0] & AMD_SMB_STS_DONE) {
296 udelay(500); 344 udelay(500);
297 amd_ec_read(smbus, AMD_SMB_STS, temp + 0); 345 status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
346 if (status)
347 return status;
298 } 348 }
299 349
300 if (~temp[0] & AMD_SMB_STS_DONE) { 350 if (~temp[0] & AMD_SMB_STS_DONE) {
301 msleep(1); 351 msleep(1);
302 amd_ec_read(smbus, AMD_SMB_STS, temp + 0); 352 status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
353 if (status)
354 return status;
303 } 355 }
304 356
305 if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS)) 357 if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
@@ -311,24 +363,35 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
311 switch (size) { 363 switch (size) {
312 case I2C_SMBUS_BYTE: 364 case I2C_SMBUS_BYTE:
313 case I2C_SMBUS_BYTE_DATA: 365 case I2C_SMBUS_BYTE_DATA:
314 amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); 366 status = amd_ec_read(smbus, AMD_SMB_DATA, &data->byte);
367 if (status)
368 return status;
315 break; 369 break;
316 370
317 case I2C_SMBUS_WORD_DATA: 371 case I2C_SMBUS_WORD_DATA:
318 case I2C_SMBUS_PROC_CALL: 372 case I2C_SMBUS_PROC_CALL:
319 amd_ec_read(smbus, AMD_SMB_DATA, temp + 0); 373 status = amd_ec_read(smbus, AMD_SMB_DATA, temp + 0);
320 amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1); 374 if (status)
375 return status;
376 status = amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1);
377 if (status)
378 return status;
321 data->word = (temp[1] << 8) | temp[0]; 379 data->word = (temp[1] << 8) | temp[0];
322 break; 380 break;
323 381
324 case I2C_SMBUS_BLOCK_DATA: 382 case I2C_SMBUS_BLOCK_DATA:
325 case I2C_SMBUS_BLOCK_PROC_CALL: 383 case I2C_SMBUS_BLOCK_PROC_CALL:
326 amd_ec_read(smbus, AMD_SMB_BCNT, &len); 384 status = amd_ec_read(smbus, AMD_SMB_BCNT, &len);
385 if (status)
386 return status;
327 len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX); 387 len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
328 case I2C_SMBUS_I2C_BLOCK_DATA: 388 case I2C_SMBUS_I2C_BLOCK_DATA:
329 for (i = 0; i < len; i++) 389 for (i = 0; i < len; i++) {
330 amd_ec_read(smbus, AMD_SMB_DATA + i, 390 status = amd_ec_read(smbus, AMD_SMB_DATA + i,
331 data->block + i + 1); 391 data->block + i + 1);
392 if (status)
393 return status;
394 }
332 data->block[0] = len; 395 data->block[0] = len;
333 break; 396 break;
334 } 397 }