xref: /OK3568_Linux_fs/kernel/drivers/nvme/host/fc.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2016, Avago Technologies
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #ifndef _NVME_FC_TRANSPORT_H
7*4882a593Smuzhiyun #define _NVME_FC_TRANSPORT_H 1
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun /*
11*4882a593Smuzhiyun  * Common definitions between the nvme_fc (host) transport and
12*4882a593Smuzhiyun  * nvmet_fc (target) transport implementation.
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun /*
16*4882a593Smuzhiyun  * ******************  FC-NVME LS HANDLING ******************
17*4882a593Smuzhiyun  */
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun union nvmefc_ls_requests {
20*4882a593Smuzhiyun 	struct fcnvme_ls_rqst_w0		w0;
21*4882a593Smuzhiyun 	struct fcnvme_ls_cr_assoc_rqst		rq_cr_assoc;
22*4882a593Smuzhiyun 	struct fcnvme_ls_cr_conn_rqst		rq_cr_conn;
23*4882a593Smuzhiyun 	struct fcnvme_ls_disconnect_assoc_rqst	rq_dis_assoc;
24*4882a593Smuzhiyun 	struct fcnvme_ls_disconnect_conn_rqst	rq_dis_conn;
25*4882a593Smuzhiyun } __aligned(128);	/* alignment for other things alloc'd with */
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun union nvmefc_ls_responses {
28*4882a593Smuzhiyun 	struct fcnvme_ls_rjt			rsp_rjt;
29*4882a593Smuzhiyun 	struct fcnvme_ls_cr_assoc_acc		rsp_cr_assoc;
30*4882a593Smuzhiyun 	struct fcnvme_ls_cr_conn_acc		rsp_cr_conn;
31*4882a593Smuzhiyun 	struct fcnvme_ls_disconnect_assoc_acc	rsp_dis_assoc;
32*4882a593Smuzhiyun 	struct fcnvme_ls_disconnect_conn_acc	rsp_dis_conn;
33*4882a593Smuzhiyun } __aligned(128);	/* alignment for other things alloc'd with */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun static inline void
nvme_fc_format_rsp_hdr(void * buf,u8 ls_cmd,__be32 desc_len,u8 rqst_ls_cmd)36*4882a593Smuzhiyun nvme_fc_format_rsp_hdr(void *buf, u8 ls_cmd, __be32 desc_len, u8 rqst_ls_cmd)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	struct fcnvme_ls_acc_hdr *acc = buf;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	acc->w0.ls_cmd = ls_cmd;
41*4882a593Smuzhiyun 	acc->desc_list_len = desc_len;
42*4882a593Smuzhiyun 	acc->rqst.desc_tag = cpu_to_be32(FCNVME_LSDESC_RQST);
43*4882a593Smuzhiyun 	acc->rqst.desc_len =
44*4882a593Smuzhiyun 			fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rqst));
45*4882a593Smuzhiyun 	acc->rqst.w0.ls_cmd = rqst_ls_cmd;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun static inline int
nvme_fc_format_rjt(void * buf,u16 buflen,u8 ls_cmd,u8 reason,u8 explanation,u8 vendor)49*4882a593Smuzhiyun nvme_fc_format_rjt(void *buf, u16 buflen, u8 ls_cmd,
50*4882a593Smuzhiyun 			u8 reason, u8 explanation, u8 vendor)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	struct fcnvme_ls_rjt *rjt = buf;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	nvme_fc_format_rsp_hdr(buf, FCNVME_LSDESC_RQST,
55*4882a593Smuzhiyun 			fcnvme_lsdesc_len(sizeof(struct fcnvme_ls_rjt)),
56*4882a593Smuzhiyun 			ls_cmd);
57*4882a593Smuzhiyun 	rjt->rjt.desc_tag = cpu_to_be32(FCNVME_LSDESC_RJT);
58*4882a593Smuzhiyun 	rjt->rjt.desc_len = fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rjt));
59*4882a593Smuzhiyun 	rjt->rjt.reason_code = reason;
60*4882a593Smuzhiyun 	rjt->rjt.reason_explanation = explanation;
61*4882a593Smuzhiyun 	rjt->rjt.vendor = vendor;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	return sizeof(struct fcnvme_ls_rjt);
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /* Validation Error indexes into the string table below */
67*4882a593Smuzhiyun enum {
68*4882a593Smuzhiyun 	VERR_NO_ERROR		= 0,
69*4882a593Smuzhiyun 	VERR_CR_ASSOC_LEN	= 1,
70*4882a593Smuzhiyun 	VERR_CR_ASSOC_RQST_LEN	= 2,
71*4882a593Smuzhiyun 	VERR_CR_ASSOC_CMD	= 3,
72*4882a593Smuzhiyun 	VERR_CR_ASSOC_CMD_LEN	= 4,
73*4882a593Smuzhiyun 	VERR_ERSP_RATIO		= 5,
74*4882a593Smuzhiyun 	VERR_ASSOC_ALLOC_FAIL	= 6,
75*4882a593Smuzhiyun 	VERR_QUEUE_ALLOC_FAIL	= 7,
76*4882a593Smuzhiyun 	VERR_CR_CONN_LEN	= 8,
77*4882a593Smuzhiyun 	VERR_CR_CONN_RQST_LEN	= 9,
78*4882a593Smuzhiyun 	VERR_ASSOC_ID		= 10,
79*4882a593Smuzhiyun 	VERR_ASSOC_ID_LEN	= 11,
80*4882a593Smuzhiyun 	VERR_NO_ASSOC		= 12,
81*4882a593Smuzhiyun 	VERR_CONN_ID		= 13,
82*4882a593Smuzhiyun 	VERR_CONN_ID_LEN	= 14,
83*4882a593Smuzhiyun 	VERR_INVAL_CONN		= 15,
84*4882a593Smuzhiyun 	VERR_CR_CONN_CMD	= 16,
85*4882a593Smuzhiyun 	VERR_CR_CONN_CMD_LEN	= 17,
86*4882a593Smuzhiyun 	VERR_DISCONN_LEN	= 18,
87*4882a593Smuzhiyun 	VERR_DISCONN_RQST_LEN	= 19,
88*4882a593Smuzhiyun 	VERR_DISCONN_CMD	= 20,
89*4882a593Smuzhiyun 	VERR_DISCONN_CMD_LEN	= 21,
90*4882a593Smuzhiyun 	VERR_DISCONN_SCOPE	= 22,
91*4882a593Smuzhiyun 	VERR_RS_LEN		= 23,
92*4882a593Smuzhiyun 	VERR_RS_RQST_LEN	= 24,
93*4882a593Smuzhiyun 	VERR_RS_CMD		= 25,
94*4882a593Smuzhiyun 	VERR_RS_CMD_LEN		= 26,
95*4882a593Smuzhiyun 	VERR_RS_RCTL		= 27,
96*4882a593Smuzhiyun 	VERR_RS_RO		= 28,
97*4882a593Smuzhiyun 	VERR_LSACC		= 29,
98*4882a593Smuzhiyun 	VERR_LSDESC_RQST	= 30,
99*4882a593Smuzhiyun 	VERR_LSDESC_RQST_LEN	= 31,
100*4882a593Smuzhiyun 	VERR_CR_ASSOC		= 32,
101*4882a593Smuzhiyun 	VERR_CR_ASSOC_ACC_LEN	= 33,
102*4882a593Smuzhiyun 	VERR_CR_CONN		= 34,
103*4882a593Smuzhiyun 	VERR_CR_CONN_ACC_LEN	= 35,
104*4882a593Smuzhiyun 	VERR_DISCONN		= 36,
105*4882a593Smuzhiyun 	VERR_DISCONN_ACC_LEN	= 37,
106*4882a593Smuzhiyun };
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun static char *validation_errors[] = {
109*4882a593Smuzhiyun 	"OK",
110*4882a593Smuzhiyun 	"Bad CR_ASSOC Length",
111*4882a593Smuzhiyun 	"Bad CR_ASSOC Rqst Length",
112*4882a593Smuzhiyun 	"Not CR_ASSOC Cmd",
113*4882a593Smuzhiyun 	"Bad CR_ASSOC Cmd Length",
114*4882a593Smuzhiyun 	"Bad Ersp Ratio",
115*4882a593Smuzhiyun 	"Association Allocation Failed",
116*4882a593Smuzhiyun 	"Queue Allocation Failed",
117*4882a593Smuzhiyun 	"Bad CR_CONN Length",
118*4882a593Smuzhiyun 	"Bad CR_CONN Rqst Length",
119*4882a593Smuzhiyun 	"Not Association ID",
120*4882a593Smuzhiyun 	"Bad Association ID Length",
121*4882a593Smuzhiyun 	"No Association",
122*4882a593Smuzhiyun 	"Not Connection ID",
123*4882a593Smuzhiyun 	"Bad Connection ID Length",
124*4882a593Smuzhiyun 	"Invalid Connection ID",
125*4882a593Smuzhiyun 	"Not CR_CONN Cmd",
126*4882a593Smuzhiyun 	"Bad CR_CONN Cmd Length",
127*4882a593Smuzhiyun 	"Bad DISCONN Length",
128*4882a593Smuzhiyun 	"Bad DISCONN Rqst Length",
129*4882a593Smuzhiyun 	"Not DISCONN Cmd",
130*4882a593Smuzhiyun 	"Bad DISCONN Cmd Length",
131*4882a593Smuzhiyun 	"Bad Disconnect Scope",
132*4882a593Smuzhiyun 	"Bad RS Length",
133*4882a593Smuzhiyun 	"Bad RS Rqst Length",
134*4882a593Smuzhiyun 	"Not RS Cmd",
135*4882a593Smuzhiyun 	"Bad RS Cmd Length",
136*4882a593Smuzhiyun 	"Bad RS R_CTL",
137*4882a593Smuzhiyun 	"Bad RS Relative Offset",
138*4882a593Smuzhiyun 	"Not LS_ACC",
139*4882a593Smuzhiyun 	"Not LSDESC_RQST",
140*4882a593Smuzhiyun 	"Bad LSDESC_RQST Length",
141*4882a593Smuzhiyun 	"Not CR_ASSOC Rqst",
142*4882a593Smuzhiyun 	"Bad CR_ASSOC ACC Length",
143*4882a593Smuzhiyun 	"Not CR_CONN Rqst",
144*4882a593Smuzhiyun 	"Bad CR_CONN ACC Length",
145*4882a593Smuzhiyun 	"Not Disconnect Rqst",
146*4882a593Smuzhiyun 	"Bad Disconnect ACC Length",
147*4882a593Smuzhiyun };
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun #define NVME_FC_LAST_LS_CMD_VALUE	FCNVME_LS_DISCONNECT_CONN
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun static char *nvmefc_ls_names[] = {
152*4882a593Smuzhiyun 	"Reserved (0)",
153*4882a593Smuzhiyun 	"RJT (1)",
154*4882a593Smuzhiyun 	"ACC (2)",
155*4882a593Smuzhiyun 	"Create Association",
156*4882a593Smuzhiyun 	"Create Connection",
157*4882a593Smuzhiyun 	"Disconnect Association",
158*4882a593Smuzhiyun 	"Disconnect Connection",
159*4882a593Smuzhiyun };
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun static inline void
nvmefc_fmt_lsreq_discon_assoc(struct nvmefc_ls_req * lsreq,struct fcnvme_ls_disconnect_assoc_rqst * discon_rqst,struct fcnvme_ls_disconnect_assoc_acc * discon_acc,u64 association_id)162*4882a593Smuzhiyun nvmefc_fmt_lsreq_discon_assoc(struct nvmefc_ls_req *lsreq,
163*4882a593Smuzhiyun 	struct fcnvme_ls_disconnect_assoc_rqst *discon_rqst,
164*4882a593Smuzhiyun 	struct fcnvme_ls_disconnect_assoc_acc *discon_acc,
165*4882a593Smuzhiyun 	u64 association_id)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun 	lsreq->rqstaddr = discon_rqst;
168*4882a593Smuzhiyun 	lsreq->rqstlen = sizeof(*discon_rqst);
169*4882a593Smuzhiyun 	lsreq->rspaddr = discon_acc;
170*4882a593Smuzhiyun 	lsreq->rsplen = sizeof(*discon_acc);
171*4882a593Smuzhiyun 	lsreq->timeout = NVME_FC_LS_TIMEOUT_SEC;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	discon_rqst->w0.ls_cmd = FCNVME_LS_DISCONNECT_ASSOC;
174*4882a593Smuzhiyun 	discon_rqst->desc_list_len = cpu_to_be32(
175*4882a593Smuzhiyun 				sizeof(struct fcnvme_lsdesc_assoc_id) +
176*4882a593Smuzhiyun 				sizeof(struct fcnvme_lsdesc_disconn_cmd));
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	discon_rqst->associd.desc_tag = cpu_to_be32(FCNVME_LSDESC_ASSOC_ID);
179*4882a593Smuzhiyun 	discon_rqst->associd.desc_len =
180*4882a593Smuzhiyun 			fcnvme_lsdesc_len(
181*4882a593Smuzhiyun 				sizeof(struct fcnvme_lsdesc_assoc_id));
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	discon_rqst->associd.association_id = cpu_to_be64(association_id);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	discon_rqst->discon_cmd.desc_tag = cpu_to_be32(
186*4882a593Smuzhiyun 						FCNVME_LSDESC_DISCONN_CMD);
187*4882a593Smuzhiyun 	discon_rqst->discon_cmd.desc_len =
188*4882a593Smuzhiyun 			fcnvme_lsdesc_len(
189*4882a593Smuzhiyun 				sizeof(struct fcnvme_lsdesc_disconn_cmd));
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun static inline int
nvmefc_vldt_lsreq_discon_assoc(u32 rqstlen,struct fcnvme_ls_disconnect_assoc_rqst * rqst)193*4882a593Smuzhiyun nvmefc_vldt_lsreq_discon_assoc(u32 rqstlen,
194*4882a593Smuzhiyun 	struct fcnvme_ls_disconnect_assoc_rqst *rqst)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	int ret = 0;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	if (rqstlen < sizeof(struct fcnvme_ls_disconnect_assoc_rqst))
199*4882a593Smuzhiyun 		ret = VERR_DISCONN_LEN;
200*4882a593Smuzhiyun 	else if (rqst->desc_list_len !=
201*4882a593Smuzhiyun 			fcnvme_lsdesc_len(
202*4882a593Smuzhiyun 				sizeof(struct fcnvme_ls_disconnect_assoc_rqst)))
203*4882a593Smuzhiyun 		ret = VERR_DISCONN_RQST_LEN;
204*4882a593Smuzhiyun 	else if (rqst->associd.desc_tag != cpu_to_be32(FCNVME_LSDESC_ASSOC_ID))
205*4882a593Smuzhiyun 		ret = VERR_ASSOC_ID;
206*4882a593Smuzhiyun 	else if (rqst->associd.desc_len !=
207*4882a593Smuzhiyun 			fcnvme_lsdesc_len(
208*4882a593Smuzhiyun 				sizeof(struct fcnvme_lsdesc_assoc_id)))
209*4882a593Smuzhiyun 		ret = VERR_ASSOC_ID_LEN;
210*4882a593Smuzhiyun 	else if (rqst->discon_cmd.desc_tag !=
211*4882a593Smuzhiyun 			cpu_to_be32(FCNVME_LSDESC_DISCONN_CMD))
212*4882a593Smuzhiyun 		ret = VERR_DISCONN_CMD;
213*4882a593Smuzhiyun 	else if (rqst->discon_cmd.desc_len !=
214*4882a593Smuzhiyun 			fcnvme_lsdesc_len(
215*4882a593Smuzhiyun 				sizeof(struct fcnvme_lsdesc_disconn_cmd)))
216*4882a593Smuzhiyun 		ret = VERR_DISCONN_CMD_LEN;
217*4882a593Smuzhiyun 	/*
218*4882a593Smuzhiyun 	 * As the standard changed on the LS, check if old format and scope
219*4882a593Smuzhiyun 	 * something other than Association (e.g. 0).
220*4882a593Smuzhiyun 	 */
221*4882a593Smuzhiyun 	else if (rqst->discon_cmd.rsvd8[0])
222*4882a593Smuzhiyun 		ret = VERR_DISCONN_SCOPE;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	return ret;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun #endif /* _NVME_FC_TRANSPORT_H */
228