xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/lmrc/lmrc.h (revision da7fc762b82ced1a0ec19a51e04cdf823187ec77)
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 2024 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 	LMRC_INITLEVEL_RAID =		(1 << 13),
77 	LMRC_INITLEVEL_PHYS =		(1 << 14),
78 };
79 
80 #define	INITLEVEL_SET(_lmrc, name)				\
81 	do {							\
82 		VERIFY(!((_lmrc)->l_init_level & (name)));	\
83 		(_lmrc)->l_init_level |= (name);		\
84 	} while (0)
85 
86 #define	INITLEVEL_CLEAR(_lmrc, name)				\
87 	do {							\
88 		VERIFY((_lmrc)->l_init_level & (name));	\
89 		(_lmrc)->l_init_level &= ~(name);		\
90 	} while (0)
91 
92 #define	INITLEVEL_ACTIVE(_lmrc, name)				\
93 	(((_lmrc)->l_init_level & (name)) != 0)
94 
95 struct lmrc_dma {
96 	ddi_dma_handle_t	ld_hdl;
97 	ddi_acc_handle_t	ld_acc;
98 	void			*ld_buf;
99 	size_t			ld_len;
100 };
101 
102 typedef	void (lmrc_mpt_cmd_cb_t)(lmrc_t *, lmrc_mpt_cmd_t *);
103 
104 struct lmrc_mpt_cmd {
105 	list_node_t		mpt_node;
106 	lmrc_dma_t		mpt_chain_dma;
107 	lmrc_dma_t		mpt_sense_dma;
108 	uint16_t		mpt_smid;
109 	uint16_t		mpt_queue;
110 
111 	lmrc_mfi_cmd_t		*mpt_mfi;
112 	struct scsi_pkt		*mpt_pkt;
113 
114 	void			*mpt_io_frame;
115 	Mpi25IeeeSgeChain64_t	*mpt_chain;
116 	uint8_t			*mpt_sense;
117 
118 	kmutex_t		mpt_lock;
119 	kcondvar_t		mpt_cv;
120 	boolean_t		mpt_complete;
121 	hrtime_t		mpt_timeout;
122 
123 	taskq_ent_t		mpt_tqent;
124 
125 	lmrc_t			*mpt_lmrc;
126 };
127 
128 typedef	void (lmrc_mfi_cmd_cb_t)(lmrc_t *, lmrc_mfi_cmd_t *);
129 
130 struct lmrc_mfi_cmd {
131 	list_node_t		mfi_node;
132 	lmrc_dma_t		mfi_frame_dma;
133 
134 	lmrc_mfi_frame_t	*mfi_frame;
135 	uint32_t		mfi_idx;
136 	uint16_t		mfi_smid;
137 
138 	kmutex_t		mfi_lock;
139 	kcondvar_t		mfi_cv;
140 	lmrc_dma_t		mfi_data_dma;
141 
142 	lmrc_mfi_cmd_cb_t	*mfi_callback;
143 	taskq_ent_t		mfi_tqent;
144 	lmrc_mpt_cmd_t		*mfi_mpt;
145 
146 	lmrc_t			*mfi_lmrc;
147 };
148 
149 struct lmrc_scsa_cmd {
150 	lmrc_mpt_cmd_t		*sc_mpt;
151 	lmrc_tgt_t		*sc_tgt;
152 };
153 
154 struct lmrc_tgt {
155 	krwlock_t		tgt_lock;
156 	kmutex_t		tgt_mpt_active_lock;
157 	list_t			tgt_mpt_active;
158 	lmrc_t			*tgt_lmrc;
159 	uint16_t		tgt_dev_id;
160 	uint8_t			tgt_type;
161 	uint8_t			tgt_interconnect_type;
162 	uint64_t		tgt_wwn;
163 	lmrc_pd_info_t		*tgt_pd_info;
164 	char			tgt_wwnstr[SCSI_WWN_BUFLEN];
165 };
166 
167 struct lmrc {
168 	dev_info_t		*l_dip;
169 	dev_info_t		*l_raid_dip;
170 	dev_info_t		*l_phys_dip;
171 
172 	char			l_iocname[16];
173 
174 	lmrc_init_level_t	l_init_level;
175 	lmrc_adapter_class_t	l_class;
176 
177 	kmutex_t		l_mpt_cmd_lock;
178 	list_t			l_mpt_cmd_list;
179 	lmrc_mpt_cmd_t		**l_mpt_cmds;
180 
181 	kmutex_t		l_mfi_cmd_lock;
182 	list_t			l_mfi_cmd_list;
183 	lmrc_mfi_cmd_t		**l_mfi_cmds;
184 
185 	lmrc_dma_t		l_ioreq_dma;
186 	lmrc_dma_t		l_reply_dma;
187 
188 	ksema_t			l_ioctl_sema;
189 
190 	kthread_t		*l_thread;
191 	kmutex_t		l_thread_lock;
192 	kcondvar_t		l_thread_cv;
193 	boolean_t		l_thread_stop;
194 
195 	lmrc_ctrl_info_t	*l_ctrl_info;
196 
197 	ddi_intr_handle_t	*l_intr_htable;
198 	size_t			l_intr_htable_size;
199 	int			l_intr_types;
200 	int			l_intr_type;
201 	int			l_intr_count;
202 	uint_t			l_intr_pri;
203 	int			l_intr_cap;
204 
205 	uint16_t		*l_last_reply_idx;
206 	uint32_t		l_rphi[LMRC_MAX_REPLY_POST_HOST_INDEX];
207 
208 	int			l_fm_capabilities;
209 
210 	/* Controller HW/FW properties */
211 	boolean_t		l_disable_online_ctrl_reset;
212 	boolean_t		l_fw_fault;
213 	boolean_t		l_fw_msix_enabled;
214 	boolean_t		l_fw_sync_cache_support;
215 	size_t			l_fw_supported_vd_count;
216 	size_t			l_fw_supported_pd_count;
217 
218 	boolean_t		l_msix_combined;
219 	boolean_t		l_atomic_desc_support;
220 	boolean_t		l_64bit_dma_support;
221 	boolean_t		l_max_256_vd_support;
222 	boolean_t		l_use_seqnum_jbod_fp;
223 	boolean_t		l_pdmap_tgtid_support;
224 
225 	size_t			l_max_reply_queues;
226 	size_t			l_max_num_sge;
227 	size_t			l_max_sge_in_main_msg;
228 	size_t			l_max_sge_in_chain;
229 
230 	uint32_t		l_fw_outstanding_cmds;
231 	uint32_t		l_max_fw_cmds;
232 	uint32_t		l_max_scsi_cmds;
233 	size_t			l_reply_q_depth;
234 
235 	size_t			l_reply_alloc_sz;
236 	size_t			l_io_frames_alloc_sz;
237 	size_t			l_max_chain_frame_sz;
238 	size_t			l_chain_offset_mfi_pthru;
239 	size_t			l_chain_offset_io_request;
240 
241 	size_t			l_max_raid_map_sz;
242 	size_t			l_max_map_sz;
243 	size_t			l_current_map_sz;
244 
245 	size_t			l_nvme_page_sz;
246 
247 	scsi_hba_tran_t		*l_hba_tran;
248 	dev_info_t		*l_iport;
249 	taskq_t			*l_taskq;
250 
251 	ddi_dma_attr_t		l_dma_attr;
252 	ddi_dma_attr_t		l_dma_attr_32;
253 	ddi_device_acc_attr_t	l_acc_attr;
254 	caddr_t			l_regmap;
255 	ddi_acc_handle_t	l_reghandle;
256 	kmutex_t		l_reg_lock;
257 
258 	krwlock_t		l_raidmap_lock;
259 	lmrc_fw_raid_map_t	*l_raidmap;
260 
261 	krwlock_t		l_pdmap_lock;
262 	lmrc_pd_map_t		*l_pdmap;
263 
264 	lmrc_tgt_t		l_targets[LMRC_MAX_LD + LMRC_MAX_PD];
265 
266 	scsi_hba_tgtmap_t	*l_raid_tgtmap;
267 	scsi_hba_tgtmap_t	*l_phys_tgtmap;
268 
269 };
270 
271 int lmrc_check_acc_handle(ddi_acc_handle_t);
272 int lmrc_check_dma_handle(ddi_dma_handle_t);
273 
274 void lmrc_dma_build_sgl(lmrc_t *, lmrc_mpt_cmd_t *, const ddi_dma_cookie_t *,
275     uint_t);
276 size_t lmrc_dma_get_size(lmrc_dma_t *);
277 void lmrc_dma_set_addr64(lmrc_dma_t *, uint64_t *);
278 void lmrc_dma_set_addr32(lmrc_dma_t *, uint32_t *);
279 int lmrc_dma_alloc(lmrc_t *, ddi_dma_attr_t, lmrc_dma_t *, size_t, uint64_t,
280     uint_t);
281 void lmrc_dma_free(lmrc_dma_t *);
282 
283 void lmrc_disable_intr(lmrc_t *);
284 void lmrc_enable_intr(lmrc_t *);
285 uint_t lmrc_intr_ack(lmrc_t *);
286 
287 void lmrc_send_atomic_request(lmrc_t *, lmrc_atomic_req_desc_t);
288 void lmrc_send_request(lmrc_t *, lmrc_req_desc_t);
289 lmrc_atomic_req_desc_t lmrc_build_atomic_request(lmrc_t *, lmrc_mpt_cmd_t *,
290     uint8_t);
291 
292 void lmrc_fm_ereport(lmrc_t *, const char *);
293 
294 int lmrc_hba_attach(lmrc_t *);
295 void lmrc_hba_detach(lmrc_t *);
296 
297 void lmrc_thread(void *);
298 int lmrc_adapter_init(lmrc_t *);
299 int lmrc_ioc_init(lmrc_t *);
300 int lmrc_fw_init(lmrc_t *);
301 
302 void lmrc_tgt_init(lmrc_tgt_t *, uint16_t, char *, lmrc_pd_info_t *);
303 void lmrc_tgt_clear(lmrc_tgt_t *);
304 lmrc_tgt_t *lmrc_tgt_find(lmrc_t *, struct scsi_device *);
305 
306 void lmrc_wakeup_mfi(lmrc_t *, lmrc_mfi_cmd_t *);
307 void lmrc_issue_mfi(lmrc_t *, lmrc_mfi_cmd_t *, lmrc_mfi_cmd_cb_t *);
308 int lmrc_wait_mfi(lmrc_t *, lmrc_mfi_cmd_t *, uint8_t);
309 int lmrc_issue_blocked_mfi(lmrc_t *, lmrc_mfi_cmd_t *);
310 
311 int lmrc_poll_for_reply(lmrc_t *, lmrc_mpt_cmd_t *);
312 int lmrc_process_replies(lmrc_t *, uint8_t);
313 
314 int lmrc_abort_mpt(lmrc_t *, lmrc_tgt_t *, lmrc_mpt_cmd_t *);
315 lmrc_mpt_cmd_t *lmrc_get_mpt(lmrc_t *);
316 void lmrc_put_mpt(lmrc_mpt_cmd_t *);
317 
318 lmrc_mfi_cmd_t *lmrc_get_dcmd(lmrc_t *, uint16_t, uint32_t, uint32_t, uint_t);
319 void lmrc_put_dcmd(lmrc_t *, lmrc_mfi_cmd_t *);
320 
321 lmrc_mfi_cmd_t *lmrc_get_mfi(lmrc_t *);
322 void lmrc_put_mfi(lmrc_mfi_cmd_t *);
323 int lmrc_abort_outstanding_mfi(lmrc_t *, const size_t);
324 int lmrc_build_mptmfi_passthru(lmrc_t *, lmrc_mfi_cmd_t *);
325 
326 int lmrc_start_aen(lmrc_t *);
327 
328 int lmrc_ctrl_shutdown(lmrc_t *);
329 
330 /*
331  * per-target active MPT command list functions
332  */
333 
334 /*
335  * lmrc_tgt_first_active_mpt
336  *
337  * Returns the first active MPT command of a target. The MPT command is returned
338  * locked.
339  */
340 static inline lmrc_mpt_cmd_t *
341 lmrc_tgt_first_active_mpt(lmrc_tgt_t *tgt)
342 {
343 	lmrc_mpt_cmd_t *mpt = list_head(&tgt->tgt_mpt_active);
344 
345 	ASSERT(mutex_owned(&tgt->tgt_mpt_active_lock));
346 
347 	if (mpt != NULL)
348 		mutex_enter(&mpt->mpt_lock);
349 
350 	return (mpt);
351 }
352 
353 /*
354  * lmrc_tgt_next_active_mpt
355  *
356  * Given a MPT command on the active list of a target, returns the next active
357  * MPT command on that target. The given MPT command is unlocked, and the next
358  * command is returned locked.
359  */
360 static inline lmrc_mpt_cmd_t *
361 lmrc_tgt_next_active_mpt(lmrc_tgt_t *tgt, lmrc_mpt_cmd_t *mpt)
362 {
363 	lmrc_mpt_cmd_t *nextmpt;
364 
365 	ASSERT(mutex_owned(&tgt->tgt_mpt_active_lock));
366 
367 	nextmpt = list_next(&tgt->tgt_mpt_active, mpt);
368 	mutex_exit(&mpt->mpt_lock);
369 
370 	if (nextmpt != NULL)
371 		mutex_enter(&nextmpt->mpt_lock);
372 
373 	return (nextmpt);
374 }
375 
376 /*
377  * lmrc_tgt_add_active_mpt
378  *
379  * Adds a MPT command to the active command list of a target. The command
380  * mutex must be held. There's no risk for a deadlock against the iterator
381  * functions.
382  */
383 static inline void
384 lmrc_tgt_add_active_mpt(lmrc_tgt_t *tgt, lmrc_mpt_cmd_t *mpt)
385 {
386 	ASSERT(mutex_owned(&mpt->mpt_lock));
387 
388 	mutex_enter(&tgt->tgt_mpt_active_lock);
389 	list_insert_head(&tgt->tgt_mpt_active, mpt);
390 	mutex_exit(&tgt->tgt_mpt_active_lock);
391 }
392 
393 /*
394  * lmrc_tgt_rem_active_mpt
395  *
396  * Removes a MPT command from the active command list of a target. The command
397  * must not be locked to avoid a deadlock with against the iterator functions.
398  */
399 static inline void
400 lmrc_tgt_rem_active_mpt(lmrc_tgt_t *tgt, lmrc_mpt_cmd_t *mpt)
401 {
402 	ASSERT(!mutex_owned(&mpt->mpt_lock));
403 
404 	mutex_enter(&tgt->tgt_mpt_active_lock);
405 	list_remove(&tgt->tgt_mpt_active, mpt);
406 	mutex_exit(&tgt->tgt_mpt_active_lock);
407 }
408 
409 /*
410  * Number of replies to be processed before the Reply Post Host register
411  * is updated.
412  */
413 #define	LMRC_THRESHOLD_REPLY_COUNT		50
414 
415 #endif /* _LMRC_H */
416