Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : :
9 : : #include "spdk_internal/cunit.h"
10 : :
11 : : #define UNIT_TEST_NO_VTOPHYS
12 : :
13 : : #include "nvme/nvme_pcie.c"
14 : : #include "nvme/nvme_pcie_common.c"
15 : : #include "common/lib/nvme/common_stubs.h"
16 : :
17 : : pid_t g_spdk_nvme_pid;
18 [ - + ]: 12 : DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0);
19 [ - + ]: 6 : DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0);
20 : :
21 [ # # ]: 0 : DEFINE_STUB(nvme_get_quirks, uint64_t, (const struct spdk_pci_id *id), 0);
22 : :
23 [ # # ]: 0 : DEFINE_STUB(nvme_wait_for_completion, int,
24 : : (struct spdk_nvme_qpair *qpair,
25 : : struct nvme_completion_poll_status *status), 0);
26 : 0 : DEFINE_STUB_V(nvme_completion_poll_cb, (void *arg, const struct spdk_nvme_cpl *cpl));
27 : :
28 [ # # ]: 0 : DEFINE_STUB(nvme_ctrlr_submit_admin_request, int, (struct spdk_nvme_ctrlr *ctrlr,
29 : : struct nvme_request *req), 0);
30 : :
31 [ # # ]: 0 : DEFINE_STUB(nvme_ctrlr_proc_get_devhandle, struct spdk_pci_device *,
32 : : (struct spdk_nvme_ctrlr *ctrlr), NULL);
33 [ - + ]: 12 : DEFINE_STUB(spdk_pci_device_unmap_bar, int, (struct spdk_pci_device *dev, uint32_t bar, void *addr),
34 : : 0);
35 [ # # ]: 0 : DEFINE_STUB(spdk_pci_device_attach, int, (struct spdk_pci_driver *driver, spdk_pci_enum_cb enum_cb,
36 : : void *enum_ctx, struct spdk_pci_addr *pci_address), 0);
37 [ # # ]: 0 : DEFINE_STUB(spdk_pci_device_claim, int, (struct spdk_pci_device *dev), 0);
38 : 0 : DEFINE_STUB_V(spdk_pci_device_unclaim, (struct spdk_pci_device *dev));
39 : 0 : DEFINE_STUB_V(spdk_pci_device_detach, (struct spdk_pci_device *device));
40 [ # # ]: 0 : DEFINE_STUB(spdk_pci_device_cfg_write16, int, (struct spdk_pci_device *dev, uint16_t value,
41 : : uint32_t offset), 0);
42 [ # # ]: 0 : DEFINE_STUB(spdk_pci_device_cfg_read16, int, (struct spdk_pci_device *dev, uint16_t *value,
43 : : uint32_t offset), 0);
44 [ # # ]: 0 : DEFINE_STUB(spdk_pci_device_get_id, struct spdk_pci_id, (struct spdk_pci_device *dev), {0});
45 [ # # ]: 0 : DEFINE_STUB(spdk_pci_event_listen, int, (void), 0);
46 [ # # ]: 0 : DEFINE_STUB(spdk_pci_register_error_handler, int, (spdk_pci_error_handler sighandler, void *ctx),
47 : : 0);
48 : 0 : DEFINE_STUB_V(spdk_pci_unregister_error_handler, (spdk_pci_error_handler sighandler));
49 [ # # ]: 0 : DEFINE_STUB(spdk_pci_enumerate, int,
50 : : (struct spdk_pci_driver *driver, spdk_pci_enum_cb enum_cb, void *enum_ctx),
51 : : -1);
52 : :
53 : 6 : SPDK_LOG_REGISTER_COMPONENT(nvme)
54 : :
55 : : struct dev_mem_resource {
56 : : uint64_t phys_addr;
57 : : uint64_t len;
58 : : void *addr;
59 : : };
60 : :
61 : : struct nvme_pcie_ut_bdev_io {
62 : : struct iovec iovs[NVME_MAX_SGL_DESCRIPTORS];
63 : : int iovpos;
64 : : };
65 : :
66 : : struct nvme_driver *g_spdk_nvme_driver = NULL;
67 : :
68 : : int
69 : 12 : spdk_pci_device_map_bar(struct spdk_pci_device *dev, uint32_t bar,
70 : : void **mapped_addr, uint64_t *phys_addr, uint64_t *size)
71 : : {
72 : 12 : struct dev_mem_resource *dev_mem_res = (void *)dev;
73 : :
74 : 12 : *mapped_addr = dev_mem_res->addr;
75 : 12 : *phys_addr = dev_mem_res->phys_addr;
76 : 12 : *size = dev_mem_res->len;
77 : :
78 : 12 : return 0;
79 : : }
80 : :
81 : : void
82 : 18 : nvme_ctrlr_fail(struct spdk_nvme_ctrlr *ctrlr, bool hot_remove)
83 : : {
84 : 18 : CU_ASSERT(ctrlr != NULL);
85 [ + - ]: 18 : if (hot_remove) {
86 : 18 : ctrlr->is_removed = true;
87 : : }
88 : :
89 : 18 : ctrlr->is_failed = true;
90 : 18 : }
91 : :
92 : : static uint64_t g_vtophys_size = 0;
93 : :
94 [ # # ]: 0 : DEFINE_RETURN_MOCK(spdk_vtophys, uint64_t);
95 : : uint64_t
96 : 12330 : spdk_vtophys(const void *buf, uint64_t *size)
97 : : {
98 [ + + + + ]: 12330 : if (size && g_vtophys_size > 0) {
99 : 60 : *size = g_vtophys_size;
100 : : }
101 : :
102 [ - + + + : 12330 : HANDLE_RETURN_MOCK(spdk_vtophys);
+ + ]
103 : :
104 : 12270 : return (uintptr_t)buf;
105 : : }
106 : :
107 [ # # ]: 0 : DEFINE_STUB(spdk_pci_device_get_addr, struct spdk_pci_addr, (struct spdk_pci_device *dev), {});
108 [ # # ]: 0 : DEFINE_STUB(nvme_ctrlr_probe, int, (const struct spdk_nvme_transport_id *trid,
109 : : struct spdk_nvme_probe_ctx *probe_ctx, void *devhandle), 0);
110 [ - + - + ]: 18 : DEFINE_STUB(spdk_pci_device_is_removed, bool, (struct spdk_pci_device *dev), false);
111 [ - + ]: 6 : DEFINE_STUB(nvme_get_ctrlr_by_trid_unsafe, struct spdk_nvme_ctrlr *,
112 : : (const struct spdk_nvme_transport_id *trid, const char *hostnqn), NULL);
113 [ # # ]: 0 : DEFINE_STUB(spdk_nvme_ctrlr_get_regs_csts, union spdk_nvme_csts_register,
114 : : (struct spdk_nvme_ctrlr *ctrlr), {});
115 [ # # ]: 0 : DEFINE_STUB(nvme_ctrlr_get_process, struct spdk_nvme_ctrlr_process *,
116 : : (struct spdk_nvme_ctrlr *ctrlr, pid_t pid), NULL);
117 [ # # # # ]: 0 : DEFINE_STUB(nvme_completion_is_retry, bool, (const struct spdk_nvme_cpl *cpl), false);
118 : 0 : DEFINE_STUB_V(spdk_nvme_qpair_print_command, (struct spdk_nvme_qpair *qpair,
119 : : struct spdk_nvme_cmd *cmd));
120 : 0 : DEFINE_STUB_V(spdk_nvme_qpair_print_completion, (struct spdk_nvme_qpair *qpair,
121 : : struct spdk_nvme_cpl *cpl));
122 : :
123 : : static void
124 : 126 : prp_list_prep(struct nvme_tracker *tr, struct nvme_request *req, uint32_t *prp_index)
125 : : {
126 [ - + ]: 126 : memset(req, 0, sizeof(*req));
127 [ - + ]: 126 : memset(tr, 0, sizeof(*tr));
128 : 126 : tr->req = req;
129 : 126 : tr->prp_sgl_bus_addr = 0xDEADBEEF;
130 [ + + ]: 126 : if (prp_index) {
131 : 102 : *prp_index = 0;
132 : : }
133 : 126 : }
134 : :
135 : : static void
136 : 6 : test_prp_list_append(void)
137 : : {
138 : 5 : struct nvme_request req;
139 : 5 : struct nvme_tracker tr;
140 : 6 : struct spdk_nvme_ctrlr ctrlr = {};
141 : 5 : uint32_t prp_index;
142 : :
143 : 6 : ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
144 : : /* Non-DWORD-aligned buffer (invalid) */
145 : 6 : prp_list_prep(&tr, &req, &prp_index);
146 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100001, 0x1000,
147 : : 0x1000) == -EFAULT);
148 : :
149 : : /* 512-byte buffer, 4K aligned */
150 : 6 : prp_list_prep(&tr, &req, &prp_index);
151 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x200, 0x1000) == 0);
152 : 6 : CU_ASSERT(prp_index == 1);
153 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
154 : :
155 : : /* 512-byte buffer, non-4K-aligned */
156 : 6 : prp_list_prep(&tr, &req, &prp_index);
157 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x108000, 0x200, 0x1000) == 0);
158 : 6 : CU_ASSERT(prp_index == 1);
159 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x108000);
160 : :
161 : : /* 4K buffer, 4K aligned */
162 : 6 : prp_list_prep(&tr, &req, &prp_index);
163 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x1000,
164 : : 0x1000) == 0);
165 : 6 : CU_ASSERT(prp_index == 1);
166 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
167 : :
168 : : /* 4K buffer, non-4K aligned */
169 : 6 : prp_list_prep(&tr, &req, &prp_index);
170 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x1000,
171 : : 0x1000) == 0);
172 : 6 : CU_ASSERT(prp_index == 2);
173 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
174 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp2 == 0x101000);
175 : :
176 : : /* 8K buffer, 4K aligned */
177 : 6 : prp_list_prep(&tr, &req, &prp_index);
178 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x2000,
179 : : 0x1000) == 0);
180 : 6 : CU_ASSERT(prp_index == 2);
181 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
182 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp2 == 0x101000);
183 : :
184 : : /* 8K buffer, non-4K aligned */
185 : 6 : prp_list_prep(&tr, &req, &prp_index);
186 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x2000,
187 : : 0x1000) == 0);
188 : 6 : CU_ASSERT(prp_index == 3);
189 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
190 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
191 : 6 : CU_ASSERT(tr.u.prp[0] == 0x101000);
192 : 6 : CU_ASSERT(tr.u.prp[1] == 0x102000);
193 : :
194 : : /* 12K buffer, 4K aligned */
195 : 6 : prp_list_prep(&tr, &req, &prp_index);
196 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x3000,
197 : : 0x1000) == 0);
198 : 6 : CU_ASSERT(prp_index == 3);
199 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
200 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
201 : 6 : CU_ASSERT(tr.u.prp[0] == 0x101000);
202 : 6 : CU_ASSERT(tr.u.prp[1] == 0x102000);
203 : :
204 : : /* 12K buffer, non-4K aligned */
205 : 6 : prp_list_prep(&tr, &req, &prp_index);
206 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x3000,
207 : : 0x1000) == 0);
208 : 6 : CU_ASSERT(prp_index == 4);
209 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
210 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
211 : 6 : CU_ASSERT(tr.u.prp[0] == 0x101000);
212 : 6 : CU_ASSERT(tr.u.prp[1] == 0x102000);
213 : 6 : CU_ASSERT(tr.u.prp[2] == 0x103000);
214 : :
215 : : /* Two 4K buffers, both 4K aligned */
216 : 6 : prp_list_prep(&tr, &req, &prp_index);
217 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x1000,
218 : : 0x1000) == 0);
219 : 6 : CU_ASSERT(prp_index == 1);
220 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x900000, 0x1000,
221 : : 0x1000) == 0);
222 : 6 : CU_ASSERT(prp_index == 2);
223 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
224 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp2 == 0x900000);
225 : :
226 : : /* Two 4K buffers, first non-4K aligned, second 4K aligned */
227 : 6 : prp_list_prep(&tr, &req, &prp_index);
228 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x1000,
229 : : 0x1000) == 0);
230 : 6 : CU_ASSERT(prp_index == 2);
231 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x900000, 0x1000,
232 : : 0x1000) == 0);
233 : 6 : CU_ASSERT(prp_index == 3);
234 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
235 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
236 : 6 : CU_ASSERT(tr.u.prp[0] == 0x101000);
237 : 6 : CU_ASSERT(tr.u.prp[1] == 0x900000);
238 : :
239 : : /* Two 4K buffers, both non-4K aligned (invalid) */
240 : 6 : prp_list_prep(&tr, &req, &prp_index);
241 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x1000,
242 : : 0x1000) == 0);
243 : 6 : CU_ASSERT(prp_index == 2);
244 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x900800, 0x1000,
245 : : 0x1000) == -EFAULT);
246 : 6 : CU_ASSERT(prp_index == 2);
247 : :
248 : : /* 4K buffer, 4K aligned, but vtophys fails */
249 : 6 : MOCK_SET(spdk_vtophys, SPDK_VTOPHYS_ERROR);
250 : 6 : prp_list_prep(&tr, &req, &prp_index);
251 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x1000,
252 : : 0x1000) == -EFAULT);
253 [ - - - + ]: 6 : MOCK_CLEAR(spdk_vtophys);
254 : :
255 : : /* Largest aligned buffer that can be described in NVME_MAX_PRP_LIST_ENTRIES (plus PRP1) */
256 : 6 : prp_list_prep(&tr, &req, &prp_index);
257 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000,
258 : : (NVME_MAX_PRP_LIST_ENTRIES + 1) * 0x1000, 0x1000) == 0);
259 : 6 : CU_ASSERT(prp_index == NVME_MAX_PRP_LIST_ENTRIES + 1);
260 : :
261 : : /* Largest non-4K-aligned buffer that can be described in NVME_MAX_PRP_LIST_ENTRIES (plus PRP1) */
262 : 6 : prp_list_prep(&tr, &req, &prp_index);
263 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800,
264 : : NVME_MAX_PRP_LIST_ENTRIES * 0x1000, 0x1000) == 0);
265 : 6 : CU_ASSERT(prp_index == NVME_MAX_PRP_LIST_ENTRIES + 1);
266 : :
267 : : /* Buffer too large to be described in NVME_MAX_PRP_LIST_ENTRIES */
268 : 6 : prp_list_prep(&tr, &req, &prp_index);
269 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000,
270 : : (NVME_MAX_PRP_LIST_ENTRIES + 2) * 0x1000, 0x1000) == -EFAULT);
271 : :
272 : : /* Non-4K-aligned buffer too large to be described in NVME_MAX_PRP_LIST_ENTRIES */
273 : 6 : prp_list_prep(&tr, &req, &prp_index);
274 : 6 : CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800,
275 : : (NVME_MAX_PRP_LIST_ENTRIES + 1) * 0x1000, 0x1000) == -EFAULT);
276 : 6 : }
277 : :
278 : : struct spdk_event_entry {
279 : : struct spdk_pci_event event;
280 : : STAILQ_ENTRY(spdk_event_entry) link;
281 : : };
282 : :
283 : : static STAILQ_HEAD(, spdk_event_entry) g_events = STAILQ_HEAD_INITIALIZER(g_events);
284 : : static bool g_device_allowed = false;
285 : :
286 : : int
287 : 42 : spdk_pci_get_event(int fd, struct spdk_pci_event *event)
288 : : {
289 : : struct spdk_event_entry *entry;
290 : :
291 [ + + ]: 42 : if (STAILQ_EMPTY(&g_events)) {
292 : 30 : return 0;
293 : : }
294 : :
295 : 12 : entry = STAILQ_FIRST(&g_events);
296 [ + - ]: 12 : STAILQ_REMOVE_HEAD(&g_events, link);
297 : :
298 : 12 : *event = entry->event;
299 : :
300 : 12 : return 1;
301 : : }
302 : :
303 : : int
304 : 6 : spdk_pci_device_allow(struct spdk_pci_addr *pci_addr)
305 : : {
306 : 6 : g_device_allowed = true;
307 : :
308 : 6 : return 0;
309 : : }
310 : :
311 : : static void
312 : 6 : test_nvme_pcie_hotplug_monitor(void)
313 : : {
314 : 6 : struct nvme_pcie_ctrlr pctrlr = {};
315 : 6 : struct spdk_event_entry entry = {};
316 : 5 : struct nvme_driver driver;
317 : 5 : pthread_mutexattr_t attr;
318 : 6 : struct spdk_nvme_probe_ctx test_nvme_probe_ctx = {};
319 : :
320 : : /* Initiate variables and ctrlr */
321 : 6 : driver.initialized = true;
322 : 6 : driver.hotplug_fd = 123;
323 [ - + ]: 6 : CU_ASSERT(pthread_mutexattr_init(&attr) == 0);
324 [ - + ]: 6 : CU_ASSERT(pthread_mutex_init(&pctrlr.ctrlr.ctrlr_lock, &attr) == 0);
325 [ - + ]: 6 : CU_ASSERT(pthread_mutex_init(&driver.lock, &attr) == 0);
326 : 6 : TAILQ_INIT(&driver.shared_attached_ctrlrs);
327 : 6 : g_spdk_nvme_driver = &driver;
328 : :
329 : : /* Case 1: SPDK_NVME_UEVENT_ADD/ NVME_VFIO / NVME_UIO */
330 : 6 : entry.event.action = SPDK_UEVENT_ADD;
331 : 6 : spdk_pci_addr_parse(&entry.event.traddr, "0000:05:00.0");
332 : 6 : CU_ASSERT(STAILQ_EMPTY(&g_events));
333 : 6 : STAILQ_INSERT_TAIL(&g_events, &entry, link);
334 : :
335 : 6 : _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
336 : :
337 : 6 : CU_ASSERT(STAILQ_EMPTY(&g_events));
338 [ - + ]: 6 : CU_ASSERT(g_device_allowed == true);
339 : 6 : g_device_allowed = false;
340 : :
341 : : /* Case 2: SPDK_NVME_UEVENT_REMOVE/ NVME_UIO */
342 : 6 : entry.event.action = SPDK_UEVENT_REMOVE;
343 : 6 : spdk_pci_addr_parse(&entry.event.traddr, "0000:05:00.0");
344 : 6 : CU_ASSERT(STAILQ_EMPTY(&g_events));
345 : 6 : STAILQ_INSERT_TAIL(&g_events, &entry, link);
346 : :
347 : 6 : MOCK_SET(nvme_get_ctrlr_by_trid_unsafe, &pctrlr.ctrlr);
348 : :
349 : 6 : _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
350 : :
351 : 6 : CU_ASSERT(STAILQ_EMPTY(&g_events));
352 [ - + ]: 6 : CU_ASSERT(pctrlr.ctrlr.is_failed == true);
353 [ - + ]: 6 : CU_ASSERT(pctrlr.ctrlr.is_removed == true);
354 : 6 : pctrlr.ctrlr.is_failed = false;
355 : 6 : pctrlr.ctrlr.is_removed = false;
356 [ - - - + ]: 6 : MOCK_CLEAR(nvme_get_ctrlr_by_trid_unsafe);
357 : :
358 : : /* Case 3: SPDK_NVME_UEVENT_REMOVE/ NVME_VFIO without event */
359 : 6 : pctrlr.ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
360 [ - + ]: 6 : snprintf(pctrlr.ctrlr.trid.traddr, sizeof(pctrlr.ctrlr.trid.traddr), "0000:02:00.0");
361 : 6 : pctrlr.ctrlr.remove_cb = NULL;
362 : 6 : pctrlr.ctrlr.is_failed = false;
363 : 6 : pctrlr.ctrlr.is_removed = false;
364 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_driver->shared_attached_ctrlrs, &pctrlr.ctrlr, tailq);
365 : :
366 : : /* This should be set in the vfio req notifier cb */
367 : 6 : MOCK_SET(spdk_pci_device_is_removed, true);
368 : :
369 : 6 : _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
370 : :
371 : 6 : CU_ASSERT(STAILQ_EMPTY(&g_events));
372 [ - + ]: 6 : CU_ASSERT(pctrlr.ctrlr.is_failed == true);
373 [ - + ]: 6 : CU_ASSERT(pctrlr.ctrlr.is_removed == true);
374 : 6 : pctrlr.ctrlr.is_failed = false;
375 : 6 : pctrlr.ctrlr.is_removed = false;
376 [ - - - + ]: 6 : MOCK_CLEAR(spdk_pci_device_is_removed);
377 : :
378 : : /* Case 4: Removed device detected in another process */
379 : 6 : MOCK_SET(spdk_pci_device_is_removed, false);
380 : :
381 : 6 : _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
382 : :
383 [ - + ]: 6 : CU_ASSERT(pctrlr.ctrlr.is_failed == false);
384 : :
385 : 6 : MOCK_SET(spdk_pci_device_is_removed, true);
386 : :
387 : 6 : _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
388 : :
389 [ - + ]: 6 : CU_ASSERT(pctrlr.ctrlr.is_failed == true);
390 : :
391 [ - + ]: 6 : pthread_mutex_destroy(&driver.lock);
392 [ - + ]: 6 : pthread_mutex_destroy(&pctrlr.ctrlr.ctrlr_lock);
393 [ - + ]: 6 : pthread_mutexattr_destroy(&attr);
394 : 6 : g_spdk_nvme_driver = NULL;
395 : 6 : }
396 : :
397 : : static void
398 : 6 : test_shadow_doorbell_update(void)
399 : : {
400 : : bool ret;
401 : :
402 : : /* nvme_pcie_qpair_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) */
403 : 6 : ret = nvme_pcie_qpair_need_event(10, 15, 14);
404 : 6 : CU_ASSERT(ret == false);
405 : :
406 : 6 : ret = nvme_pcie_qpair_need_event(14, 15, 14);
407 : 6 : CU_ASSERT(ret == true);
408 : 6 : }
409 : :
410 : : static void
411 : 6 : test_build_contig_hw_sgl_request(void)
412 : : {
413 : 6 : struct spdk_nvme_qpair qpair = {};
414 : 6 : struct nvme_request req = {};
415 : 6 : struct nvme_tracker tr = {};
416 : 6 : struct spdk_nvme_ctrlr ctrlr = {};
417 : : int rc;
418 : :
419 : 6 : ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
420 : 6 : qpair.ctrlr = &ctrlr;
421 : : /* Test 1: Payload covered by a single mapping */
422 : 6 : req.payload_size = 100;
423 : 6 : req.payload = NVME_PAYLOAD_CONTIG((void *)0xbeef0, NULL);
424 : 6 : g_vtophys_size = 100;
425 : 6 : MOCK_SET(spdk_vtophys, 0xDEADBEEF);
426 : :
427 : 6 : rc = nvme_pcie_qpair_build_contig_hw_sgl_request(&qpair, &req, &tr, 0);
428 : 6 : CU_ASSERT(rc == 0);
429 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
430 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.address == 0xDEADBEEF);
431 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 100);
432 : :
433 [ - - - + ]: 6 : MOCK_CLEAR(spdk_vtophys);
434 : 6 : g_vtophys_size = 0;
435 [ - + ]: 6 : memset(&qpair, 0, sizeof(qpair));
436 [ - + ]: 6 : memset(&req, 0, sizeof(req));
437 [ - + ]: 6 : memset(&tr, 0, sizeof(tr));
438 : :
439 : : /* Test 2: Payload covered by a single mapping, but request is at an offset */
440 : 6 : qpair.ctrlr = &ctrlr;
441 : 6 : req.payload_size = 100;
442 : 6 : req.payload_offset = 50;
443 : 6 : req.payload = NVME_PAYLOAD_CONTIG((void *)0xbeef0, NULL);
444 : 6 : g_vtophys_size = 1000;
445 : 6 : MOCK_SET(spdk_vtophys, 0xDEADBEEF);
446 : :
447 : 6 : rc = nvme_pcie_qpair_build_contig_hw_sgl_request(&qpair, &req, &tr, 0);
448 : 6 : CU_ASSERT(rc == 0);
449 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
450 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.address == 0xDEADBEEF);
451 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 100);
452 : :
453 [ - - - + ]: 6 : MOCK_CLEAR(spdk_vtophys);
454 : 6 : g_vtophys_size = 0;
455 [ - + ]: 6 : memset(&qpair, 0, sizeof(qpair));
456 [ - + ]: 6 : memset(&req, 0, sizeof(req));
457 [ - + ]: 6 : memset(&tr, 0, sizeof(tr));
458 : :
459 : : /* Test 3: Payload spans two mappings */
460 : 6 : qpair.ctrlr = &ctrlr;
461 : 6 : req.payload_size = 100;
462 : 6 : req.payload = NVME_PAYLOAD_CONTIG((void *)0xbeef0, NULL);
463 : 6 : g_vtophys_size = 60;
464 : 6 : tr.prp_sgl_bus_addr = 0xFF0FF;
465 : 6 : MOCK_SET(spdk_vtophys, 0xDEADBEEF);
466 : :
467 : 6 : rc = nvme_pcie_qpair_build_contig_hw_sgl_request(&qpair, &req, &tr, 0);
468 : 6 : CU_ASSERT(rc == 0);
469 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_LAST_SEGMENT);
470 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.address == tr.prp_sgl_bus_addr);
471 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 2 * sizeof(struct spdk_nvme_sgl_descriptor));
472 : 6 : CU_ASSERT(tr.u.sgl[0].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
473 : 6 : CU_ASSERT(tr.u.sgl[0].unkeyed.length == 60);
474 : 6 : CU_ASSERT(tr.u.sgl[0].address == 0xDEADBEEF);
475 : 6 : CU_ASSERT(tr.u.sgl[1].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
476 : 6 : CU_ASSERT(tr.u.sgl[1].unkeyed.length == 40);
477 : 6 : CU_ASSERT(tr.u.sgl[1].address == 0xDEADBEEF);
478 : :
479 [ - - - + ]: 6 : MOCK_CLEAR(spdk_vtophys);
480 : 6 : g_vtophys_size = 0;
481 [ - + ]: 6 : memset(&qpair, 0, sizeof(qpair));
482 [ - + ]: 6 : memset(&req, 0, sizeof(req));
483 [ - + ]: 6 : memset(&tr, 0, sizeof(tr));
484 : 6 : }
485 : :
486 : : static void
487 : 6 : test_nvme_pcie_qpair_build_metadata(void)
488 : : {
489 : 6 : struct nvme_pcie_qpair pqpair = {};
490 : 6 : struct spdk_nvme_qpair *qpair = &pqpair.qpair;
491 : 6 : struct nvme_tracker tr = {};
492 : 6 : struct nvme_request req = {};
493 : 6 : struct spdk_nvme_ctrlr ctrlr = {};
494 : : int rc;
495 : :
496 : 6 : ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
497 : 6 : tr.req = &req;
498 : 6 : qpair->ctrlr = &ctrlr;
499 : :
500 : 6 : req.payload = NVME_PAYLOAD_CONTIG(NULL, (void *)0xDEADBEE0);
501 : 6 : req.md_offset = 0;
502 : 6 : req.md_size = 4096;
503 : : /* The nvme_pcie_qpair_build_metadata() function expects the cmd.psdt
504 : : * is set to SPDK_NVME_PSDT_SGL_MPTR_CONTIG, and then if metadata is
505 : : * built using SGL, cmd.psdt is changed to SPDK_NVME_PSDT_SGL_MPTR_SGL
506 : : * by this function. We need to verify if this indeed is the case.
507 : : */
508 : 6 : req.cmd.psdt = SPDK_NVME_PSDT_SGL_MPTR_CONTIG;
509 : 6 : tr.prp_sgl_bus_addr = 0xDBADBEEF;
510 : 6 : MOCK_SET(spdk_vtophys, 0xDCADBEE0);
511 : :
512 : 6 : rc = nvme_pcie_qpair_build_metadata(qpair, &tr, true, true, true);
513 : 6 : CU_ASSERT(rc == 0);
514 : 6 : CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_SGL);
515 : 6 : CU_ASSERT(tr.meta_sgl.address == 0xDCADBEE0);
516 : 6 : CU_ASSERT(tr.meta_sgl.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
517 : 6 : CU_ASSERT(tr.meta_sgl.unkeyed.length == 4096);
518 : 6 : CU_ASSERT(tr.meta_sgl.unkeyed.subtype == 0);
519 : 6 : CU_ASSERT(req.cmd.mptr == (0xDBADBEEF - sizeof(struct spdk_nvme_sgl_descriptor)));
520 : :
521 : : /* Non-IOVA contiguous metadata buffers should fail. */
522 : 6 : g_vtophys_size = 1024;
523 : 6 : req.cmd.psdt = SPDK_NVME_PSDT_SGL_MPTR_CONTIG;
524 : 6 : rc = nvme_pcie_qpair_build_metadata(qpair, &tr, true, true, true);
525 : 6 : CU_ASSERT(rc == -EINVAL);
526 : 6 : g_vtophys_size = 0;
527 : :
528 [ - - - + ]: 6 : MOCK_CLEAR(spdk_vtophys);
529 : :
530 : : /* Build non sgl metadata */
531 : 6 : MOCK_SET(spdk_vtophys, 0xDDADBEE0);
532 : :
533 : 6 : rc = nvme_pcie_qpair_build_metadata(qpair, &tr, false, false, true);
534 : 6 : CU_ASSERT(rc == 0);
535 : 6 : CU_ASSERT(req.cmd.mptr == 0xDDADBEE0);
536 : :
537 : : /* Build non sgl metadata while sgls are supported */
538 [ - + ]: 6 : memset(&tr.meta_sgl, 0, sizeof(tr.meta_sgl));
539 : : /* If SGLs are supported, but not in metadata, the cmd.psdt
540 : : * shall not be changed to SPDK_NVME_PSDT_SGL_MPTR_SGL
541 : : */
542 : 6 : req.cmd.psdt = SPDK_NVME_PSDT_SGL_MPTR_CONTIG;
543 : 6 : rc = nvme_pcie_qpair_build_metadata(qpair, &tr, true, false, true);
544 : 6 : CU_ASSERT(rc == 0);
545 : 6 : CU_ASSERT(tr.meta_sgl.address == 0);
546 : 6 : CU_ASSERT(tr.meta_sgl.unkeyed.length == 0);
547 : 6 : CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_CONTIG);
548 : 6 : CU_ASSERT(req.cmd.mptr == 0xDDADBEE0);
549 : :
550 : : /* Non-IOVA contiguous metadata buffers should fail. */
551 : 6 : g_vtophys_size = 1024;
552 : 6 : rc = nvme_pcie_qpair_build_metadata(qpair, &tr, false, false, true);
553 : 6 : CU_ASSERT(rc == -EINVAL);
554 : 6 : g_vtophys_size = 0;
555 : :
556 [ - - - + ]: 6 : MOCK_CLEAR(spdk_vtophys);
557 : 6 : }
558 : :
559 : : static int
560 : 30 : nvme_pcie_ut_next_sge(void *cb_arg, void **address, uint32_t *length)
561 : : {
562 : 30 : struct nvme_pcie_ut_bdev_io *bio = cb_arg;
563 : : struct iovec *iov;
564 : :
565 [ - + ]: 30 : SPDK_CU_ASSERT_FATAL(bio->iovpos < NVME_MAX_SGL_DESCRIPTORS);
566 : :
567 : 30 : iov = &bio->iovs[bio->iovpos];
568 : :
569 : 30 : *address = iov->iov_base;
570 : 30 : *length = iov->iov_len;
571 : 30 : bio->iovpos++;
572 : :
573 : 30 : return 0;
574 : : }
575 : :
576 : : static void
577 : 18 : nvme_pcie_ut_reset_sgl(void *cb_arg, uint32_t offset)
578 : : {
579 : 18 : struct nvme_pcie_ut_bdev_io *bio = cb_arg;
580 : : struct iovec *iov;
581 : :
582 [ + - ]: 18 : for (bio->iovpos = 0; bio->iovpos < NVME_MAX_SGL_DESCRIPTORS; bio->iovpos++) {
583 : 18 : iov = &bio->iovs[bio->iovpos];
584 : : /* Offset must be aligned with the start of any SGL entry */
585 [ + - ]: 18 : if (offset == 0) {
586 : 18 : break;
587 : : }
588 : :
589 [ # # ]: 0 : SPDK_CU_ASSERT_FATAL(offset >= iov->iov_len);
590 : 0 : offset -= iov->iov_len;
591 : : }
592 : :
593 [ - + ]: 18 : SPDK_CU_ASSERT_FATAL(offset == 0);
594 [ - + ]: 18 : SPDK_CU_ASSERT_FATAL(bio->iovpos < NVME_MAX_SGL_DESCRIPTORS);
595 : 18 : }
596 : :
597 : : static void
598 : 6 : test_nvme_pcie_qpair_build_prps_sgl_request(void)
599 : : {
600 : 6 : struct spdk_nvme_qpair qpair = {};
601 : 6 : struct nvme_request req = {};
602 : 6 : struct nvme_tracker tr = {};
603 : 6 : struct spdk_nvme_ctrlr ctrlr = {};
604 : 6 : struct nvme_pcie_ut_bdev_io bio = {};
605 : : int rc;
606 : :
607 : 6 : tr.req = &req;
608 : 6 : qpair.ctrlr = &ctrlr;
609 : 6 : req.payload = NVME_PAYLOAD_SGL(nvme_pcie_ut_reset_sgl, nvme_pcie_ut_next_sge, &bio, NULL);
610 : 6 : req.payload_size = 4096;
611 : 6 : ctrlr.page_size = 4096;
612 : 6 : bio.iovs[0].iov_base = (void *)0x100000;
613 : 6 : bio.iovs[0].iov_len = 4096;
614 : :
615 : 6 : rc = nvme_pcie_qpair_build_prps_sgl_request(&qpair, &req, &tr, NULL);
616 : 6 : CU_ASSERT(rc == 0);
617 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
618 : 6 : }
619 : :
620 : : static void
621 : 6 : test_nvme_pcie_qpair_build_hw_sgl_request(void)
622 : : {
623 : 6 : struct spdk_nvme_qpair qpair = {};
624 : 6 : struct nvme_request req = {};
625 : 6 : struct nvme_tracker tr = {};
626 : 6 : struct nvme_pcie_ut_bdev_io bio = {};
627 : 6 : struct spdk_nvme_ctrlr ctrlr = {};
628 : : int rc;
629 : :
630 : 6 : ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
631 : 6 : qpair.ctrlr = &ctrlr;
632 : 6 : req.payload = NVME_PAYLOAD_SGL(nvme_pcie_ut_reset_sgl, nvme_pcie_ut_next_sge, &bio, NULL);
633 : 6 : req.cmd.opc = SPDK_NVME_OPC_WRITE;
634 : 6 : tr.prp_sgl_bus_addr = 0xDAADBEE0;
635 : 6 : g_vtophys_size = 4096;
636 : :
637 : : /* Multiple vectors, 2k + 4k + 2k */
638 : 6 : req.payload_size = 8192;
639 : 6 : bio.iovpos = 3;
640 : 6 : bio.iovs[0].iov_base = (void *)0xDBADBEE0;
641 : 6 : bio.iovs[0].iov_len = 2048;
642 : 6 : bio.iovs[1].iov_base = (void *)0xDCADBEE0;
643 : 6 : bio.iovs[1].iov_len = 4096;
644 : 6 : bio.iovs[2].iov_base = (void *)0xDDADBEE0;
645 : 6 : bio.iovs[2].iov_len = 2048;
646 : :
647 : 6 : rc = nvme_pcie_qpair_build_hw_sgl_request(&qpair, &req, &tr, true);
648 : 6 : CU_ASSERT(rc == 0);
649 : 6 : CU_ASSERT(tr.u.sgl[0].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
650 : 6 : CU_ASSERT(tr.u.sgl[0].unkeyed.length == 2048);
651 : 6 : CU_ASSERT(tr.u.sgl[0].address == 0xDBADBEE0);
652 : 6 : CU_ASSERT(tr.u.sgl[0].unkeyed.subtype == 0);
653 : 6 : CU_ASSERT(tr.u.sgl[1].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
654 : 6 : CU_ASSERT(tr.u.sgl[1].unkeyed.length == 4096);
655 : 6 : CU_ASSERT(tr.u.sgl[1].address == 0xDCADBEE0);
656 : 6 : CU_ASSERT(tr.u.sgl[2].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
657 : 6 : CU_ASSERT(tr.u.sgl[2].unkeyed.length == 2048);
658 : 6 : CU_ASSERT(tr.u.sgl[2].unkeyed.length == 2048);
659 : 6 : CU_ASSERT(tr.u.sgl[2].address == 0xDDADBEE0);
660 : 6 : CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_CONTIG);
661 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.subtype == 0);
662 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_LAST_SEGMENT);
663 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.address == 0xDAADBEE0);
664 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 48);
665 : :
666 : : /* Single vector */
667 [ - + ]: 6 : memset(&tr, 0, sizeof(tr));
668 [ - + ]: 6 : memset(&bio, 0, sizeof(bio));
669 [ - + ]: 6 : memset(&req, 0, sizeof(req));
670 : 6 : req.payload = NVME_PAYLOAD_SGL(nvme_pcie_ut_reset_sgl, nvme_pcie_ut_next_sge, &bio, NULL);
671 : 6 : req.cmd.opc = SPDK_NVME_OPC_WRITE;
672 : 6 : req.payload_size = 4096;
673 : 6 : bio.iovpos = 1;
674 : 6 : bio.iovs[0].iov_base = (void *)0xDBADBEE0;
675 : 6 : bio.iovs[0].iov_len = 4096;
676 : :
677 : 6 : rc = nvme_pcie_qpair_build_hw_sgl_request(&qpair, &req, &tr, true);
678 : 6 : CU_ASSERT(rc == 0);
679 : 6 : CU_ASSERT(tr.u.sgl[0].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
680 : 6 : CU_ASSERT(tr.u.sgl[0].unkeyed.length == 4096);
681 : 6 : CU_ASSERT(tr.u.sgl[0].address == 0xDBADBEE0);
682 : 6 : CU_ASSERT(tr.u.sgl[0].unkeyed.subtype == 0);
683 : 6 : CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_CONTIG);
684 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.subtype == 0);
685 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
686 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.address == 0xDBADBEE0);
687 : 6 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 4096);
688 : 6 : }
689 : :
690 : : static void
691 : 6 : test_nvme_pcie_qpair_build_contig_request(void)
692 : : {
693 : 6 : struct nvme_pcie_qpair pqpair = {};
694 : 6 : struct nvme_request req = {};
695 : 6 : struct nvme_tracker tr = {};
696 : 6 : struct spdk_nvme_ctrlr ctrlr = {};
697 : : int rc;
698 : :
699 : 6 : pqpair.qpair.ctrlr = &ctrlr;
700 : 6 : ctrlr.page_size = 0x1000;
701 : :
702 : : /* 1 prp, 4k-aligned */
703 : 6 : prp_list_prep(&tr, &req, NULL);
704 : 6 : req.payload = NVME_PAYLOAD_CONTIG((void *)0x100000, NULL);
705 : 6 : req.payload_size = 0x1000;
706 : :
707 : 6 : rc = nvme_pcie_qpair_build_contig_request(&pqpair.qpair, &req, &tr, true);
708 : 6 : CU_ASSERT(rc == 0);
709 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
710 : :
711 : : /* 2 prps, non-4K-aligned */
712 : 6 : prp_list_prep(&tr, &req, NULL);
713 : 6 : req.payload = NVME_PAYLOAD_CONTIG((void *)0x100000, NULL);
714 : 6 : req.payload_size = 0x1000;
715 : 6 : req.payload_offset = 0x800;
716 : :
717 : 6 : rc = nvme_pcie_qpair_build_contig_request(&pqpair.qpair, &req, &tr, true);
718 : 6 : CU_ASSERT(rc == 0);
719 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
720 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp2 == 0x101000);
721 : :
722 : : /* 3 prps, 4k-aligned */
723 : 6 : prp_list_prep(&tr, &req, NULL);
724 : 6 : req.payload = NVME_PAYLOAD_CONTIG((void *)0x100000, NULL);
725 : 6 : req.payload_size = 0x3000;
726 : :
727 : 6 : rc = nvme_pcie_qpair_build_contig_request(&pqpair.qpair, &req, &tr, true);
728 : 6 : CU_ASSERT(rc == 0);
729 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
730 : 6 : CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
731 : 6 : CU_ASSERT(tr.u.prp[0] == 0x101000);
732 : 6 : CU_ASSERT(tr.u.prp[1] == 0x102000);
733 : :
734 : : /* address not dword aligned */
735 : 6 : prp_list_prep(&tr, &req, NULL);
736 : 6 : req.payload = NVME_PAYLOAD_CONTIG((void *)0x100001, NULL);
737 : 6 : req.payload_size = 0x3000;
738 : 6 : req.qpair = &pqpair.qpair;
739 : 6 : TAILQ_INIT(&pqpair.outstanding_tr);
740 : 6 : TAILQ_INSERT_TAIL(&pqpair.outstanding_tr, &tr, tq_list);
741 : :
742 : 6 : rc = nvme_pcie_qpair_build_contig_request(&pqpair.qpair, &req, &tr, true);
743 : 6 : CU_ASSERT(rc == -EFAULT);
744 : 6 : }
745 : :
746 : : static void
747 : 6 : test_nvme_pcie_ctrlr_regs_get_set(void)
748 : : {
749 : 6 : struct nvme_pcie_ctrlr pctrlr = {};
750 : 6 : volatile struct spdk_nvme_registers regs = {};
751 : 5 : uint32_t value_4;
752 : 5 : uint64_t value_8;
753 : : int rc;
754 : :
755 : 6 : pctrlr.regs = ®s;
756 : :
757 : 6 : rc = nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, 8, 4);
758 : 6 : CU_ASSERT(rc == 0);
759 : :
760 : 6 : rc = nvme_pcie_ctrlr_get_reg_4(&pctrlr.ctrlr, 8, &value_4);
761 : 6 : CU_ASSERT(rc == 0);
762 : 6 : CU_ASSERT(value_4 == 4);
763 : :
764 : 6 : rc = nvme_pcie_ctrlr_set_reg_8(&pctrlr.ctrlr, 0, 0x100000000);
765 : 6 : CU_ASSERT(rc == 0);
766 : :
767 : 6 : rc = nvme_pcie_ctrlr_get_reg_8(&pctrlr.ctrlr, 0, &value_8);
768 : 6 : CU_ASSERT(rc == 0);
769 : 6 : CU_ASSERT(value_8 == 0x100000000);
770 : 6 : }
771 : :
772 : : static void
773 : 6 : test_nvme_pcie_ctrlr_map_unmap_cmb(void)
774 : : {
775 : 6 : struct nvme_pcie_ctrlr pctrlr = {};
776 : 6 : volatile struct spdk_nvme_registers regs = {};
777 : 6 : union spdk_nvme_cmbsz_register cmbsz = {};
778 : 6 : union spdk_nvme_cmbloc_register cmbloc = {};
779 : 6 : struct dev_mem_resource cmd_res = {};
780 : : int rc;
781 : :
782 : 6 : pctrlr.regs = ®s;
783 : 6 : pctrlr.devhandle = (void *)&cmd_res;
784 : 6 : cmd_res.addr = (void *)0x7f7c0080d000;
785 : 6 : cmd_res.len = 0x800000;
786 : 6 : cmd_res.phys_addr = 0xFC800000;
787 : : /* Configure cmb size with unit size 4k, offset 100, unsupported SQ */
788 : 6 : cmbsz.bits.sz = 512;
789 : 6 : cmbsz.bits.szu = 0;
790 : 6 : cmbsz.bits.sqs = 0;
791 : 6 : cmbloc.bits.bir = 0;
792 : 6 : cmbloc.bits.ofst = 100;
793 : :
794 : 6 : nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbsz.raw),
795 : : cmbsz.raw);
796 : 6 : nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbloc.raw),
797 : : cmbloc.raw);
798 : :
799 : 6 : nvme_pcie_ctrlr_map_cmb(&pctrlr);
800 : 6 : CU_ASSERT(pctrlr.cmb.bar_va == (void *)0x7f7c0080d000);
801 : 6 : CU_ASSERT(pctrlr.cmb.bar_pa == 0xFC800000);
802 : 6 : CU_ASSERT(pctrlr.cmb.size == 512 * 4096);
803 : 6 : CU_ASSERT(pctrlr.cmb.current_offset == 4096 * 100);
804 [ - + ]: 6 : CU_ASSERT(pctrlr.ctrlr.opts.use_cmb_sqs == false);
805 : :
806 : 6 : rc = nvme_pcie_ctrlr_unmap_cmb(&pctrlr);
807 : 6 : CU_ASSERT(rc == 0);
808 : :
809 : : /* Invalid mapping information */
810 [ - + ]: 6 : memset(&pctrlr.cmb, 0, sizeof(pctrlr.cmb));
811 : 6 : nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbsz.raw), 0);
812 : 6 : nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbloc.raw), 0);
813 : :
814 : 6 : nvme_pcie_ctrlr_map_cmb(&pctrlr);
815 : 6 : CU_ASSERT(pctrlr.cmb.bar_va == NULL);
816 : 6 : CU_ASSERT(pctrlr.cmb.bar_pa == 0);
817 : 6 : CU_ASSERT(pctrlr.cmb.size == 0);
818 : 6 : CU_ASSERT(pctrlr.cmb.current_offset == 0);
819 [ - + ]: 6 : CU_ASSERT(pctrlr.ctrlr.opts.use_cmb_sqs == false);
820 : 6 : }
821 : :
822 : :
823 : : static void
824 : 36 : prepare_map_io_cmd(struct nvme_pcie_ctrlr *pctrlr)
825 : : {
826 : 36 : union spdk_nvme_cmbsz_register cmbsz = {};
827 : 36 : union spdk_nvme_cmbloc_register cmbloc = {};
828 : :
829 : 36 : cmbsz.bits.sz = 512;
830 : 36 : cmbsz.bits.wds = 1;
831 : 36 : cmbsz.bits.rds = 1;
832 : :
833 : 36 : nvme_pcie_ctrlr_set_reg_4(&pctrlr->ctrlr, offsetof(struct spdk_nvme_registers, cmbsz.raw),
834 : : cmbsz.raw);
835 : 36 : nvme_pcie_ctrlr_set_reg_4(&pctrlr->ctrlr, offsetof(struct spdk_nvme_registers, cmbloc.raw),
836 : : cmbloc.raw);
837 : :
838 : 36 : pctrlr->cmb.bar_va = (void *)0x7F7C0080D000;
839 : 36 : pctrlr->cmb.bar_pa = 0xFC800000;
840 : 36 : pctrlr->cmb.current_offset = 1ULL << 22;
841 : 36 : pctrlr->cmb.size = (1ULL << 22) * 512;
842 : 36 : pctrlr->cmb.mem_register_addr = NULL;
843 : 36 : pctrlr->ctrlr.opts.use_cmb_sqs = false;
844 : 36 : }
845 : :
846 : : static void
847 : 6 : test_nvme_pcie_ctrlr_map_io_cmb(void)
848 : : {
849 : 6 : struct nvme_pcie_ctrlr pctrlr = {};
850 : 6 : volatile struct spdk_nvme_registers regs = {};
851 : 6 : union spdk_nvme_cmbsz_register cmbsz = {};
852 : 6 : void *mem_reg_addr = NULL;
853 : 5 : size_t size;
854 : : int rc;
855 : :
856 : 6 : pctrlr.regs = ®s;
857 : 6 : prepare_map_io_cmd(&pctrlr);
858 : :
859 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
860 : : /* Ceil the current cmb vaddr and cmb size to 2MB_aligned */
861 : 6 : CU_ASSERT(mem_reg_addr == (void *)0x7F7C00E00000);
862 : 6 : CU_ASSERT(size == 0x7FE00000);
863 : :
864 : 6 : rc = nvme_pcie_ctrlr_unmap_io_cmb(&pctrlr.ctrlr);
865 : 6 : CU_ASSERT(rc == 0);
866 : 6 : CU_ASSERT(pctrlr.cmb.mem_register_addr == NULL);
867 : 6 : CU_ASSERT(pctrlr.cmb.mem_register_size == 0);
868 : :
869 : : /* cmb mem_register_addr not NULL */
870 : 6 : prepare_map_io_cmd(&pctrlr);
871 : 6 : pctrlr.cmb.mem_register_addr = (void *)0xDEADBEEF;
872 : 6 : pctrlr.cmb.mem_register_size = 1024;
873 : :
874 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
875 : 6 : CU_ASSERT(size == 1024);
876 : 6 : CU_ASSERT(mem_reg_addr == (void *)0xDEADBEEF);
877 : :
878 : : /* cmb.bar_va is NULL */
879 : 6 : prepare_map_io_cmd(&pctrlr);
880 : 6 : pctrlr.cmb.bar_va = NULL;
881 : :
882 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
883 : 6 : CU_ASSERT(mem_reg_addr == NULL);
884 : 6 : CU_ASSERT(size == 0);
885 : :
886 : : /* submission queue already used */
887 : 6 : prepare_map_io_cmd(&pctrlr);
888 : 6 : pctrlr.ctrlr.opts.use_cmb_sqs = true;
889 : :
890 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
891 : 6 : CU_ASSERT(mem_reg_addr == NULL);
892 : 6 : CU_ASSERT(size == 0);
893 : :
894 : 6 : pctrlr.ctrlr.opts.use_cmb_sqs = false;
895 : :
896 : : /* Only SQS is supported */
897 : 6 : prepare_map_io_cmd(&pctrlr);
898 : 6 : cmbsz.bits.wds = 0;
899 : 6 : cmbsz.bits.rds = 0;
900 : 6 : nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbsz.raw),
901 : : cmbsz.raw);
902 : :
903 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
904 : 6 : CU_ASSERT(mem_reg_addr == NULL);
905 : 6 : CU_ASSERT(size == 0);
906 : :
907 : : /* CMB size is less than 4MB */
908 : 6 : prepare_map_io_cmd(&pctrlr);
909 : 6 : pctrlr.cmb.size = 1ULL << 16;
910 : :
911 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
912 : 6 : CU_ASSERT(mem_reg_addr == NULL);
913 : 6 : CU_ASSERT(size == 0);
914 : 6 : }
915 : :
916 : : static void
917 : 6 : test_nvme_pcie_ctrlr_map_unmap_pmr(void)
918 : : {
919 : 6 : struct nvme_pcie_ctrlr pctrlr = {};
920 : 6 : volatile struct spdk_nvme_registers regs = {};
921 : 6 : union spdk_nvme_pmrcap_register pmrcap = {};
922 : 6 : struct dev_mem_resource cmd_res = {};
923 : : int rc;
924 : :
925 : 6 : pctrlr.regs = ®s;
926 : 6 : pctrlr.devhandle = (void *)&cmd_res;
927 : 6 : regs.cap.bits.pmrs = 1;
928 : 6 : cmd_res.addr = (void *)0x7F7C0080d000;
929 : 6 : cmd_res.len = 0x800000;
930 : 6 : cmd_res.phys_addr = 0xFC800000;
931 : 6 : pmrcap.bits.bir = 2;
932 : 6 : pmrcap.bits.cmss = 1;
933 : 6 : nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr,
934 : : offsetof(struct spdk_nvme_registers, pmrcap.raw),
935 : : pmrcap.raw);
936 : :
937 : 6 : nvme_pcie_ctrlr_map_pmr(&pctrlr);
938 : 6 : CU_ASSERT(pctrlr.regs->pmrmscu == 0);
939 : : /* Controller memory space enable, bit 1 */
940 : 6 : CU_ASSERT(pctrlr.regs->pmrmscl.raw == 0xFC800002);
941 : 6 : CU_ASSERT(pctrlr.regs->pmrsts.raw == 0);
942 : 6 : CU_ASSERT(pctrlr.pmr.bar_va == (void *)0x7F7C0080d000);
943 : 6 : CU_ASSERT(pctrlr.pmr.bar_pa == 0xFC800000);
944 : 6 : CU_ASSERT(pctrlr.pmr.size == 0x800000);
945 : :
946 : 6 : rc = nvme_pcie_ctrlr_unmap_pmr(&pctrlr);
947 : 6 : CU_ASSERT(rc == 0);
948 : 6 : CU_ASSERT(pctrlr.regs->pmrmscu == 0);
949 : 6 : CU_ASSERT(pctrlr.regs->pmrmscl.raw == 0);
950 : :
951 : : /* pmrcap value invalid */
952 [ - + ]: 6 : memset(&pctrlr, 0, sizeof(pctrlr));
953 [ - + ]: 6 : memset((void *)®s, 0, sizeof(regs));
954 [ - + ]: 6 : memset(&cmd_res, 0, sizeof(cmd_res));
955 : :
956 : 6 : pctrlr.regs = ®s;
957 : 6 : pctrlr.devhandle = (void *)&cmd_res;
958 : 6 : regs.cap.bits.pmrs = 1;
959 : 6 : cmd_res.addr = (void *)0x7F7C0080d000;
960 : 6 : cmd_res.len = 0x800000;
961 : 6 : cmd_res.phys_addr = 0xFC800000;
962 : 6 : pmrcap.raw = 0;
963 : 6 : nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr,
964 : : offsetof(struct spdk_nvme_registers, pmrcap.raw),
965 : : pmrcap.raw);
966 : :
967 : 6 : nvme_pcie_ctrlr_map_pmr(&pctrlr);
968 : 6 : CU_ASSERT(pctrlr.pmr.bar_va == NULL);
969 : 6 : CU_ASSERT(pctrlr.pmr.bar_pa == 0);
970 : 6 : CU_ASSERT(pctrlr.pmr.size == 0);
971 : 6 : }
972 : :
973 : : static void
974 : 6 : test_nvme_pcie_ctrlr_config_pmr(void)
975 : : {
976 : 6 : struct nvme_pcie_ctrlr pctrlr = {};
977 : 6 : union spdk_nvme_pmrcap_register pmrcap = {};
978 : 6 : union spdk_nvme_pmrsts_register pmrsts = {};
979 : 6 : union spdk_nvme_cap_register cap = {};
980 : 6 : union spdk_nvme_pmrctl_register pmrctl = {};
981 : 6 : volatile struct spdk_nvme_registers regs = {};
982 : : int rc;
983 : :
984 : : /* pmrctl enable */
985 : 6 : pctrlr.regs = ®s;
986 : 6 : pmrcap.bits.pmrtu = 0;
987 : 6 : pmrcap.bits.pmrto = 1;
988 : 6 : pmrsts.bits.nrdy = false;
989 : 6 : pmrctl.bits.en = 0;
990 : 6 : cap.bits.pmrs = 1;
991 : :
992 : 6 : rc = nvme_pcie_ctrlr_set_pmrctl(&pctrlr, &pmrctl);
993 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(rc == 0);
994 : 6 : rc = nvme_pcie_ctrlr_set_reg_8(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cap.raw),
995 : : cap.raw);
996 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(rc == 0);
997 : 6 : rc = nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, pmrcap.raw),
998 : : pmrcap.raw);
999 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(rc == 0);
1000 : 6 : rc = nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, pmrsts.raw),
1001 : : pmrsts.raw);
1002 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(rc == 0);
1003 : :
1004 : 6 : rc = nvme_pcie_ctrlr_config_pmr(&pctrlr.ctrlr, true);
1005 : 6 : CU_ASSERT(rc == 0);
1006 : 6 : rc = nvme_pcie_ctrlr_get_pmrctl(&pctrlr, &pmrctl);
1007 : 6 : CU_ASSERT(rc == 0);
1008 : 6 : CU_ASSERT(pmrctl.bits.en == true);
1009 : :
1010 : : /* pmrctl disable */
1011 : 6 : pmrsts.bits.nrdy = true;
1012 : 6 : rc = nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, pmrsts.raw),
1013 : : pmrsts.raw);
1014 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(rc == 0);
1015 : 6 : rc = nvme_pcie_ctrlr_set_pmrctl(&pctrlr, &pmrctl);
1016 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(rc == 0);
1017 : :
1018 : 6 : rc = nvme_pcie_ctrlr_config_pmr(&pctrlr.ctrlr, false);
1019 : 6 : CU_ASSERT(rc == 0);
1020 : 6 : rc = nvme_pcie_ctrlr_get_pmrctl(&pctrlr, &pmrctl);
1021 : 6 : CU_ASSERT(rc == 0);
1022 : 6 : CU_ASSERT(pmrctl.bits.en == false);
1023 : :
1024 : : /* configuration exist */
1025 : 6 : rc = nvme_pcie_ctrlr_config_pmr(&pctrlr.ctrlr, false);
1026 : 6 : CU_ASSERT(rc == -EINVAL);
1027 : 6 : }
1028 : :
1029 : : static void
1030 : 36 : map_io_pmr_init(struct nvme_pcie_ctrlr *pctrlr, union spdk_nvme_pmrcap_register *pmrcap)
1031 : : {
1032 : 36 : pmrcap->raw = 0;
1033 : 36 : pmrcap->bits.rds = 1;
1034 : 36 : pmrcap->bits.wds = 1;
1035 : 36 : nvme_pcie_ctrlr_set_reg_4(&pctrlr->ctrlr, offsetof(struct spdk_nvme_registers, pmrcap.raw),
1036 : : pmrcap->raw);
1037 : 36 : pctrlr->regs->cap.bits.pmrs = 1;
1038 : 36 : pctrlr->pmr.mem_register_size = 0;
1039 : 36 : pctrlr->pmr.mem_register_addr = NULL;
1040 : 36 : pctrlr->pmr.bar_va = (void *)0x7F7C00E30000;
1041 : 36 : pctrlr->pmr.size = (1 << 22) * 128;
1042 : 36 : }
1043 : :
1044 : : static void
1045 : 6 : test_nvme_pcie_ctrlr_map_io_pmr(void)
1046 : : {
1047 : 6 : struct nvme_pcie_ctrlr pctrlr = {};
1048 : : struct spdk_nvme_ctrlr *ctrlr;
1049 : 6 : volatile struct spdk_nvme_registers regs = {};
1050 : 5 : union spdk_nvme_pmrcap_register pmrcap;
1051 : 6 : void *mem_reg_addr = NULL;
1052 : 6 : size_t rt_size = 0;
1053 : :
1054 : 6 : ctrlr = &pctrlr.ctrlr;
1055 : 6 : pctrlr.regs = ®s;
1056 : :
1057 : : /* PMR is not supported by the controller */
1058 : 6 : map_io_pmr_init(&pctrlr, &pmrcap);
1059 : 6 : regs.cap.bits.pmrs = 0;
1060 : :
1061 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
1062 : 6 : CU_ASSERT(mem_reg_addr == NULL);
1063 : :
1064 : : /* mem_register_addr not NULL. */
1065 : 6 : map_io_pmr_init(&pctrlr, &pmrcap);
1066 : 6 : pctrlr.pmr.mem_register_addr = (void *)0xDEADBEEF;
1067 : 6 : pctrlr.pmr.mem_register_size = 1024;
1068 : :
1069 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
1070 : 6 : CU_ASSERT(rt_size == 1024);
1071 : 6 : CU_ASSERT(mem_reg_addr == (void *)0xDEADBEEF);
1072 : :
1073 : : /* PMR not available */
1074 : 6 : map_io_pmr_init(&pctrlr, &pmrcap);
1075 : 6 : pctrlr.pmr.bar_va = NULL;
1076 : 6 : pctrlr.pmr.mem_register_addr = NULL;
1077 : :
1078 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
1079 : 6 : CU_ASSERT(mem_reg_addr == NULL);
1080 : 6 : CU_ASSERT(rt_size == 0);
1081 : :
1082 : : /* WDS / RDS is not supported */
1083 : 6 : map_io_pmr_init(&pctrlr, &pmrcap);
1084 : 6 : pmrcap.bits.rds = 0;
1085 : 6 : pmrcap.bits.wds = 0;
1086 : 6 : nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, pmrcap.raw),
1087 : : pmrcap.raw);
1088 : :
1089 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
1090 : 6 : CU_ASSERT(mem_reg_addr == NULL);
1091 : 6 : CU_ASSERT(rt_size == 0);
1092 : :
1093 : : /* PMR is less than 4MiB in size then abort PMR mapping */
1094 : 6 : map_io_pmr_init(&pctrlr, &pmrcap);
1095 : 6 : pctrlr.pmr.size = (1ULL << 20);
1096 : :
1097 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
1098 : 6 : CU_ASSERT(mem_reg_addr == NULL);
1099 : 6 : CU_ASSERT(rt_size == 0);
1100 : :
1101 : : /* All parameters success */
1102 : 6 : map_io_pmr_init(&pctrlr, &pmrcap);
1103 : :
1104 : 6 : mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
1105 : 6 : CU_ASSERT(mem_reg_addr == (void *)0x7F7C01000000);
1106 : 6 : CU_ASSERT(rt_size == 0x1FE00000);
1107 : 6 : }
1108 : :
1109 : : int
1110 : 6 : main(int argc, char **argv)
1111 : : {
1112 : 6 : CU_pSuite suite = NULL;
1113 : : unsigned int num_failures;
1114 : :
1115 : 6 : CU_initialize_registry();
1116 : :
1117 : 6 : suite = CU_add_suite("nvme_pcie", NULL, NULL);
1118 : 6 : CU_ADD_TEST(suite, test_prp_list_append);
1119 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_hotplug_monitor);
1120 : 6 : CU_ADD_TEST(suite, test_shadow_doorbell_update);
1121 : 6 : CU_ADD_TEST(suite, test_build_contig_hw_sgl_request);
1122 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_qpair_build_metadata);
1123 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_qpair_build_prps_sgl_request);
1124 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_qpair_build_hw_sgl_request);
1125 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_qpair_build_contig_request);
1126 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_regs_get_set);
1127 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_map_unmap_cmb);
1128 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_map_io_cmb);
1129 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_map_unmap_pmr);
1130 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_config_pmr);
1131 : 6 : CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_map_io_pmr);
1132 : :
1133 : 6 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
1134 : 6 : CU_cleanup_registry();
1135 : 6 : return num_failures;
1136 : : }
|