aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew.r.wilcox@intel.com>2011-01-26 14:34:32 -0500
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2011-11-04 15:52:52 -0400
commitbd38c5557cf482fc195e2264b32ea62eed60730a (patch)
tree94204652ead86752f5545e4f0bf9befd25c83351
parentb8deb62cf271fa9381edc8cf52bcae2f0225c55a (diff)
NVMe: Change NVME_IOCTL_GET_RANGE_TYPE to return all the ranges
Factor out most of nvme_identify() into a new nvme_submit_user_admin_command() function. Change nvme_get_range_type() to call it and change nvme_ioctl to realise that it's getting back all 64 ranges. Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
-rw-r--r--drivers/block/nvme.c49
1 files changed, 19 insertions, 30 deletions
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c
index 25ca7af96469..b28d188d10f8 100644
--- a/drivers/block/nvme.c
+++ b/drivers/block/nvme.c
@@ -677,18 +677,17 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
677 return result; 677 return result;
678} 678}
679 679
680static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) 680static int nvme_submit_user_admin_command(struct nvme_dev *dev, unsigned long addr,
681 unsigned length, struct nvme_command *cmd)
681{ 682{
682 struct nvme_dev *dev = ns->dev;
683 int i, err, count, nents, offset; 683 int i, err, count, nents, offset;
684 struct nvme_command c;
685 struct scatterlist sg[2]; 684 struct scatterlist sg[2];
686 struct page *pages[2]; 685 struct page *pages[2];
687 686
688 if (addr & 3) 687 if (addr & 3)
689 return -EINVAL; 688 return -EINVAL;
690 offset = offset_in_page(addr); 689 offset = offset_in_page(addr);
691 count = offset ? 2 : 1; 690 count = ((offset + length) > PAGE_SIZE) ? 2 : 1;
692 691
693 err = get_user_pages_fast(addr, count, 1, pages); 692 err = get_user_pages_fast(addr, count, 1, pages);
694 if (err < count) { 693 if (err < count) {
@@ -704,13 +703,9 @@ static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns)
704 if (!nents) 703 if (!nents)
705 goto put_pages; 704 goto put_pages;
706 705
707 memset(&c, 0, sizeof(c)); 706 nvme_setup_prps(&cmd->common, sg, length);
708 c.identify.opcode = nvme_admin_identify;
709 c.identify.nsid = cns ? 0 : cpu_to_le32(ns->ns_id);
710 nvme_setup_prps(&c.common, sg, 4096);
711 c.identify.cns = cpu_to_le32(cns);
712 707
713 err = nvme_submit_admin_cmd(dev, &c, NULL); 708 err = nvme_submit_admin_cmd(dev, cmd, NULL);
714 709
715 if (err) 710 if (err)
716 err = -EIO; 711 err = -EIO;
@@ -723,34 +718,28 @@ static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns)
723 return err; 718 return err;
724} 719}
725 720
726static int nvme_get_range_type(struct nvme_ns *ns, void __user *addr) 721static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns)
727{ 722{
728 struct nvme_dev *dev = ns->dev;
729 int status;
730 struct nvme_command c; 723 struct nvme_command c;
731 void *page;
732 dma_addr_t dma_addr;
733 724
734 page = dma_alloc_coherent(&dev->pci_dev->dev, 4096, &dma_addr, 725 memset(&c, 0, sizeof(c));
735 GFP_KERNEL); 726 c.identify.opcode = nvme_admin_identify;
727 c.identify.nsid = cns ? 0 : cpu_to_le32(ns->ns_id);
728 c.identify.cns = cpu_to_le32(cns);
729
730 return nvme_submit_user_admin_command(ns->dev, addr, 4096, &c);
731}
732
733static int nvme_get_range_type(struct nvme_ns *ns, unsigned long addr)
734{
735 struct nvme_command c;
736 736
737 memset(&c, 0, sizeof(c)); 737 memset(&c, 0, sizeof(c));
738 c.features.opcode = nvme_admin_get_features; 738 c.features.opcode = nvme_admin_get_features;
739 c.features.nsid = cpu_to_le32(ns->ns_id); 739 c.features.nsid = cpu_to_le32(ns->ns_id);
740 c.features.prp1 = cpu_to_le64(dma_addr);
741 c.features.fid = cpu_to_le32(NVME_FEAT_LBA_RANGE); 740 c.features.fid = cpu_to_le32(NVME_FEAT_LBA_RANGE);
742 741
743 status = nvme_submit_admin_cmd(dev, &c, NULL); 742 return nvme_submit_user_admin_command(ns->dev, addr, 4096, &c);
744
745 /* XXX: Assuming first range for now */
746 if (status)
747 status = -EIO;
748 else if (copy_to_user(addr, page, 64))
749 status = -EFAULT;
750
751 dma_free_coherent(&dev->pci_dev->dev, 4096, page, dma_addr);
752
753 return status;
754} 743}
755 744
756static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, 745static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
@@ -764,7 +753,7 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
764 case NVME_IOCTL_IDENTIFY_CTRL: 753 case NVME_IOCTL_IDENTIFY_CTRL:
765 return nvme_identify(ns, arg, 1); 754 return nvme_identify(ns, arg, 1);
766 case NVME_IOCTL_GET_RANGE_TYPE: 755 case NVME_IOCTL_GET_RANGE_TYPE:
767 return nvme_get_range_type(ns, (void __user *)arg); 756 return nvme_get_range_type(ns, arg);
768 default: 757 default:
769 return -ENOTTY; 758 return -ENOTTY;
770 } 759 }