aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Schaefer <fschaefer.oss@googlemail.com>2013-01-03 12:27:02 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-01-04 22:13:29 -0500
commitf5ae371aca34bd0660a75f8838198466e9d5166c (patch)
tree494eb875735be1d44d1cf369b95c1f9b471b94f0
parent6ea887efadec30ec830ed9466073715b7d339d2b (diff)
[media] em28xx: respect the message size constraints for i2c transfers
The em2800 can transfer up to 4 bytes per i2c message. All other em25xx/em27xx/28xx chips can transfer at least 64 bytes per message. I2C adapters should never split messages transferred via the I2C subsystem into multiple message transfers, because the result will almost always NOT be the same as when the whole data is transferred to the I2C client in a single message. If the message size exceeds the capabilities of the I2C adapter, -EOPNOTSUPP should be returned. 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-i2c.c44
1 files changed, 18 insertions, 26 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index 44533e4574ff..c508c1297a26 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -50,14 +50,18 @@ do { \
50} while (0) 50} while (0)
51 51
52/* 52/*
53 * em2800_i2c_send_max4() 53 * em2800_i2c_send_bytes()
54 * send up to 4 bytes to the i2c device 54 * send up to 4 bytes to the em2800 i2c device
55 */ 55 */
56static int em2800_i2c_send_max4(struct em28xx *dev, u8 addr, u8 *buf, u16 len) 56static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
57{ 57{
58 int ret; 58 int ret;
59 int write_timeout; 59 int write_timeout;
60 u8 b2[6]; 60 u8 b2[6];
61
62 if (len < 1 || len > 4)
63 return -EOPNOTSUPP;
64
61 BUG_ON(len < 1 || len > 4); 65 BUG_ON(len < 1 || len > 4);
62 b2[5] = 0x80 + len - 1; 66 b2[5] = 0x80 + len - 1;
63 b2[4] = addr; 67 b2[4] = addr;
@@ -86,29 +90,6 @@ static int em2800_i2c_send_max4(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
86} 90}
87 91
88/* 92/*
89 * em2800_i2c_send_bytes()
90 */
91static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
92{
93 u8 *bufPtr = buf;
94 int ret;
95 int wrcount = 0;
96 int count;
97 int maxLen = 4;
98 while (len > 0) {
99 count = (len > maxLen) ? maxLen : len;
100 ret = em2800_i2c_send_max4(dev, addr, bufPtr, count);
101 if (ret > 0) {
102 len -= count;
103 bufPtr += count;
104 wrcount += count;
105 } else
106 return (ret < 0) ? ret : -EFAULT;
107 }
108 return wrcount;
109}
110
111/*
112 * em2800_i2c_check_for_device() 93 * em2800_i2c_check_for_device()
113 * check if there is a i2c_device at the supplied address 94 * check if there is a i2c_device at the supplied address
114 */ 95 */
@@ -150,6 +131,10 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
150static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) 131static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
151{ 132{
152 int ret; 133 int ret;
134
135 if (len < 1 || len > 4)
136 return -EOPNOTSUPP;
137
153 /* check for the device and set i2c read address */ 138 /* check for the device and set i2c read address */
154 ret = em2800_i2c_check_for_device(dev, addr); 139 ret = em2800_i2c_check_for_device(dev, addr);
155 if (ret) { 140 if (ret) {
@@ -176,6 +161,9 @@ static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
176 int wrcount = 0; 161 int wrcount = 0;
177 int write_timeout, ret; 162 int write_timeout, ret;
178 163
164 if (len < 1 || len > 64)
165 return -EOPNOTSUPP;
166
179 wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); 167 wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
180 168
181 /* Seems to be required after a write */ 169 /* Seems to be required after a write */
@@ -197,6 +185,10 @@ static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
197static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len) 185static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
198{ 186{
199 int ret; 187 int ret;
188
189 if (len < 1 || len > 64)
190 return -EOPNOTSUPP;
191
200 ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); 192 ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
201 if (ret < 0) { 193 if (ret < 0) {
202 em28xx_warn("reading i2c device failed (error=%i)\n", ret); 194 em28xx_warn("reading i2c device failed (error=%i)\n", ret);