diff options
Diffstat (limited to 'include/linux/nvme.h')
| -rw-r--r-- | include/linux/nvme.h | 406 | 
1 files changed, 386 insertions, 20 deletions
| diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 7d51b2904cb7..d8b37bab2887 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -16,6 +16,78 @@  #define _LINUX_NVME_H  #include <linux/types.h> +#include <linux/uuid.h> + +/* NQN names in commands fields specified one size */ +#define NVMF_NQN_FIELD_LEN	256 + +/* However the max length of a qualified name is another size */ +#define NVMF_NQN_SIZE		223 + +#define NVMF_TRSVCID_SIZE	32 +#define NVMF_TRADDR_SIZE	256 +#define NVMF_TSAS_SIZE		256 + +#define NVME_DISC_SUBSYS_NAME	"nqn.2014-08.org.nvmexpress.discovery" + +#define NVME_RDMA_IP_PORT	4420 + +enum nvme_subsys_type { +	NVME_NQN_DISC	= 1,		/* Discovery type target subsystem */ +	NVME_NQN_NVME	= 2,		/* NVME type target subsystem */ +}; + +/* Address Family codes for Discovery Log Page entry ADRFAM field */ +enum { +	NVMF_ADDR_FAMILY_PCI	= 0,	/* PCIe */ +	NVMF_ADDR_FAMILY_IP4	= 1,	/* IP4 */ +	NVMF_ADDR_FAMILY_IP6	= 2,	/* IP6 */ +	NVMF_ADDR_FAMILY_IB	= 3,	/* InfiniBand */ +	NVMF_ADDR_FAMILY_FC	= 4,	/* Fibre Channel */ +}; + +/* Transport Type codes for Discovery Log Page entry TRTYPE field */ +enum { +	NVMF_TRTYPE_RDMA	= 1,	/* RDMA */ +	NVMF_TRTYPE_FC		= 2,	/* Fibre Channel */ +	NVMF_TRTYPE_LOOP	= 254,	/* Reserved for host usage */ +	NVMF_TRTYPE_MAX, +}; + +/* Transport Requirements codes for Discovery Log Page entry TREQ field */ +enum { +	NVMF_TREQ_NOT_SPECIFIED	= 0,	/* Not specified */ +	NVMF_TREQ_REQUIRED	= 1,	/* Required */ +	NVMF_TREQ_NOT_REQUIRED	= 2,	/* Not Required */ +}; + +/* RDMA QP Service Type codes for Discovery Log Page entry TSAS + * RDMA_QPTYPE field + */ +enum { +	NVMF_RDMA_QPTYPE_CONNECTED	= 0, /* Reliable Connected */ +	NVMF_RDMA_QPTYPE_DATAGRAM	= 1, /* Reliable Datagram */ +}; + +/* RDMA QP Service Type codes for Discovery Log Page entry TSAS + * RDMA_QPTYPE field + */ +enum { +	NVMF_RDMA_PRTYPE_NOT_SPECIFIED	= 0, /* No Provider Specified */ +	NVMF_RDMA_PRTYPE_IB		= 1, /* InfiniBand */ +	NVMF_RDMA_PRTYPE_ROCE		= 2, /* InfiniBand RoCE */ +	NVMF_RDMA_PRTYPE_ROCEV2		= 3, /* InfiniBand RoCEV2 */ +	NVMF_RDMA_PRTYPE_IWARP		= 4, /* IWARP */ +}; + +/* RDMA Connection Management Service Type codes for Discovery Log Page + * entry TSAS RDMA_CMS field + */ +enum { +	NVMF_RDMA_CMS_RDMA_CM	= 0, /* Sockets based enpoint addressing */ +}; + +#define NVMF_AQ_DEPTH		32  enum {  	NVME_REG_CAP	= 0x0000,	/* Controller Capabilities */ @@ -50,6 +122,13 @@ enum {  #define NVME_CMB_CQS(cmbsz)	((cmbsz) & 0x2)  #define NVME_CMB_SQS(cmbsz)	((cmbsz) & 0x1) +/* + * Submission and Completion Queue Entry Sizes for the NVM command set. + * (In bytes and specified as a power of two (2^n)). + */ +#define NVME_NVM_IOSQES		6 +#define NVME_NVM_IOCQES		4 +  enum {  	NVME_CC_ENABLE		= 1 << 0,  	NVME_CC_CSS_NVM		= 0 << 4, @@ -61,8 +140,8 @@ enum {  	NVME_CC_SHN_NORMAL	= 1 << 14,  	NVME_CC_SHN_ABRUPT	= 2 << 14,  	NVME_CC_SHN_MASK	= 3 << 14, -	NVME_CC_IOSQES		= 6 << 16, -	NVME_CC_IOCQES		= 4 << 20, +	NVME_CC_IOSQES		= NVME_NVM_IOSQES << 16, +	NVME_CC_IOCQES		= NVME_NVM_IOCQES << 20,  	NVME_CSTS_RDY		= 1 << 0,  	NVME_CSTS_CFS		= 1 << 1,  	NVME_CSTS_NSSRO		= 1 << 4, @@ -107,7 +186,11 @@ struct nvme_id_ctrl {  	__u8			mdts;  	__le16			cntlid;  	__le32			ver; -	__u8			rsvd84[172]; +	__le32			rtd3r; +	__le32			rtd3e; +	__le32			oaes; +	__le32			ctratt; +	__u8			rsvd100[156];  	__le16			oacs;  	__u8			acl;  	__u8			aerl; @@ -119,10 +202,12 @@ struct nvme_id_ctrl {  	__u8			apsta;  	__le16			wctemp;  	__le16			cctemp; -	__u8			rsvd270[242]; +	__u8			rsvd270[50]; +	__le16			kas; +	__u8			rsvd322[190];  	__u8			sqes;  	__u8			cqes; -	__u8			rsvd514[2]; +	__le16			maxcmd;  	__le32			nn;  	__le16			oncs;  	__le16			fuses; @@ -135,7 +220,15 @@ struct nvme_id_ctrl {  	__le16			acwu;  	__u8			rsvd534[2];  	__le32			sgls; -	__u8			rsvd540[1508]; +	__u8			rsvd540[228]; +	char			subnqn[256]; +	__u8			rsvd1024[768]; +	__le32			ioccsz; +	__le32			iorcsz; +	__le16			icdoff; +	__u8			ctrattr; +	__u8			msdbd; +	__u8			rsvd1804[244];  	struct nvme_id_power_state	psd[32];  	__u8			vs[1024];  }; @@ -274,6 +367,12 @@ struct nvme_reservation_status {  	} regctl_ds[];  }; +enum nvme_async_event_type { +	NVME_AER_TYPE_ERROR	= 0, +	NVME_AER_TYPE_SMART	= 1, +	NVME_AER_TYPE_NOTICE	= 2, +}; +  /* I/O commands */  enum nvme_opcode { @@ -290,6 +389,84 @@ enum nvme_opcode {  	nvme_cmd_resv_release	= 0x15,  }; +/* + * Descriptor subtype - lower 4 bits of nvme_(keyed_)sgl_desc identifier + * + * @NVME_SGL_FMT_ADDRESS:     absolute address of the data block + * @NVME_SGL_FMT_OFFSET:      relative offset of the in-capsule data block + * @NVME_SGL_FMT_INVALIDATE:  RDMA transport specific remote invalidation + *                            request subtype + */ +enum { +	NVME_SGL_FMT_ADDRESS		= 0x00, +	NVME_SGL_FMT_OFFSET		= 0x01, +	NVME_SGL_FMT_INVALIDATE		= 0x0f, +}; + +/* + * Descriptor type - upper 4 bits of nvme_(keyed_)sgl_desc identifier + * + * For struct nvme_sgl_desc: + *   @NVME_SGL_FMT_DATA_DESC:		data block descriptor + *   @NVME_SGL_FMT_SEG_DESC:		sgl segment descriptor + *   @NVME_SGL_FMT_LAST_SEG_DESC:	last sgl segment descriptor + * + * For struct nvme_keyed_sgl_desc: + *   @NVME_KEY_SGL_FMT_DATA_DESC:	keyed data block descriptor + */ +enum { +	NVME_SGL_FMT_DATA_DESC		= 0x00, +	NVME_SGL_FMT_SEG_DESC		= 0x02, +	NVME_SGL_FMT_LAST_SEG_DESC	= 0x03, +	NVME_KEY_SGL_FMT_DATA_DESC	= 0x04, +}; + +struct nvme_sgl_desc { +	__le64	addr; +	__le32	length; +	__u8	rsvd[3]; +	__u8	type; +}; + +struct nvme_keyed_sgl_desc { +	__le64	addr; +	__u8	length[3]; +	__u8	key[4]; +	__u8	type; +}; + +union nvme_data_ptr { +	struct { +		__le64	prp1; +		__le64	prp2; +	}; +	struct nvme_sgl_desc	sgl; +	struct nvme_keyed_sgl_desc ksgl; +}; + +/* + * Lowest two bits of our flags field (FUSE field in the spec): + * + * @NVME_CMD_FUSE_FIRST:   Fused Operation, first command + * @NVME_CMD_FUSE_SECOND:  Fused Operation, second command + * + * Highest two bits in our flags field (PSDT field in the spec): + * + * @NVME_CMD_PSDT_SGL_METABUF:	Use SGLS for this transfer, + *	If used, MPTR contains addr of single physical buffer (byte aligned). + * @NVME_CMD_PSDT_SGL_METASEG:	Use SGLS for this transfer, + *	If used, MPTR contains an address of an SGL segment containing + *	exactly 1 SGL descriptor (qword aligned). + */ +enum { +	NVME_CMD_FUSE_FIRST	= (1 << 0), +	NVME_CMD_FUSE_SECOND	= (1 << 1), + +	NVME_CMD_SGL_METABUF	= (1 << 6), +	NVME_CMD_SGL_METASEG	= (1 << 7), +	NVME_CMD_SGL_ALL	= NVME_CMD_SGL_METABUF | NVME_CMD_SGL_METASEG, +}; +  struct nvme_common_command {  	__u8			opcode;  	__u8			flags; @@ -297,8 +474,7 @@ struct nvme_common_command {  	__le32			nsid;  	__le32			cdw2[2];  	__le64			metadata; -	__le64			prp1; -	__le64			prp2; +	union nvme_data_ptr	dptr;  	__le32			cdw10[6];  }; @@ -309,8 +485,7 @@ struct nvme_rw_command {  	__le32			nsid;  	__u64			rsvd2;  	__le64			metadata; -	__le64			prp1; -	__le64			prp2; +	union nvme_data_ptr	dptr;  	__le64			slba;  	__le16			length;  	__le16			control; @@ -350,8 +525,7 @@ struct nvme_dsm_cmd {  	__u16			command_id;  	__le32			nsid;  	__u64			rsvd2[2]; -	__le64			prp1; -	__le64			prp2; +	union nvme_data_ptr	dptr;  	__le32			nr;  	__le32			attributes;  	__u32			rsvd12[4]; @@ -384,6 +558,7 @@ enum nvme_admin_opcode {  	nvme_admin_async_event		= 0x0c,  	nvme_admin_activate_fw		= 0x10,  	nvme_admin_download_fw		= 0x11, +	nvme_admin_keep_alive		= 0x18,  	nvme_admin_format_nvm		= 0x80,  	nvme_admin_security_send	= 0x81,  	nvme_admin_security_recv	= 0x82, @@ -408,6 +583,7 @@ enum {  	NVME_FEAT_WRITE_ATOMIC	= 0x0a,  	NVME_FEAT_ASYNC_EVENT	= 0x0b,  	NVME_FEAT_AUTO_PST	= 0x0c, +	NVME_FEAT_KATO		= 0x0f,  	NVME_FEAT_SW_PROGRESS	= 0x80,  	NVME_FEAT_HOST_ID	= 0x81,  	NVME_FEAT_RESV_MASK	= 0x82, @@ -415,6 +591,7 @@ enum {  	NVME_LOG_ERROR		= 0x01,  	NVME_LOG_SMART		= 0x02,  	NVME_LOG_FW_SLOT	= 0x03, +	NVME_LOG_DISC		= 0x70,  	NVME_LOG_RESERVATION	= 0x80,  	NVME_FWACT_REPL		= (0 << 3),  	NVME_FWACT_REPL_ACTV	= (1 << 3), @@ -427,8 +604,7 @@ struct nvme_identify {  	__u16			command_id;  	__le32			nsid;  	__u64			rsvd2[2]; -	__le64			prp1; -	__le64			prp2; +	union nvme_data_ptr	dptr;  	__le32			cns;  	__u32			rsvd11[5];  }; @@ -439,8 +615,7 @@ struct nvme_features {  	__u16			command_id;  	__le32			nsid;  	__u64			rsvd2[2]; -	__le64			prp1; -	__le64			prp2; +	union nvme_data_ptr	dptr;  	__le32			fid;  	__le32			dword11;  	__u32			rsvd12[4]; @@ -499,8 +674,7 @@ struct nvme_download_firmware {  	__u8			flags;  	__u16			command_id;  	__u32			rsvd1[5]; -	__le64			prp1; -	__le64			prp2; +	union nvme_data_ptr	dptr;  	__le32			numd;  	__le32			offset;  	__u32			rsvd12[4]; @@ -516,6 +690,143 @@ struct nvme_format_cmd {  	__u32			rsvd11[5];  }; +struct nvme_get_log_page_command { +	__u8			opcode; +	__u8			flags; +	__u16			command_id; +	__le32			nsid; +	__u64			rsvd2[2]; +	union nvme_data_ptr	dptr; +	__u8			lid; +	__u8			rsvd10; +	__le16			numdl; +	__le16			numdu; +	__u16			rsvd11; +	__le32			lpol; +	__le32			lpou; +	__u32			rsvd14[2]; +}; + +/* + * Fabrics subcommands. + */ +enum nvmf_fabrics_opcode { +	nvme_fabrics_command		= 0x7f, +}; + +enum nvmf_capsule_command { +	nvme_fabrics_type_property_set	= 0x00, +	nvme_fabrics_type_connect	= 0x01, +	nvme_fabrics_type_property_get	= 0x04, +}; + +struct nvmf_common_command { +	__u8	opcode; +	__u8	resv1; +	__u16	command_id; +	__u8	fctype; +	__u8	resv2[35]; +	__u8	ts[24]; +}; + +/* + * The legal cntlid range a NVMe Target will provide. + * Note that cntlid of value 0 is considered illegal in the fabrics world. + * Devices based on earlier specs did not have the subsystem concept; + * therefore, those devices had their cntlid value set to 0 as a result. + */ +#define NVME_CNTLID_MIN		1 +#define NVME_CNTLID_MAX		0xffef +#define NVME_CNTLID_DYNAMIC	0xffff + +#define MAX_DISC_LOGS	255 + +/* Discovery log page entry */ +struct nvmf_disc_rsp_page_entry { +	__u8		trtype; +	__u8		adrfam; +	__u8		nqntype; +	__u8		treq; +	__le16		portid; +	__le16		cntlid; +	__le16		asqsz; +	__u8		resv8[22]; +	char		trsvcid[NVMF_TRSVCID_SIZE]; +	__u8		resv64[192]; +	char		subnqn[NVMF_NQN_FIELD_LEN]; +	char		traddr[NVMF_TRADDR_SIZE]; +	union tsas { +		char		common[NVMF_TSAS_SIZE]; +		struct rdma { +			__u8	qptype; +			__u8	prtype; +			__u8	cms; +			__u8	resv3[5]; +			__u16	pkey; +			__u8	resv10[246]; +		} rdma; +	} tsas; +}; + +/* Discovery log page header */ +struct nvmf_disc_rsp_page_hdr { +	__le64		genctr; +	__le64		numrec; +	__le16		recfmt; +	__u8		resv14[1006]; +	struct nvmf_disc_rsp_page_entry entries[0]; +}; + +struct nvmf_connect_command { +	__u8		opcode; +	__u8		resv1; +	__u16		command_id; +	__u8		fctype; +	__u8		resv2[19]; +	union nvme_data_ptr dptr; +	__le16		recfmt; +	__le16		qid; +	__le16		sqsize; +	__u8		cattr; +	__u8		resv3; +	__le32		kato; +	__u8		resv4[12]; +}; + +struct nvmf_connect_data { +	uuid_le		hostid; +	__le16		cntlid; +	char		resv4[238]; +	char		subsysnqn[NVMF_NQN_FIELD_LEN]; +	char		hostnqn[NVMF_NQN_FIELD_LEN]; +	char		resv5[256]; +}; + +struct nvmf_property_set_command { +	__u8		opcode; +	__u8		resv1; +	__u16		command_id; +	__u8		fctype; +	__u8		resv2[35]; +	__u8		attrib; +	__u8		resv3[3]; +	__le32		offset; +	__le64		value; +	__u8		resv4[8]; +}; + +struct nvmf_property_get_command { +	__u8		opcode; +	__u8		resv1; +	__u16		command_id; +	__u8		fctype; +	__u8		resv2[35]; +	__u8		attrib; +	__u8		resv3[3]; +	__le32		offset; +	__u8		resv4[16]; +}; +  struct nvme_command {  	union {  		struct nvme_common_command common; @@ -529,10 +840,30 @@ struct nvme_command {  		struct nvme_format_cmd format;  		struct nvme_dsm_cmd dsm;  		struct nvme_abort_cmd abort; +		struct nvme_get_log_page_command get_log_page; +		struct nvmf_common_command fabrics; +		struct nvmf_connect_command connect; +		struct nvmf_property_set_command prop_set; +		struct nvmf_property_get_command prop_get;  	};  }; +static inline bool nvme_is_write(struct nvme_command *cmd) +{ +	/* +	 * What a mess... +	 * +	 * Why can't we simply have a Fabrics In and Fabrics out command? +	 */ +	if (unlikely(cmd->common.opcode == nvme_fabrics_command)) +		return cmd->fabrics.opcode & 1; +	return cmd->common.opcode & 1; +} +  enum { +	/* +	 * Generic Command Status: +	 */  	NVME_SC_SUCCESS			= 0x0,  	NVME_SC_INVALID_OPCODE		= 0x1,  	NVME_SC_INVALID_FIELD		= 0x2, @@ -551,10 +882,18 @@ enum {  	NVME_SC_SGL_INVALID_DATA	= 0xf,  	NVME_SC_SGL_INVALID_METADATA	= 0x10,  	NVME_SC_SGL_INVALID_TYPE	= 0x11, + +	NVME_SC_SGL_INVALID_OFFSET	= 0x16, +	NVME_SC_SGL_INVALID_SUBTYPE	= 0x17, +  	NVME_SC_LBA_RANGE		= 0x80,  	NVME_SC_CAP_EXCEEDED		= 0x81,  	NVME_SC_NS_NOT_READY		= 0x82,  	NVME_SC_RESERVATION_CONFLICT	= 0x83, + +	/* +	 * Command Specific Status: +	 */  	NVME_SC_CQ_INVALID		= 0x100,  	NVME_SC_QID_INVALID		= 0x101,  	NVME_SC_QUEUE_SIZE		= 0x102, @@ -572,9 +911,29 @@ enum {  	NVME_SC_FEATURE_NOT_CHANGEABLE	= 0x10e,  	NVME_SC_FEATURE_NOT_PER_NS	= 0x10f,  	NVME_SC_FW_NEEDS_RESET_SUBSYS	= 0x110, + +	/* +	 * I/O Command Set Specific - NVM commands: +	 */  	NVME_SC_BAD_ATTRIBUTES		= 0x180,  	NVME_SC_INVALID_PI		= 0x181,  	NVME_SC_READ_ONLY		= 0x182, + +	/* +	 * I/O Command Set Specific - Fabrics commands: +	 */ +	NVME_SC_CONNECT_FORMAT		= 0x180, +	NVME_SC_CONNECT_CTRL_BUSY	= 0x181, +	NVME_SC_CONNECT_INVALID_PARAM	= 0x182, +	NVME_SC_CONNECT_RESTART_DISC	= 0x183, +	NVME_SC_CONNECT_INVALID_HOST	= 0x184, + +	NVME_SC_DISCOVERY_RESTART	= 0x190, +	NVME_SC_AUTH_REQUIRED		= 0x191, + +	/* +	 * Media and Data Integrity Errors: +	 */  	NVME_SC_WRITE_FAULT		= 0x280,  	NVME_SC_READ_ERROR		= 0x281,  	NVME_SC_GUARD_CHECK		= 0x282, @@ -582,12 +941,19 @@ enum {  	NVME_SC_REFTAG_CHECK		= 0x284,  	NVME_SC_COMPARE_FAILED		= 0x285,  	NVME_SC_ACCESS_DENIED		= 0x286, +  	NVME_SC_DNR			= 0x4000,  };  struct nvme_completion { -	__le32	result;		/* Used by admin commands to return data */ -	__u32	rsvd; +	/* +	 * Used by Admin and Fabrics commands to return data: +	 */ +	union { +		__le16	result16; +		__le32	result; +		__le64	result64; +	};  	__le16	sq_head;	/* how much of this queue may be reclaimed */  	__le16	sq_id;		/* submission queue that generated this entry */  	__u16	command_id;	/* of the command which completed */ |