diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-11 19:45:59 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-11 19:45:59 -0400 |
| commit | 3e8072d48b2dd0898e99698018b2045f8cd49965 (patch) | |
| tree | 5710e46918d4e358f22fb6038ad81d1abdd3f1f8 | |
| parent | a63b747b41d6f6c9116fb2260381a3c96fe5dc02 (diff) | |
| parent | edd10d33283899fb15d99a290dcc9ceb3604ca78 (diff) | |
Merge git://git.infradead.org/users/willy/linux-nvme
Pull NVMe driver updates from Matthew Wilcox:
"Various updates to the NVMe driver. The most user-visible change is
that drive hotplugging now works and CPU hotplug while an NVMe drive
is installed should also work better"
* git://git.infradead.org/users/willy/linux-nvme:
NVMe: Retry failed commands with non-fatal errors
NVMe: Add getgeo to block ops
NVMe: Start-stop nvme_thread during device add-remove.
NVMe: Make I/O timeout a module parameter
NVMe: CPU hot plug notification
NVMe: per-cpu io queues
NVMe: Replace DEFINE_PCI_DEVICE_TABLE
NVMe: Fix divide-by-zero in nvme_trans_io_get_num_cmds
NVMe: IOCTL path RCU protect queue access
NVMe: RCU protected access to io queues
NVMe: Initialize device reference count earlier
NVMe: Add CONFIG_PM_SLEEP to suspend/resume functions
| -rw-r--r-- | drivers/block/nvme-core.c | 684 | ||||
| -rw-r--r-- | drivers/block/nvme-scsi.c | 43 | ||||
| -rw-r--r-- | include/linux/nvme.h | 21 | ||||
| -rw-r--r-- | include/uapi/linux/nvme.h | 1 |
4 files changed, 504 insertions, 245 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index da085ff10d25..7c64fa756cce 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * NVM Express device driver | 2 | * NVM Express device driver |
| 3 | * Copyright (c) 2011, Intel Corporation. | 3 | * Copyright (c) 2011-2014, Intel Corporation. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms and conditions of the GNU General Public License, | 6 | * under the terms and conditions of the GNU General Public License, |
| @@ -20,10 +20,12 @@ | |||
| 20 | #include <linux/bio.h> | 20 | #include <linux/bio.h> |
| 21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
| 22 | #include <linux/blkdev.h> | 22 | #include <linux/blkdev.h> |
| 23 | #include <linux/cpu.h> | ||
| 23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 24 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
| 25 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
| 26 | #include <linux/genhd.h> | 27 | #include <linux/genhd.h> |
| 28 | #include <linux/hdreg.h> | ||
| 27 | #include <linux/idr.h> | 29 | #include <linux/idr.h> |
| 28 | #include <linux/init.h> | 30 | #include <linux/init.h> |
| 29 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
| @@ -35,6 +37,7 @@ | |||
| 35 | #include <linux/module.h> | 37 | #include <linux/module.h> |
| 36 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
| 37 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
| 40 | #include <linux/percpu.h> | ||
| 38 | #include <linux/poison.h> | 41 | #include <linux/poison.h> |
| 39 | #include <linux/ptrace.h> | 42 | #include <linux/ptrace.h> |
| 40 | #include <linux/sched.h> | 43 | #include <linux/sched.h> |
| @@ -47,6 +50,11 @@ | |||
| 47 | #define SQ_SIZE(depth) (depth * sizeof(struct nvme_command)) | 50 | #define SQ_SIZE(depth) (depth * sizeof(struct nvme_command)) |
| 48 | #define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion)) | 51 | #define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion)) |
| 49 | #define ADMIN_TIMEOUT (60 * HZ) | 52 | #define ADMIN_TIMEOUT (60 * HZ) |
| 53 | #define IOD_TIMEOUT (4 * NVME_IO_TIMEOUT) | ||
| 54 | |||
| 55 | unsigned char io_timeout = 30; | ||
| 56 | module_param(io_timeout, byte, 0644); | ||
| 57 | MODULE_PARM_DESC(io_timeout, "timeout in seconds for I/O"); | ||
| 50 | 58 | ||
| 51 | static int nvme_major; | 59 | static int nvme_major; |
| 52 | module_param(nvme_major, int, 0); | 60 | module_param(nvme_major, int, 0); |
| @@ -58,6 +66,7 @@ static DEFINE_SPINLOCK(dev_list_lock); | |||
| 58 | static LIST_HEAD(dev_list); | 66 | static LIST_HEAD(dev_list); |
| 59 | static struct task_struct *nvme_thread; | 67 | static struct task_struct *nvme_thread; |
| 60 | static struct workqueue_struct *nvme_workq; | 68 | static struct workqueue_struct *nvme_workq; |
| 69 | static wait_queue_head_t nvme_kthread_wait; | ||
| 61 | 70 | ||
| 62 | static void nvme_reset_failed_dev(struct work_struct *ws); | 71 | static void nvme_reset_failed_dev(struct work_struct *ws); |
| 63 | 72 | ||
| @@ -74,6 +83,7 @@ struct async_cmd_info { | |||
| 74 | * commands and one for I/O commands). | 83 | * commands and one for I/O commands). |
| 75 | */ | 84 | */ |
| 76 | struct nvme_queue { | 85 | struct nvme_queue { |
| 86 | struct rcu_head r_head; | ||
| 77 | struct device *q_dmadev; | 87 | struct device *q_dmadev; |
| 78 | struct nvme_dev *dev; | 88 | struct nvme_dev *dev; |
| 79 | char irqname[24]; /* nvme4294967295-65535\0 */ | 89 | char irqname[24]; /* nvme4294967295-65535\0 */ |
| @@ -85,6 +95,7 @@ struct nvme_queue { | |||
| 85 | wait_queue_head_t sq_full; | 95 | wait_queue_head_t sq_full; |
| 86 | wait_queue_t sq_cong_wait; | 96 | wait_queue_t sq_cong_wait; |
| 87 | struct bio_list sq_cong; | 97 | struct bio_list sq_cong; |
| 98 | struct list_head iod_bio; | ||
| 88 | u32 __iomem *q_db; | 99 | u32 __iomem *q_db; |
| 89 | u16 q_depth; | 100 | u16 q_depth; |
| 90 | u16 cq_vector; | 101 | u16 cq_vector; |
| @@ -95,6 +106,7 @@ struct nvme_queue { | |||
| 95 | u8 cq_phase; | 106 | u8 cq_phase; |
| 96 | u8 cqe_seen; | 107 | u8 cqe_seen; |
| 97 | u8 q_suspended; | 108 | u8 q_suspended; |
| 109 | cpumask_var_t cpu_mask; | ||
| 98 | struct async_cmd_info cmdinfo; | 110 | struct async_cmd_info cmdinfo; |
| 99 | unsigned long cmdid_data[]; | 111 | unsigned long cmdid_data[]; |
| 100 | }; | 112 | }; |
| @@ -118,7 +130,7 @@ static inline void _nvme_check_size(void) | |||
| 118 | BUILD_BUG_ON(sizeof(struct nvme_smart_log) != 512); | 130 | BUILD_BUG_ON(sizeof(struct nvme_smart_log) != 512); |
| 119 | } | 131 | } |
| 120 | 132 | ||
| 121 | typedef void (*nvme_completion_fn)(struct nvme_dev *, void *, | 133 | typedef void (*nvme_completion_fn)(struct nvme_queue *, void *, |
| 122 | struct nvme_completion *); | 134 | struct nvme_completion *); |
| 123 | 135 | ||
| 124 | struct nvme_cmd_info { | 136 | struct nvme_cmd_info { |
| @@ -190,7 +202,7 @@ static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx, | |||
| 190 | #define CMD_CTX_FLUSH (0x318 + CMD_CTX_BASE) | 202 | #define CMD_CTX_FLUSH (0x318 + CMD_CTX_BASE) |
| 191 | #define CMD_CTX_ABORT (0x31C + CMD_CTX_BASE) | 203 | #define CMD_CTX_ABORT (0x31C + CMD_CTX_BASE) |
| 192 | 204 | ||
| 193 | static void special_completion(struct nvme_dev *dev, void *ctx, | 205 | static void special_completion(struct nvme_queue *nvmeq, void *ctx, |
| 194 | struct nvme_completion *cqe) | 206 | struct nvme_completion *cqe) |
| 195 | { | 207 | { |
| 196 | if (ctx == CMD_CTX_CANCELLED) | 208 | if (ctx == CMD_CTX_CANCELLED) |
| @@ -198,26 +210,26 @@ static void special_completion(struct nvme_dev *dev, void *ctx, | |||
| 198 | if (ctx == CMD_CTX_FLUSH) | 210 | if (ctx == CMD_CTX_FLUSH) |
| 199 | return; | 211 | return; |
| 200 | if (ctx == CMD_CTX_ABORT) { | 212 | if (ctx == CMD_CTX_ABORT) { |
| 201 | ++dev->abort_limit; | 213 | ++nvmeq->dev->abort_limit; |
| 202 | return; | 214 | return; |
| 203 | } | 215 | } |
| 204 | if (ctx == CMD_CTX_COMPLETED) { | 216 | if (ctx == CMD_CTX_COMPLETED) { |
| 205 | dev_warn(&dev->pci_dev->dev, | 217 | dev_warn(nvmeq->q_dmadev, |
| 206 | "completed id %d twice on queue %d\n", | 218 | "completed id %d twice on queue %d\n", |
| 207 | cqe->command_id, le16_to_cpup(&cqe->sq_id)); | 219 | cqe->command_id, le16_to_cpup(&cqe->sq_id)); |
| 208 | return; | 220 | return; |
| 209 | } | 221 | } |
| 210 | if (ctx == CMD_CTX_INVALID) { | 222 | if (ctx == CMD_CTX_INVALID) { |
| 211 | dev_warn(&dev->pci_dev->dev, | 223 | dev_warn(nvmeq->q_dmadev, |
| 212 | "invalid id %d completed on queue %d\n", | 224 | "invalid id %d completed on queue %d\n", |
| 213 | cqe->command_id, le16_to_cpup(&cqe->sq_id)); | 225 | cqe->command_id, le16_to_cpup(&cqe->sq_id)); |
| 214 | return; | 226 | return; |
| 215 | } | 227 | } |
| 216 | 228 | ||
| 217 | dev_warn(&dev->pci_dev->dev, "Unknown special completion %p\n", ctx); | 229 | dev_warn(nvmeq->q_dmadev, "Unknown special completion %p\n", ctx); |
| 218 | } | 230 | } |
| 219 | 231 | ||
| 220 | static void async_completion(struct nvme_dev *dev, void *ctx, | 232 | static void async_completion(struct nvme_queue *nvmeq, void *ctx, |
| 221 | struct nvme_completion *cqe) | 233 | struct nvme_completion *cqe) |
| 222 | { | 234 | { |
| 223 | struct async_cmd_info *cmdinfo = ctx; | 235 | struct async_cmd_info *cmdinfo = ctx; |
| @@ -262,14 +274,34 @@ static void *cancel_cmdid(struct nvme_queue *nvmeq, int cmdid, | |||
| 262 | return ctx; | 274 | return ctx; |
| 263 | } | 275 | } |
| 264 | 276 | ||
| 265 | struct nvme_queue *get_nvmeq(struct nvme_dev *dev) | 277 | static struct nvme_queue *raw_nvmeq(struct nvme_dev *dev, int qid) |
| 278 | { | ||
| 279 | return rcu_dereference_raw(dev->queues[qid]); | ||
| 280 | } | ||
| 281 | |||
| 282 | static struct nvme_queue *get_nvmeq(struct nvme_dev *dev) __acquires(RCU) | ||
| 283 | { | ||
| 284 | unsigned queue_id = get_cpu_var(*dev->io_queue); | ||
| 285 | rcu_read_lock(); | ||
| 286 | return rcu_dereference(dev->queues[queue_id]); | ||
| 287 | } | ||
| 288 | |||
| 289 | static void put_nvmeq(struct nvme_queue *nvmeq) __releases(RCU) | ||
| 266 | { | 290 | { |
| 267 | return dev->queues[get_cpu() + 1]; | 291 | rcu_read_unlock(); |
| 292 | put_cpu_var(nvmeq->dev->io_queue); | ||
| 268 | } | 293 | } |
| 269 | 294 | ||
