diff options
author | Matthew Wilcox <matthew.r.wilcox@intel.com> | 2011-01-26 14:34:32 -0500 |
---|---|---|
committer | Matthew Wilcox <matthew.r.wilcox@intel.com> | 2011-11-04 15:52:52 -0400 |
commit | bd38c5557cf482fc195e2264b32ea62eed60730a (patch) | |
tree | 94204652ead86752f5545e4f0bf9befd25c83351 | |
parent | b8deb62cf271fa9381edc8cf52bcae2f0225c55a (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.c | 49 |
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 | ||
680 | static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) | 680 | static 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 | ||
726 | static int nvme_get_range_type(struct nvme_ns *ns, void __user *addr) | 721 | static 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 | |||
733 | static 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 | ||
756 | static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, | 745 | static 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 | } |