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