xref: /illumos-gate/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h (revision 679c9deae74d7b935e94eaaff2566ea45c1afe2b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * Copyright 2019, Joyent, Inc.
28  */
29 
30 #ifndef _SRPT_IMPL_H_
31 #define	_SRPT_IMPL_H_
32 
33 /*
34  * Prototypes and data structures for the SRP Target Port Provider.
35  */
36 
37 #include <sys/types.h>
38 #include <sys/ddi.h>
39 #include <sys/ib/ibtl/ibti.h>
40 #include <sys/modctl.h>
41 
42 #include <sys/stmf.h>
43 #include <sys/stmf_ioctl.h>
44 #include <sys/portif.h>
45 
46 #include <sys/ib/mgt/ibdma/ibdma.h>
47 
48 #ifdef __cplusplus
49 extern "C" {
50 #endif
51 
52 /* Format the session identifier */
53 #define	ALIAS_STR(s, a, b)						\
54 	((void) snprintf((s), sizeof ((s)), "%016llx:%016llx",		\
55 	    (u_longlong_t)(a), (u_longlong_t)(b)))
56 
57 /* Format the EUI name */
58 #define	EUI_STR(s, a)							\
59 	((void) snprintf((s), sizeof ((s)), "eui.%016llX", (u_longlong_t)(a)))
60 
61 /*
62  * We should/could consider making some of these values tunables.
63  * Specifically, SEND_MSG_SIZE and SEND_MSG_DEPTH.
64  */
65 enum {
66 	SRPT_DEFAULT_IOC_SRQ_SIZE = 4096,
67 	SRPT_DEFAULT_SEND_MSG_DEPTH = 128,
68 	/*
69 	 * SEND_MSG_SIZE must be a multiple of 64 as it is registered
70 	 * as memory regions with IB.  To support a scatter/gather table
71 	 * size of 32, the size must be at not less than 960.  To support
72 	 * the maximum scatter/gather table size of 255, the IU must
73 	 * be at least 4160 bytes.
74 	 */
75 	SRPT_DEFAULT_SEND_MSG_SIZE = 4160,
76 	SRPT_DEFAULT_MAX_RDMA_SIZE = 65536,
77 	SRPT_MIN_T_I_IU_LEN = 52,
78 	SRPT_EUI_ID_LEN = 20,
79 	SRPT_RECV_WC_POLL_SIZE = 16,
80 	SRPT_SEND_WC_POLL_SIZE = 16,
81 	SRPT_MAX_OUT_IO_PER_CMD = 16,
82 	SRPT_FENCE_SEND = 1,
83 	SRPT_NO_FENCE_SEND = 0
84 };
85 
86 struct srpt_target_port_s;
87 
88 #define	SRPT_ALIAS_LEN	(SRP_PORT_ID_LEN * 2 + 2)
89 
90 /*
91  * SRP Session - represents a SCSI I_T_Nexus.
92  *
93  * Sessions map 1 or more initiator logins to a specific I/O
94  * Controller SCSI Target Port.  Targets create sessions
95  * at initiator login and release when no longer referenced
96  * by a login.
97  */
98 typedef struct srpt_session_s {
99 	krwlock_t			ss_rwlock;
100 	list_node_t			ss_node;
101 
102 	/*
103 	 * ADVANCED FEATURE, NOT YET SUPPORTED.
104 	 * In multi-channel mode, multiple RDMA communication
105 	 * channels may reference the same SCSI session.  When
106 	 * a channel releases its reference to the SCSI session,
107 	 * it should have no tasks associated with the session.
108 	 *
109 	 * If multi-channel is implemented, add a channel list
110 	 * to this object instead of tracking it on the target.
111 	 *
112 	 * Will also need a session state & mode.  Mode is to
113 	 * track if the session is MULTI or SINGLE channel.
114 	 */
115 
116 	stmf_scsi_session_t		*ss_ss;
117 	struct srpt_target_port_s	*ss_tgt;
118 	list_t				ss_task_list;
119 
120 	/*
121 	 * SRP Initiator and target identifiers are 128-bit.
122 	 *
123 	 * The specification defines the initiator to be 64-bits of
124 	 * ID extension and 64 bits of GUID, but these are really
125 	 * just a recommendation.  Generally the extension is used
126 	 * to create unique I_T_Nexus from the same initiator and
127 	 * target.  Initiators are inconsistent on the GUID they
128 	 * use, some use the HCA Node, some the HCA port.
129 	 *
130 	 * The specification defines the target to be 64-bits of
131 	 * service ID followed by 64-bits of I/O Controller GUID.
132 	 * In the case where there is a single default target
133 	 * service, they will be the same (our default).
134 	 */
135 	uint8_t				ss_i_id[SRP_PORT_ID_LEN];
136 	uint8_t				ss_t_id[SRP_PORT_ID_LEN];
137 
138 	/* So we can see the full 128-bit initiator login from stmfadm */
139 	char				ss_i_alias[SRPT_ALIAS_LEN];
140 	uint8_t				ss_hw_port;
141 
142 	char				ss_t_alias[SRPT_ALIAS_LEN];
143 	char				ss_i_name[SRPT_EUI_ID_LEN + 1];
144 	char				ss_t_name[SRPT_EUI_ID_LEN + 1];
145 	char				ss_i_gid[SRPT_ALIAS_LEN];
146 	char				ss_t_gid[SRPT_ALIAS_LEN];
147 } srpt_session_t;
148 
149 /*
150  * Send work request types.
151  */
152 typedef enum srpt_swqe_type_e {
153 	SRPT_SWQE_TYPE_DATA = 1,
154 	SRPT_SWQE_TYPE_RESP
155 } srpt_swqe_type_t;
156 
157 typedef struct srpt_swqe_s {
158 	srpt_swqe_type_t	sw_type;
159 	void			*sw_addr;
160 	ibt_wrid_t		sw_next;
161 } srpt_swqe_t;
162 
163 /*
164  * SRP Channel - the RDMA communications channel associated with
165  * a specific SRP login.
166  */
167 typedef enum srpt_channel_state_e {
168 	SRPT_CHANNEL_CONNECTING = 0,
169 	SRPT_CHANNEL_CONNECTED,
170 	SRPT_CHANNEL_DISCONNECTING
171 } srpt_channel_state_t;
172 
173 typedef struct srpt_channel_s {
174 	krwlock_t			ch_rwlock;
175 
176 	kmutex_t			ch_reflock;
177 	uint_t				ch_refcnt;
178 	kcondvar_t			ch_cv_complete;
179 	uint_t				ch_cv_waiters;
180 
181 	list_node_t			ch_stp_node;
182 	srpt_channel_state_t		ch_state;
183 	ibt_cq_hdl_t			ch_scq_hdl;
184 	ibt_cq_hdl_t			ch_rcq_hdl;
185 	ibt_channel_hdl_t		ch_chan_hdl;
186 	ibt_chan_sizes_t		ch_sizes;
187 
188 	uint32_t			ch_req_lim_delta;
189 	uint32_t			ch_ti_iu_len;
190 	struct srpt_target_port_s	*ch_tgt;
191 	srpt_session_t			*ch_session;
192 
193 	/*
194 	 * Map IB send WQE request IDs to the
195 	 * apporpriate operation type (for errors).
196 	 */
197 	kmutex_t			ch_swqe_lock;
198 	srpt_swqe_t			*ch_swqe;
199 	uint32_t			ch_num_swqe;
200 	uint32_t			ch_head;
201 	uint32_t			ch_tail;
202 	uint32_t			ch_swqe_posted;
203 } srpt_channel_t;
204 
205 /*
206  * SRP Information Unit (IU).  Each IU structure contains
207  * the buffer for the IU itself (received over the RC
208  * channel), and all of the context required by the target
209  * to process this request represented by the IU.
210  * Available IU structures are managed on the I/O Controller
211  * shared receive queue.
212  */
213 enum {
214 	SRPT_IU_STMF_ABORTING	= 1 << 0,	/* STMF called abort */
215 	SRPT_IU_SRP_ABORTING	= 1 << 1,	/* SRP initiator aborting */
216 	SRPT_IU_ABORTED		= 1 << 2,	/* Task has been aborted */
217 	SRPT_IU_RESP_SENT	= 1 << 3	/* Response queued */
218 };
219 
220 typedef struct srpt_iu_s {
221 	/*
222 	 * The buffer for the IU itself.  When unused (a
223 	 * reference count of zero), this buffer is posted
224 	 * on the I/O Controllers SRPT SRQ.
225 	 */
226 	void			*iu_buf;
227 	ibt_wr_ds_t		iu_sge;
228 	struct srpt_ioc_s	*iu_ioc;
229 	uint_t			iu_pool_ndx;
230 	kmutex_t		iu_lock;
231 
232 	/*
233 	 * The following are reset for each IU request
234 	 * processed by this buffer.
235 	 */
236 	list_node_t		iu_ss_task_node;
237 	srpt_channel_t		*iu_ch;
238 
239 	uint_t			iu_num_rdescs;
240 	srp_direct_desc_t	*iu_rdescs;
241 	uint_t			iu_tot_xfer_len;
242 
243 	uint64_t		iu_tag;
244 	uint_t			iu_flags;
245 	uint32_t		iu_sq_posted_cnt;
246 	scsi_task_t		*iu_stmf_task;
247 } srpt_iu_t;
248 
249 /*
250  * SRP SCSI Target Port.  By default each HCA creates a single
251  * SCSI Target Port based on the associated I/O Controller
252  * (HCA) node GUID and made available through each physical
253  * hardware port of the I/O Controller.
254  */
255 typedef enum srpt_target_state_e {
256 	SRPT_TGT_STATE_OFFLINE = 0,
257 	SRPT_TGT_STATE_ONLINING,
258 	SRPT_TGT_STATE_ONLINE,
259 	SRPT_TGT_STATE_OFFLINING
260 } srpt_target_state_t;
261 
262 typedef struct srpt_hw_port_s {
263 	ibt_sbind_hdl_t		hwp_bind_hdl;
264 	ib_gid_t		hwp_gid;
265 } srpt_hw_port_t;
266 
267 typedef struct srpt_target_port_s {
268 	stmf_local_port_t	*tp_lport;
269 	struct srpt_ioc_s	*tp_ioc;
270 
271 	kmutex_t		tp_lock;
272 	srpt_target_state_t	tp_state;
273 	kcondvar_t		tp_offline_complete;
274 	uint_t			tp_drv_disabled;
275 
276 	/*
277 	 * We are using a simple list for channels right now, we
278 	 * probably should  switch this over to the AVL
279 	 * implementation eventually (but lookups are not done
280 	 * in the data path so this is not urgent).
281 	 */
282 	kmutex_t		tp_ch_list_lock;
283 	list_t			tp_ch_list;
284 
285 	/*
286 	 * A list of active sessions.  Session lifetime is
287 	 * determined by having active channels, but track
288 	 * them here for easier determination to when a
289 	 * target can truly be offlined, and as a step toward
290 	 * being session-focused rather than channel-focused.
291 	 * If we ever truly support multi-channel, move the
292 	 * channels to be part of the session object.
293 	 *
294 	 * Sessions should remain on this list until they
295 	 * are deregistered from STMF.  This allows the target
296 	 * to properly track when it can consider itself 'offline'.
297 	 */
298 	kmutex_t		tp_sess_list_lock;
299 	kcondvar_t		tp_sess_complete;
300 	list_t			tp_sess_list;
301 
302 	uint_t			tp_srp_enabled;
303 	ibt_srv_hdl_t		tp_ibt_svc_hdl;
304 	ibt_srv_desc_t		tp_ibt_svc_desc;
305 	ib_svc_id_t		tp_ibt_svc_id;
306 	scsi_devid_desc_t	*tp_scsi_devid;
307 	uint8_t			tp_srp_port_id[SRP_PORT_ID_LEN];
308 
309 	uint_t			tp_nports;
310 	srpt_hw_port_t		*tp_hw_port;
311 	/*
312 	 * track the number of active ports so we can offline the target if
313 	 * none
314 	 */
315 	uint32_t		tp_num_active_ports;
316 	/* state STMF wants the target in.  We may be offline due to no ports */
317 	srpt_target_state_t	tp_requested_state;
318 } srpt_target_port_t;
319 
320 /*
321  * SRP Target hardware device.  A SRP Target hardware device
322  * is an IB HCA.  All ports of the HCA comprise a single
323  * I/O Controller that is registered with the IB Device
324  * Managment Agent.
325  */
326 typedef struct srpt_ioc_s {
327 	list_node_t			ioc_node;
328 
329 	krwlock_t			ioc_rwlock;
330 	ibt_hca_hdl_t			ioc_ibt_hdl;
331 	ibt_hca_attr_t			ioc_attr;
332 	ib_guid_t			ioc_guid;
333 
334 	/*
335 	 * By default each HCA is a single SRP.T10 service based on
336 	 * the HCA GUID.  We have implemented the target here as a
337 	 * pointer to facilitate moving to a list of targets if
338 	 * appropriate down the road.
339 	 */
340 	srpt_target_port_t		*ioc_tgt_port;
341 
342 
343 	/*
344 	 * Each HCA registers a single I/O Controller with the
345 	 * IB Device Management Agent.
346 	 */
347 	ibdma_hdl_t			ioc_ibdma_hdl;
348 	ib_dm_ioc_ctrl_profile_t	ioc_profile;
349 	ib_dm_srv_t			ioc_svc;
350 
351 	ibt_pd_hdl_t			ioc_pd_hdl;
352 	ibt_srq_sizes_t			ioc_srq_attr;
353 	ibt_srq_hdl_t			ioc_srq_hdl;
354 
355 	/*
356 	 * The I/O Controller pool of IU resources allocated
357 	 * at controller creation.
358 	 */
359 	uint32_t			ioc_num_iu_entries;
360 	srpt_iu_t			*ioc_iu_pool;
361 	ibt_mr_hdl_t			ioc_iu_mr_hdl;
362 	void				*ioc_iu_bufs;  /* iu buffer space */
363 
364 	/*
365 	 * Each I/O Controller has it's own data buffer
366 	 * vmem arena.  Pool is created at controller creation,
367 	 * and expanded as required.  This keeps IB memory
368 	 * registrations to a minimum in the data path.
369 	 */
370 	struct srpt_vmem_pool_s		*ioc_dbuf_pool;
371 	stmf_dbuf_store_t		*ioc_stmf_ds;
372 } srpt_ioc_t;
373 
374 /*
375  * Memory regions
376  */
377 typedef struct srpt_mr_s {
378 	ibt_mr_hdl_t			mr_hdl;
379 	ib_vaddr_t			mr_va;
380 	ib_memlen_t			mr_len;
381 	ibt_lkey_t			mr_lkey;
382 	ibt_rkey_t			mr_rkey;
383 	avl_node_t			mr_avl;
384 } srpt_mr_t;
385 
386 /*
387  * SRP Target vmem arena definition
388  */
389 typedef struct srpt_vmem_pool_s {
390 	srpt_ioc_t		*svp_ioc;
391 	ib_memlen_t		svp_chunksize;
392 	vmem_t			*svp_vmem;
393 	uint64_t		svp_total_size;
394 	uint64_t		svp_max_size;
395 	avl_tree_t		svp_mr_list;
396 	krwlock_t		svp_lock;
397 	ibt_mr_flags_t		svp_flags;
398 } srpt_vmem_pool_t;
399 
400 /*
401  * SRP port provider data buffer, allocated and freed
402  * via calls to the IOC datastore.
403  */
404 typedef struct srpt_ds_dbuf_s {
405 	stmf_data_buf_t			*db_stmf_buf;
406 	srpt_ioc_t			*db_ioc;
407 	ibt_mr_hdl_t			db_mr_hdl;
408 	ibt_wr_ds_t			db_sge;
409 	srpt_iu_t			*db_iu;
410 } srpt_ds_dbuf_t;
411 
412 /*
413  * SRP Target service state
414  */
415 typedef enum {
416 	SRPT_SVC_DISABLED,
417 	SRPT_SVC_ENABLED
418 } srpt_svc_state_t;
419 
420 typedef struct {
421 	ddi_modhandle_t		ibdmah;
422 	ibdma_hdl_t		(*ibdma_register)(ib_guid_t,
423 				    ib_dm_ioc_ctrl_profile_t *, ib_dm_srv_t *);
424 	ibdma_status_t		(*ibdma_unregister)(ibdma_hdl_t);
425 	ibdma_status_t		(*ibdma_update)(ibdma_hdl_t,
426 				    ib_dm_ioc_ctrl_profile_t *, ib_dm_srv_t *);
427 } srpt_ibdma_ops_t;
428 
429 /*
430  * SRP Target protocol driver context data structure, maintaining
431  * the global state of the protocol.
432  */
433 typedef struct srpt_ctxt_s {
434 	dev_info_t			*sc_dip;
435 	krwlock_t			sc_rwlock;
436 	srpt_svc_state_t		sc_svc_state;
437 
438 	ibt_clnt_hdl_t			sc_ibt_hdl;
439 
440 	/*
441 	 * SRP Target I/O Controllers. Each IBT HCA represents an
442 	 * I/O Controller.  Must hold rwlock as a writer to update.
443 	 */
444 	list_t				sc_ioc_list;
445 	uint_t				sc_num_iocs;
446 
447 	/* Back-end COMSTAR port provider interface. */
448 	stmf_port_provider_t		*sc_pp;
449 
450 	/* IBDMA entry points */
451 	srpt_ibdma_ops_t		sc_ibdma_ops;
452 
453 	/*
454 	 *  List of explicitly configured HCAs and their configurable
455 	 *  attributes.
456 	 */
457 	nvlist_t			*sc_cfg_hca_nv;
458 } srpt_ctxt_t;
459 
460 typedef struct srpt_iu_data_s {
461 	union {
462 		uint8_t			srp_op;
463 		srp_cmd_req_t		srp_cmd;
464 		srp_tsk_mgmt_t		srp_tsk_mgmt;
465 		srp_i_logout_t		srp_i_logout;
466 		srp_rsp_t		srp_rsp;
467 	} rx_iu;
468 } srpt_iu_data_t;
469 
470 extern srpt_ctxt_t *srpt_ctxt;
471 
472 /*
473  * For Non recoverable or Major Errors
474  */
475 #define	SRPT_LOG_L0	0
476 
477 /*
478  * For additional information on Non recoverable errors and
479  * warnings/informational message for sys-admin types.
480  */
481 #define	SRPT_LOG_L1	1
482 
483 /*
484  * debug only
485  * for more verbose trace than L1, for e.g. recoverable errors,
486  * or intersting trace
487  */
488 #define	SRPT_LOG_L2	2
489 
490 /*
491  * debug only
492  * for more verbose trace than L2, for e.g. printing function entries....
493  */
494 #define	SRPT_LOG_L3	3
495 
496 /*
497  * debug only
498  * for more verbose trace than L3, for e.g. printing minor function entries...
499  */
500 #define	SRPT_LOG_L4	4
501 
502 /*
503  * srpt_errlevel can be set in the debugger to enable additional logging.
504  * You can also add set srpt:srpt_errlevel={0,1,2,3,4} in /etc/system.
505  * The default log level is L1.
506  */
507 #define	SRPT_LOG_DEFAULT_LEVEL SRPT_LOG_L1
508 
509 extern uint_t srpt_errlevel;
510 
511 
512 #define	SRPT_DPRINTF_L0(...) cmn_err(CE_WARN, __VA_ARGS__)
513 #define	SRPT_DPRINTF_L1(...) cmn_err(CE_NOTE, __VA_ARGS__)
514 #define	SRPT_DPRINTF_L2(...)	if (srpt_errlevel >= SRPT_LOG_L2) { \
515 					cmn_err(CE_NOTE, __VA_ARGS__);\
516 				}
517 #ifdef	DEBUG
518 #define	SRPT_DPRINTF_L3(...)	if (srpt_errlevel >= SRPT_LOG_L3) { \
519 					cmn_err(CE_NOTE, __VA_ARGS__);\
520 				}
521 #define	SRPT_DPRINTF_L4(...)	if (srpt_errlevel >= SRPT_LOG_L4) { \
522 					cmn_err(CE_NOTE, __VA_ARGS__);\
523 				}
524 #else
525 #define	SRPT_DPRINTF_L3(...) (void)(0)
526 #define	SRPT_DPRINTF_L4(...) (void)(0)
527 #endif
528 
529 #ifdef __cplusplus
530 }
531 #endif
532 
533 #endif /* _SRPT_IMPL_H_ */
534