diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-09-29 13:31:52 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-09-29 13:31:52 -0400 |
| commit | 21e98932dcf15fe7eabd09a35f2020e0dd86b685 (patch) | |
| tree | b733ff7fc6b56b77633d703fac1de2db8623b1ce | |
| parent | 9c603e53d380459fb62fec7cd085acb0b74ac18f (diff) | |
| parent | a09115b23e2002bb35b7bfd337683f00875671ec (diff) | |
Merge git://git.infradead.org/users/willy/linux-nvme
Pull NVMe driver fixes from Matthew Wilcox:
"Now that actual hardware has been released (don't have any yet
myself), people are starting to want some of these fixes merged."
Willy doesn't have hardware? Guys...
* git://git.infradead.org/users/willy/linux-nvme:
NVMe: Cancel outstanding IOs on queue deletion
NVMe: Free admin queue memory on initialisation failure
NVMe: Use ida for nvme device instance
NVMe: Fix whitespace damage in nvme_init
NVMe: handle allocation failure in nvme_map_user_pages()
NVMe: Fix uninitialized iod compiler warning
NVMe: Do not set IO queue depth beyond device max
NVMe: Set block queue max sectors
NVMe: use namespace id for nvme_get_features
NVMe: replace nvme_ns with nvme_dev for user admin
NVMe: Fix nvme module init when nvme_major is set
NVMe: Set request queue logical block size
| -rw-r--r-- | drivers/block/nvme.c | 153 | ||||
| -rw-r--r-- | include/linux/nvme.h | 2 |
2 files changed, 105 insertions, 50 deletions
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 38a2d0631882..ad16c68c8645 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c | |||
| @@ -79,6 +79,7 @@ struct nvme_dev { | |||
| 79 | char serial[20]; | 79 | char serial[20]; |
| 80 | char model[40]; | 80 | char model[40]; |
| 81 | char firmware_rev[8]; | 81 | char firmware_rev[8]; |
| 82 | u32 max_hw_sectors; | ||
| 82 | }; | 83 | }; |
| 83 | 84 | ||
| 84 | /* | 85 | /* |
| @@ -835,15 +836,15 @@ static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns, | |||
| 835 | } | 836 | } |
| 836 | 837 | ||
| 837 | static int nvme_get_features(struct nvme_dev *dev, unsigned fid, | 838 | static int nvme_get_features(struct nvme_dev *dev, unsigned fid, |
| 838 | unsigned dword11, dma_addr_t dma_addr) | 839 | unsigned nsid, dma_addr_t dma_addr) |
| 839 | { | 840 | { |
| 840 | struct nvme_command c; | 841 | struct nvme_command c; |
| 841 | 842 | ||
| 842 | memset(&c, 0, sizeof(c)); | 843 | memset(&c, 0, sizeof(c)); |
| 843 | c.features.opcode = nvme_admin_get_features; | 844 | c.features.opcode = nvme_admin_get_features; |
| 845 | c.features.nsid = cpu_to_le32(nsid); | ||
| 844 | c.features.prp1 = cpu_to_le64(dma_addr); | 846 | c.features.prp1 = cpu_to_le64(dma_addr); |
| 845 | c.features.fid = cpu_to_le32(fid); | 847 | c.features.fid = cpu_to_le32(fid); |
| 846 | c.features.dword11 = cpu_to_le32(dword11); | ||
| 847 | 848 | ||
| 848 | return nvme_submit_admin_cmd(dev, &c, NULL); | 849 | return nvme_submit_admin_cmd(dev, &c, NULL); |
| 849 | } | 850 | } |
| @@ -862,11 +863,51 @@ static int nvme_set_features(struct nvme_dev *dev, unsigned fid, | |||
| 862 | return nvme_submit_admin_cmd(dev, &c, result); | 863 | return nvme_submit_admin_cmd(dev, &c, result); |
| 863 | } | 864 | } |
| 864 | 865 | ||
| 866 | /** | ||
| 867 | * nvme_cancel_ios - Cancel outstanding I/Os | ||
| 868 | * @queue: The queue to cancel I/Os on | ||
| 869 | * @timeout: True to only cancel I/Os which have timed out | ||
| 870 | */ | ||
| 871 | static void nvme_cancel_ios(struct nvme_queue *nvmeq, bool timeout) | ||
| 872 | { | ||
| 873 | int depth = nvmeq->q_depth - 1; | ||
| 874 | struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); | ||
| 875 | unsigned long now = jiffies; | ||
| 876 | int cmdid; | ||
| 877 | |||
| 878 | for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) { | ||
| 879 | void *ctx; | ||
| 880 | nvme_completion_fn fn; | ||
| 881 | static struct nvme_completion cqe = { | ||
| 882 | .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1, | ||
| 883 | }; | ||
| 884 | |||
| 885 | if (timeout && !time_after(now, info[cmdid].timeout)) | ||
| 886 | continue; | ||
| 887 | dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d\n", cmdid); | ||
| 888 | ctx = cancel_cmdid(nvmeq, cmdid, &fn); | ||
| 889 | fn(nvmeq->dev, ctx, &cqe); | ||
| 890 | } | ||
| 891 | } | ||
| 892 | |||
| 893 | static void nvme_free_queue_mem(struct nvme_queue *nvmeq) | ||
| 894 | { | ||
| 895 | dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth), | ||
| 896 | (void *)nvmeq->cqes, nvmeq->cq_dma_addr); | ||
| 897 | dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth), | ||
| 898 | nvmeq->sq_cmds, nvmeq->sq_dma_addr); | ||
| 899 | kfree(nvmeq); | ||
| 900 | } | ||
| 901 | |||
| 865 | static void nvme_free_queue(struct nvme_dev *dev, int qid) | 902 | static void nvme_free_queue(struct nvme_dev *dev, int qid) |
| 866 | { | 903 | { |
| 867 | struct nvme_queue *nvmeq = dev->queues[qid]; | 904 | struct nvme_queue *nvmeq = dev->queues[qid]; |
| 868 | int vector = dev->entry[nvmeq->cq_vector].vector; | 905 | int vector = dev->entry[nvmeq->cq_vector].vector; |
| 869 | 906 | ||
| 907 | spin_lock_irq(&nvmeq->q_lock); | ||
| 908 | nvme_cancel_ios(nvmeq, false); | ||
| 909 | spin_unlock_irq(&nvmeq->q_lock); | ||
| 910 | |||
| 870 | irq_set_affinity_hint(vector, NULL); | 911 | irq_set_affinity_hint(vector, NULL); |
| 871 | free_irq(vector, nvmeq); | 912 | free_irq(vector, nvmeq); |
| 872 | 913 | ||
| @@ -876,18 +917,15 @@ static void nvme_free_queue(struct nvme_dev *dev, int qid) | |||
| 876 | adapter_delete_cq(dev, qid); | 917 | adapter_delete_cq(dev, qid); |
| 877 | } | 918 | } |
| 878 | 919 | ||
| 879 | dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth), | 920 | nvme_free_queue_mem(nvmeq); |
| 880 | (void *)nvmeq->cqes, nvmeq->cq_dma_addr); | ||
| 881 | dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth), | ||
| 882 | nvmeq->sq_cmds, nvmeq->sq_dma_addr); | ||
| 883 | kfree(nvmeq); | ||
| 884 | } | 921 | } |
| 885 | 922 | ||
| 886 | static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, | 923 | static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, |
| 887 | int depth, int vector) | 924 | int depth, int vector) |
| 888 | { | 925 | { |
| 889 | struct device *dmadev = &dev->pci_dev->dev; | 926 | struct device *dmadev = &dev->pci_dev->dev; |
| 890 | unsigned extra = (depth / 8) + (depth * sizeof(struct nvme_cmd_info)); | 927 | unsigned extra = DIV_ROUND_UP(depth, 8) + (depth * |
| 928 | sizeof(struct nvme_cmd_info)); | ||
| 891 | struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL); | 929 | struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL); |
| 892 | if (!nvmeq) | 930 | if (!nvmeq) |
| 893 | return NULL; | 931 | return NULL; |
| @@ -975,7 +1013,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, | |||
| 975 | 1013 | ||
| 976 | static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) | 1014 | static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) |
| 977 | { | 1015 | { |
| 978 | int result; | 1016 | int result = 0; |
| 979 | u32 aqa; | 1017 | u32 aqa; |
| 980 | u64 cap; | 1018 | u64 cap; |
| 981 | unsigned long timeout; | 1019 | unsigned long timeout; |
| @@ -1005,17 +1043,22 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) | |||
| 1005 | timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies; | 1043 | timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies; |
| 1006 | dev->db_stride = NVME_CAP_STRIDE(cap); | 1044 | dev->db_stride = NVME_CAP_STRIDE(cap); |
| 1007 | 1045 | ||
| 1008 | while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) { | 1046 | while (!result && !(readl(&dev->bar->csts) & NVME_CSTS_RDY)) { |
| 1009 | msleep(100); | 1047 | msleep(100); |
| 1010 | if (fatal_signal_pending(current)) | 1048 | if (fatal_signal_pending(current)) |
| 1011 | return -EINTR; | 1049 | result = -EINTR; |
| 1012 | if (time_after(jiffies, timeout)) { | 1050 | if (time_after(jiffies, timeout)) { |
| 1013 | dev_err(&dev->pci_dev->dev, | 1051 | dev_err(&dev->pci_dev->dev, |
| 1014 | "Device not ready; aborting initialisation\n"); | 1052 | "Device not ready; aborting initialisation\n"); |
| 1015 | return -ENODEV; | 1053 | result = -ENODEV; |
| 1016 | } | 1054 | } |
| 1017 | } | 1055 | } |
| 1018 | 1056 | ||
| 1057 | if (result) { | ||
| 1058 | nvme_free_queue_mem(nvmeq); | ||
| 1059 | return result; | ||
| 1060 | } | ||
| 1061 | |||
| 1019 | result = queue_request_irq(dev, nvmeq, "nvme admin"); | 1062 | result = queue_request_irq(dev, nvmeq, "nvme admin"); |
| 1020 | dev->queues[0] = nvmeq; | 1063 | dev->queues[0] = nvmeq; |
| 1021 | return result; | 1064 | return result; |
| @@ -1037,6 +1080,8 @@ static struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write, | |||
| 1037 | offset = offset_in_page(addr); | 1080 | offset = offset_in_page(addr); |
| 1038 | count = DIV_ROUND_UP(offset + length, PAGE_SIZE); | 1081 | count = DIV_ROUND_UP(offset + length, PAGE_SIZE); |
| 1039 | pages = kcalloc(count, sizeof(*pages), GFP_KERNEL); | 1082 | pages = kcalloc(count, sizeof(*pages), GFP_KERNEL); |
| 1083 | if (!pages) | ||
| 1084 | return ERR_PTR(-ENOMEM); | ||
| 1040 | 1085 | ||
| 1041 | err = get_user_pages_fast(addr, count, 1, pages); | 1086 | err = get_user_pages_fast(addr, count, 1, pages); |
| 1042 | if (err < count) { | 1087 | if (err < count) { |
| @@ -1146,14 +1191,13 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) | |||
| 1146 | return status; | 1191 | return status; |
| 1147 | } | 1192 | } |
| 1148 | 1193 | ||
| 1149 | static int nvme_user_admin_cmd(struct nvme_ns *ns, | 1194 | static int nvme_user_admin_cmd(struct nvme_dev *dev, |
| 1150 | struct nvme_admin_cmd __user *ucmd) | 1195 | struct nvme_admin_cmd __user *ucmd) |
| 1151 | { | 1196 | { |
| 1152 | struct nvme_dev *dev = ns->dev; | ||
| 1153 | struct nvme_admin_cmd cmd; | 1197 | struct nvme_admin_cmd cmd; |
| 1154 | struct nvme_command c; | 1198 | struct nvme_command c; |
| 1155 | int status, length; | 1199 | int status, length; |
| 1156 | struct nvme_iod *iod; | 1200 | struct nvme_iod *uninitialized_var(iod); |
