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