Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
7d5cb456
Commit
7d5cb456
authored
Sep 20, 2017
by
Al Viro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
i2c compat ioctls: move to ->compat_ioctl()
Signed-off-by:
Al Viro
<
viro@zeniv.linux.org.uk
>
parent
abca5fc5
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
180 additions
and
210 deletions
+180
-210
drivers/i2c/i2c-dev.c
drivers/i2c/i2c-dev.c
+180
-88
fs/compat_ioctl.c
fs/compat_ioctl.c
+0
-122
No files found.
drivers/i2c/i2c-dev.c
View file @
7d5cb456
...
...
@@ -35,6 +35,7 @@
#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/compat.h>
/*
* 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)
}
static
noinline
int
i2cdev_ioctl_rdwr
(
struct
i2c_client
*
client
,
unsigned
long
arg
)
unsigned
nmsgs
,
struct
i2c_msg
*
msgs
)
{
struct
i2c_rdwr_ioctl_data
rdwr_arg
;
struct
i2c_msg
*
rdwr_pa
;
u8
__user
**
data_ptrs
;
int
i
,
res
;
if
(
copy_from_user
(
&
rdwr_arg
,
(
struct
i2c_rdwr_ioctl_data
__user
*
)
arg
,
sizeof
(
rdwr_arg
)))
return
-
EFAULT
;
/* Put an arbitrary limit on the number of messages that can
* be sent at once */
if
(
rdwr_arg
.
nmsgs
>
I2C_RDWR_IOCTL_MAX_MSGS
)
return
-
EINVAL
;
rdwr_pa
=
memdup_user
(
rdwr_arg
.
msgs
,
rdwr_arg
.
nmsgs
*
sizeof
(
struct
i2c_msg
));
if
(
IS_ERR
(
rdwr_pa
))
return
PTR_ERR
(
rdwr_pa
);
data_ptrs
=
kmalloc
(
rdwr_arg
.
nmsgs
*
sizeof
(
u8
__user
*
),
GFP_KERNEL
);
data_ptrs
=
kmalloc
(
nmsgs
*
sizeof
(
u8
__user
*
),
GFP_KERNEL
);
if
(
data_ptrs
==
NULL
)
{
kfree
(
rdwr_pa
);
kfree
(
msgs
);
return
-
ENOMEM
;
}
res
=
0
;
for
(
i
=
0
;
i
<
rdwr_arg
.
nmsgs
;
i
++
)
{
for
(
i
=
0
;
i
<
nmsgs
;
i
++
)
{
/* Limit the size of the message to a sane amount */
if
(
rdwr_pa
[
i
].
len
>
8192
)
{
if
(
msgs
[
i
].
len
>
8192
)
{
res
=
-
EINVAL
;
break
;
}
data_ptrs
[
i
]
=
(
u8
__user
*
)
rdwr_pa
[
i
].
buf
;
rdwr_pa
[
i
].
buf
=
memdup_user
(
data_ptrs
[
i
],
rdwr_pa
[
i
].
len
);
if
(
IS_ERR
(
rdwr_pa
[
i
].
buf
))
{
res
=
PTR_ERR
(
rdwr_pa
[
i
].
buf
);
data_ptrs
[
i
]
=
(
u8
__user
*
)
msgs
[
i
].
buf
;
msgs
[
i
].
buf
=
memdup_user
(
data_ptrs
[
i
],
msgs
[
i
].
len
);
if
(
IS_ERR
(
msgs
[
i
].
buf
))
{
res
=
PTR_ERR
(
msgs
[
i
].
buf
);
break
;
}
...
...
@@ -292,121 +276,117 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
* greater (for example to account for a checksum byte at
* the end of the message.)
*/
if
(
rdwr_pa
[
i
].
flags
&
I2C_M_RECV_LEN
)
{
if
(
!
(
rdwr_pa
[
i
].
flags
&
I2C_M_RD
)
||
rdwr_pa
[
i
].
buf
[
0
]
<
1
||
rdwr_pa
[
i
].
len
<
rdwr_pa
[
i
].
buf
[
0
]
+
if
(
msgs
[
i
].
flags
&
I2C_M_RECV_LEN
)
{
if
(
!
(
msgs
[
i
].
flags
&
I2C_M_RD
)
||
msgs
[
i
].
buf
[
0
]
<
1
||
msgs
[
i
].
len
<
msgs
[
i
].
buf
[
0
]
+
I2C_SMBUS_BLOCK_MAX
)
{
res
=
-
EINVAL
;
break
;
}
rdwr_pa
[
i
].
len
=
rdwr_pa
[
i
].
buf
[
0
];
msgs
[
i
].
len
=
msgs
[
i
].
buf
[
0
];
}
}
if
(
res
<
0
)
{
int
j
;
for
(
j
=
0
;
j
<
i
;
++
j
)
kfree
(
rdwr_pa
[
j
].
buf
);
kfree
(
msgs
[
j
].
buf
);
kfree
(
data_ptrs
);
kfree
(
rdwr_pa
);
kfree
(
msgs
);
return
res
;
}
res
=
i2c_transfer
(
client
->
adapter
,
rdwr_pa
,
rdwr_arg
.
nmsgs
);
res
=
i2c_transfer
(
client
->
adapter
,
msgs
,
nmsgs
);
while
(
i
--
>
0
)
{
if
(
res
>=
0
&&
(
rdwr_pa
[
i
].
flags
&
I2C_M_RD
))
{
if
(
copy_to_user
(
data_ptrs
[
i
],
rdwr_pa
[
i
].
buf
,
rdwr_pa
[
i
].
len
))
if
(
res
>=
0
&&
(
msgs
[
i
].
flags
&
I2C_M_RD
))
{
if
(
copy_to_user
(
data_ptrs
[
i
],
msgs
[
i
].
buf
,
msgs
[
i
].
len
))
res
=
-
EFAULT
;
}
kfree
(
rdwr_pa
[
i
].
buf
);
kfree
(
msgs
[
i
].
buf
);
}
kfree
(
data_ptrs
);
kfree
(
rdwr_pa
);
kfree
(
msgs
);
return
res
;
}
static
noinline
int
i2cdev_ioctl_smbus
(
struct
i2c_client
*
client
,
unsigned
long
arg
)
u8
read_write
,
u8
command
,
u32
size
,
union
i2c_smbus_data
__user
*
data
)
{
struct
i2c_smbus_ioctl_data
data_arg
;
union
i2c_smbus_data
temp
=
{};
int
datasize
,
res
;
if
(
copy_from_user
(
&
data_arg
,
(
struct
i2c_smbus_ioctl_data
__user
*
)
arg
,
sizeof
(
struct
i2c_smbus_ioctl_data
)))
return
-
EFAULT
;
if
((
data_arg
.
size
!=
I2C_SMBUS_BYTE
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_QUICK
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_BYTE_DATA
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_WORD_DATA
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_PROC_CALL
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_BLOCK_DATA
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_I2C_BLOCK_BROKEN
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_I2C_BLOCK_DATA
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_BLOCK_PROC_CALL
))
{
if
((
size
!=
I2C_SMBUS_BYTE
)
&&
(
size
!=
I2C_SMBUS_QUICK
)
&&
(
size
!=
I2C_SMBUS_BYTE_DATA
)
&&
(
size
!=
I2C_SMBUS_WORD_DATA
)
&&
(
size
!=
I2C_SMBUS_PROC_CALL
)
&&
(
size
!=
I2C_SMBUS_BLOCK_DATA
)
&&
(
size
!=
I2C_SMBUS_I2C_BLOCK_BROKEN
)
&&
(
size
!=
I2C_SMBUS_I2C_BLOCK_DATA
)
&&
(
size
!=
I2C_SMBUS_BLOCK_PROC_CALL
))
{
dev_dbg
(
&
client
->
adapter
->
dev
,
"size out of range (%x) in ioctl I2C_SMBUS.
\n
"
,
data_arg
.
size
);
size
);
return
-
EINVAL
;
}
/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
so the check is valid if size==I2C_SMBUS_QUICK too. */
if
((
data_arg
.
read_write
!=
I2C_SMBUS_READ
)
&&
(
data_arg
.
read_write
!=
I2C_SMBUS_WRITE
))
{
if
((
read_write
!=
I2C_SMBUS_READ
)
&&
(
read_write
!=
I2C_SMBUS_WRITE
))
{
dev_dbg
(
&
client
->
adapter
->
dev
,
"read_write out of range (%x) in ioctl I2C_SMBUS.
\n
"
,
data_arg
.
read_write
);
read_write
);
return
-
EINVAL
;
}
/* Note that command values are always valid! */
if
((
data_arg
.
size
==
I2C_SMBUS_QUICK
)
||
((
data_arg
.
size
==
I2C_SMBUS_BYTE
)
&&
(
data_arg
.
read_write
==
I2C_SMBUS_WRITE
)))
if
((
size
==
I2C_SMBUS_QUICK
)
||
((
size
==
I2C_SMBUS_BYTE
)
&&
(
read_write
==
I2C_SMBUS_WRITE
)))
/* These are special: we do not use data */
return
i2c_smbus_xfer
(
client
->
adapter
,
client
->
addr
,
client
->
flags
,
data_arg
.
read_write
,
data_arg
.
command
,
data_arg
.
size
,
NULL
);
client
->
flags
,
read_write
,
command
,
size
,
NULL
);
if
(
data
_arg
.
data
==
NULL
)
{
if
(
data
==
NULL
)
{
dev_dbg
(
&
client
->
adapter
->
dev
,
"data is NULL pointer in ioctl I2C_SMBUS.
\n
"
);
return
-
EINVAL
;
}
if
((
data_arg
.
size
==
I2C_SMBUS_BYTE_DATA
)
||
(
data_arg
.
size
==
I2C_SMBUS_BYTE
))
datasize
=
sizeof
(
data
_arg
.
data
->
byte
);
else
if
((
data_arg
.
size
==
I2C_SMBUS_WORD_DATA
)
||
(
data_arg
.
size
==
I2C_SMBUS_PROC_CALL
))
datasize
=
sizeof
(
data
_arg
.
data
->
word
);
if
((
size
==
I2C_SMBUS_BYTE_DATA
)
||
(
size
==
I2C_SMBUS_BYTE
))
datasize
=
sizeof
(
data
->
byte
);
else
if
((
size
==
I2C_SMBUS_WORD_DATA
)
||
(
size
==
I2C_SMBUS_PROC_CALL
))
datasize
=
sizeof
(
data
->
word
);
else
/* size == smbus block, i2c block, or block proc. call */
datasize
=
sizeof
(
data
_arg
.
data
->
block
);
datasize
=
sizeof
(
data
->
block
);
if
((
data_arg
.
size
==
I2C_SMBUS_PROC_CALL
)
||
(
data_arg
.
size
==
I2C_SMBUS_BLOCK_PROC_CALL
)
||
(
data_arg
.
size
==
I2C_SMBUS_I2C_BLOCK_DATA
)
||
(
data_arg
.
read_write
==
I2C_SMBUS_WRITE
))
{
if
(
copy_from_user
(
&
temp
,
data
_arg
.
data
,
datasize
))
if
((
size
==
I2C_SMBUS_PROC_CALL
)
||
(
size
==
I2C_SMBUS_BLOCK_PROC_CALL
)
||
(
size
==
I2C_SMBUS_I2C_BLOCK_DATA
)
||
(
read_write
==
I2C_SMBUS_WRITE
))
{
if
(
copy_from_user
(
&
temp
,
data
,
datasize
))
return
-
EFAULT
;
}
if
(
data_arg
.
size
==
I2C_SMBUS_I2C_BLOCK_BROKEN
)
{
if
(
size
==
I2C_SMBUS_I2C_BLOCK_BROKEN
)
{
/* Convert old I2C block commands to the new
convention. This preserves binary compatibility. */
data_arg
.
size
=
I2C_SMBUS_I2C_BLOCK_DATA
;
if
(
data_arg
.
read_write
==
I2C_SMBUS_READ
)
size
=
I2C_SMBUS_I2C_BLOCK_DATA
;
if
(
read_write
==
I2C_SMBUS_READ
)
temp
.
block
[
0
]
=
I2C_SMBUS_BLOCK_MAX
;
}
res
=
i2c_smbus_xfer
(
client
->
adapter
,
client
->
addr
,
client
->
flags
,
data_arg
.
read_write
,
data_arg
.
command
,
data_arg
.
size
,
&
temp
);
if
(
!
res
&&
((
data_arg
.
size
==
I2C_SMBUS_PROC_CALL
)
||
(
data_arg
.
size
==
I2C_SMBUS_BLOCK_PROC_CALL
)
||
(
data_arg
.
read_write
==
I2C_SMBUS_READ
)))
{
if
(
copy_to_user
(
data
_arg
.
data
,
&
temp
,
datasize
))
read_write
,
command
,
size
,
&
temp
);
if
(
!
res
&&
((
size
==
I2C_SMBUS_PROC_CALL
)
||
(
size
==
I2C_SMBUS_BLOCK_PROC_CALL
)
||
(
read_write
==
I2C_SMBUS_READ
)))
{
if
(
copy_to_user
(
data
,
&
temp
,
datasize
))
return
-
EFAULT
;
}
return
res
;
...
...
@@ -454,12 +434,39 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
funcs
=
i2c_get_functionality
(
client
->
adapter
);
return
put_user
(
funcs
,
(
unsigned
long
__user
*
)
arg
);
case
I2C_RDWR
:
return
i2cdev_ioctl_rdwr
(
client
,
arg
);
case
I2C_RDWR
:
{
struct
i2c_rdwr_ioctl_data
rdwr_arg
;
struct
i2c_msg
*
rdwr_pa
;
if
(
copy_from_user
(
&
rdwr_arg
,
(
struct
i2c_rdwr_ioctl_data
__user
*
)
arg
,
sizeof
(
rdwr_arg
)))
return
-
EFAULT
;
/* Put an arbitrary limit on the number of messages that can
* be sent at once */
if
(
rdwr_arg
.
nmsgs
>
I2C_RDWR_IOCTL_MAX_MSGS
)
return
-
EINVAL
;
case
I2C_SMBUS
:
return
i2cdev_ioctl_smbus
(
client
,
arg
);
rdwr_pa
=
memdup_user
(
rdwr_arg
.
msgs
,
rdwr_arg
.
nmsgs
*
sizeof
(
struct
i2c_msg
));
if
(
IS_ERR
(
rdwr_pa
))
return
PTR_ERR
(
rdwr_pa
);
return
i2cdev_ioctl_rdwr
(
client
,
rdwr_arg
.
nmsgs
,
rdwr_pa
);
}
case
I2C_SMBUS
:
{
struct
i2c_smbus_ioctl_data
data_arg
;
if
(
copy_from_user
(
&
data_arg
,
(
struct
i2c_smbus_ioctl_data
__user
*
)
arg
,
sizeof
(
struct
i2c_smbus_ioctl_data
)))
return
-
EFAULT
;
return
i2cdev_ioctl_smbus
(
client
,
data_arg
.
read_write
,
data_arg
.
command
,
data_arg
.
size
,
data_arg
.
data
);
}
case
I2C_RETRIES
:
client
->
adapter
->
retries
=
arg
;
break
;
...
...
@@ -480,6 +487,90 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return
0
;
}
#ifdef CONFIG_COMPAT
struct
i2c_smbus_ioctl_data32
{
u8
read_write
;
u8
command
;
u32
size
;
compat_caddr_t
data
;
/* union i2c_smbus_data *data */
};
struct
i2c_msg32
{
u16
addr
;
u16
flags
;
u16
len
;
compat_caddr_t
buf
;
};
struct
i2c_rdwr_ioctl_data32
{
compat_caddr_t
msgs
;
/* struct i2c_msg __user *msgs */
u32
nmsgs
;
};
static
long
compat_i2cdev_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
i2c_client
*
client
=
file
->
private_data
;
unsigned
long
funcs
;
switch
(
cmd
)
{
case
I2C_FUNCS
:
funcs
=
i2c_get_functionality
(
client
->
adapter
);
return
put_user
(
funcs
,
(
compat_ulong_t
__user
*
)
arg
);
case
I2C_RDWR
:
{
struct
i2c_rdwr_ioctl_data32
rdwr_arg
;
struct
i2c_msg32
*
p
;
struct
i2c_msg
*
rdwr_pa
;
int
i
;
if
(
copy_from_user
(
&
rdwr_arg
,
(
struct
i2c_rdwr_ioctl_data32
__user
*
)
arg
,
sizeof
(
rdwr_arg
)))
return
-
EFAULT
;
if
(
rdwr_arg
.
nmsgs
>
I2C_RDWR_IOCTL_MAX_MSGS
)
return
-
EINVAL
;
rdwr_pa
=
kmalloc_array
(
rdwr_arg
.
nmsgs
,
sizeof
(
struct
i2c_msg
),
GFP_KERNEL
);
if
(
!
rdwr_pa
)
return
-
ENOMEM
;
p
=
compat_ptr
(
rdwr_arg
.
msgs
);
for
(
i
=
0
;
i
<
rdwr_arg
.
nmsgs
;
i
++
)
{
struct
i2c_msg32
umsg
;
if
(
copy_from_user
(
&
umsg
,
p
+
i
,
sizeof
(
umsg
)))
{
kfree
(
rdwr_pa
);
return
-
EFAULT
;
}
rdwr_pa
[
i
]
=
(
struct
i2c_msg
)
{
.
addr
=
umsg
.
addr
,
.
flags
=
umsg
.
flags
,
.
len
=
umsg
.
len
,
.
buf
=
compat_ptr
(
umsg
.
buf
)
};
}
return
i2cdev_ioctl_rdwr
(
client
,
rdwr_arg
.
nmsgs
,
rdwr_pa
);
}
case
I2C_SMBUS
:
{
struct
i2c_smbus_ioctl_data32
data32
;
if
(
copy_from_user
(
&
data32
,
(
void
__user
*
)
arg
,
sizeof
(
data32
)))
return
-
EFAULT
;
return
i2cdev_ioctl_smbus
(
client
,
data32
.
read_write
,
data32
.
command
,
data32
.
size
,
compat_ptr
(
data32
.
data
));
}
default:
return
i2cdev_ioctl
(
file
,
cmd
,
arg
);
}
}
#else
#define compat_i2cdev_ioctl NULL
#endif
static
int
i2cdev_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
unsigned
int
minor
=
iminor
(
inode
);
...
...
@@ -527,6 +618,7 @@ static const struct file_operations i2cdev_fops = {
.
read
=
i2cdev_read
,
.
write
=
i2cdev_write
,
.
unlocked_ioctl
=
i2cdev_ioctl
,
.
compat_ioctl
=
compat_i2cdev_ioctl
,
.
open
=
i2cdev_open
,
.
release
=
i2cdev_release
,
};
...
...
fs/compat_ioctl.c
View file @
7d5cb456
...
...
@@ -53,8 +53,6 @@
#include <linux/if_tun.h>
#include <linux/ctype.h>
#include <linux/syscalls.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/atalk.h>
#include <linux/gfp.h>
#include <linux/cec.h>
...
...
@@ -136,22 +134,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return
vfs_ioctl
(
file
,
cmd
,
arg
);
}
static
int
w_long
(
struct
file
*
file
,
unsigned
int
cmd
,
compat_ulong_t
__user
*
argp
)
{
int
err
;
unsigned
long
__user
*
valp
=
compat_alloc_user_space
(
sizeof
(
*
valp
));
if
(
valp
==
NULL
)
return
-
EFAULT
;
err
=
do_ioctl
(
file
,
cmd
,
(
unsigned
long
)
valp
);
if
(
err
)
return
err
;
if
(
convert_in_user
(
valp
,
argp
))
return
-
EFAULT
;
return
0
;
}
struct
compat_video_event
{
int32_t
type
;
compat_time_t
timestamp
;
...
...
@@ -670,96 +652,6 @@ static int serial_struct_ioctl(struct file *file,
return
err
;
}
/*
* I2C layer ioctls
*/
struct
i2c_msg32
{
u16
addr
;
u16
flags
;
u16
len
;
compat_caddr_t
buf
;
};
struct
i2c_rdwr_ioctl_data32
{
compat_caddr_t
msgs
;
/* struct i2c_msg __user *msgs */
u32
nmsgs
;
};
struct
i2c_smbus_ioctl_data32
{
u8
read_write
;
u8
command
;
u32
size
;
compat_caddr_t
data
;
/* union i2c_smbus_data *data */
};
struct
i2c_rdwr_aligned
{
struct
i2c_rdwr_ioctl_data
cmd
;
struct
i2c_msg
msgs
[
0
];
};
static
int
do_i2c_rdwr_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
struct
i2c_rdwr_ioctl_data32
__user
*
udata
)
{
struct
i2c_rdwr_aligned
__user
*
tdata
;
struct
i2c_msg
__user
*
tmsgs
;
struct
i2c_msg32
__user
*
umsgs
;
compat_caddr_t
datap
;
u32
nmsgs
;
int
i
;
if
(
get_user
(
nmsgs
,
&
udata
->
nmsgs
))
return
-
EFAULT
;
if
(
nmsgs
>
I2C_RDWR_IOCTL_MAX_MSGS
)
return
-
EINVAL
;
if
(
get_user
(
datap
,
&
udata
->
msgs
))
return
-
EFAULT
;
umsgs
=
compat_ptr
(
datap
);
tdata
=
compat_alloc_user_space
(
sizeof
(
*
tdata
)
+
nmsgs
*
sizeof
(
struct
i2c_msg
));
tmsgs
=
&
tdata
->
msgs
[
0
];
if
(
put_user
(
nmsgs
,
&
tdata
->
cmd
.
nmsgs
)
||
put_user
(
tmsgs
,
&
tdata
->
cmd
.
msgs
))
return
-
EFAULT
;
for
(
i
=
0
;
i
<
nmsgs
;
i
++
)
{
if
(
copy_in_user
(
&
tmsgs
[
i
].
addr
,
&
umsgs
[
i
].
addr
,
3
*
sizeof
(
u16
)))
return
-
EFAULT
;
if
(
get_user
(
datap
,
&
umsgs
[
i
].
buf
)
||
put_user
(
compat_ptr
(
datap
),
&
tmsgs
[
i
].
buf
))
return
-
EFAULT
;
}
return
do_ioctl
(
file
,
cmd
,
(
unsigned
long
)
tdata
);
}
static
int
do_i2c_smbus_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
struct
i2c_smbus_ioctl_data32
__user
*
udata
)
{
struct
i2c_smbus_ioctl_data
__user
*
tdata
;
union
{
/* beginnings of those have identical layouts */
struct
i2c_smbus_ioctl_data32
data32
;
struct
i2c_smbus_ioctl_data
data
;
}
v
;
tdata
=
compat_alloc_user_space
(
sizeof
(
*
tdata
));
if
(
tdata
==
NULL
)
return
-
ENOMEM
;
memset
(
&
v
,
0
,
sizeof
(
v
));
if
(
copy_from_user
(
&
v
.
data32
,
udata
,
sizeof
(
v
.
data32
)))
return
-
EFAULT
;
v
.
data
.
data
=
compat_ptr
(
v
.
data32
.
data
);
if
(
copy_to_user
(
tdata
,
&
v
.
data
,
sizeof
(
v
.
data
)))
return
-
EFAULT
;
return
do_ioctl
(
file
,
cmd
,
(
unsigned
long
)
tdata
);
}
#define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t)
#define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t)
#define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t)
...
...
@@ -1282,13 +1174,6 @@ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER)
COMPATIBLE_IOCTL
(
PCIIOC_MMAP_IS_IO
)
COMPATIBLE_IOCTL
(
PCIIOC_MMAP_IS_MEM
)
COMPATIBLE_IOCTL
(
PCIIOC_WRITE_COMBINE
)
/* i2c */
COMPATIBLE_IOCTL
(
I2C_SLAVE
)
COMPATIBLE_IOCTL
(
I2C_SLAVE_FORCE
)
COMPATIBLE_IOCTL
(
I2C_TENBIT
)
COMPATIBLE_IOCTL
(
I2C_PEC
)
COMPATIBLE_IOCTL
(
I2C_RETRIES
)
COMPATIBLE_IOCTL
(
I2C_TIMEOUT
)
/* hiddev */
COMPATIBLE_IOCTL
(
HIDIOCGVERSION
)
COMPATIBLE_IOCTL
(
HIDIOCAPPLICATION
)
...
...
@@ -1463,13 +1348,6 @@ static long do_ioctl_trans(unsigned int cmd,
case
TIOCGSERIAL
:
case
TIOCSSERIAL
:
return
serial_struct_ioctl
(
file
,
cmd
,
argp
);
/* i2c */
case
I2C_FUNCS
:
return
w_long
(
file
,
cmd
,
argp
);
case
I2C_RDWR
:
return
do_i2c_rdwr_ioctl
(
file
,
cmd
,
argp
);
case
I2C_SMBUS
:
return
do_i2c_smbus_ioctl
(
file
,
cmd
,
argp
);
/* Not implemented in the native kernel */
case
RTC_IRQP_READ32
:
case
RTC_IRQP_SET32
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment