xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/lmrc/lmrc.h (revision 1f606c5b8e527ed924f5cbdbbce612887c7dbe32)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2023 Racktop Systems, Inc.
14  */
15 #ifndef _LMRC_H
16 #define	_LMRC_H
17 
18 #include <sys/list.h>
19 #include <sys/types.h>
20 
21 #include <sys/scsi/scsi.h>
22 #include <sys/taskq_impl.h>
23 
24 #if !defined(_LITTLE_ENDIAN) || !defined(_BIT_FIELDS_LTOH)
25 #error "lmrc only works on little endian systems"
26 #endif
27 
28 typedef enum lmrc_adapter_class	lmrc_adapter_class_t;
29 typedef enum lmrc_init_level	lmrc_init_level_t;
30 typedef struct lmrc_dma		lmrc_dma_t;
31 typedef struct lmrc_mpt_cmd	lmrc_mpt_cmd_t;
32 typedef struct lmrc_mfi_cmd	lmrc_mfi_cmd_t;
33 typedef struct lmrc_scsa_cmd	lmrc_scsa_cmd_t;
34 typedef struct lmrc_pd		lmrc_pd_t;
35 typedef struct lmrc_tgt		lmrc_tgt_t;
36 typedef struct lmrc		lmrc_t;
37 
38 #include "lmrc_reg.h"
39 #include "lmrc_phys.h"
40 
41 extern void *lmrc_state;
42 
43 enum lmrc_adapter_class {
44 	LMRC_ACLASS_OTHER,
45 	LMRC_ACLASS_GEN3,
46 	LMRC_ACLASS_VENTURA,
47 	LMRC_ACLASS_AERO,
48 };
49 
50 /* iports for RAID and physical targets */
51 #define	LMRC_IPORT_RAID		"v0"
52 #define	LMRC_IPORT_PHYS		"p0"
53 
54 /* in seconds */
55 #define	LMRC_IO_TIMEOUT				10
56 #define	LMRC_RESET_TIMEOUT			180
57 #define	LMRC_RESET_WAIT_TIME			3
58 #define	LMRC_INTERNAL_CMD_WAIT_TIME		180
59 
60 #define	LMRC_MAX_RESET_TRIES			3
61 
62 enum lmrc_init_level {
63 	LMRC_INITLEVEL_BASIC =		(1 << 0),
64 	LMRC_INITLEVEL_THREAD =		(1 << 1),
65 	LMRC_INITLEVEL_FM =		(1 << 2),
66 	LMRC_INITLEVEL_REGS =		(1 << 3),
67 	LMRC_INITLEVEL_INTR =		(1 << 4),
68 	LMRC_INITLEVEL_SYNC =		(1 << 5),
69 	LMRC_INITLEVEL_HBA =		(1 << 6),
70 	LMRC_INITLEVEL_NODE =		(1 << 7),
71 	LMRC_INITLEVEL_TASKQ =		(1 << 8),
72 	LMRC_INITLEVEL_AEN =		(1 << 9),
73 	LMRC_INITLEVEL_MFICMDS =	(1 << 10),
74 	LMRC_INITLEVEL_MPTCMDS =	(1 << 11),
75 	LMRC_INITLEVEL_FW =		(1 << 12),
76 };
77 
78 #define	INITLEVEL_SET(_lmrc, name)				\
79 	do {							\
80 		VERIFY(!((_lmrc)->l_init_level & (name)));	\
81 		(_lmrc)->l_init_level |= (name);		\
82 	} while (0)
83 
84 #define	INITLEVEL_CLEAR(_lmrc, name)				\
85 	do {							\
86 		VERIFY((_lmrc)->l_init_level & (name));	\
87 		(_lmrc)->l_init_level &= ~(name);		\
88 	} while (0)
89 
90 #define	INITLEVEL_ACTIVE(_lmrc, name)				\
91 	(((_lmrc)->l_init_level & (name)) != 0)
92 
93 struct lmrc_dma {
94 	ddi_dma_handle_t	ld_hdl;
95 	ddi_acc_handle_t	ld_acc;
96 	void			*ld_buf;
97 	size_t			ld_len;
98 };
99 
100 typedef	void (lmrc_mpt_cmd_cb_t)(lmrc_t *, lmrc_mpt_cmd_t *);
101 
102 struct lmrc_mpt_cmd {
103 	list_node_t		mpt_node;
104 	lmrc_dma_t		mpt_chain_dma;
105 	lmrc_dma_t		mpt_sense_dma;
106 	uint16_t		mpt_smid;
107 	uint16_t		mpt_queue;
108 
109 	lmrc_mfi_cmd_t		*mpt_mfi;
110 	struct scsi_pkt		*mpt_pkt;
111 
112 	void			*mpt_io_frame;
113 	Mpi25IeeeSgeChain64_t	*mpt_chain;
114 	uint8_t			*mpt_sense;
115 
116 	kmutex_t		mpt_lock;
117 	kcondvar_t		mpt_cv;
118 	boolean_t		mpt_complete;
119 	hrtime_t		mpt_timeout;
120 
121 	taskq_ent_t		mpt_tqent;
122 
123 	lmrc_t			*mpt_lmrc;
124 };
125 
126 typedef	void (lmrc_mfi_cmd_cb_t)(lmrc_t *, lmrc_mfi_cmd_t *);
127 
128 struct lmrc_mfi_cmd {
129 	list_node_t		mfi_node;
130 	lmrc_dma_t		mfi_frame_dma;
131 
132 	lmrc_mfi_frame_t	*mfi_frame;
133 	uint32_t		mfi_idx;
134 	uint16_t		mfi_smid;
135 
136 	kmutex_t		mfi_lock;
137 	kcondvar_t		mfi_cv;
138 	lmrc_dma_t		mfi_data_dma;
139 
140 	lmrc_mfi_cmd_cb_t	*mfi_callback;
141 	taskq_ent_t		mfi_tqent;
142 	lmrc_mpt_cmd_t		*mfi_mpt;
143 
144 	lmrc_t			*mfi_lmrc;
145 };
146 
147 struct lmrc_scsa_cmd {
148 	lmrc_mpt_cmd_t		*sc_mpt;
149 	lmrc_tgt_t		*sc_tgt;
150 };
151 
152 struct lmrc_tgt {
153 	krwlock_t		tgt_lock;
154 	kmutex_t		tgt_mpt_active_lock;
155 	list_t			tgt_mpt_active;
156 	lmrc_t			*tgt_lmrc;
157 	uint16_t		tgt_dev_id;
158 	uint8_t			tgt_type;
159 	uint8_t			tgt_interconnect_type;
160 	uint64_t		tgt_wwn;
161 	lmrc_pd_info_t		*tgt_pd_info;
162 	char			tgt_wwnstr[SCSI_WWN_BUFLEN];
163 };
164 
165 struct lmrc {
166 	dev_info_t		*l_dip;
167 	dev_info_t		*l_raid_dip;
168 	dev_info_t		*l_phys_dip;
169 
170 	char			l_iocname[16];
171 
172 	lmrc_init_level_t	l_init_level;
173 	lmrc_adapter_class_t	l_class;
174 
175 	kmutex_t		l_mpt_cmd_lock;
176 	list_t			l_mpt_cmd_list;
177 	lmrc_mpt_cmd_t		**l_mpt_cmds;
178 
179 	kmutex_t		l_mfi_cmd_lock;
180 	list_t			l_mfi_cmd_list;
181 	lmrc_mfi_cmd_t		**l_mfi_cmds;
182 
183 	lmrc_dma_t		l_ioreq_dma;
184 	lmrc_dma_t		l_reply_dma;
185 
186 	ksema_t			l_ioctl_sema;
187 
188 	kthread_t		*l_thread;
189 	kmutex_t		l_thread_lock;
190 	kcondvar_t		l_thread_cv;
191 	boolean_t		l_thread_stop;
192 
193 	lmrc_ctrl_info_t	*l_ctrl_info;
194 
195 	ddi_intr_handle_t	*l_intr_htable;
196 	size_t			l_intr_htable_size;
197 	int			l_intr_types;
198 	int			l_intr_type;
199 	int			l_intr_count;
200 	uint_t			l_intr_pri;
201 	int			l_intr_cap;
202 
203 	uint16_t		*l_last_reply_idx;
204 	uint32_t		l_rphi[LMRC_MAX_REPLY_POST_HOST_INDEX];
205 
206 	int			l_fm_capabilities;
207 
208 	/* Controller HW/FW properties */
209 	boolean_t		l_disable_online_ctrl_reset;
210 	boolean_t		l_fw_fault;
211 	boolean_t		l_fw_msix_enabled;
212 	boolean_t		l_fw_sync_cache_support;
213 	size_t			l_fw_supported_vd_count;
214 	size_t			l_fw_supported_pd_count;
215 
216 	boolean_t		l_msix_combined;
217 	boolean_t		l_atomic_desc_support;
218 	boolean_t		l_64bit_dma_support;
219 	boolean_t		l_max_256_vd_support;
220 	boolean_t		l_use_seqnum_jbod_fp;
221 	boolean_t		l_pdmap_tgtid_support;
222 
223 	size_t			l_max_reply_queues;
224 	size_t			l_max_num_sge;
225 	size_t			l_max_sge_in_main_msg;
226 	size_t			l_max_sge_in_chain;
227 
228 	uint32_t		l_fw_outstanding_cmds;
229 	uint32_t		l_max_fw_cmds;
230 	uint32_t		l_max_scsi_cmds;
231 	size_t			l_reply_q_depth;
232 
233 	size_t			l_reply_alloc_sz;
234 	size_t			l_io_frames_alloc_sz;
235 	size_t			l_max_chain_frame_sz;
236 	size_t			l_chain_offset_mfi_pthru;
237 	size_t			l_chain_offset_io_request;
238 
239 	size_t			l_max_raid_map_sz;
240 	size_t			l_max_map_sz;
241 	size_t			l_current_map_sz;
242 
243 	size_t			l_nvme_page_sz;
244 
245 	scsi_hba_tran_t		*l_hba_tran;
246 	dev_info_t		*l_iport;
247 	taskq_t			*l_taskq;
248 
249 	ddi_dma_attr_t		l_dma_attr;
250 	ddi_dma_attr_t		l_dma_attr_32;
251 	ddi_device_acc_attr_t	l_acc_attr;
252 	caddr_t			l_regmap;
253 	ddi_acc_handle_t	l_reghandle;
254 	kmutex_t		l_reg_lock;
255 
256 	krwlock_t		l_raidmap_lock;
257 	lmrc_fw_raid_map_t	*l_raidmap;
258 
259 	krwlock_t		l_pdmap_lock;
260 	lmrc_pd_map_t		*l_pdmap;
261 
262 	lmrc_tgt_t		l_targets[LMRC_MAX_LD + LMRC_MAX_PD];
263 
264 	scsi_hba_tgtmap_t	*l_raid_tgtmap;
265 	scsi_hba_tgtmap_t	*l_phys_tgtmap;
266 
267 };
268 
269 int lmrc_check_acc_handle(ddi_acc_handle_t);
270 int lmrc_check_dma_handle(ddi_dma_handle_t);
271 
272 void lmrc_dma_build_sgl(lmrc_t *, lmrc_mpt_cmd_t *, const ddi_dma_cookie_t *,
273     uint_t);
274 size_t lmrc_dma_get_size(lmrc_dma_t *);
275 void lmrc_dma_set_addr64(lmrc_dma_t *, uint64_t *);
276 void lmrc_dma_set_addr32(lmrc_dma_t *, uint32_t *);
277 int lmrc_dma_alloc(lmrc_t *, ddi_dma_attr_t, lmrc_dma_t *, size_t, uint64_t,
278     uint_t);
279 void lmrc_dma_free(lmrc_dma_t *);
280 
281 void lmrc_disable_intr(lmrc_t *);
282 void lmrc_enable_intr(lmrc_t *);
283 uint_t lmrc_intr_ack(lmrc_t *);
284 
285 void lmrc_send_atomic_request(lmrc_t *, lmrc_atomic_req_desc_t);
286 void lmrc_send_request(lmrc_t *, lmrc_req_desc_t);
287 lmrc_atomic_req_desc_t lmrc_build_atomic_request(lmrc_t *, lmrc_mpt_cmd_t *,
288     uint8_t);
289 
290 void lmrc_fm_ereport(lmrc_t *, const char *);
291 
292 int lmrc_hba_attach(lmrc_t *);
293 void lmrc_hba_detach(lmrc_t *);
294 
295 void lmrc_thread(void *);
296 int lmrc_adapter_init(lmrc_t *);
297 int lmrc_ioc_init(lmrc_t *);
298 int lmrc_fw_init(lmrc_t *);
299 
300 void lmrc_tgt_init(lmrc_tgt_t *, uint16_t, char *, lmrc_pd_info_t *);
301 void lmrc_tgt_clear(lmrc_tgt_t *);
302 lmrc_tgt_t *lmrc_tgt_find(lmrc_t *, struct scsi_device *);
303 
304 void lmrc_wakeup_mfi(lmrc_t *, lmrc_mfi_cmd_t *);
305 void lmrc_issue_mfi(lmrc_t *, lmrc_mfi_cmd_t *, lmrc_mfi_cmd_cb_t *);
306 int lmrc_wait_mfi(lmrc_t *, lmrc_mfi_cmd_t *, uint8_t);
307 int lmrc_issue_blocked_mfi(lmrc_t *, lmrc_mfi_cmd_t *);
308 
309 int lmrc_poll_for_reply(lmrc_t *, lmrc_mpt_cmd_t *);
310 int lmrc_process_replies(lmrc_t *, uint8_t);
311 
312 int lmrc_abort_mpt(lmrc_t *, lmrc_tgt_t *, lmrc_mpt_cmd_t *);
313 lmrc_mpt_cmd_t *lmrc_get_mpt(lmrc_t *);
314 void lmrc_put_mpt(lmrc_mpt_cmd_t *);
315 
316 lmrc_mfi_cmd_t *lmrc_get_dcmd(lmrc_t *, uint16_t, uint32_t, uint32_t, uint_t);
317 void lmrc_put_dcmd(lmrc_t *, lmrc_mfi_cmd_t *);
318 
319 lmrc_mfi_cmd_t *lmrc_get_mfi(lmrc_t *);
320 void lmrc_put_mfi(lmrc_mfi_cmd_t *);
321 int lmrc_abort_outstanding_mfi(lmrc_t *, const size_t);
322 int lmrc_build_mptmfi_passthru(lmrc_t *, lmrc_mfi_cmd_t *);
323 
324 int lmrc_start_aen(lmrc_t *);
325 
326 int lmrc_ctrl_shutdown(lmrc_t *);
327 
328 /*
329  * per-target active MPT command list functions
330  */
331 
332 /*
333  * lmrc_tgt_first_active_mpt
334  *
335  * Returns the first active MPT command of a target. The MPT command is returned
336  * locked.
337  */
338 static inline lmrc_mpt_cmd_t *
339 lmrc_tgt_first_active_mpt(lmrc_tgt_t *tgt)
340 {
341 	lmrc_mpt_cmd_t *mpt = list_head(&tgt->tgt_mpt_active);
342 
343 	ASSERT(mutex_owned(&tgt->tgt_mpt_active_lock));
344 
345 	if (mpt != NULL)
346 		mutex_enter(&mpt->mpt_lock);
347 
348 	return (mpt);
349 }
350 
351 /*
352  * lmrc_tgt_next_active_mpt
353  *
354  * Given a MPT command on the active list of a target, returns the next active
355  * MPT command on that target. The given MPT command is unlocked, and the next
356  * command is returned locked.
357  */
358 static inline lmrc_mpt_cmd_t *
359 lmrc_tgt_next_active_mpt(lmrc_tgt_t *tgt, lmrc_mpt_cmd_t *mpt)
360 {
361 	lmrc_mpt_cmd_t *nextmpt;
362 
363 	ASSERT(mutex_owned(&tgt->tgt_mpt_active_lock));
364 
365 	nextmpt = list_next(&tgt->tgt_mpt_active, mpt);
366 	mutex_exit(&mpt->mpt_lock);
367 
368 	if (nextmpt != NULL)
369 		mutex_enter(&nextmpt->mpt_lock);
370 
371 	return (nextmpt);
372 }
373 
374 /*
375  * lmrc_tgt_add_active_mpt
376  *
377  * Adds a MPT command to the active command list of a target. The command
378  * mutex must be held. There's no risk for a deadlock against the iterator
379  * functions.
380  */
381 static inline void
382 lmrc_tgt_add_active_mpt(lmrc_tgt_t *tgt, lmrc_mpt_cmd_t *mpt)
383 {
384 	ASSERT(mutex_owned(&mpt->mpt_lock));
385 
386 	mutex_enter(&tgt->tgt_mpt_active_lock);
387 	list_insert_head(&tgt->tgt_mpt_active, mpt);
388 	mutex_exit(&tgt->tgt_mpt_active_lock);
389 }
390 
391 /*
392  * lmrc_tgt_rem_active_mpt
393  *
394  * Removes a MPT command from the active command list of a target. The command
395  * must not be locked to avoid a deadlock with against the iterator functions.
396  */
397 static inline void
398 lmrc_tgt_rem_active_mpt(lmrc_tgt_t *tgt, lmrc_mpt_cmd_t *mpt)
399 {
400 	ASSERT(!mutex_owned(&mpt->mpt_lock));
401 
402 	mutex_enter(&tgt->tgt_mpt_active_lock);
403 	list_remove(&tgt->tgt_mpt_active, mpt);
404 	mutex_exit(&tgt->tgt_mpt_active_lock);
405 }
406 
407 /*
408  * Number of replies to be processed before the Reply Post Host register
409  * is updated.
410  */
411 #define	LMRC_THRESHOLD_REPLY_COUNT		50
412 
413 #endif /* _LMRC_H */
414