diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-09-20 01:02:27 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-09-20 01:02:27 -0400 |
commit | 7d5cb45655f2e9e37ef75d18f50c0072ef14a38b (patch) | |
tree | 7d9c9c588704dc338b8dbdd2482bd99df0558d2c | |
parent | abca5fc535a3ee0f36fb6d4468a453eaae769921 (diff) |
i2c compat ioctls: move to ->compat_ioctl()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | drivers/i2c/i2c-dev.c | 268 | ||||
-rw-r--r-- | fs/compat_ioctl.c | 122 |
2 files changed, 180 insertions, 210 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 6f638bbc922d..2cab27a68479 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/notifier.h> | 35 | #include <linux/notifier.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <linux/compat.h> | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a | 41 | * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a |
@@ -238,46 +239,29 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) | |||
238 | } | 239 | } |
239 | 240 | ||
240 | static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, | 241 | static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, |
241 | unsigned long arg) | 242 | unsigned nmsgs, struct i2c_msg *msgs) |
242 | { | 243 | { |
243 | struct i2c_rdwr_ioctl_data rdwr_arg; | ||
244 | struct i2c_msg *rdwr_pa; | ||
245 | u8 __user **data_ptrs; | 244 | u8 __user **data_ptrs; |
246 | int i, res; | 245 | int i, res; |
247 | 246 | ||
248 | if (copy_from_user(&rdwr_arg, | 247 | data_ptrs = kmalloc(nmsgs * sizeof(u8 __user *), GFP_KERNEL); |
249 | (struct i2c_rdwr_ioctl_data __user *)arg, | ||
250 | sizeof(rdwr_arg))) | ||
251 | return -EFAULT; | ||
252 | |||
253 | /* Put an arbitrary limit on the number of messages that can | ||
254 | * be sent at once */ | ||
255 | if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) | ||
256 | return -EINVAL; | ||
257 | |||
258 | rdwr_pa = memdup_user(rdwr_arg.msgs, | ||
259 | rdwr_arg.nmsgs * sizeof(struct i2c_msg)); | ||
260 | if (IS_ERR(rdwr_pa)) | ||
261 | return PTR_ERR(rdwr_pa); | ||
262 | |||
263 | data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); | ||
264 | if (data_ptrs == NULL) { | 248 | if (data_ptrs == NULL) { |
265 | kfree(rdwr_pa); | 249 | kfree(msgs); |
266 | return -ENOMEM; | 250 | return -ENOMEM; |
267 | } | 251 | } |
268 | 252 | ||
269 | res = 0; | 253 | res = 0; |
270 | for (i = 0; i < rdwr_arg.nmsgs; i++) { | 254 | for (i = 0; i < nmsgs; i++) { |
271 | /* Limit the size of the message to a sane amount */ | 255 | /* Limit the size of the message to a sane amount */ |
272 | if (rdwr_pa[i].len > 8192) { | 256 | if (msgs[i].len > 8192) { |
273 | res = -EINVAL; | 257 | res = -EINVAL; |
274 | break; | 258 | break; |
275 | } | 259 | } |
276 | 260 | ||
277 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; | 261 | data_ptrs[i] = (u8 __user *)msgs[i].buf; |
278 | rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); | 262 | msgs[i].buf = memdup_user(data_ptrs[i], msgs[i].len); |
279 | if (IS_ERR(rdwr_pa[i].buf)) { | 263 | if (IS_ERR(msgs[i].buf)) { |
280 | res = PTR_ERR(rdwr_pa[i].buf); | 264 | res = PTR_ERR(msgs[i].buf); |
281 | break; | 265 | break; |
282 | } | 266 | } |
283 | 267 | ||
@@ -292,121 +276,117 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, | |||
292 | * greater (for example to account for a checksum byte at | 276 | * greater (for example to account for a checksum byte at |
293 | * the end of the message.) | 277 | * the end of the message.) |
294 | */ | 278 | */ |
295 | if (rdwr_pa[i].flags & I2C_M_RECV_LEN) { | 279 | if (msgs[i].flags & I2C_M_RECV_LEN) { |
296 | if (!(rdwr_pa[i].flags & I2C_M_RD) || | 280 | if (!(msgs[i].flags & I2C_M_RD) || |
297 | rdwr_pa[i].buf[0] < 1 || | 281 | msgs[i].buf[0] < 1 || |
298 | rdwr_pa[i].len < rdwr_pa[i].buf[0] + | 282 | msgs[i].len < msgs[i].buf[0] + |
299 | I2C_SMBUS_BLOCK_MAX) { | 283 | I2C_SMBUS_BLOCK_MAX) { |
300 | res = -EINVAL; | 284 | res = -EINVAL; |
301 | break; | 285 | break; |
302 | } | 286 | } |
303 | 287 | ||
304 | rdwr_pa[i].len = rdwr_pa[i].buf[0]; | 288 | msgs[i].len = msgs[i].buf[0]; |
305 | } | 289 | } |
306 | } | 290 | } |
307 | if (res < 0) { | 291 | if (res < 0) { |
308 | int j; | 292 | int j; |
309 | for (j = 0; j < i; ++j) | 293 | for (j = 0; j < i; ++j) |
310 | kfree(rdwr_pa[j].buf); | 294 | kfree(msgs[j].buf); |
311 | kfree(data_ptrs); | 295 | kfree(data_ptrs); |
312 | kfree(rdwr_pa); | 296 | kfree(msgs); |
313 | return res; | 297 | return res; |
314 | } | 298 | } |
315 | 299 | ||
316 | res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs); | 300 | res = i2c_transfer(client->adapter, msgs, nmsgs); |
317 | while (i-- > 0) { | 301 | while (i-- > 0) { |
318 | if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) { | 302 | if (res >= 0 && (msgs[i].flags & I2C_M_RD)) { |
319 | if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, | 303 | if (copy_to_user(data_ptrs[i], msgs[i].buf, |
320 | rdwr_pa[i].len)) | 304 | msgs[i].len)) |
321 | res = -EFAULT; | 305 | res = -EFAULT; |
322 | } | 306 | } |
323 | kfree(rdwr_pa[i].buf); | 307 | kfree(msgs[i].buf); |
324 | } | 308 | } |
325 | kfree(data_ptrs); | 309 | kfree(data_ptrs); |
326 | kfree(rdwr_pa); | 310 | kfree(msgs); |
327 | return res; | 311 | return res; |
328 | } | 312 | } |
329 | 313 | ||
330 | static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, | 314 | static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, |
331 | unsigned long arg) | 315 | u8 read_write, u8 command, u32 size, |
316 | union i2c_smbus_data __user *data) | ||
332 | { | 317 | { |
333 | struct i2c_smbus_ioctl_data data_arg; | ||
334 | union i2c_smbus_data temp = {}; | 318 | union i2c_smbus_data temp = {}; |
335 | int datasize, res; | 319 | int datasize, res; |
336 | 320 | ||
337 | if (copy_from_user(&data_arg, | 321 | if ((size != I2C_SMBUS_BYTE) && |
338 | (struct i2c_smbus_ioctl_data __user *) arg, | 322 | (size != I2C_SMBUS_QUICK) && |
339 | sizeof(struct i2c_smbus_ioctl_data))) | 323 | (size != I2C_SMBUS_BYTE_DATA) && |
340 | return -EFAULT; | 324 | (size != I2C_SMBUS_WORD_DATA) && |
341 | if ((data_arg.size != I2C_SMBUS_BYTE) && | 325 | (size != I2C_SMBUS_PROC_CALL) && |
342 | (data_arg.size != I2C_SMBUS_QUICK) && | 326 | (size != I2C_SMBUS_BLOCK_DATA) && |
343 | (data_arg.size != I2C_SMBUS_BYTE_DATA) && | 327 | (size != I2C_SMBUS_I2C_BLOCK_BROKEN) && |
344 | (data_arg.size != I2C_SMBUS_WORD_DATA) && | 328 | (size != I2C_SMBUS_I2C_BLOCK_DATA) && |
345 | (data_arg.size != I2C_SMBUS_PROC_CALL) && | 329 | (size != I2C_SMBUS_BLOCK_PROC_CALL)) { |
346 | (data_arg.size != I2C_SMBUS_BLOCK_DATA) && | ||
347 | (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) && | ||
348 | (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) && | ||
349 | (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) { | ||
350 | dev_dbg(&client->adapter->dev, | 330 | dev_dbg(&client->adapter->dev, |
351 | "size out of range (%x) in ioctl I2C_SMBUS.\n", | 331 | "size out of range (%x) in ioctl I2C_SMBUS.\n", |
352 | data_arg.size); | 332 | size); |
353 | return -EINVAL; | 333 | return -EINVAL; |
354 | } | 334 | } |
355 | /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, | 335 | /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, |
356 | so the check is valid if size==I2C_SMBUS_QUICK too. */ | 336 | so the check is valid if size==I2C_SMBUS_QUICK too. */ |
357 | if ((data_arg.read_write != I2C_SMBUS_READ) && | 337 | if ((read_write != I2C_SMBUS_READ) && |
358 | (data_arg.read_write != I2C_SMBUS_WRITE)) { | 338 | (read_write != I2C_SMBUS_WRITE)) { |
359 | dev_dbg(&client->adapter->dev, | 339 | dev_dbg(&client->adapter->dev, |
360 | "read_write out of range (%x) in ioctl I2C_SMBUS.\n", | 340 | "read_write out of range (%x) in ioctl I2C_SMBUS.\n", |
361 | data_arg.read_write); | 341 | read_write); |
362 | return -EINVAL; | 342 | return -EINVAL; |
363 | } | 343 | } |
364 | 344 | ||
365 | /* Note that command values are always valid! */ | 345 | /* Note that command values are always valid! */ |
366 | 346 | ||
367 | if ((data_arg.size == I2C_SMBUS_QUICK) || | 347 | if ((size == I2C_SMBUS_QUICK) || |
368 | ((data_arg.size == I2C_SMBUS_BYTE) && | 348 | ((size == I2C_SMBUS_BYTE) && |
369 | (data_arg.read_write == I2C_SMBUS_WRITE))) | 349 | (read_write == I2C_SMBUS_WRITE))) |
370 | /* These are special: we do not use data */ | 350 | /* These are special: we do not use data */ |
371 | return i2c_smbus_xfer(client->adapter, client->addr, | 351 | return i2c_smbus_xfer(client->adapter, client->addr, |
372 | client->flags, data_arg.read_write, | 352 | client->flags, read_write, |
373 | data_arg.command, data_arg.size, NULL); | 353 | command, size, NULL); |
374 | 354 | ||
375 | if (data_arg.data == NULL) { | 355 | if (data == NULL) { |
376 | dev_dbg(&client->adapter->dev, | 356 | dev_dbg(&client->adapter->dev, |
377 | "data is NULL pointer in ioctl I2C_SMBUS.\n"); | 357 | "data is NULL pointer in ioctl I2C_SMBUS.\n"); |
378 | return -EINVAL; | 358 | return -EINVAL; |
379 | } | 359 | } |
380 | 360 | ||
381 | if ((data_arg.size == I2C_SMBUS_BYTE_DATA) || | 361 | if ((size == I2C_SMBUS_BYTE_DATA) || |
382 | (data_arg.size == I2C_SMBUS_BYTE)) | 362 | (size == I2C_SMBUS_BYTE)) |
383 | datasize = sizeof(data_arg.data->byte); | 363 | datasize = sizeof(data->byte); |
384 | else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || | 364 | else if ((size == I2C_SMBUS_WORD_DATA) || |
385 | (data_arg.size == I2C_SMBUS_PROC_CALL)) | 365 | (size == I2C_SMBUS_PROC_CALL)) |
386 | datasize = sizeof(data_arg.data->word); | 366 | datasize = sizeof(data->word); |
387 | else /* size == smbus block, i2c block, or block proc. call */ | 367 | else /* size == smbus block, i2c block, or block proc. call */ |
388 | datasize = sizeof(data_arg.data->block); | 368 | datasize = sizeof(data->block); |
389 | 369 | ||
390 | if ((data_arg.size == I2C_SMBUS_PROC_CALL) || | 370 | if ((size == I2C_SMBUS_PROC_CALL) || |
391 | (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || | 371 | (size == I2C_SMBUS_BLOCK_PROC_CALL) || |
392 | (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) || | 372 | (size == I2C_SMBUS_I2C_BLOCK_DATA) || |
393 | (data_arg.read_write == I2C_SMBUS_WRITE)) { | 373 | (read_write == I2C_SMBUS_WRITE)) { |
394 | if (copy_from_user(&temp, data_arg.data, datasize)) | 374 | if (copy_from_user(&temp, data, datasize)) |
395 | return -EFAULT; | 375 | return -EFAULT; |
396 | } | 376 | } |
397 | if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) { | 377 | if (size == I2C_SMBUS_I2C_BLOCK_BROKEN) { |
398 | /* Convert old I2C block commands to the new | 378 | /* Convert old I2C block commands to the new |
399 | convention. This preserves binary compatibility. */ | 379 | convention. This preserves binary compatibility. */ |
400 | data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA; | 380 | size = I2C_SMBUS_I2C_BLOCK_DATA; |
401 | if (data_arg.read_write == I2C_SMBUS_READ) | 381 | if (read_write == I2C_SMBUS_READ) |
402 | temp.block[0] = I2C_SMBUS_BLOCK_MAX; | 382 | temp.block[0] = I2C_SMBUS_BLOCK_MAX; |
403 | } | 383 | } |
404 | res = i2c_smbus_xfer(client->adapter, client->addr, client->flags, | 384 | res = i2c_smbus_xfer(client->adapter, client->addr, client->flags, |
405 | data_arg.read_write, data_arg.command, data_arg.size, &temp); | 385 | read_write, command, size, &temp); |
406 | if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || | 386 | if (!res && ((size == I2C_SMBUS_PROC_CALL) || |
407 | (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || | 387 | (size == I2C_SMBUS_BLOCK_PROC_CALL) || |
408 | (data_arg.read_write == I2C_SMBUS_READ))) { | 388 | (read_write == I2C_SMBUS_READ))) { |
409 | if (copy_to_user(data_arg.data, &temp, datasize)) | 389 | if (copy_to_user(data, &temp, datasize)) |
410 | return -EFAULT; | 390 | return -EFAULT; |
411 | } | 391 | } |
412 | return res; | 392 | return res; |
@@ -454,12 +434,39 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
454 | funcs = i2c_get_functionality(client->adapter); | 434 | funcs = i2c_get_functionality(client->adapter); |
455 | return put_user(funcs, (unsigned long __user *)arg); | 435 | return put_user(funcs, (unsigned long __user *)arg); |
456 | 436 | ||
457 | case I2C_RDWR: | 437 | case I2C_RDWR: { |
458 | return i2cdev_ioctl_rdwr(client, arg); | 438 | struct i2c_rdwr_ioctl_data rdwr_arg; |
439 | struct i2c_msg *rdwr_pa; | ||
440 | |||
441 | if (copy_from_user(&rdwr_arg, | ||
442 | (struct i2c_rdwr_ioctl_data __user *)arg, | ||
443 | sizeof(rdwr_arg))) | ||
444 | return -EFAULT; | ||
445 | |||
446 | /* Put an arbitrary limit on the number of messages that can | ||
447 | * be sent at once */ | ||
448 | if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) | ||
449 | return -EINVAL; | ||
459 | 450 | ||
460 | case I2C_SMBUS: | 451 | rdwr_pa = memdup_user(rdwr_arg.msgs, |
461 | return i2cdev_ioctl_smbus(client, arg); | 452 | rdwr_arg.nmsgs * sizeof(struct i2c_msg)); |
453 | if (IS_ERR(rdwr_pa)) | ||
454 | return PTR_ERR(rdwr_pa); | ||
455 | |||
456 | return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); | ||
457 | } | ||
462 | 458 | ||
459 | case I2C_SMBUS: { | ||
460 | struct i2c_smbus_ioctl_data data_arg; | ||
461 | if (copy_from_user(&data_arg, | ||
462 | (struct i2c_smbus_ioctl_data __user *) arg, | ||
463 | sizeof(struct i2c_smbus_ioctl_data))) | ||
464 | return -EFAULT; | ||
465 | return i2cdev_ioctl_smbus(client, data_arg.read_write, | ||
466 | data_arg.command, | ||
467 | data_arg.size, | ||
468 | data_arg.data); | ||
469 | } | ||
463 | case I2C_RETRIES: | 470 | case I2C_RETRIES: |
464 | client->adapter->retries = arg; | 471 | client->adapter->retries = arg; |
465 | break; | 472 | break; |
@@ -480,6 +487,90 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
480 | return 0; | 487 | return 0; |
481 | } | 488 | } |
482 | 489 | ||
490 | #ifdef CONFIG_COMPAT | ||
491 | |||
492 | struct i2c_smbus_ioctl_data32 { | ||
493 | u8 read_write; | ||
494 | u8 command; | ||
495 | u32 size; | ||
496 | compat_caddr_t data; /* union i2c_smbus_data *data */ | ||
497 | }; | ||
498 | |||
499 | struct i2c_msg32 { | ||
500 | u16 addr; | ||
501 | u16 flags; | ||
502 | u16 len; | ||
503 | compat_caddr_t buf; | ||
504 | }; | ||
505 | |||
506 | struct i2c_rdwr_ioctl_data32 { | ||
507 | compat_caddr_t msgs; /* struct i2c_msg __user *msgs */ | ||
508 | u32 nmsgs; | ||
509 | }; | ||
510 | |||
511 | static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
512 | { | ||
513 | struct i2c_client *client = file->private_data; | ||
514 | unsigned long funcs; | ||
515 | switch (cmd) { | ||
516 | case I2C_FUNCS: | ||
517 | funcs = i2c_get_functionality(client->adapter); | ||
518 | return put_user(funcs, (compat_ulong_t __user *)arg); | ||
519 | case I2C_RDWR: { | ||
520 | struct i2c_rdwr_ioctl_data32 rdwr_arg; | ||
521 | struct i2c_msg32 *p; | ||
522 | struct i2c_msg *rdwr_pa; | ||
523 | int i; | ||
524 | |||
525 | if (copy_from_user(&rdwr_arg, | ||
526 | (struct i2c_rdwr_ioctl_data32 __user *)arg, | ||
527 | sizeof(rdwr_arg))) | ||
528 | return -EFAULT; | ||
529 | |||
530 | if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) | ||
531 | return -EINVAL; | ||
532 | |||
533 | rdwr_pa = kmalloc_array(rdwr_arg.nmsgs, sizeof(struct i2c_msg), | ||
534 | GFP_KERNEL); | ||
535 | if (!rdwr_pa) | ||
536 | return -ENOMEM; | ||
537 | |||
538 | p = compat_ptr(rdwr_arg.msgs); | ||
539 | for (i = 0; i < rdwr_arg.nmsgs; i++) { | ||
540 | struct i2c_msg32 umsg; | ||
541 | if (copy_from_user(&umsg, p + i, sizeof(umsg))) { | ||
542 | kfree(rdwr_pa); | ||
543 | return -EFAULT; | ||
544 | } | ||
545 | rdwr_pa[i] = (struct i2c_msg) { | ||
546 | .addr = umsg.addr, | ||
547 | .flags = umsg.flags, | ||
548 | .len = umsg.len, | ||
549 | .buf = compat_ptr(umsg.buf) | ||
550 | }; | ||
551 | } | ||
552 | |||
553 | return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); | ||
554 | } | ||
555 | case I2C_SMBUS: { | ||
556 | struct i2c_smbus_ioctl_data32 data32; | ||
557 | if (copy_from_user(&data32, | ||
558 | (void __user *) arg, | ||
559 | sizeof(data32))) | ||
560 | return -EFAULT; | ||
561 | return i2cdev_ioctl_smbus(client, data32.read_write, | ||
562 | data32.command, | ||
563 | data32.size, | ||
564 | compat_ptr(data32.data)); | ||
565 | } | ||
566 | default: | ||
567 | return i2cdev_ioctl(file, cmd, arg); | ||
568 | } | ||
569 | } | ||
570 | #else | ||
571 | #define compat_i2cdev_ioctl NULL | ||
572 | #endif | ||
573 | |||
483 | static int i2cdev_open(struct inode *inode, struct file *file) | 574 | static int i2cdev_open(struct inode *inode, struct file *file) |
484 | { | 575 | { |
485 | unsigned int minor = iminor(inode); | 576 | unsigned int minor = iminor(inode); |
@@ -527,6 +618,7 @@ static const struct file_operations i2cdev_fops = { | |||
527 | .read = i2cdev_read, | 618 | .read = i2cdev_read, |
528 | .write = i2cdev_write, | 619 | .write = i2cdev_write, |
529 | .unlocked_ioctl = i2cdev_ioctl, | 620 | .unlocked_ioctl = i2cdev_ioctl, |
621 | .compat_ioctl = compat_i2cdev_ioctl, | ||
530 | .open = i2cdev_open, | 622 | .open = i2cdev_open, |
531 | .release = i2cdev_release, | 623 | .release = i2cdev_release, |
532 | }; | 624 | }; |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index d27b326d96f4..a545deeeaff5 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -53,8 +53,6 @@ | |||
53 | #include <linux/if_tun.h> | 53 | #include <linux/if_tun.h> |
54 | #include <linux/ctype.h> | 54 | #include <linux/ctype.h> |
55 | #include <linux/syscalls.h> | 55 | #include <linux/syscalls.h> |
56 | #include <linux/i2c.h> | ||
57 | #include <linux/i2c-dev.h> | ||
58 | #include <linux/atalk.h> | 56 | #include <linux/atalk.h> |
59 | #include <linux/gfp.h> | 57 | #include <linux/gfp.h> |
60 | #include <linux/cec.h> | 58 | #include <linux/cec.h> |
@@ -136,22 +134,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
136 | return vfs_ioctl(file, cmd, arg); | 134 | return vfs_ioctl(file, cmd, arg); |
137 | } | 135 | } |
138 | 136 | ||
139 | static int w_long(struct file *file, | ||
140 | unsigned int cmd, compat_ulong_t __user *argp) | ||
141 | { | ||
142 | int err; | ||
143 | unsigned long __user *valp = compat_alloc_user_space(sizeof(*valp)); | ||
144 | |||
145 | if (valp == NULL) | ||
146 | return -EFAULT; | ||
147 | err = do_ioctl(file, cmd, (unsigned long)valp); | ||
148 | if (err) | ||
149 | return err; | ||
150 | if (convert_in_user(valp, argp)) | ||
151 | return -EFAULT; | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | struct compat_video_event { | 137 | struct compat_video_event { |
156 | int32_t type; | 138 | int32_t type; |
157 | compat_time_t timestamp; | 139 | compat_time_t timestamp; |
@@ -670,96 +652,6 @@ static int serial_struct_ioctl(struct file *file, | |||
670 | return err; | 652 | return err; |
671 | } | 653 | } |
672 | 654 | ||
673 | /* | ||
674 | * I2C layer ioctls | ||
675 | */ | ||
676 | |||
677 | struct i2c_msg32 { | ||
678 | u16 addr; | ||
679 | u16 flags; | ||
680 | u16 len; | ||
681 | compat_caddr_t buf; | ||
682 | }; | ||
683 | |||
684 | struct i2c_rdwr_ioctl_data32 { | ||
685 | compat_caddr_t msgs; /* struct i2c_msg __user *msgs */ | ||
686 | u32 nmsgs; | ||
687 | }; | ||
688 | |||
689 | struct i2c_smbus_ioctl_data32 { | ||
690 | u8 read_write; | ||
691 | u8 command; | ||
692 | u32 size; | ||
693 | compat_caddr_t data; /* union i2c_smbus_data *data */ | ||
694 | }; | ||
695 | |||
696 | struct i2c_rdwr_aligned { | ||
697 | struct i2c_rdwr_ioctl_data cmd; | ||
698 | struct i2c_msg msgs[0]; | ||
699 | }; | ||
700 | |||
701 | static int do_i2c_rdwr_ioctl(struct file *file, | ||
702 | unsigned int cmd, struct i2c_rdwr_ioctl_data32 __user *udata) | ||
703 | { | ||
704 | struct i2c_rdwr_aligned __user *tdata; | ||
705 | struct i2c_msg __user *tmsgs; | ||
706 | struct i2c_msg32 __user *umsgs; | ||
707 | compat_caddr_t datap; | ||
708 | u32 nmsgs; | ||
709 | int i; | ||
710 | |||
711 | if (get_user(nmsgs, &udata->nmsgs)) | ||
712 | return -EFAULT; | ||
713 | if (nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) | ||
714 | return -EINVAL; | ||
715 | |||
716 | if (get_user(datap, &udata->msgs)) | ||
717 | return -EFAULT; | ||
718 | umsgs = compat_ptr(datap); | ||
719 | |||
720 | tdata = compat_alloc_user_space(sizeof(*tdata) + | ||
721 | nmsgs * sizeof(struct i2c_msg)); | ||
722 | tmsgs = &tdata->msgs[0]; | ||
723 | |||
724 | if (put_user(nmsgs, &tdata->cmd.nmsgs) || | ||
725 | put_user(tmsgs, &tdata->cmd.msgs)) | ||
726 | return -EFAULT; | ||
727 | |||
728 | for (i = 0; i < nmsgs; i++) { | ||
729 | if (copy_in_user(&tmsgs[i].addr, &umsgs[i].addr, 3*sizeof(u16))) | ||
730 | return -EFAULT; | ||
731 | if (get_user(datap, &umsgs[i].buf) || | ||
732 | put_user(compat_ptr(datap), &tmsgs[i].buf)) | ||
733 | return -EFAULT; | ||
734 | } | ||
735 | return do_ioctl(file, cmd, (unsigned long)tdata); | ||
736 | } | ||
737 | |||
738 | static int do_i2c_smbus_ioctl(struct file *file, | ||
739 | unsigned int cmd, struct i2c_smbus_ioctl_data32 __user *udata) | ||
740 | { | ||
741 | struct i2c_smbus_ioctl_data __user *tdata; | ||
742 | union { | ||
743 | /* beginnings of those have identical layouts */ | ||
744 | struct i2c_smbus_ioctl_data32 data32; | ||
745 | struct i2c_smbus_ioctl_data data; | ||
746 | } v; | ||
747 | |||
748 | tdata = compat_alloc_user_space(sizeof(*tdata)); | ||
749 | if (tdata == NULL) | ||
750 | return -ENOMEM; | ||
751 | |||
752 | memset(&v, 0, sizeof(v)); | ||
753 | if (copy_from_user(&v.data32, udata, sizeof(v.data32))) | ||
754 | return -EFAULT; | ||
755 | v.data.data = compat_ptr(v.data32.data); | ||
756 | |||
757 | if (copy_to_user(tdata, &v.data, sizeof(v.data))) | ||
758 | return -EFAULT; | ||
759 | |||
760 | return do_ioctl(file, cmd, (unsigned long)tdata); | ||
761 | } | ||
762 | |||
763 | #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) | 655 | #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) |
764 | #define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) | 656 | #define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) |
765 | #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) | 657 | #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) |
@@ -1282,13 +1174,6 @@ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) | |||
1282 | COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) | 1174 | COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) |
1283 | COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) | 1175 | COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) |
1284 | COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) | 1176 | COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) |
1285 | /* i2c */ | ||
1286 | COMPATIBLE_IOCTL(I2C_SLAVE) | ||
1287 | COMPATIBLE_IOCTL(I2C_SLAVE_FORCE) | ||
1288 | COMPATIBLE_IOCTL(I2C_TENBIT) | ||
1289 | COMPATIBLE_IOCTL(I2C_PEC) | ||
1290 | COMPATIBLE_IOCTL(I2C_RETRIES) | ||
1291 | COMPATIBLE_IOCTL(I2C_TIMEOUT) | ||
1292 | /* hiddev */ | 1177 | /* hiddev */ |
1293 | COMPATIBLE_IOCTL(HIDIOCGVERSION) | 1178 | COMPATIBLE_IOCTL(HIDIOCGVERSION) |
1294 | COMPATIBLE_IOCTL(HIDIOCAPPLICATION) | 1179 | COMPATIBLE_IOCTL(HIDIOCAPPLICATION) |
@@ -1463,13 +1348,6 @@ static long do_ioctl_trans(unsigned int cmd, | |||
1463 | case TIOCGSERIAL: | 1348 | case TIOCGSERIAL: |
1464 | case TIOCSSERIAL: | 1349 | case TIOCSSERIAL: |
1465 | return serial_struct_ioctl(file, cmd, argp); | 1350 | return serial_struct_ioctl(file, cmd, argp); |
1466 | /* i2c */ | ||
1467 | case I2C_FUNCS: | ||
1468 | return w_long(file, cmd, argp); | ||
1469 | case I2C_RDWR: | ||
1470 | return do_i2c_rdwr_ioctl(file, cmd, argp); | ||
1471 | case I2C_SMBUS: | ||
1472 | return do_i2c_smbus_ioctl(file, cmd, argp); | ||
1473 | /* Not implemented in the native kernel */ | 1351 | /* Not implemented in the native kernel */ |
1474 | case RTC_IRQP_READ32: | 1352 | case RTC_IRQP_READ32: |
1475 | case RTC_IRQP_SET32: | 1353 | case RTC_IRQP_SET32: |