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