in genwqe/card_dev.c [1052:1227]
static long genwqe_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
int rc = 0;
struct genwqe_file *cfile = (struct genwqe_file *)filp->private_data;
struct genwqe_dev *cd = cfile->cd;
struct pci_dev *pci_dev = cd->pci_dev;
struct genwqe_reg_io __user *io;
u64 val;
u32 reg_offs;
/* Return -EIO if card hit EEH */
if (pci_channel_offline(pci_dev))
return -EIO;
if (_IOC_TYPE(cmd) != GENWQE_IOC_CODE)
return -EINVAL;
switch (cmd) {
case GENWQE_GET_CARD_STATE:
put_user(cd->card_state, (enum genwqe_card_state __user *)arg);
return 0;
/* Register access */
case GENWQE_READ_REG64: {
io = (struct genwqe_reg_io __user *)arg;
if (get_user(reg_offs, &io->num))
return -EFAULT;
if ((reg_offs >= cd->mmio_len) || (reg_offs & 0x7))
return -EINVAL;
val = __genwqe_readq(cd, reg_offs);
put_user(val, &io->val64);
return 0;
}
case GENWQE_WRITE_REG64: {
io = (struct genwqe_reg_io __user *)arg;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if ((filp->f_flags & O_ACCMODE) == O_RDONLY)
return -EPERM;
if (get_user(reg_offs, &io->num))
return -EFAULT;
if ((reg_offs >= cd->mmio_len) || (reg_offs & 0x7))
return -EINVAL;
if (get_user(val, &io->val64))
return -EFAULT;
__genwqe_writeq(cd, reg_offs, val);
return 0;
}
case GENWQE_READ_REG32: {
io = (struct genwqe_reg_io __user *)arg;
if (get_user(reg_offs, &io->num))
return -EFAULT;
if ((reg_offs >= cd->mmio_len) || (reg_offs & 0x3))
return -EINVAL;
val = __genwqe_readl(cd, reg_offs);
put_user(val, &io->val64);
return 0;
}
case GENWQE_WRITE_REG32: {
io = (struct genwqe_reg_io __user *)arg;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if ((filp->f_flags & O_ACCMODE) == O_RDONLY)
return -EPERM;
if (get_user(reg_offs, &io->num))
return -EFAULT;
if ((reg_offs >= cd->mmio_len) || (reg_offs & 0x3))
return -EINVAL;
if (get_user(val, &io->val64))
return -EFAULT;
__genwqe_writel(cd, reg_offs, val);
return 0;
}
/* Flash update/reading */
case GENWQE_SLU_UPDATE: {
struct genwqe_bitstream load;
if (!genwqe_is_privileged(cd))
return -EPERM;
if ((filp->f_flags & O_ACCMODE) == O_RDONLY)
return -EPERM;
if (copy_from_user(&load, (void __user *)arg,
sizeof(load)))
return -EFAULT;
rc = do_flash_update(cfile, &load);
if (copy_to_user((void __user *)arg, &load, sizeof(load)))
return -EFAULT;
return rc;
}
case GENWQE_SLU_READ: {
struct genwqe_bitstream load;
if (!genwqe_is_privileged(cd))
return -EPERM;
if (genwqe_flash_readback_fails(cd))
return -ENOSPC; /* known to fail for old versions */
if (copy_from_user(&load, (void __user *)arg, sizeof(load)))
return -EFAULT;
rc = do_flash_read(cfile, &load);
if (copy_to_user((void __user *)arg, &load, sizeof(load)))
return -EFAULT;
return rc;
}
/* memory pinning and unpinning */
case GENWQE_PIN_MEM: {
struct genwqe_mem m;
if (copy_from_user(&m, (void __user *)arg, sizeof(m)))
return -EFAULT;
return genwqe_pin_mem(cfile, &m);
}
case GENWQE_UNPIN_MEM: {
struct genwqe_mem m;
if (copy_from_user(&m, (void __user *)arg, sizeof(m)))
return -EFAULT;
return genwqe_unpin_mem(cfile, &m);
}
/* launch an DDCB and wait for completion */
case GENWQE_EXECUTE_DDCB:
return do_execute_ddcb(cfile, arg, 0);
case GENWQE_EXECUTE_RAW_DDCB: {
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
return do_execute_ddcb(cfile, arg, 1);
}
default:
return -EINVAL;
}
return rc;
}