aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-dev.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-12 13:06:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-12 13:06:29 -0400
commit1c00650c233c404fadf9347329214d55283bd17a (patch)
tree9de7cda2fe2e54411cc24ff3befd758c9cb9cd74 /drivers/i2c/i2c-dev.c
parent26df0766a73a859bb93dc58e747c5028557a23fd (diff)
parent7f528135da9704d67db1f727162024b078e1cd8f (diff)
Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: i2c: I2C bus multiplexer driver pca954x i2c: Multiplexed I2C bus core support i2c: Use a separate mutex for userspace client lists i2c: Make i2c_default_probe self-sufficient i2c: Drop dummy variable i2c: Move adapter locking helpers to i2c-core V4L/DVB: Use custom I2C probing function mechanism i2c: Add support for custom probe function i2c-dev: Use memdup_user i2c-dev: Remove unnecessary kmalloc casts
Diffstat (limited to 'drivers/i2c/i2c-dev.c')
-rw-r--r--drivers/i2c/i2c-dev.c66
1 files changed, 46 insertions, 20 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index e0694e4d86c7..5f3a52d517c3 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -167,13 +167,9 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf,
167 if (count > 8192) 167 if (count > 8192)
168 count = 8192; 168 count = 8192;
169 169
170 tmp = kmalloc(count, GFP_KERNEL); 170 tmp = memdup_user(buf, count);
171 if (tmp == NULL) 171 if (IS_ERR(tmp))
172 return -ENOMEM; 172 return PTR_ERR(tmp);
173 if (copy_from_user(tmp, buf, count)) {
174 kfree(tmp);
175 return -EFAULT;
176 }
177 173
178 pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n", 174 pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n",
179 iminor(file->f_path.dentry->d_inode), count); 175 iminor(file->f_path.dentry->d_inode), count);
@@ -193,12 +189,50 @@ static int i2cdev_check(struct device *dev, void *addrp)
193 return dev->driver ? -EBUSY : 0; 189 return dev->driver ? -EBUSY : 0;
194} 190}
195 191
192/* walk up mux tree */
193static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr)
194{
195 int result;
196
197 result = device_for_each_child(&adapter->dev, &addr, i2cdev_check);
198
199 if (!result && i2c_parent_is_i2c_adapter(adapter))
200 result = i2cdev_check_mux_parents(
201 to_i2c_adapter(adapter->dev.parent), addr);
202
203 return result;
204}
205
206/* recurse down mux tree */
207static int i2cdev_check_mux_children(struct device *dev, void *addrp)
208{
209 int result;
210
211 if (dev->type == &i2c_adapter_type)
212 result = device_for_each_child(dev, addrp,
213 i2cdev_check_mux_children);
214 else
215 result = i2cdev_check(dev, addrp);
216
217 return result;
218}
219
196/* This address checking function differs from the one in i2c-core 220/* This address checking function differs from the one in i2c-core
197 in that it considers an address with a registered device, but no 221 in that it considers an address with a registered device, but no
198 driver bound to it, as NOT busy. */ 222 driver bound to it, as NOT busy. */
199static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) 223static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
200{ 224{
201 return device_for_each_child(&adapter->dev, &addr, i2cdev_check); 225 int result = 0;
226
227 if (i2c_parent_is_i2c_adapter(adapter))
228 result = i2cdev_check_mux_parents(
229 to_i2c_adapter(adapter->dev.parent), addr);
230
231 if (!result)
232 result = device_for_each_child(&adapter->dev, &addr,
233 i2cdev_check_mux_children);
234
235 return result;
202} 236}
203 237
204static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, 238static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
@@ -219,9 +253,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
219 if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) 253 if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
220 return -EINVAL; 254 return -EINVAL;
221 255
222 rdwr_pa = (struct i2c_msg *) 256 rdwr_pa = kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL);
223 kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
224 GFP_KERNEL);
225 if (!rdwr_pa) 257 if (!rdwr_pa)
226 return -ENOMEM; 258 return -ENOMEM;
227 259
@@ -247,15 +279,9 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
247 break; 279 break;
248 } 280 }
249 data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; 281 data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
250 rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL); 282 rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len);
251 if (rdwr_pa[i].buf == NULL) { 283 if (IS_ERR(rdwr_pa[i].buf)) {
252 res = -ENOMEM; 284 res = PTR_ERR(rdwr_pa[i].buf);
253 break;
254 }
255 if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i],
256 rdwr_pa[i].len)) {
257 ++i; /* Needs to be kfreed too */
258 res = -EFAULT;
259 break; 285 break;
260 } 286 }
261 } 287 }