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