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