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 Oxide Computer Company
14 */
15
16 /*
17 * libnvme logic specific to Solidigm (nee Intel) device families. This
18 * currently supports the Intel P5510, Intel/Solidigm P5[56]20, and the Solidigm
19 * PS10[13]0.
20 *
21 * The Intel/Solidigm 5000 series controllers all used the same PCI device ID.
22 * To determine the specific device in question that we should be targeting we
23 * must use the subsystem ID. The P5[56]20 was branded under both Solidigm and
24 * Intel and therefore may use both vendor IDs. For the PS10[13]0 series we opt
25 * to break out all the subsystems again here because of the above experience.
26 */
27
28 #include <string.h>
29 #include <sys/sysmacros.h>
30 #include <sys/debug.h>
31 #include <sys/nvme/solidigm.h>
32
33 #include "libnvme_impl.h"
34
35 CTASSERT(SOLIDIGM_P5XXX_LOG_SMART == SOLIDIGM_P5XXX_LOG_SMART);
36
37 static bool
nvme_solidigm_outlier_var_len(uint64_t * outp,const void * data,size_t len)38 nvme_solidigm_outlier_var_len(uint64_t *outp, const void *data, size_t len)
39 {
40 solidigm_vul_p5xxx_lat_outlier_t hdr;
41
42 if (len < sizeof (solidigm_vul_p5xxx_lat_outlier_t)) {
43 return (false);
44 }
45
46 (void) memcpy(&hdr, data, sizeof (hdr));
47 *outp = (uint64_t)hdr.lao_nents * sizeof (soligm_vul_lat_ent_t);
48 return (true);
49 }
50
51 static const nvme_log_page_info_t solidigm_log_read_lat = {
52 .nlpi_short = "solidigm/rlat",
53 .nlpi_human = "Read Latency",
54 .nlpi_lid = SOLIDIGM_P5XXX_LOG_READ_LAT,
55 .nlpi_csi = NVME_CSI_NVM,
56 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
57 .nlpi_source = NVME_LOG_DISC_S_DB,
58 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
59 .nlpi_len = sizeof (solidigm_vul_p5xxx_lat_t)
60 };
61
62 static const nvme_log_page_info_t solidigm_log_write_lat = {
63 .nlpi_short = "solidigm/wlat",
64 .nlpi_human = "Write Latency",
65 .nlpi_lid = SOLIDIGM_P5XXX_LOG_WRITE_LAT,
66 .nlpi_csi = NVME_CSI_NVM,
67 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
68 .nlpi_source = NVME_LOG_DISC_S_DB,
69 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
70 .nlpi_len = sizeof (solidigm_vul_p5xxx_lat_t)
71 };
72
73 /*
74 * While the P5000 series and the PS10x0 series use the same structure for this
75 * log, they show up at different log addresses due to the OCP support in the
76 * latter.
77 */
78 static const nvme_log_page_info_t solidigm_p5xxx_log_temp = {
79 .nlpi_short = "solidigm/temp",
80 .nlpi_human = "Temperature Statistics",
81 .nlpi_lid = SOLIDIGM_P5XXX_LOG_TEMP,
82 .nlpi_csi = NVME_CSI_NVM,
83 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
84 .nlpi_source = NVME_LOG_DISC_S_DB,
85 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
86 .nlpi_len = sizeof (solidigm_vul_temp_t)
87 };
88
89 static const nvme_log_page_info_t solidigm_ps10x0_log_temp = {
90 .nlpi_short = "solidigm/temp",
91 .nlpi_human = "Temperature Statistics",
92 .nlpi_lid = SOLIDIGM_PS10x0_LOG_TEMP,
93 .nlpi_csi = NVME_CSI_NVM,
94 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
95 .nlpi_source = NVME_LOG_DISC_S_DB,
96 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
97 .nlpi_len = sizeof (solidigm_vul_temp_t)
98 };
99
100 /*
101 * The SMART log page is shared across all devices that we support currently.
102 */
103 static const nvme_log_page_info_t solidigm_log_smart = {
104 .nlpi_short = "solidigm/smart",
105 .nlpi_human = "SMART",
106 .nlpi_lid = SOLIDIGM_PS10x0_LOG_SMART,
107 .nlpi_csi = NVME_CSI_NVM,
108 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
109 .nlpi_source = NVME_LOG_DISC_S_DB,
110 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
111 .nlpi_len = sizeof (solidigm_vul_smart_log_t)
112 };
113
114 static const nvme_log_page_info_t solidigm_log_io_queue = {
115 .nlpi_short = "solidigm/ioqueue",
116 .nlpi_human = "I/O Queue Metrics",
117 .nlpi_lid = SOLIDIGM_P5XXX_LOG_IO_QUEUE,
118 .nlpi_csi = NVME_CSI_NVM,
119 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
120 .nlpi_source = NVME_LOG_DISC_S_DB,
121 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
122 .nlpi_len = sizeof (solidigm_vul_p5xxx_ioq_t)
123 };
124
125 static const nvme_log_page_info_t solidigm_log_name = {
126 .nlpi_short = "solidigm/name",
127 .nlpi_human = "Drive Marketing Name",
128 .nlpi_lid = SOLIDIGM_P5XXX_LOG_MARK_DESC,
129 .nlpi_csi = NVME_CSI_NVM,
130 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
131 .nlpi_source = NVME_LOG_DISC_S_DB,
132 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
133 .nlpi_len = SOLIDIGM_VUC_MARK_NAME_LEN
134 };
135
136 static const nvme_log_page_info_t solidigm_log_power = {
137 .nlpi_short = "solidigm/power",
138 .nlpi_human = "Power Usage",
139 .nlpi_lid = SOLIDIGM_P5X20_LOG_POWER,
140 .nlpi_csi = NVME_CSI_NVM,
141 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
142 .nlpi_source = NVME_LOG_DISC_S_DB,
143 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
144 .nlpi_len = sizeof (solidigm_vul_p5x2x_power_t)
145 };
146
147 static const nvme_log_page_info_t solidigm_log_gc = {
148 .nlpi_short = "solidigm/gc",
149 .nlpi_human = "Garbage Collection",
150 .nlpi_lid = SOLIDIGM_P5XXX_LOG_GC,
151 .nlpi_csi = NVME_CSI_NVM,
152 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
153 .nlpi_source = NVME_LOG_DISC_S_DB,
154 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
155 .nlpi_len = sizeof (solidigm_vul_p5xxx_gc_t)
156 };
157
158 static const nvme_log_page_info_t solidigm_log_outlier = {
159 .nlpi_short = "solidigm/outlier",
160 .nlpi_human = "Latency Outlier",
161 .nlpi_lid = SOLIDIGM_P5XXX_LOG_OUTLIER,
162 .nlpi_csi = NVME_CSI_NVM,
163 .nlpi_kind = NVME_LOG_ID_VENDOR_SPECIFIC,
164 .nlpi_source = NVME_LOG_DISC_S_DB,
165 .nlpi_scope = NVME_LOG_SCOPE_CTRL,
166 .nlpi_len = sizeof (solidigm_vul_p5xxx_lat_outlier_t),
167 .nlpi_var_func = nvme_solidigm_outlier_var_len
168 };
169
170 static const nvme_log_page_info_t *intel_p5510_log_pages[] = {
171 &solidigm_log_read_lat, &solidigm_log_write_lat,
172 &solidigm_p5xxx_log_temp, &solidigm_log_smart, &solidigm_log_io_queue,
173 &solidigm_log_name, &solidigm_log_gc, &solidigm_log_outlier
174 };
175
176 static const nvme_vsd_ident_t intel_p5510_idents[] = {
177 {
178 .nvdi_vid = INTEL_PCI_VID,
179 .nvdi_did = SOLIDIGM_P5XXX_DID,
180 .nvdi_svid = INTEL_PCI_VID,
181 .nvdi_sdid = SOLIDIGM_P5510_U2_SDID,
182 .nvdi_subsys = true,
183 .nvdi_human = "Intel P5510"
184 }
185 };
186
187 const nvme_vsd_t intel_p5510 = {
188 .nvd_ident = intel_p5510_idents,
189 .nvd_nident = ARRAY_SIZE(intel_p5510_idents),
190 .nvd_logs = intel_p5510_log_pages,
191 .nvd_nlogs = ARRAY_SIZE(intel_p5510_log_pages)
192 };
193
194 static const nvme_log_page_info_t *solidigm_p5x20_log_pages[] = {
195 &ocp_log_smart, &solidigm_log_read_lat, &solidigm_log_write_lat,
196 &solidigm_p5xxx_log_temp, &solidigm_log_smart, &solidigm_log_io_queue,
197 &solidigm_log_name, &solidigm_log_power, &solidigm_log_gc,
198 &solidigm_log_outlier
199
200 };
201
202 static const nvme_vsd_ident_t intel_p5x20_idents[] = {
203 {
204 .nvdi_vid = INTEL_PCI_VID,
205 .nvdi_did = SOLIDIGM_P5XXX_DID,
206 .nvdi_svid = INTEL_PCI_VID,
207 .nvdi_sdid = SOLIDIGM_P5520_U2_SDID,
208 .nvdi_subsys = true,
209 .nvdi_human = "Intel P5520 U.2"
210 }, {
211 .nvdi_vid = INTEL_PCI_VID,
212 .nvdi_did = SOLIDIGM_P5XXX_DID,
213 .nvdi_svid = INTEL_PCI_VID,
214 .nvdi_sdid = SOLIDIGM_P5520_E1S_9P5MM_SDID,
215 .nvdi_subsys = true,
216 .nvdi_human = "Intel P5520 E1.S 9.5mm"
217 }, {
218 .nvdi_vid = INTEL_PCI_VID,
219 .nvdi_did = SOLIDIGM_P5XXX_DID,
220 .nvdi_svid = INTEL_PCI_VID,
221 .nvdi_sdid = SOLIDIGM_P5520_E1S_15MM_SDID,
222 .nvdi_subsys = true,
223 .nvdi_human = "Intel P5520 E1.S 15mm"
224 }, {
225 .nvdi_vid = INTEL_PCI_VID,
226 .nvdi_did = SOLIDIGM_P5XXX_DID,
227 .nvdi_svid = INTEL_PCI_VID,
228 .nvdi_sdid = SOLIDIGM_P5520_E1L_SDID,
229 .nvdi_subsys = true,
230 .nvdi_human = "Intel P5520 E1.L 15mm"
231 }, {
232 .nvdi_vid = INTEL_PCI_VID,
233 .nvdi_did = SOLIDIGM_P5XXX_DID,
234 .nvdi_svid = INTEL_PCI_VID,
235 .nvdi_sdid = SOLIDIGM_P5620_U2_SDID,
236 .nvdi_subsys = true,
237 .nvdi_human = "Intel P5620 U.2"
238 }, {
239 .nvdi_vid = SOLIDIGM_PCI_VID,
240 .nvdi_did = SOLIDIGM_P5XXX_DID,
241 .nvdi_svid = SOLIDIGM_PCI_VID,
242 .nvdi_sdid = SOLIDIGM_P5520_U2_SDID,
243 .nvdi_subsys = true,
244 .nvdi_human = "Solidigm P5520 U.2"
245 }, {
246 .nvdi_vid = SOLIDIGM_PCI_VID,
247 .nvdi_did = SOLIDIGM_P5XXX_DID,
248 .nvdi_svid = SOLIDIGM_PCI_VID,
249 .nvdi_sdid = SOLIDIGM_P5520_E1S_9P5MM_SDID,
250 .nvdi_subsys = true,
251 .nvdi_human = "Solidigm P5520 E1.S 9.5mm"
252 }, {
253 .nvdi_vid = SOLIDIGM_PCI_VID,
254 .nvdi_did = SOLIDIGM_P5XXX_DID,
255 .nvdi_svid = SOLIDIGM_PCI_VID,
256 .nvdi_sdid = SOLIDIGM_P5520_E1S_15MM_SDID,
257 .nvdi_subsys = true,
258 .nvdi_human = "Solidigm P5520 E1.S 15mm"
259 }, {
260 .nvdi_vid = SOLIDIGM_PCI_VID,
261 .nvdi_did = SOLIDIGM_P5XXX_DID,
262 .nvdi_svid = SOLIDIGM_PCI_VID,
263 .nvdi_sdid = SOLIDIGM_P5520_E1L_SDID,
264 .nvdi_subsys = true,
265 .nvdi_human = "Solidigm P5520 E1.L 15mm"
266 }, {
267 .nvdi_vid = SOLIDIGM_PCI_VID,
268 .nvdi_did = SOLIDIGM_P5XXX_DID,
269 .nvdi_svid = SOLIDIGM_PCI_VID,
270 .nvdi_sdid = SOLIDIGM_P5620_U2_SDID,
271 .nvdi_subsys = true,
272 .nvdi_human = "Solidigm P5620 U.2"
273 }
274 };
275
276 const nvme_vsd_t solidigm_p5x20 = {
277 .nvd_ident = intel_p5x20_idents,
278 .nvd_nident = ARRAY_SIZE(intel_p5x20_idents),
279 .nvd_logs = solidigm_p5x20_log_pages,
280 .nvd_nlogs = ARRAY_SIZE(solidigm_p5x20_log_pages)
281 };
282
283
284 static const nvme_log_page_info_t *solidigm_ps10x0_log_pages[] = {
285 &ocp_log_smart, &ocp_log_errrec, &ocp_log_fwact, &ocp_log_lat,
286 &ocp_log_devcap, &ocp_log_unsup, &solidigm_log_smart,
287 &solidigm_ps10x0_log_temp
288 };
289
290 static const nvme_vsd_ident_t solidigm_ps10x0_idents[] = {
291 {
292 .nvdi_vid = SOLIDIGM_PCI_VID,
293 .nvdi_did = SOLIDIGM_PS10X0_DID,
294 .nvdi_svid = SOLIDIGM_PCI_VID,
295 .nvdi_sdid = SOLIDIGM_PS1010_U2_SDID,
296 .nvdi_subsys = true,
297 .nvdi_human = "Solidigm PS1010 U.2"
298 }, {
299 .nvdi_vid = SOLIDIGM_PCI_VID,
300 .nvdi_did = SOLIDIGM_PS10X0_DID,
301 .nvdi_svid = SOLIDIGM_PCI_VID,
302 .nvdi_sdid = SOLIDIGM_PS1010_E3_SDID,
303 .nvdi_subsys = true,
304 .nvdi_human = "Solidigm PS1010 E3.S"
305 }, {
306 .nvdi_vid = SOLIDIGM_PCI_VID,
307 .nvdi_did = SOLIDIGM_PS10X0_DID,
308 .nvdi_svid = SOLIDIGM_PCI_VID,
309 .nvdi_sdid = SOLIDIGM_PS1030_U2_SDID,
310 .nvdi_subsys = true,
311 .nvdi_human = "Solidigm PS1030 U.2"
312 }, {
313 .nvdi_vid = SOLIDIGM_PCI_VID,
314 .nvdi_did = SOLIDIGM_PS10X0_DID,
315 .nvdi_svid = SOLIDIGM_PCI_VID,
316 .nvdi_sdid = SOLIDIGM_PS1010_E3_SDID,
317 .nvdi_subsys = true,
318 .nvdi_human = "Solidigm PS1030 E3.S"
319 }
320 };
321
322 const nvme_vsd_t solidigm_ps10x0 = {
323 .nvd_ident = solidigm_ps10x0_idents,
324 .nvd_nident = ARRAY_SIZE(solidigm_ps10x0_idents),
325 .nvd_logs = solidigm_ps10x0_log_pages,
326 .nvd_nlogs = ARRAY_SIZE(solidigm_ps10x0_log_pages)
327 };
328