summaryrefslogtreecommitdiff
path: root/drivers/block/nvme-core.c
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2014-09-12 16:07:20 -0600
committerJens Axboe <axboe@fb.com>2014-11-04 13:17:09 -0700
commit7963e521811ed19396d47793cc77d87c643ab891 (patch)
tree5587991bb23e2694f627e7ff73b784eda2dd1cc8 /drivers/block/nvme-core.c
parent1b9dbf7fe02d85f70e8efc1c12c070206c0d5c5f (diff)
downloadlwn-7963e521811ed19396d47793cc77d87c643ab891.tar.gz
lwn-7963e521811ed19396d47793cc77d87c643ab891.zip
NVMe: Passthrough IOCTL for IO commands
The NVME_IOCTL_SUBMIT_IO only works for IO commands with block data transfers and isn't usable for other NVMe commands like flush, data set management, or any sort of vendor unique command. The NVME_IOCTL_ADMIN_CMD, however, can easily be modified to accept arbitrary IO commands in addition to arbitrary admin commands without breaking backward compatibility. This patch just adds a new IOCTL to distinguish if the driver should submit the command on an IO or Admin queue. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block/nvme-core.c')
-rw-r--r--drivers/block/nvme-core.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 93ee55ee3775..70be3a151eb7 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -1732,10 +1732,10 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
return status;
}
-static int nvme_user_admin_cmd(struct nvme_dev *dev,
- struct nvme_admin_cmd __user *ucmd)
+static int nvme_user_cmd(struct nvme_dev *dev,
+ struct nvme_passthru_cmd __user *ucmd, bool ioq)
{
- struct nvme_admin_cmd cmd;
+ struct nvme_passthru_cmd cmd;
struct nvme_command c;
int status, length;
struct nvme_iod *uninitialized_var(iod);
@@ -1774,6 +1774,9 @@ static int nvme_user_admin_cmd(struct nvme_dev *dev,
ADMIN_TIMEOUT;
if (length != cmd.data_len)
status = -ENOMEM;
+ else if (ioq)
+ status = nvme_submit_sync_cmd(dev, this_cpu_read(*dev->io_queue), &c,
+ &cmd.result, timeout);
else
status = nvme_submit_sync_cmd(dev, 0, &c, &cmd.result, timeout);
@@ -1799,7 +1802,9 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
force_successful_syscall_return();
return ns->ns_id;
case NVME_IOCTL_ADMIN_CMD:
- return nvme_user_admin_cmd(ns->dev, (void __user *)arg);
+ return nvme_user_cmd(ns->dev, (void __user *)arg, false);
+ case NVME_IOCTL_IO_CMD:
+ return nvme_user_cmd(ns->dev, (void __user *)arg, true);
case NVME_IOCTL_SUBMIT_IO:
return nvme_submit_io(ns, (void __user *)arg);
case SG_GET_VERSION_NUM:
@@ -2743,7 +2748,9 @@ static long nvme_dev_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
struct nvme_dev *dev = f->private_data;
switch (cmd) {
case NVME_IOCTL_ADMIN_CMD:
- return nvme_user_admin_cmd(dev, (void __user *)arg);
+ return nvme_user_cmd(dev, (void __user *)arg, false);
+ case NVME_IOCTL_IO_CMD:
+ return nvme_user_cmd(dev, (void __user *)arg, true);
default:
return -ENOTTY;
}