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 
16 #ifndef _LMRC_RAID_H
17 #define	_LMRC_RAID_H
18 
19 #include <sys/types.h>
20 #include <sys/debug.h>
21 
22 #include <sys/scsi/adapters/mfi/mfi_evt.h>
23 #include <sys/scsi/adapters/mfi/mfi_ld.h>
24 
25 #include <sys/scsi/adapters/mpi/mpi2_type.h>
26 #include <sys/scsi/adapters/mpi/mpi2.h>
27 #include <sys/scsi/adapters/mpi/mpi2_cnfg.h>
28 #include <sys/scsi/adapters/mpi/mpi2_ioc.h>
29 
30 typedef struct lmrc_raidctx_g35		lmrc_raidctx_g35_t;
31 typedef struct lmrc_devhdl_info		lmrc_devhdl_info_t;
32 typedef struct lmrc_array_info		lmrc_array_info_t;
33 typedef struct lmrc_quad_element	lmrc_quad_element_t;
34 typedef struct lmrc_span_info		lmrc_span_info_t;
35 typedef struct lmrc_ld_span		lmrc_ld_span_t;
36 typedef struct lmrc_span_block_info	lmrc_span_block_info_t;
37 typedef struct lmrc_ld_raid		lmrc_ld_raid_t;
38 typedef struct lmrc_ld_span_map		lmrc_ld_span_map_t;
39 
40 typedef struct lmrc_fw_raid_map		lmrc_fw_raid_map_t;
41 typedef struct lmrc_raid_map_desc	lmrc_raid_map_desc_t;
42 
43 
44 #include "lmrc.h"
45 
46 #pragma pack(1)
47 
48 struct lmrc_raidctx_g35 {
49 	uint8_t		rc_type:4;
50 	uint8_t		rc_nseg:4;
51 	uint8_t		rc_rsvd0;
52 	uint16_t	rc_timeout;
53 
54 	struct {
55 		uint16_t	rf_rsvd:1;
56 		uint16_t	rf_sld:1;
57 		uint16_t	rf_c2f:1;
58 		uint16_t	rf_fwn:1;
59 		uint16_t	rf_sqn:1;
60 		uint16_t	rf_sbs:1;
61 		uint16_t	rf_rw:1;
62 		uint16_t	rf_log:1;
63 		uint16_t	rf_cpu_sel:4;
64 		uint16_t	rf_set_divert:4;
65 	} rc_routing_flags;
66 
67 	uint16_t	rc_ld_tgtid;
68 	uint64_t	rc_reg_lock_rowlba;
69 	uint32_t	rc_reg_lock_len;
70 
71 	union {
72 		uint16_t	rc_next_lmid;
73 		uint16_t	rc_peer_smid;
74 	} rc_smid;
75 
76 	uint8_t		rc_exstatus;
77 	uint8_t		rc_status;
78 
79 	struct {
80 		uint8_t	rf_pref_cpu:1;
81 		uint8_t	rf_rsvd1:3;
82 		uint8_t	rf_io_subtype:3;
83 		uint8_t	rf_rsvd2:1;
84 	} rc_raid_flags;
85 
86 	uint8_t		rc_span_arm;
87 	uint16_t	rc_cfg_seqnum;
88 	struct {
89 		uint16_t	rc_num_sge:12;
90 		uint16_t	rc_rsvd1:3;
91 		uint16_t	rc_stream_detected:1;
92 	};
93 	uint8_t		rc_rsvd2[2];
94 };
95 CTASSERT(sizeof (lmrc_raidctx_g35_t) == 0x20);
96 
97 /*
98  * rc_raid_flags values
99  */
100 #define	LMRC_RF_IO_SUBTYPE_NONE			0
101 #define	LMRC_RF_IO_SUBTYPE_SYSTEM_PD		1
102 #define	LMRC_RF_IO_SUBTYPE_RMW_DATA		2
103 #define	LMRC_RF_IO_SUBTYPE_RMW_P		3
104 #define	LMRC_RF_IO_SUBTYPE_RMW_Q		4
105 #define	LMRC_RF_IO_SUBTYPE_CACHE_BYPASS		6
106 #define	LMRC_RF_IO_SUBTYPE_LDIO_BW_LIMIT	7
107 
108 /*
109  * RAID map related structures
110  */
111 #define	LMRC_MIN_MAP_SIZE			0x10000
112 
113 #define	LMRC_MAX_SPAN_DEPTH		8
114 #define	LMRC_MAX_QUAD_DEPTH		LMRC_SPAN_DEPTH
115 #define	LMRC_MAX_ROW_SIZE		32
116 #define	LMRC_MAX_LOGICAL_DRIVES_EXT	256
117 #define	LMRC_MAX_LOGICAL_DRIVES_DYN	512
118 #define	LMRC_MAX_ARRAYS			128
119 #define	LMRC_MAX_ARRAYS_EXT		256
120 #define	LMRC_MAX_API_ARRAYS_EXT		(LMRC_MAX_ARRAYS_EXT)
121 #define	LMRC_MAX_API_ARRAYS_DYN		512
122 
123 #define	LMRC_RAIDMAP_MAX_SPAN_DEPTH	(LMRC_MAX_SPAN_DEPTH)
124 #define	LMRC_RAIDMAP_MAX_ROW_SIZE	(LMRC_MAX_ROW_SIZE)
125 #define	LMRC_RAIDMAP_ARRAYS		(LMRC_MAX_ARRAYS)
126 #define	LMRC_RAIDMAP_MAX_PHYS_DEV_DYN	512
127 
128 #define	LMRC_DEVHDL_IFTYPE_UNKNOWN		0
129 #define	LMRC_DEVHDL_IFTYPE_PARALLEL_SCSI	1
130 #define	LMRC_DEVHDL_IFTYPE_SAS_PD		2
131 #define	LMRC_DEVHDL_IFTYPE_SATA_PD		3
132 #define	LMRC_DEVHDL_IFTYPE_FC_PD		4
133 #define	LMRC_DEVHDL_IFTYPE_NVME_PD		5
134 
135 #define	LMRC_DEVHDL_INVALID			0xFFFF
136 
137 struct lmrc_devhdl_info {
138 	uint16_t	di_cur_devhdl;
139 	uint8_t		di_valid_handles;
140 	uint8_t		di_iftype;
141 	uint16_t	di_devhdl[2];
142 };
143 
144 struct lmrc_array_info {
145 	uint16_t	ai_pd[LMRC_RAIDMAP_MAX_ROW_SIZE];
146 };
147 
148 struct lmrc_quad_element {
149 	uint64_t	qe_logstart;
150 	uint64_t	qe_logend;
151 	uint64_t	qe_offset_in_span;
152 	uint32_t	qe_diff;
153 	uint32_t	qe_reserved;
154 };
155 
156 struct lmrc_span_info {
157 	uint32_t		si_nelem;
158 	uint32_t		si_reserved;
159 	lmrc_quad_element_t	si_quad[LMRC_RAIDMAP_MAX_SPAN_DEPTH];
160 };
161 
162 struct lmrc_ld_span {
163 	uint64_t	ls_start_blk;
164 	uint64_t	ls_nblk;
165 	uint16_t	ls_arrayref;
166 	uint8_t		ls_span_rowsz;
167 	uint8_t		ls_span_row_datasz;
168 	uint8_t		ls_reserved[4];
169 };
170 
171 struct lmrc_span_block_info {
172 	uint64_t	sbi_num_rows;
173 	lmrc_ld_span_t	sbi_span;
174 	lmrc_span_info_t	sbi_block_span_info;
175 };
176 
177 struct lmrc_ld_raid {
178 	struct {
179 		uint32_t lc_fp_cap:1;
180 		uint32_t lc_ra_cap:1;
181 		uint32_t lc_reserved5:2;
182 		uint32_t lc_ld_pi_mode:4;
183 		uint32_t lc_pd_pi_mode:4;
184 		uint32_t lc_encryption_type:8;
185 		uint32_t lc_fp_write_cap:1;
186 		uint32_t lc_fp_read_cap:1;
187 		uint32_t lc_fp_write_across_stripe:1;
188 		uint32_t lc_fp_read_across_stripe:1;
189 		uint32_t lc_fp_non_rw_cap:1;
190 		uint32_t lc_tm_cap:1;
191 		uint32_t lc_fp_cache_bypass_cap:1;
192 		uint32_t lc_reserved4:5;
193 	} lr_cap;
194 
195 	uint32_t lr_reserved6;
196 	uint64_t lr_size;
197 
198 	uint8_t lr_span_depth;
199 	uint8_t lr_level;
200 	uint8_t lr_stripe_shift;
201 	uint8_t lr_row_size;
202 
203 	uint8_t lr_row_data_size;
204 	uint8_t lr_write_mode;
205 	uint8_t lr_prl;
206 	uint8_t lr_srl;
207 
208 	uint16_t lr_target_id;
209 	uint8_t lr_ld_state;
210 	uint8_t lr_reg_type_req_on_write;
211 	uint8_t lr_mod_factor;
212 	uint8_t lr_reg_type_req_on_read;
213 	uint16_t lr_seq_num;
214 
215 	struct {
216 		uint32_t lf_reserved:30;
217 		uint32_t lf_reg_type_req_on_read_ls_valid:1;
218 		uint32_t lf_ld_sync_required:1;
219 	} lr_flags;
220 
221 	uint8_t lr_lun[8];
222 	uint8_t lr_fp_io_timeout_for_ld;
223 	uint8_t lr_reserved2[3];
224 	uint32_t lr_logical_block_length;
225 
226 	struct {
227 		uint32_t le_reserved1:24;
228 		uint32_t le_ld_logical_block_exp:4;
229 		uint32_t le_ld_pi_exp:4;
230 	} lr_exponent;
231 	uint8_t lr_reserved3[0x80 - 0x38];
232 };
233 
234 struct lmrc_ld_span_map {
235 	lmrc_ld_raid_t sm_ld_raid;
236 	uint8_t sm_data_arm_map[LMRC_RAIDMAP_MAX_ROW_SIZE];
237 	lmrc_span_block_info_t sm_span_block[LMRC_RAIDMAP_MAX_SPAN_DEPTH];
238 };
239 
240 /*
241  * RAID map descriptor
242  */
243 struct lmrc_raid_map_desc {
244 	uint32_t	rmd_type;	/* descriptor type */
245 	uint32_t	rmd_off;	/* offset in RAID map buffer */
246 	uint32_t	rmd_bufsz;	/* size of buffer */
247 	uint32_t	rmd_desc_nelem;	/* number of elements in buffer */
248 };
249 
250 #define	LMRC_RAID_MAP_DESC_TYPE_DEVHDL	0
251 #define	LMRC_RAID_MAP_DESC_TYPE_LD_ID	1
252 #define	LMRC_RAID_MAP_DESC_TYPE_ARRAY	2
253 #define	LMRC_RAID_MAP_DESC_TYPE_SPAN	3
254 #define	LMRC_RAID_MAP_DESC_TYPES_COUNT	(LMRC_RAID_MAP_DESC_TYPE_SPAN + 1)
255 
256 /*
257  * Dynamic RAID Map
258  */
259 struct lmrc_fw_raid_map {
260 	uint32_t	rm_raidmap_sz;
261 	uint32_t	rm_desc_table_off;
262 	uint32_t	rm_desc_table_sz;
263 	uint32_t	rm_desc_table_nelem;
264 	uint64_t	rm_pci_thres_bandw;
265 	uint32_t	rm_rsvd[3];
266 
267 	uint8_t		rm_fp_pd_io_timeout;
268 	uint8_t		rm_rsvd2[3];
269 	uint32_t	rm_rmw_fp_seqnum;
270 	uint16_t	rm_ld_count;
271 	uint16_t	rm_ar_count;
272 	uint16_t	rm_span_count;
273 	uint16_t	rm_rsvd3[3];
274 
275 	/*
276 	 * FreeBSD uses this for driver purposes and claims FW doesn't
277 	 * modify this.
278 	 */
279 	union {
280 		struct {
281 			lmrc_devhdl_info_t	*rm_devhdl;
282 			uint16_t		*rm_ld_id;
283 			lmrc_array_info_t	*rm_array;
284 			lmrc_ld_span_map_t	*rm_span;
285 		};
286 		void		*rm_desc_ptrs[LMRC_RAID_MAP_DESC_TYPES_COUNT];
287 	};
288 
289 	/* Variable size descriptor table. */
290 	lmrc_raid_map_desc_t	rm_desc_table[LMRC_RAID_MAP_DESC_TYPES_COUNT];
291 
292 	/* Variable size buffer containing all data */
293 	uint32_t	rm_desc_data[0];
294 };
295 
296 #pragma pack(0)
297 
298 /* RAID map accessor functions */
299 static inline lmrc_ld_raid_t *
lmrc_ld_raid_get(uint16_t ld_id,lmrc_fw_raid_map_t * rm)300 lmrc_ld_raid_get(uint16_t ld_id, lmrc_fw_raid_map_t *rm)
301 {
302 	if (ld_id >= rm->rm_ld_count)
303 		return (NULL);
304 
305 	return (&rm->rm_span[ld_id].sm_ld_raid);
306 }
307 
308 static inline uint16_t
lmrc_ld_id_get(uint16_t tgtid,lmrc_fw_raid_map_t * rm)309 lmrc_ld_id_get(uint16_t tgtid, lmrc_fw_raid_map_t *rm)
310 {
311 	ASSERT3U(tgtid, <,
312 	    rm->rm_desc_table[LMRC_RAID_MAP_DESC_TYPE_LD_ID].rmd_desc_nelem);
313 
314 	uint32_t nelem =
315 	    rm->rm_desc_table[LMRC_RAID_MAP_DESC_TYPE_LD_ID].rmd_desc_nelem;
316 
317 	if (tgtid >= nelem)
318 		return (LMRC_DEVHDL_INVALID);
319 
320 	return (rm->rm_ld_id[tgtid]);
321 }
322 
323 static inline uint16_t
lmrc_tgtid_get(uint16_t ld_id,lmrc_fw_raid_map_t * rm)324 lmrc_tgtid_get(uint16_t ld_id, lmrc_fw_raid_map_t *rm)
325 {
326 	lmrc_ld_raid_t *raid;
327 
328 	if (ld_id >= rm->rm_ld_count)
329 		return (LMRC_DEVHDL_INVALID);
330 
331 	raid = lmrc_ld_raid_get(ld_id, rm);
332 	if (raid == NULL)
333 		return (LMRC_DEVHDL_INVALID);
334 
335 	return (raid->lr_target_id);
336 }
337 
338 /* other helper functions */
339 static inline boolean_t
lmrc_cmd_is_rw(uint8_t cdb0)340 lmrc_cmd_is_rw(uint8_t cdb0)
341 {
342 	switch (cdb0) {
343 	case SCMD_READ:
344 	case SCMD_WRITE:
345 	case SCMD_READ_G1:
346 	case SCMD_WRITE_G1:
347 	case SCMD_READ_G4:
348 	case SCMD_WRITE_G4:
349 	case SCMD_READ_G5:
350 	case SCMD_WRITE_G5:
351 		return (B_TRUE);
352 	default:
353 		return (B_FALSE);
354 	}
355 }
356 
357 typedef lmrc_raidctx_g35_t	MPI25_SCSI_IO_VENDOR_UNIQUE;
358 #define	MPI25_SCSI_IO_VENDOR_UNIQUE_REGION
359 #include <sys/scsi/adapters/mpi/mpi2_init.h>
360 
361 int lmrc_setup_raidmap(lmrc_t *);
362 void lmrc_free_raidmap(lmrc_t *);
363 
364 boolean_t lmrc_ld_tm_capable(lmrc_t *, uint16_t);
365 
366 int lmrc_get_ld_list(lmrc_t *);
367 
368 int lmrc_raid_attach(dev_info_t *);
369 int lmrc_raid_detach(dev_info_t *);
370 
371 int lmrc_raid_aen_handler(lmrc_t *, mfi_evt_detail_t *);
372 
373 #endif /* _LMRC_RAID_H */
374