aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Schaefer <fschaefer.oss@googlemail.com>2013-01-03 12:27:05 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-01-04 22:18:25 -0500
commit45f04e82d035006afe5023850393e9b3b74b85c2 (patch)
tree2679cd0361ad64a61f08c58820ada06c59a10a53
parenteaf33c404cd60ba4b442324766abbb5da8c94381 (diff)
[media] em28xx: fix+improve+unify i2c error handling, debug messages and code comments
- do not pass USB specific error codes to userspace/i2c-subsystem - unify the returned error codes and make them compliant with the i2c subsystem spec - check number of actually transferred bytes (via USB) everywehere - fix/improve debug messages - improve code comments Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/usb/em28xx/em28xx-core.c5
-rw-r--r--drivers/media/usb/em28xx/em28xx-i2c.c116
2 files changed, 89 insertions, 32 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
index 6916e87bc624..80f87bbbd554 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
+++ b/drivers/media/usb/em28xx/em28xx-core.c
@@ -101,7 +101,7 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
101 if (reg_debug) 101 if (reg_debug)
102 printk(" failed!\n"); 102 printk(" failed!\n");
103 mutex_unlock(&dev->ctrl_urb_lock); 103 mutex_unlock(&dev->ctrl_urb_lock);
104 return ret; 104 return usb_translate_errors(ret);
105 } 105 }
106 106
107 if (len) 107 if (len)
@@ -182,6 +182,9 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
182 0x0000, reg, dev->urb_buf, len, HZ); 182 0x0000, reg, dev->urb_buf, len, HZ);
183 mutex_unlock(&dev->ctrl_urb_lock); 183 mutex_unlock(&dev->ctrl_urb_lock);
184 184
185 if (ret < 0)
186 return usb_translate_errors(ret);
187
185 if (dev->wait_after_write) 188 if (dev->wait_after_write)
186 msleep(dev->wait_after_write); 189 msleep(dev->wait_after_write);
187 190
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index 4a24ed08e46a..f784b516ae1c 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -76,18 +76,26 @@ static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
76 /* trigger write */ 76 /* trigger write */
77 ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); 77 ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
78 if (ret != 2 + len) { 78 if (ret != 2 + len) {
79 em28xx_warn("writing to i2c device failed (error=%i)\n", ret); 79 em28xx_warn("failed to trigger write to i2c address 0x%x "
80 return -EIO; 80 "(error=%i)\n", addr, ret);
81 return (ret < 0) ? ret : -EIO;
81 } 82 }
82 /* wait for completion */ 83 /* wait for completion */
83 for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0; 84 for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0;
84 write_timeout -= 5) { 85 write_timeout -= 5) {
85 ret = dev->em28xx_read_reg(dev, 0x05); 86 ret = dev->em28xx_read_reg(dev, 0x05);
86 if (ret == 0x80 + len - 1) 87 if (ret == 0x80 + len - 1) {
87 return len; 88 return len;
89 } else if (ret == 0x94 + len - 1) {
90 return -ENODEV;
91 } else if (ret < 0) {
92 em28xx_warn("failed to get i2c transfer status from "
93 "bridge register (error=%i)\n", ret);
94 return ret;
95 }
88 msleep(5); 96 msleep(5);
89 } 97 }
90 em28xx_warn("i2c write timed out\n"); 98 em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
91 return -EIO; 99 return -EIO;
92} 100}
93 101
@@ -168,24 +176,48 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
168static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, 176static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
169 u16 len, int stop) 177 u16 len, int stop)
170{ 178{
171 int wrcount = 0;
172 int write_timeout, ret; 179 int write_timeout, ret;
173 180
174 if (len < 1 || len > 64) 181 if (len < 1 || len > 64)
175 return -EOPNOTSUPP; 182 return -EOPNOTSUPP;
183 /* NOTE: limited by the USB ctrl message constraints
184 * Zero length reads always succeed, even if no device is connected */
176 185
177 wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); 186 /* Write to i2c device */
187 ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
188 if (ret != len) {
189 if (ret < 0) {
190 em28xx_warn("writing to i2c device at 0x%x failed "
191 "(error=%i)\n", addr, ret);
192 return ret;
193 } else {
194 em28xx_warn("%i bytes write to i2c device at 0x%x "
195 "requested, but %i bytes written\n",
196 len, addr, ret);
197 return -EIO;
198 }
199 }
178 200
179 /* Seems to be required after a write */ 201 /* Check success of the i2c operation */
180 for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0; 202 for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0;
181 write_timeout -= 5) { 203 write_timeout -= 5) {
182 ret = dev->em28xx_read_reg(dev, 0x05); 204 ret = dev->em28xx_read_reg(dev, 0x05);
183 if (!ret) 205 if (ret == 0) { /* success */
184 break; 206 return len;
207 } else if (ret == 0x10) {
208 return -ENODEV;
209 } else if (ret < 0) {
210 em28xx_warn("failed to read i2c transfer status from "
211 "bridge (error=%i)\n", ret);
212 return ret;
213 }
185 msleep(5); 214 msleep(5);
215 /* NOTE: do we really have to wait for success ?
216 Never seen anything else than 0x00 or 0x10
217 (even with high payload) ... */
186 } 218 }
187 219 em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
188 return wrcount; 220 return -EIO;
189} 221}
190 222
191/* 223/*
@@ -198,15 +230,40 @@ static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
198 230
199 if (len < 1 || len > 64) 231 if (len < 1 || len > 64)
200 return -EOPNOTSUPP; 232 return -EOPNOTSUPP;
233 /* NOTE: limited by the USB ctrl message constraints
234 * Zero length reads always succeed, even if no device is connected */
201 235
236 /* Read data from i2c device */
202 ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); 237 ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
238 if (ret != len) {
239 if (ret < 0) {
240 em28xx_warn("reading from i2c device at 0x%x failed "
241 "(error=%i)\n", addr, ret);
242 return ret;
243 } else {
244 em28xx_warn("%i bytes requested from i2c device at "
245 "0x%x, but %i bytes received\n",
246 len, addr, ret);
247 return -EIO;
248 }
249 }
250
251 /* Check success of the i2c operation */
252 ret = dev->em28xx_read_reg(dev, 0x05);
203 if (ret < 0) { 253 if (ret < 0) {
204 em28xx_warn("reading i2c device failed (error=%i)\n", ret); 254 em28xx_warn("failed to read i2c transfer status from "
255 "bridge (error=%i)\n", ret);
205 return ret; 256 return ret;
206 } 257 }
207 if (dev->em28xx_read_reg(dev, 0x5) != 0) 258 if (ret > 0) {
208 return -ENODEV; 259 if (ret == 0x10) {
209 return ret; 260 return -ENODEV;
261 } else {
262 em28xx_warn("unknown i2c error (status=%i)\n", ret);
263 return -EIO;
264 }
265 }
266 return len;
210} 267}
211 268
212/* 269/*
@@ -216,15 +273,12 @@ static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
216static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr) 273static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
217{ 274{
218 int ret; 275 int ret;
276 u8 buf;
219 277
220 ret = dev->em28xx_read_reg_req(dev, 2, addr); 278 ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1);
221 if (ret < 0) { 279 if (ret == 1)
222 em28xx_warn("reading from i2c device failed (error=%i)\n", ret); 280 return 0;
223 return ret; 281 return (ret < 0) ? ret : -EIO;
224 }
225 if (dev->em28xx_read_reg(dev, 0x5) != 0)
226 return -ENODEV;
227 return 0;
228} 282}
229 283
230/* 284/*
@@ -249,11 +303,11 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
249 rc = em2800_i2c_check_for_device(dev, addr); 303 rc = em2800_i2c_check_for_device(dev, addr);
250 else 304 else
251 rc = em28xx_i2c_check_for_device(dev, addr); 305 rc = em28xx_i2c_check_for_device(dev, addr);
252 if (rc < 0) { 306 if (rc == -ENODEV) {
253 dprintk2(2, " no device\n"); 307 if (i2c_debug >= 2)
308 printk(" no device\n");
254 return rc; 309 return rc;
255 } 310 }
256
257 } else if (msgs[i].flags & I2C_M_RD) { 311 } else if (msgs[i].flags & I2C_M_RD) {
258 /* read bytes */ 312 /* read bytes */
259 if (dev->board.is_em2800) 313 if (dev->board.is_em2800)
@@ -284,16 +338,16 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
284 msgs[i].len, 338 msgs[i].len,
285 i == num - 1); 339 i == num - 1);
286 } 340 }
287 if (rc < 0) 341 if (rc < 0) {
288 goto err; 342 if (i2c_debug >= 2)
343 printk(" ERROR: %i\n", rc);
344 return rc;
345 }
289 if (i2c_debug >= 2) 346 if (i2c_debug >= 2)
290 printk("\n"); 347 printk("\n");
291 } 348 }
292 349
293 return num; 350 return num;
294err:
295 dprintk2(2, " ERROR: %i\n", rc);
296 return rc;
297} 351}
298 352
299/* based on linux/sunrpc/svcauth.h and linux/hash.h 353/* based on linux/sunrpc/svcauth.h and linux/hash.h