aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/nvme.c
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew.r.wilcox@intel.com>2011-02-01 16:13:29 -0500
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2011-11-04 15:52:53 -0400
commita53295b6998f62d961c29e54051c1cf1d738c2b3 (patch)
tree835a6f4ecbb8de47c232d7a1c5b4f76292d4dc24 /drivers/block/nvme.c
parent7fc3cdabba75c2516b8b645eb0ca7907aea70415 (diff)
NVMe: Add NVME_IOCTL_SUBMIT_IO
Allow userspace to submit synchronous I/O like the SCSI sg interface does. Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Diffstat (limited to 'drivers/block/nvme.c')
-rw-r--r--drivers/block/nvme.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c
index f44d6cd87ea2..40fb2e1bdfe4 100644
--- a/drivers/block/nvme.c
+++ b/drivers/block/nvme.c
@@ -780,6 +780,47 @@ static int nvme_get_range_type(struct nvme_ns *ns, unsigned long addr)
780 return nvme_submit_user_admin_command(ns->dev, addr, 4096, &c); 780 return nvme_submit_user_admin_command(ns->dev, addr, 4096, &c);
781} 781}
782 782
783static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
784{
785 struct nvme_dev *dev = ns->dev;
786 struct nvme_queue *nvmeq;
787 struct nvme_user_io io;
788 struct nvme_command c;
789 unsigned length;
790 u32 result;
791 int nents, status;
792 struct scatterlist *sg;
793
794 if (copy_from_user(&io, uio, sizeof(io)))
795 return -EFAULT;
796 length = io.nblocks << io.block_shift;
797 nents = nvme_map_user_pages(dev, io.opcode & 1, io.addr, length, &sg);
798 if (nents < 0)
799 return nents;
800
801 memset(&c, 0, sizeof(c));
802 c.rw.opcode = io.opcode;
803 c.rw.flags = io.flags;
804 c.rw.nsid = cpu_to_le32(io.nsid);
805 c.rw.slba = cpu_to_le64(io.slba);
806 c.rw.length = cpu_to_le16(io.nblocks - 1);
807 c.rw.control = cpu_to_le16(io.control);
808 c.rw.dsmgmt = cpu_to_le16(io.dsmgmt);
809 c.rw.reftag = cpu_to_le32(io.reftag); /* XXX: endian? */
810 c.rw.apptag = cpu_to_le16(io.apptag);
811 c.rw.appmask = cpu_to_le16(io.appmask);
812 /* XXX: metadata */
813 nvme_setup_prps(&c.common, sg, length);
814
815 nvmeq = get_nvmeq(ns);
816 status = nvme_submit_sync_cmd(nvmeq, &c, &result);
817 put_nvmeq(nvmeq);
818
819 nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg, nents);
820 put_user(result, &uio->result);
821 return status;
822}
823
783static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, 824static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
784 unsigned long arg) 825 unsigned long arg)
785{ 826{
@@ -792,6 +833,8 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
792 return nvme_identify(ns, arg, 1); 833 return nvme_identify(ns, arg, 1);
793 case NVME_IOCTL_GET_RANGE_TYPE: 834 case NVME_IOCTL_GET_RANGE_TYPE:
794 return nvme_get_range_type(ns, arg); 835 return nvme_get_range_type(ns, arg);
836 case NVME_IOCTL_SUBMIT_IO:
837 return nvme_submit_io(ns, (void __user *)arg);
795 default: 838 default:
796 return -ENOTTY; 839 return -ENOTTY;
797 } 840 }