diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-09 19:35:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-09 19:35:00 -0400 |
commit | 2d4fe27850420606155fb1f7d18ab2b40153e67b (patch) | |
tree | 56b0d465e1189babf4ac668a5b048a747bfb9682 /include | |
parent | 2e99f3a12b20ab3afad0e042cc0bdd0ee855dca0 (diff) | |
parent | 94f370cab6e5ac514b658c6b2b3aa308cefc5c7a (diff) |
Merge git://git.infradead.org/users/willy/linux-nvme
Pull NVMe driver update from Matthew Wilcox:
"Lots of exciting new features in the NVM Express driver this time,
including support for emulating SCSI commands, discard support and the
ability to submit per-sector metadata with I/Os.
It's still mostly bugfixes though!"
* git://git.infradead.org/users/willy/linux-nvme: (27 commits)
NVMe: Use user defined admin ioctl timeout
NVMe: Simplify Firmware Activate code slightly
NVMe: Only clear the enable bit when disabling controller
NVMe: Wait for device to acknowledge shutdown
NVMe: Schedule timeout for sync commands
NVMe: Meta-data support in NVME_IOCTL_SUBMIT_IO
NVMe: Device specific stripe size handling
NVMe: Split non-mergeable bio requests
NVMe: Remove dead code in nvme_dev_add
NVMe: Check for NULL memory in nvme_dev_add
NVMe: Fix error clean-up on nvme_alloc_queue
NVMe: Free admin queue on request_irq error
NVMe: Add scsi unmap to SG_IO
NVMe: queue usage fixes in nvme-scsi
NVMe: Set TASK_INTERRUPTIBLE before processing queues
NVMe: Add a character device for each nvme device
NVMe: Fix endian-related problems in user I/O submission path
NVMe: Fix I/O cancellation status on big-endian machines
NVMe: Fix sparse warnings in scsi emulation
NVMe: Don't fail initialisation unnecessarily
...
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/nvme.h | 158 |
1 files changed, 156 insertions, 2 deletions
diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 4fa3b0b9b071..f451c8d6e231 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h | |||
@@ -107,6 +107,12 @@ struct nvme_id_ctrl { | |||
107 | __u8 vs[1024]; | 107 | __u8 vs[1024]; |
108 | }; | 108 | }; |
109 | 109 | ||
110 | enum { | ||
111 | NVME_CTRL_ONCS_COMPARE = 1 << 0, | ||
112 | NVME_CTRL_ONCS_WRITE_UNCORRECTABLE = 1 << 1, | ||
113 | NVME_CTRL_ONCS_DSM = 1 << 2, | ||
114 | }; | ||
115 | |||
110 | struct nvme_lbaf { | 116 | struct nvme_lbaf { |
111 | __le16 ms; | 117 | __le16 ms; |
112 | __u8 ds; | 118 | __u8 ds; |
@@ -201,11 +207,11 @@ struct nvme_common_command { | |||
201 | __u8 flags; | 207 | __u8 flags; |
202 | __u16 command_id; | 208 | __u16 command_id; |
203 | __le32 nsid; | 209 | __le32 nsid; |
204 | __u32 cdw2[2]; | 210 | __le32 cdw2[2]; |
205 | __le64 metadata; | 211 | __le64 metadata; |
206 | __le64 prp1; | 212 | __le64 prp1; |
207 | __le64 prp2; | 213 | __le64 prp2; |
208 | __u32 cdw10[6]; | 214 | __le32 cdw10[6]; |
209 | }; | 215 | }; |
210 | 216 | ||
211 | struct nvme_rw_command { | 217 | struct nvme_rw_command { |
@@ -246,6 +252,31 @@ enum { | |||
246 | NVME_RW_DSM_COMPRESSED = 1 << 7, | 252 | NVME_RW_DSM_COMPRESSED = 1 << 7, |
247 | }; | 253 | }; |
248 | 254 | ||
255 | struct nvme_dsm_cmd { | ||
256 | __u8 opcode; | ||
257 | __u8 flags; | ||
258 | __u16 command_id; | ||
259 | __le32 nsid; | ||
260 | __u64 rsvd2[2]; | ||
261 | __le64 prp1; | ||
262 | __le64 prp2; | ||
263 | __le32 nr; | ||
264 | __le32 attributes; | ||
265 | __u32 rsvd12[4]; | ||
266 | }; | ||
267 | |||
268 | enum { | ||
269 | NVME_DSMGMT_IDR = 1 << 0, | ||
270 | NVME_DSMGMT_IDW = 1 << 1, | ||
271 | NVME_DSMGMT_AD = 1 << 2, | ||
272 | }; | ||
273 | |||
274 | struct nvme_dsm_range { | ||
275 | __le32 cattr; | ||
276 | __le32 nlb; | ||
277 | __le64 slba; | ||
278 | }; | ||
279 | |||
249 | /* Admin commands */ | 280 | /* Admin commands */ |
250 | 281 | ||
251 | enum nvme_admin_opcode { | 282 | enum nvme_admin_opcode { |
@@ -285,6 +316,9 @@ enum { | |||
285 | NVME_FEAT_WRITE_ATOMIC = 0x0a, | 316 | NVME_FEAT_WRITE_ATOMIC = 0x0a, |
286 | NVME_FEAT_ASYNC_EVENT = 0x0b, | 317 | NVME_FEAT_ASYNC_EVENT = 0x0b, |
287 | NVME_FEAT_SW_PROGRESS = 0x0c, | 318 | NVME_FEAT_SW_PROGRESS = 0x0c, |
319 | NVME_FWACT_REPL = (0 << 3), | ||
320 | NVME_FWACT_REPL_ACTV = (1 << 3), | ||
321 | NVME_FWACT_ACTV = (2 << 3), | ||
288 | }; | 322 | }; |
289 | 323 | ||
290 | struct nvme_identify { | 324 | struct nvme_identify { |
@@ -362,6 +396,16 @@ struct nvme_download_firmware { | |||
362 | __u32 rsvd12[4]; | 396 | __u32 rsvd12[4]; |
363 | }; | 397 | }; |
364 | 398 | ||
399 | struct nvme_format_cmd { | ||
400 | __u8 opcode; | ||
401 | __u8 flags; | ||
402 | __u16 command_id; | ||
403 | __le32 nsid; | ||
404 | __u64 rsvd2[4]; | ||
405 | __le32 cdw10; | ||
406 | __u32 rsvd11[5]; | ||
407 | }; | ||
408 | |||
365 | struct nvme_command { | 409 | struct nvme_command { |
366 | union { | 410 | union { |
367 | struct nvme_common_command common; | 411 | struct nvme_common_command common; |
@@ -372,6 +416,8 @@ struct nvme_command { | |||
372 | struct nvme_create_sq create_sq; | 416 | struct nvme_create_sq create_sq; |
373 | struct nvme_delete_queue delete_queue; | 417 | struct nvme_delete_queue delete_queue; |
374 | struct nvme_download_firmware dlfw; | 418 | struct nvme_download_firmware dlfw; |
419 | struct nvme_format_cmd format; | ||
420 | struct nvme_dsm_cmd dsm; | ||
375 | }; | 421 | }; |
376 | }; | 422 | }; |
377 | 423 | ||
@@ -388,6 +434,7 @@ enum { | |||
388 | NVME_SC_FUSED_FAIL = 0x9, | 434 | NVME_SC_FUSED_FAIL = 0x9, |
389 | NVME_SC_FUSED_MISSING = 0xa, | 435 | NVME_SC_FUSED_MISSING = 0xa, |
390 | NVME_SC_INVALID_NS = 0xb, | 436 | NVME_SC_INVALID_NS = 0xb, |
437 | NVME_SC_CMD_SEQ_ERROR = 0xc, | ||
391 | NVME_SC_LBA_RANGE = 0x80, | 438 | NVME_SC_LBA_RANGE = 0x80, |
392 | NVME_SC_CAP_EXCEEDED = 0x81, | 439 | NVME_SC_CAP_EXCEEDED = 0x81, |
393 | NVME_SC_NS_NOT_READY = 0x82, | 440 | NVME_SC_NS_NOT_READY = 0x82, |
@@ -461,4 +508,111 @@ struct nvme_admin_cmd { | |||
461 | #define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd) | 508 | #define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd) |
462 | #define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io) | 509 | #define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io) |
463 | 510 | ||
511 | #ifdef __KERNEL__ | ||
512 | #include <linux/pci.h> | ||
513 | #include <linux/miscdevice.h> | ||
514 | #include <linux/kref.h> | ||
515 | |||
516 | #define NVME_IO_TIMEOUT (5 * HZ) | ||
517 | |||
518 | /* | ||
519 | * Represents an NVM Express device. Each nvme_dev is a PCI function. | ||
520 | */ | ||
521 | struct nvme_dev { | ||
522 | struct list_head node; | ||
523 | struct nvme_queue **queues; | ||
524 | u32 __iomem *dbs; | ||
525 | struct pci_dev *pci_dev; | ||
526 | struct dma_pool *prp_page_pool; | ||
527 | struct dma_pool *prp_small_pool; | ||
528 | int instance; | ||
529 | int queue_count; | ||
530 | int db_stride; | ||
531 | u32 ctrl_config; | ||
532 | struct msix_entry *entry; | ||
533 | struct nvme_bar __iomem *bar; | ||
534 | struct list_head namespaces; | ||
535 | struct kref kref; | ||
536 | struct miscdevice miscdev; | ||
537 | char name[12]; | ||
538 | char serial[20]; | ||
539 | char model[40]; | ||
540 | char firmware_rev[8]; | ||
541 | u32 max_hw_sectors; | ||
542 | u32 stripe_size; | ||
543 | u16 oncs; | ||
544 | }; | ||
545 | |||
546 | /* | ||
547 | * An NVM Express namespace is equivalent to a SCSI LUN | ||
548 | */ | ||
549 | struct nvme_ns { | ||
550 | struct list_head list; | ||
551 | |||
552 | struct nvme_dev *dev; | ||
553 | struct request_queue *queue; | ||
554 | struct gendisk *disk; | ||
555 | |||
556 | int ns_id; | ||
557 | int lba_shift; | ||
558 | int ms; | ||
559 | u64 mode_select_num_blocks; | ||
560 | u32 mode_select_block_len; | ||
561 | }; | ||
562 | |||
563 | /* | ||
564 | * The nvme_iod describes the data in an I/O, including the list of PRP | ||
565 | * entries. You can't see it in this data structure because C doesn't let | ||
566 | * me express that. Use nvme_alloc_iod to ensure there's enough space | ||
567 | * allocated to store the PRP list. | ||
568 | */ | ||
569 | struct nvme_iod { | ||
570 | void *private; /* For the use of the submitter of the I/O */ | ||
571 | int npages; /* In the PRP list. 0 means small pool in use */ | ||
572 | int offset; /* Of PRP list */ | ||
573 | int nents; /* Used in scatterlist */ | ||
574 | int length; /* Of data, in bytes */ | ||
575 | dma_addr_t first_dma; | ||
576 | struct scatterlist sg[0]; | ||
577 | }; | ||
578 | |||
579 | static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector) | ||
580 | { | ||
581 | return (sector >> (ns->lba_shift - 9)); | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * nvme_free_iod - frees an nvme_iod | ||
586 | * @dev: The device that the I/O was submitted to | ||
587 | * @iod: The memory to free | ||
588 | */ | ||
589 | void nvme_free_iod(struct nvme_dev *dev, struct nvme_iod *iod); | ||
590 | |||
591 | int nvme_setup_prps(struct nvme_dev *dev, struct nvme_common_command *cmd, | ||
592 | struct nvme_iod *iod, int total_len, gfp_t gfp); | ||
593 | struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write, | ||
594 | unsigned long addr, unsigned length); | ||
595 | void nvme_unmap_user_pages(struct nvme_dev *dev, int write, | ||
596 | struct nvme_iod *iod); | ||
597 | struct nvme_queue *get_nvmeq(struct nvme_dev *dev); | ||
598 | void put_nvmeq(struct nvme_queue *nvmeq); | ||
599 | int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd, | ||
600 | u32 *result, unsigned timeout); | ||
601 | int nvme_submit_flush_data(struct nvme_queue *nvmeq, struct nvme_ns *ns); | ||
602 | int nvme_submit_admin_cmd(struct nvme_dev *, struct nvme_command *, | ||
603 | u32 *result); | ||
604 | int nvme_identify(struct nvme_dev *, unsigned nsid, unsigned cns, | ||
605 | dma_addr_t dma_addr); | ||
606 | int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, | ||
607 | dma_addr_t dma_addr, u32 *result); | ||
608 | int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11, | ||
609 | dma_addr_t dma_addr, u32 *result); | ||
610 | |||
611 | struct sg_io_hdr; | ||
612 | |||
613 | int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr); | ||
614 | int nvme_sg_get_version_num(int __user *ip); | ||
615 | |||
616 | #endif | ||
617 | |||
464 | #endif /* _LINUX_NVME_H */ | 618 | #endif /* _LINUX_NVME_H */ |