|
@@ -286,8 +286,8 @@ static void sx_close(void *ptr);
|
|
|
static int sx_chars_in_buffer(void *ptr);
|
|
|
static int sx_init_board(struct sx_board *board);
|
|
|
static int sx_init_portstructs(int nboards, int nports);
|
|
|
-static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|
|
- unsigned int cmd, unsigned long arg);
|
|
|
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
|
|
|
+ unsigned long arg);
|
|
|
static int sx_init_drivers(void);
|
|
|
|
|
|
static struct tty_driver *sx_driver;
|
|
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = {
|
|
|
|
|
|
static const struct file_operations sx_fw_fops = {
|
|
|
.owner = THIS_MODULE,
|
|
|
- .ioctl = sx_fw_ioctl,
|
|
|
+ .unlocked_ioctl = sx_fw_ioctl,
|
|
|
};
|
|
|
|
|
|
static struct miscdevice sx_fw_device = {
|
|
@@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|
|
- unsigned int cmd, unsigned long arg)
|
|
|
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
|
|
|
+ unsigned long arg)
|
|
|
{
|
|
|
- int rc = 0;
|
|
|
+ long rc = 0;
|
|
|
int __user *descr = (int __user *)arg;
|
|
|
int i;
|
|
|
static struct sx_board *board = NULL;
|
|
@@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|
|
|
|
|
func_enter();
|
|
|
|
|
|
-#if 0
|
|
|
- /* Removed superuser check: Sysops can use the permissions on the device
|
|
|
- file to restrict access. Recommendation: Root only. (root.root 600) */
|
|
|
- if (!capable(CAP_SYS_ADMIN)) {
|
|
|
+ if (!capable(CAP_SYS_RAWIO))
|
|
|
return -EPERM;
|
|
|
- }
|
|
|
-#endif
|
|
|
+
|
|
|
+ lock_kernel();
|
|
|
|
|
|
sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
|
|
|
|
|
@@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|
|
for (i = 0; i < SX_NBOARDS; i++)
|
|
|
sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
|
|
|
sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
|
|
|
+ unlock_kernel();
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
|
switch (cmd) {
|
|
|
case SXIO_SET_BOARD:
|
|
|
sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
|
|
|
+ rc = -EIO;
|
|
|
if (arg >= SX_NBOARDS)
|
|
|
- return -EIO;
|
|
|
+ break;
|
|
|
sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
|
|
|
if (!(boards[arg].flags & SX_BOARD_PRESENT))
|
|
|
- return -EIO;
|
|
|
+ break;
|
|
|
sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
|
|
|
board = &boards[arg];
|
|
|
+ rc = 0;
|
|
|
+ /* FIXME: And this does ... nothing?? */
|
|
|
break;
|
|
|
case SXIO_GET_TYPE:
|
|
|
rc = -ENOENT; /* If we manage to miss one, return error. */
|
|
@@ -1746,7 +1747,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|
|
rc = SX_TYPE_SI;
|
|
|
if (IS_EISA_BOARD(board))
|
|
|
rc = SX_TYPE_SI;
|
|
|
- sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
|
|
|
+ sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
|
|
|
break;
|
|
|
case SXIO_DO_RAMTEST:
|
|
|
if (sx_initialized) /* Already initialized: better not ramtest the board. */
|
|
@@ -1760,19 +1761,26 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|
|
rc = do_memtest(board, 0, 0x7ff8);
|
|
|
/* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
|
|
|
}
|
|
|
- sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n",
|
|
|
- rc);
|
|
|
+ sx_dprintk(SX_DEBUG_FIRMWARE,
|
|
|
+ "returning memtest result= %ld\n", rc);
|
|
|
break;
|
|
|
case SXIO_DOWNLOAD:
|
|
|
- if (sx_initialized) /* Already initialized */
|
|
|
- return -EEXIST;
|
|
|
- if (!sx_reset(board))
|
|
|
- return -EIO;
|
|
|
+ if (sx_initialized) {/* Already initialized */
|
|
|
+ rc = -EEXIST;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!sx_reset(board)) {
|
|
|
+ rc = -EIO;
|
|
|
+ break;
|
|
|
+ }
|
|
|
sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
|
|
|
|
|
|
tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
|
|
|
- if (!tmp)
|
|
|
- return -ENOMEM;
|
|
|
+ if (!tmp) {
|
|
|
+ rc = -ENOMEM;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ /* FIXME: check returns */
|
|
|
get_user(nbytes, descr++);
|
|
|
get_user(offset, descr++);
|
|
|
get_user(data, descr++);
|
|
@@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|
|
(i + SX_CHUNK_SIZE > nbytes) ?
|
|
|
nbytes - i : SX_CHUNK_SIZE)) {
|
|
|
kfree(tmp);
|
|
|
- return -EFAULT;
|
|
|
+ rc = -EFAULT;
|
|
|
+ break;
|
|
|
}
|
|
|
memcpy_toio(board->base2 + offset + i, tmp,
|
|
|
(i + SX_CHUNK_SIZE > nbytes) ?
|
|
@@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|
|
rc = sx_nports;
|
|
|
break;
|
|
|
case SXIO_INIT:
|
|
|
- if (sx_initialized) /* Already initialized */
|
|
|
- return -EEXIST;
|
|
|
+ if (sx_initialized) { /* Already initialized */
|
|
|
+ rc = -EEXIST;
|
|
|
+ break;
|
|
|
+ }
|
|
|
/* This is not allowed until all boards are initialized... */
|
|
|
for (i = 0; i < SX_NBOARDS; i++) {
|
|
|
if ((boards[i].flags & SX_BOARD_PRESENT) &&
|
|
|
- !(boards[i].flags & SX_BOARD_INITIALIZED))
|
|
|
- return -EIO;
|
|
|
+ !(boards[i].flags & SX_BOARD_INITIALIZED)) {
|
|
|
+ rc = -EIO;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
for (i = 0; i < SX_NBOARDS; i++)
|
|
|
if (!(boards[i].flags & SX_BOARD_PRESENT))
|
|
@@ -1832,10 +1845,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|
|
rc = sx_nports;
|
|
|
break;
|
|
|
default:
|
|
|
- printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n",
|
|
|
- cmd);
|
|
|
+ rc = -ENOTTY;
|
|
|
break;
|
|
|
}
|
|
|
+ unlock_kernel();
|
|
|
func_exit();
|
|
|
return rc;
|
|
|
}
|