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