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 2015 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 #ifndef _NVME_VAR_H 17 #define _NVME_VAR_H 18 19 #include <sys/ddi.h> 20 #include <sys/sunddi.h> 21 #include <sys/blkdev.h> 22 #include <sys/taskq_impl.h> 23 24 /* 25 * NVMe driver state 26 */ 27 28 #ifdef __cplusplus 29 /* extern "C" { */ 30 #endif 31 32 #define NVME_FMA_INIT 0x1 33 #define NVME_REGS_MAPPED 0x2 34 #define NVME_ADMIN_QUEUE 0x4 35 #define NVME_CTRL_LIMITS 0x8 36 #define NVME_INTERRUPTS 0x10 37 38 #define NVME_MIN_ADMIN_QUEUE_LEN 16 39 #define NVME_MIN_IO_QUEUE_LEN 16 40 #define NVME_DEFAULT_ADMIN_QUEUE_LEN 256 41 #define NVME_DEFAULT_IO_QUEUE_LEN 1024 42 #define NVME_DEFAULT_ASYNC_EVENT_LIMIT 10 43 #define NVME_MIN_ASYNC_EVENT_LIMIT 1 44 45 #define NVME_ADMIN_CMD_TIMEOUT 100000 46 47 typedef struct nvme nvme_t; 48 typedef struct nvme_namespace nvme_namespace_t; 49 typedef struct nvme_dma nvme_dma_t; 50 typedef struct nvme_cmd nvme_cmd_t; 51 typedef struct nvme_qpair nvme_qpair_t; 52 typedef struct nvme_task_arg nvme_task_arg_t; 53 54 struct nvme_dma { 55 ddi_dma_handle_t nd_dmah; 56 ddi_acc_handle_t nd_acch; 57 ddi_dma_cookie_t nd_cookie; 58 uint_t nd_ncookie; 59 caddr_t nd_memp; 60 size_t nd_len; 61 }; 62 63 struct nvme_cmd { 64 nvme_sqe_t nc_sqe; 65 nvme_cqe_t nc_cqe; 66 67 void (*nc_callback)(void *); 68 bd_xfer_t *nc_xfer; 69 boolean_t nc_completed; 70 uint16_t nc_sqid; 71 72 nvme_dma_t *nc_dma; 73 74 kmutex_t nc_mutex; 75 kcondvar_t nc_cv; 76 77 taskq_ent_t nc_tqent; 78 nvme_t *nc_nvme; 79 }; 80 81 struct nvme_qpair { 82 size_t nq_nentry; 83 84 nvme_dma_t *nq_sqdma; 85 nvme_sqe_t *nq_sq; 86 uint_t nq_sqhead; 87 uint_t nq_sqtail; 88 uintptr_t nq_sqtdbl; 89 90 nvme_dma_t *nq_cqdma; 91 nvme_cqe_t *nq_cq; 92 uint_t nq_cqhead; 93 uint_t nq_cqtail; 94 uintptr_t nq_cqhdbl; 95 96 nvme_cmd_t **nq_cmd; 97 uint16_t nq_next_cmd; 98 uint_t nq_active_cmds; 99 int nq_phase; 100 101 kmutex_t nq_mutex; 102 }; 103 104 struct nvme { 105 dev_info_t *n_dip; 106 int n_progress; 107 108 caddr_t n_regs; 109 ddi_acc_handle_t n_regh; 110 111 kmem_cache_t *n_cmd_cache; 112 113 size_t n_inth_sz; 114 ddi_intr_handle_t *n_inth; 115 int n_intr_cnt; 116 uint_t n_intr_pri; 117 int n_intr_cap; 118 int n_intr_type; 119 int n_intr_types; 120 121 boolean_t n_dead; 122 boolean_t n_strict_version; 123 boolean_t n_ignore_unknown_vendor_status; 124 uint32_t n_admin_queue_len; 125 uint32_t n_io_queue_len; 126 uint16_t n_async_event_limit; 127 uint16_t n_abort_command_limit; 128 uint64_t n_max_data_transfer_size; 129 boolean_t n_volatile_write_cache_enabled; 130 int n_error_log_len; 131 132 int n_nssr_supported; 133 int n_doorbell_stride; 134 int n_timeout; 135 int n_arbitration_mechanisms; 136 int n_cont_queues_reqd; 137 int n_max_queue_entries; 138 int n_pageshift; 139 int n_pagesize; 140 141 int n_namespace_count; 142 int n_ioq_count; 143 144 nvme_identify_ctrl_t *n_idctl; 145 146 nvme_qpair_t *n_adminq; 147 nvme_qpair_t **n_ioq; 148 149 nvme_namespace_t *n_ns; 150 151 ddi_dma_attr_t n_queue_dma_attr; 152 ddi_dma_attr_t n_prp_dma_attr; 153 ddi_dma_attr_t n_sgl_dma_attr; 154 ddi_device_acc_attr_t n_reg_acc_attr; 155 ddi_iblock_cookie_t n_fm_ibc; 156 int n_fm_cap; 157 158 ksema_t n_abort_sema; 159 160 ddi_taskq_t *n_cmd_taskq; 161 162 nvme_error_log_entry_t *n_error_log; 163 nvme_health_log_t *n_health_log; 164 nvme_fwslot_log_t *n_fwslot_log; 165 166 /* errors detected by driver */ 167 uint32_t n_dma_bind_err; 168 uint32_t n_abort_failed; 169 uint32_t n_cmd_timeout; 170 uint32_t n_cmd_aborted; 171 uint32_t n_async_resubmit_failed; 172 uint32_t n_wrong_logpage; 173 uint32_t n_unknown_logpage; 174 uint32_t n_too_many_cookies; 175 uint32_t n_admin_queue_full; 176 177 /* errors detected by hardware */ 178 uint32_t n_data_xfr_err; 179 uint32_t n_internal_err; 180 uint32_t n_abort_rq_err; 181 uint32_t n_abort_sq_del; 182 uint32_t n_nvm_cap_exc; 183 uint32_t n_nvm_ns_notrdy; 184 uint32_t n_inv_cq_err; 185 uint32_t n_inv_qid_err; 186 uint32_t n_max_qsz_exc; 187 uint32_t n_inv_int_vect; 188 uint32_t n_inv_log_page; 189 uint32_t n_inv_format; 190 uint32_t n_inv_q_del; 191 uint32_t n_cnfl_attr; 192 uint32_t n_inv_prot; 193 uint32_t n_readonly; 194 195 /* errors reported by asynchronous events */ 196 uint32_t n_diagfail_event; 197 uint32_t n_persistent_event; 198 uint32_t n_transient_event; 199 uint32_t n_fw_load_event; 200 uint32_t n_reliability_event; 201 uint32_t n_temperature_event; 202 uint32_t n_spare_event; 203 uint32_t n_vendor_event; 204 uint32_t n_unknown_event; 205 206 }; 207 208 struct nvme_namespace { 209 nvme_t *ns_nvme; 210 bd_handle_t ns_bd_hdl; 211 212 uint32_t ns_id; 213 size_t ns_block_count; 214 size_t ns_block_size; 215 size_t ns_best_block_size; 216 217 boolean_t ns_ignore; 218 219 nvme_identify_nsid_t *ns_idns; 220 221 /* 222 * Section 7.7 of the spec describes how to get a unique ID for 223 * the controller: the vendor ID, the model name and the serial 224 * number shall be unique when combined. 225 * 226 * We add the hex namespace ID to get a unique ID for the namespace. 227 */ 228 char ns_devid[4 + 1 + 20 + 1 + 40 + 1 + 8 + 1]; 229 }; 230 231 struct nvme_task_arg { 232 nvme_t *nt_nvme; 233 nvme_cmd_t *nt_cmd; 234 }; 235 236 #ifdef __cplusplus 237 /* } */ 238 #endif 239 240 #endif /* _NVME_VAR_H */ 241