nvme.h 5.1 KB
Newer Older
M
Matthew Wilcox 已提交
1 2
/*
 * Definitions for the NVM Express interface
3
 * Copyright (c) 2011-2013, Intel Corporation.
M
Matthew Wilcox 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef _LINUX_NVME_H
#define _LINUX_NVME_H

22 23 24 25
#include <uapi/linux/nvme.h>
#include <linux/pci.h>
#include <linux/miscdevice.h>
#include <linux/kref.h>
M
Matthew Wilcox 已提交
26 27 28 29

struct nvme_bar {
	__u64			cap;	/* Controller Capabilities */
	__u32			vs;	/* Version */
30 31
	__u32			intms;	/* Interrupt Mask Set */
	__u32			intmc;	/* Interrupt Mask Clear */
M
Matthew Wilcox 已提交
32
	__u32			cc;	/* Controller Configuration */
33
	__u32			rsvd1;	/* Reserved */
M
Matthew Wilcox 已提交
34
	__u32			csts;	/* Controller Status */
35
	__u32			rsvd2;	/* Reserved */
M
Matthew Wilcox 已提交
36 37 38 39 40
	__u32			aqa;	/* Admin Queue Attributes */
	__u64			asq;	/* Admin SQ Base Address */
	__u64			acq;	/* Admin CQ Base Address */
};

41
#define NVME_CAP_MQES(cap)	((cap) & 0xffff)
42
#define NVME_CAP_TIMEOUT(cap)	(((cap) >> 24) & 0xff)
43
#define NVME_CAP_STRIDE(cap)	(((cap) >> 32) & 0xf)
K
Keith Busch 已提交
44
#define NVME_CAP_MPSMIN(cap)	(((cap) >> 48) & 0xf)
45

M
Matthew Wilcox 已提交
46 47 48 49 50 51
enum {
	NVME_CC_ENABLE		= 1 << 0,
	NVME_CC_CSS_NVM		= 0 << 4,
	NVME_CC_MPS_SHIFT	= 7,
	NVME_CC_ARB_RR		= 0 << 11,
	NVME_CC_ARB_WRRU	= 1 << 11,
52 53 54 55
	NVME_CC_ARB_VS		= 7 << 11,
	NVME_CC_SHN_NONE	= 0 << 14,
	NVME_CC_SHN_NORMAL	= 1 << 14,
	NVME_CC_SHN_ABRUPT	= 2 << 14,
K
Keith Busch 已提交
56
	NVME_CC_SHN_MASK	= 3 << 14,
57 58
	NVME_CC_IOSQES		= 6 << 16,
	NVME_CC_IOCQES		= 4 << 20,
M
Matthew Wilcox 已提交
59 60 61 62 63
	NVME_CSTS_RDY		= 1 << 0,
	NVME_CSTS_CFS		= 1 << 1,
	NVME_CSTS_SHST_NORMAL	= 0 << 2,
	NVME_CSTS_SHST_OCCUR	= 1 << 2,
	NVME_CSTS_SHST_CMPLT	= 2 << 2,
K
Keith Busch 已提交
64
	NVME_CSTS_SHST_MASK	= 3 << 2,
M
Matthew Wilcox 已提交
65 66 67 68
};

#define NVME_VS(major, minor)	(major << 16 | minor)

69 70 71 72 73 74 75 76 77 78 79 80 81 82
#define NVME_IO_TIMEOUT	(5 * HZ)

/*
 * Represents an NVM Express device.  Each nvme_dev is a PCI function.
 */
struct nvme_dev {
	struct list_head node;
	struct nvme_queue **queues;
	u32 __iomem *dbs;
	struct pci_dev *pci_dev;
	struct dma_pool *prp_page_pool;
	struct dma_pool *prp_small_pool;
	int instance;
	int queue_count;
83
	u32 db_stride;
84 85 86 87
	u32 ctrl_config;
	struct msix_entry *entry;
	struct nvme_bar __iomem *bar;
	struct list_head namespaces;
88 89 90
	struct kref kref;
	struct miscdevice miscdev;
	char name[12];
91 92 93 94
	char serial[20];
	char model[40];
	char firmware_rev[8];
	u32 max_hw_sectors;
95
	u32 stripe_size;
96 97 98 99 100 101 102 103 104 105 106 107 108
	u16 oncs;
};

/*
 * An NVM Express namespace is equivalent to a SCSI LUN
 */
struct nvme_ns {
	struct list_head list;

	struct nvme_dev *dev;
	struct request_queue *queue;
	struct gendisk *disk;

109
	unsigned ns_id;
110
	int lba_shift;
111
	int ms;
V
Vishal Verma 已提交
112 113
	u64 mode_select_num_blocks;
	u32 mode_select_block_len;
114 115 116 117 118 119 120 121 122 123 124 125 126 127
};

/*
 * The nvme_iod describes the data in an I/O, including the list of PRP
 * entries.  You can't see it in this data structure because C doesn't let
 * me express that.  Use nvme_alloc_iod to ensure there's enough space
 * allocated to store the PRP list.
 */
struct nvme_iod {
	void *private;		/* For the use of the submitter of the I/O */
	int npages;		/* In the PRP list. 0 means small pool in use */
	int offset;		/* Of PRP list */
	int nents;		/* Used in scatterlist */
	int length;		/* Of data, in bytes */
K
Keith Busch 已提交
128
	unsigned long start_time;
129 130 131
	dma_addr_t first_dma;
	struct scatterlist sg[0];
};
V
Vishal Verma 已提交
132

133 134 135 136 137
static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector)
{
	return (sector >> (ns->lba_shift - 9));
}

V
Vishal Verma 已提交
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
/**
 * nvme_free_iod - frees an nvme_iod
 * @dev: The device that the I/O was submitted to
 * @iod: The memory to free
 */
void nvme_free_iod(struct nvme_dev *dev, struct nvme_iod *iod);

int nvme_setup_prps(struct nvme_dev *dev, struct nvme_common_command *cmd,
			struct nvme_iod *iod, int total_len, gfp_t gfp);
struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
				unsigned long addr, unsigned length);
void nvme_unmap_user_pages(struct nvme_dev *dev, int write,
			struct nvme_iod *iod);
struct nvme_queue *get_nvmeq(struct nvme_dev *dev);
void put_nvmeq(struct nvme_queue *nvmeq);
int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd,
						u32 *result, unsigned timeout);
int nvme_submit_flush_data(struct nvme_queue *nvmeq, struct nvme_ns *ns);
int nvme_submit_admin_cmd(struct nvme_dev *, struct nvme_command *,
							u32 *result);
int nvme_identify(struct nvme_dev *, unsigned nsid, unsigned cns,
							dma_addr_t dma_addr);
int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
			dma_addr_t dma_addr, u32 *result);
int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
			dma_addr_t dma_addr, u32 *result);

struct sg_io_hdr;

int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr);
K
Keith Busch 已提交
168
int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg);
V
Vishal Verma 已提交
169 170
int nvme_sg_get_version_num(int __user *ip);

M
Matthew Wilcox 已提交
171
#endif /* _LINUX_NVME_H */