in devices/rio_mport_cdev.c [961:1006]
static int rio_mport_transfer_ioctl(struct file *filp, void __user *arg)
{
struct mport_cdev_priv *priv = filp->private_data;
struct rio_transaction transaction;
struct rio_transfer_io *transfer;
enum dma_data_direction dir;
int i, ret = 0;
size_t size;
if (unlikely(copy_from_user(&transaction, arg, sizeof(transaction))))
return -EFAULT;
if (transaction.count != 1) /* only single transfer for now */
return -EINVAL;
if ((transaction.transfer_mode &
priv->md->properties.transfer_mode) == 0)
return -ENODEV;
size = array_size(sizeof(*transfer), transaction.count);
transfer = vmalloc(size);
if (!transfer)
return -ENOMEM;
if (unlikely(copy_from_user(transfer,
(void __user *)(uintptr_t)transaction.block,
size))) {
ret = -EFAULT;
goto out_free;
}
dir = (transaction.dir == RIO_TRANSFER_DIR_READ) ?
DMA_FROM_DEVICE : DMA_TO_DEVICE;
for (i = 0; i < transaction.count && ret == 0; i++)
ret = rio_dma_transfer(filp, transaction.transfer_mode,
transaction.sync, dir, &transfer[i]);
if (unlikely(copy_to_user((void __user *)(uintptr_t)transaction.block,
transfer, size)))
ret = -EFAULT;
out_free:
vfree(transfer);
return ret;
}