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 * 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 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 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 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