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