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