Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2019 Intel Corporation.
3 : : */
4 : : #include <stdint.h>
5 : : #include <stdio.h>
6 : : #include <string.h>
7 : : #include <errno.h>
8 : :
9 : : #include <rte_common.h>
10 : : #include <rte_lcore.h>
11 : : #include <rte_cycles.h>
12 : : #include <rte_eal.h>
13 : : #include <rte_log.h>
14 : : #include <rte_pci.h>
15 : : #include <rte_mbuf.h>
16 : : #include <bus_pci_driver.h>
17 : : #include <rte_memzone.h>
18 : : #include <rte_memcpy.h>
19 : : #include <rte_rawdev.h>
20 : : #include <rte_rawdev_pmd.h>
21 : :
22 : : #include "ntb_hw_intel.h"
23 : : #include "rte_pmd_ntb.h"
24 : : #include "ntb.h"
25 : :
26 : : static const struct rte_pci_id pci_id_ntb_map[] = {
27 : : { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_SKX) },
28 : : { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_ICX) },
29 : : { .vendor_id = 0, /* sentinel */ },
30 : : };
31 : :
32 : : /* Align with enum ntb_xstats_idx */
33 : : static struct rte_rawdev_xstats_name ntb_xstats_names[] = {
34 : : {"Tx-packets"},
35 : : {"Tx-bytes"},
36 : : {"Tx-errors"},
37 : : {"Rx-packets"},
38 : : {"Rx-bytes"},
39 : : {"Rx-missed"},
40 : : };
41 : : #define NTB_XSTATS_NUM RTE_DIM(ntb_xstats_names)
42 : :
43 : : static inline void
44 : 0 : ntb_link_cleanup(struct rte_rawdev *dev)
45 : : {
46 : 0 : struct ntb_hw *hw = dev->dev_private;
47 : : int status, i;
48 : :
49 [ # # ]: 0 : if (hw->ntb_ops->spad_write == NULL ||
50 [ # # ]: 0 : hw->ntb_ops->mw_set_trans == NULL) {
51 : 0 : NTB_LOG(ERR, "Not supported to clean up link.");
52 : 0 : return;
53 : : }
54 : :
55 : : /* Clean spad registers. */
56 [ # # ]: 0 : for (i = 0; i < hw->spad_cnt; i++) {
57 : 0 : status = (*hw->ntb_ops->spad_write)(dev, i, 0, 0);
58 [ # # ]: 0 : if (status)
59 : 0 : NTB_LOG(ERR, "Failed to clean local spad.");
60 : : }
61 : :
62 : : /* Clear mw so that peer cannot access local memory.*/
63 [ # # ]: 0 : for (i = 0; i < hw->used_mw_num; i++) {
64 : 0 : status = (*hw->ntb_ops->mw_set_trans)(dev, i, 0, 0);
65 [ # # ]: 0 : if (status)
66 : 0 : NTB_LOG(ERR, "Failed to clean mw.");
67 : : }
68 : : }
69 : :
70 : : static inline int
71 : 0 : ntb_handshake_work(const struct rte_rawdev *dev)
72 : : {
73 : 0 : struct ntb_hw *hw = dev->dev_private;
74 : : uint32_t val;
75 : : int ret, i;
76 : :
77 [ # # ]: 0 : if (hw->ntb_ops->spad_write == NULL ||
78 [ # # ]: 0 : hw->ntb_ops->mw_set_trans == NULL) {
79 : 0 : NTB_LOG(ERR, "Scratchpad/MW setting is not supported.");
80 : 0 : return -ENOTSUP;
81 : : }
82 : :
83 : : /* Tell peer the mw info of local side. */
84 : 0 : ret = (*hw->ntb_ops->spad_write)(dev, SPAD_NUM_MWS, 1, hw->mw_cnt);
85 [ # # ]: 0 : if (ret < 0)
86 : : return ret;
87 [ # # ]: 0 : for (i = 0; i < hw->mw_cnt; i++) {
88 : 0 : NTB_LOG(INFO, "Local %u mw size: 0x%"PRIx64"", i,
89 : : hw->mw_size[i]);
90 : 0 : val = hw->mw_size[i] >> 32;
91 : 0 : ret = (*hw->ntb_ops->spad_write)(dev, SPAD_MW0_SZ_H + 2 * i,
92 : : 1, val);
93 [ # # ]: 0 : if (ret < 0)
94 : 0 : return ret;
95 : 0 : val = hw->mw_size[i];
96 : 0 : ret = (*hw->ntb_ops->spad_write)(dev, SPAD_MW0_SZ_L + 2 * i,
97 : : 1, val);
98 [ # # ]: 0 : if (ret < 0)
99 : 0 : return ret;
100 : : }
101 : :
102 : : /* Tell peer about the queue info and map memory to the peer. */
103 : 0 : ret = (*hw->ntb_ops->spad_write)(dev, SPAD_Q_SZ, 1, hw->queue_size);
104 [ # # ]: 0 : if (ret < 0)
105 : : return ret;
106 : 0 : ret = (*hw->ntb_ops->spad_write)(dev, SPAD_NUM_QPS, 1,
107 : 0 : hw->queue_pairs);
108 [ # # ]: 0 : if (ret < 0)
109 : : return ret;
110 : 0 : ret = (*hw->ntb_ops->spad_write)(dev, SPAD_USED_MWS, 1,
111 : 0 : hw->used_mw_num);
112 [ # # ]: 0 : if (ret < 0)
113 : : return ret;
114 [ # # ]: 0 : for (i = 0; i < hw->used_mw_num; i++) {
115 : 0 : val = (uint64_t)(size_t)(hw->mz[i]->addr) >> 32;
116 : 0 : ret = (*hw->ntb_ops->spad_write)(dev, SPAD_MW0_BA_H + 2 * i,
117 : : 1, val);
118 [ # # ]: 0 : if (ret < 0)
119 : 0 : return ret;
120 : 0 : val = (uint64_t)(size_t)(hw->mz[i]->addr);
121 : 0 : ret = (*hw->ntb_ops->spad_write)(dev, SPAD_MW0_BA_L + 2 * i,
122 : : 1, val);
123 [ # # ]: 0 : if (ret < 0)
124 : 0 : return ret;
125 : : }
126 : :
127 [ # # ]: 0 : for (i = 0; i < hw->used_mw_num; i++) {
128 : 0 : ret = (*hw->ntb_ops->mw_set_trans)(dev, i, hw->mz[i]->iova,
129 : 0 : hw->mz[i]->len);
130 [ # # ]: 0 : if (ret < 0)
131 : 0 : return ret;
132 : : }
133 : :
134 : : /* Ring doorbell 0 to tell peer the device is ready. */
135 : 0 : ret = (*hw->ntb_ops->peer_db_set)(dev, 0);
136 : : if (ret < 0)
137 : : return ret;
138 : :
139 : : return 0;
140 : : }
141 : :
142 : : static void
143 : 0 : ntb_dev_intr_handler(void *param)
144 : : {
145 : : struct rte_rawdev *dev = (struct rte_rawdev *)param;
146 : 0 : struct ntb_hw *hw = dev->dev_private;
147 : : uint32_t val_h, val_l;
148 : : uint64_t peer_mw_size;
149 : : uint64_t db_bits = 0;
150 : : uint8_t peer_mw_cnt;
151 : : int i = 0;
152 : :
153 [ # # ]: 0 : if (hw->ntb_ops->db_read == NULL ||
154 [ # # ]: 0 : hw->ntb_ops->db_clear == NULL ||
155 [ # # ]: 0 : hw->ntb_ops->peer_db_set == NULL) {
156 : 0 : NTB_LOG(ERR, "Doorbell is not supported.");
157 : 0 : return;
158 : : }
159 : :
160 : 0 : db_bits = (*hw->ntb_ops->db_read)(dev);
161 [ # # ]: 0 : if (!db_bits)
162 : 0 : NTB_LOG(ERR, "No doorbells");
163 : :
164 : : /* Doorbell 0 is for peer device ready. */
165 [ # # ]: 0 : if (db_bits & 1) {
166 : 0 : NTB_LOG(INFO, "DB0: Peer device is up.");
167 : : /* Clear received doorbell. */
168 : 0 : (*hw->ntb_ops->db_clear)(dev, 1);
169 : :
170 : : /**
171 : : * Peer dev is already up. All mw settings are already done.
172 : : * Skip them.
173 : : */
174 [ # # ]: 0 : if (hw->peer_dev_up)
175 : : return;
176 : :
177 [ # # ]: 0 : if (hw->ntb_ops->spad_read == NULL) {
178 : 0 : NTB_LOG(ERR, "Scratchpad read is not supported.");
179 : 0 : return;
180 : : }
181 : :
182 : : /* Check if mw setting on the peer is the same as local. */
183 : 0 : peer_mw_cnt = (*hw->ntb_ops->spad_read)(dev, SPAD_NUM_MWS, 0);
184 [ # # ]: 0 : if (peer_mw_cnt != hw->mw_cnt) {
185 : 0 : NTB_LOG(ERR, "Both mw cnt must be the same.");
186 : 0 : return;
187 : : }
188 : :
189 [ # # ]: 0 : for (i = 0; i < hw->mw_cnt; i++) {
190 : 0 : val_h = (*hw->ntb_ops->spad_read)
191 : 0 : (dev, SPAD_MW0_SZ_H + 2 * i, 0);
192 : 0 : val_l = (*hw->ntb_ops->spad_read)
193 : 0 : (dev, SPAD_MW0_SZ_L + 2 * i, 0);
194 : 0 : peer_mw_size = ((uint64_t)val_h << 32) | val_l;
195 : 0 : NTB_LOG(DEBUG, "Peer %u mw size: 0x%"PRIx64"", i,
196 : : peer_mw_size);
197 [ # # ]: 0 : if (peer_mw_size != hw->mw_size[i]) {
198 : 0 : NTB_LOG(ERR, "Mw config must be the same.");
199 : 0 : return;
200 : : }
201 : : }
202 : :
203 : 0 : hw->peer_dev_up = 1;
204 : :
205 : : /**
206 : : * Handshake with peer. Spad_write & mw_set_trans only works
207 : : * when both devices are up. So write spad again when db is
208 : : * received. And set db again for the later device who may miss
209 : : * the 1st db.
210 : : */
211 [ # # ]: 0 : if (ntb_handshake_work(dev) < 0) {
212 : 0 : NTB_LOG(ERR, "Handshake work failed.");
213 : 0 : return;
214 : : }
215 : :
216 : : /* To get the link info. */
217 [ # # ]: 0 : if (hw->ntb_ops->get_link_status == NULL) {
218 : 0 : NTB_LOG(ERR, "Not supported to get link status.");
219 : 0 : return;
220 : : }
221 : 0 : (*hw->ntb_ops->get_link_status)(dev);
222 : 0 : NTB_LOG(INFO, "Link is up. Link speed: %u. Link width: %u",
223 : : hw->link_speed, hw->link_width);
224 : 0 : return;
225 : : }
226 : :
227 [ # # ]: 0 : if (db_bits & (1 << 1)) {
228 : 0 : NTB_LOG(INFO, "DB1: Peer device is down.");
229 : : /* Clear received doorbell. */
230 : 0 : (*hw->ntb_ops->db_clear)(dev, 2);
231 : :
232 : : /* Peer device will be down, So clean local side too. */
233 : 0 : ntb_link_cleanup(dev);
234 : :
235 : 0 : hw->peer_dev_up = 0;
236 : : /* Response peer's dev_stop request. */
237 : 0 : (*hw->ntb_ops->peer_db_set)(dev, 2);
238 : 0 : return;
239 : : }
240 : :
241 [ # # ]: 0 : if (db_bits & (1 << 2)) {
242 : 0 : NTB_LOG(INFO, "DB2: Peer device agrees dev to be down.");
243 : : /* Clear received doorbell. */
244 : 0 : (*hw->ntb_ops->db_clear)(dev, (1 << 2));
245 : 0 : hw->peer_dev_up = 0;
246 : 0 : return;
247 : : }
248 : :
249 : : /* Clear other received doorbells. */
250 : 0 : (*hw->ntb_ops->db_clear)(dev, db_bits);
251 : : }
252 : :
253 : : static int
254 : 0 : ntb_queue_conf_get(struct rte_rawdev *dev,
255 : : uint16_t queue_id,
256 : : rte_rawdev_obj_t queue_conf,
257 : : size_t conf_size)
258 : : {
259 : : struct ntb_queue_conf *q_conf = queue_conf;
260 : 0 : struct ntb_hw *hw = dev->dev_private;
261 : :
262 [ # # ]: 0 : if (conf_size != sizeof(*q_conf))
263 : : return -EINVAL;
264 : :
265 : 0 : q_conf->tx_free_thresh = hw->tx_queues[queue_id]->tx_free_thresh;
266 : 0 : q_conf->nb_desc = hw->rx_queues[queue_id]->nb_rx_desc;
267 : 0 : q_conf->rx_mp = hw->rx_queues[queue_id]->mpool;
268 : :
269 : 0 : return 0;
270 : : }
271 : :
272 : : static void
273 : 0 : ntb_rxq_release_mbufs(struct ntb_rx_queue *q)
274 : : {
275 : : int i;
276 : :
277 [ # # # # ]: 0 : if (!q || !q->sw_ring) {
278 : 0 : NTB_LOG(ERR, "Pointer to rxq or sw_ring is NULL");
279 : 0 : return;
280 : : }
281 : :
282 [ # # ]: 0 : for (i = 0; i < q->nb_rx_desc; i++) {
283 [ # # ]: 0 : if (q->sw_ring[i].mbuf) {
284 : : rte_pktmbuf_free_seg(q->sw_ring[i].mbuf);
285 : 0 : q->sw_ring[i].mbuf = NULL;
286 : : }
287 : : }
288 : : }
289 : :
290 : : static void
291 : 0 : ntb_rxq_release(struct ntb_rx_queue *rxq)
292 : : {
293 [ # # ]: 0 : if (!rxq) {
294 : 0 : NTB_LOG(ERR, "Pointer to rxq is NULL");
295 : 0 : return;
296 : : }
297 : :
298 : 0 : ntb_rxq_release_mbufs(rxq);
299 : :
300 : 0 : rte_free(rxq->sw_ring);
301 : 0 : rte_free(rxq);
302 : : }
303 : :
304 : : static int
305 : 0 : ntb_rxq_setup(struct rte_rawdev *dev,
306 : : uint16_t qp_id,
307 : : rte_rawdev_obj_t queue_conf,
308 : : size_t conf_size)
309 : : {
310 : : struct ntb_queue_conf *rxq_conf = queue_conf;
311 : 0 : struct ntb_hw *hw = dev->dev_private;
312 : : struct ntb_rx_queue *rxq;
313 : :
314 [ # # ]: 0 : if (conf_size != sizeof(*rxq_conf))
315 : : return -EINVAL;
316 : :
317 : : /* Allocate the rx queue data structure */
318 : 0 : rxq = rte_zmalloc_socket("ntb rx queue",
319 : : sizeof(struct ntb_rx_queue),
320 : : RTE_CACHE_LINE_SIZE,
321 : : dev->socket_id);
322 [ # # ]: 0 : if (!rxq) {
323 : 0 : NTB_LOG(ERR, "Failed to allocate memory for "
324 : : "rx queue data structure.");
325 : 0 : return -ENOMEM;
326 : : }
327 : :
328 [ # # ]: 0 : if (rxq_conf->rx_mp == NULL) {
329 : 0 : NTB_LOG(ERR, "Invalid null mempool pointer.");
330 : 0 : return -EINVAL;
331 : : }
332 : 0 : rxq->nb_rx_desc = rxq_conf->nb_desc;
333 : 0 : rxq->mpool = rxq_conf->rx_mp;
334 : 0 : rxq->port_id = dev->dev_id;
335 : 0 : rxq->queue_id = qp_id;
336 : 0 : rxq->hw = hw;
337 : :
338 : : /* Allocate the software ring. */
339 : 0 : rxq->sw_ring =
340 : 0 : rte_zmalloc_socket("ntb rx sw ring",
341 : : sizeof(struct ntb_rx_entry) *
342 : 0 : rxq->nb_rx_desc,
343 : : RTE_CACHE_LINE_SIZE,
344 : : dev->socket_id);
345 [ # # ]: 0 : if (!rxq->sw_ring) {
346 : 0 : ntb_rxq_release(rxq);
347 : : rxq = NULL;
348 : 0 : NTB_LOG(ERR, "Failed to allocate memory for SW ring");
349 : 0 : return -ENOMEM;
350 : : }
351 : :
352 : 0 : hw->rx_queues[qp_id] = rxq;
353 : :
354 : 0 : return 0;
355 : : }
356 : :
357 : : static void
358 : 0 : ntb_txq_release_mbufs(struct ntb_tx_queue *q)
359 : : {
360 : : int i;
361 : :
362 [ # # # # ]: 0 : if (!q || !q->sw_ring) {
363 : 0 : NTB_LOG(ERR, "Pointer to txq or sw_ring is NULL");
364 : 0 : return;
365 : : }
366 : :
367 [ # # ]: 0 : for (i = 0; i < q->nb_tx_desc; i++) {
368 [ # # ]: 0 : if (q->sw_ring[i].mbuf) {
369 : : rte_pktmbuf_free_seg(q->sw_ring[i].mbuf);
370 : 0 : q->sw_ring[i].mbuf = NULL;
371 : : }
372 : : }
373 : : }
374 : :
375 : : static void
376 : 0 : ntb_txq_release(struct ntb_tx_queue *txq)
377 : : {
378 [ # # ]: 0 : if (!txq) {
379 : 0 : NTB_LOG(ERR, "Pointer to txq is NULL");
380 : 0 : return;
381 : : }
382 : :
383 : 0 : ntb_txq_release_mbufs(txq);
384 : :
385 : 0 : rte_free(txq->sw_ring);
386 : 0 : rte_free(txq);
387 : : }
388 : :
389 : : static int
390 : 0 : ntb_txq_setup(struct rte_rawdev *dev,
391 : : uint16_t qp_id,
392 : : rte_rawdev_obj_t queue_conf,
393 : : size_t conf_size)
394 : : {
395 : : struct ntb_queue_conf *txq_conf = queue_conf;
396 : 0 : struct ntb_hw *hw = dev->dev_private;
397 : : struct ntb_tx_queue *txq;
398 : : uint16_t i, prev;
399 : :
400 [ # # ]: 0 : if (conf_size != sizeof(*txq_conf))
401 : : return -EINVAL;
402 : :
403 : : /* Allocate the TX queue data structure. */
404 : 0 : txq = rte_zmalloc_socket("ntb tx queue",
405 : : sizeof(struct ntb_tx_queue),
406 : : RTE_CACHE_LINE_SIZE,
407 : : dev->socket_id);
408 [ # # ]: 0 : if (!txq) {
409 : 0 : NTB_LOG(ERR, "Failed to allocate memory for "
410 : : "tx queue structure");
411 : 0 : return -ENOMEM;
412 : : }
413 : :
414 : 0 : txq->nb_tx_desc = txq_conf->nb_desc;
415 : 0 : txq->port_id = dev->dev_id;
416 : 0 : txq->queue_id = qp_id;
417 : 0 : txq->hw = hw;
418 : :
419 : : /* Allocate software ring */
420 : 0 : txq->sw_ring =
421 : 0 : rte_zmalloc_socket("ntb tx sw ring",
422 : : sizeof(struct ntb_tx_entry) *
423 : 0 : txq->nb_tx_desc,
424 : : RTE_CACHE_LINE_SIZE,
425 : : dev->socket_id);
426 [ # # ]: 0 : if (!txq->sw_ring) {
427 : 0 : ntb_txq_release(txq);
428 : : txq = NULL;
429 : 0 : NTB_LOG(ERR, "Failed to allocate memory for SW TX ring");
430 : 0 : return -ENOMEM;
431 : : }
432 : :
433 : 0 : prev = txq->nb_tx_desc - 1;
434 [ # # ]: 0 : for (i = 0; i < txq->nb_tx_desc; i++) {
435 : 0 : txq->sw_ring[i].mbuf = NULL;
436 : 0 : txq->sw_ring[i].last_id = i;
437 : 0 : txq->sw_ring[prev].next_id = i;
438 : : prev = i;
439 : : }
440 : :
441 [ # # ]: 0 : txq->tx_free_thresh = txq_conf->tx_free_thresh ?
442 : : txq_conf->tx_free_thresh :
443 : : NTB_DFLT_TX_FREE_THRESH;
444 [ # # ]: 0 : if (txq->tx_free_thresh >= txq->nb_tx_desc - 3) {
445 : 0 : NTB_LOG(ERR, "tx_free_thresh must be less than nb_desc - 3. "
446 : : "(tx_free_thresh=%u qp_id=%u)", txq->tx_free_thresh,
447 : : qp_id);
448 : 0 : return -EINVAL;
449 : : }
450 : :
451 : 0 : hw->tx_queues[qp_id] = txq;
452 : :
453 : 0 : return 0;
454 : : }
455 : :
456 : :
457 : : static int
458 : 0 : ntb_queue_setup(struct rte_rawdev *dev,
459 : : uint16_t queue_id,
460 : : rte_rawdev_obj_t queue_conf,
461 : : size_t conf_size)
462 : : {
463 : 0 : struct ntb_hw *hw = dev->dev_private;
464 : : int ret;
465 : :
466 [ # # ]: 0 : if (queue_id >= hw->queue_pairs)
467 : : return -EINVAL;
468 : :
469 : 0 : ret = ntb_txq_setup(dev, queue_id, queue_conf, conf_size);
470 [ # # ]: 0 : if (ret < 0)
471 : : return ret;
472 : :
473 : 0 : ret = ntb_rxq_setup(dev, queue_id, queue_conf, conf_size);
474 : :
475 : 0 : return ret;
476 : : }
477 : :
478 : : static int
479 : 0 : ntb_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
480 : : {
481 : 0 : struct ntb_hw *hw = dev->dev_private;
482 : :
483 [ # # ]: 0 : if (queue_id >= hw->queue_pairs)
484 : : return -EINVAL;
485 : :
486 : 0 : ntb_txq_release(hw->tx_queues[queue_id]);
487 : 0 : hw->tx_queues[queue_id] = NULL;
488 : 0 : ntb_rxq_release(hw->rx_queues[queue_id]);
489 : 0 : hw->rx_queues[queue_id] = NULL;
490 : :
491 : 0 : return 0;
492 : : }
493 : :
494 : : static uint16_t
495 : 0 : ntb_queue_count(struct rte_rawdev *dev)
496 : : {
497 : 0 : struct ntb_hw *hw = dev->dev_private;
498 : 0 : return hw->queue_pairs;
499 : : }
500 : :
501 : : static int
502 : 0 : ntb_queue_init(struct rte_rawdev *dev, uint16_t qp_id)
503 : : {
504 : 0 : struct ntb_hw *hw = dev->dev_private;
505 : 0 : struct ntb_rx_queue *rxq = hw->rx_queues[qp_id];
506 : 0 : struct ntb_tx_queue *txq = hw->tx_queues[qp_id];
507 : : volatile struct ntb_header *local_hdr;
508 : : struct ntb_header *remote_hdr;
509 : 0 : uint16_t q_size = hw->queue_size;
510 : : uint32_t hdr_offset;
511 : : void *bar_addr;
512 : : uint16_t i;
513 : :
514 [ # # ]: 0 : if (hw->ntb_ops->get_peer_mw_addr == NULL) {
515 : 0 : NTB_LOG(ERR, "Getting peer mw addr is not supported.");
516 : 0 : return -EINVAL;
517 : : }
518 : :
519 : : /* Put queue info into the start of shared memory. */
520 : 0 : hdr_offset = hw->hdr_size_per_queue * qp_id;
521 : 0 : local_hdr = (volatile struct ntb_header *)
522 : 0 : ((size_t)hw->mz[0]->addr + hdr_offset);
523 : 0 : bar_addr = (*hw->ntb_ops->get_peer_mw_addr)(dev, 0);
524 [ # # ]: 0 : if (bar_addr == NULL)
525 : : return -EINVAL;
526 : 0 : remote_hdr = (struct ntb_header *)
527 : 0 : ((size_t)bar_addr + hdr_offset);
528 : :
529 : : /* rxq init. */
530 : 0 : rxq->rx_desc_ring = (struct ntb_desc *)
531 : 0 : (&remote_hdr->desc_ring);
532 : 0 : rxq->rx_used_ring = (volatile struct ntb_used *)
533 : 0 : (&local_hdr->desc_ring[q_size]);
534 : 0 : rxq->avail_cnt = &remote_hdr->avail_cnt;
535 : 0 : rxq->used_cnt = &local_hdr->used_cnt;
536 : :
537 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc - 1; i++) {
538 : 0 : struct rte_mbuf *mbuf = rte_mbuf_raw_alloc(rxq->mpool);
539 [ # # ]: 0 : if (unlikely(!mbuf)) {
540 : 0 : NTB_LOG(ERR, "Failed to allocate mbuf for RX");
541 : 0 : return -ENOMEM;
542 : : }
543 : 0 : mbuf->port = dev->dev_id;
544 : :
545 : 0 : rxq->sw_ring[i].mbuf = mbuf;
546 : :
547 : 0 : rxq->rx_desc_ring[i].addr = rte_pktmbuf_mtod(mbuf, size_t);
548 : 0 : rxq->rx_desc_ring[i].len = mbuf->buf_len - RTE_PKTMBUF_HEADROOM;
549 : : }
550 : : rte_wmb();
551 : 0 : *rxq->avail_cnt = rxq->nb_rx_desc - 1;
552 : 0 : rxq->last_avail = rxq->nb_rx_desc - 1;
553 : 0 : rxq->last_used = 0;
554 : :
555 : : /* txq init */
556 : 0 : txq->tx_desc_ring = (volatile struct ntb_desc *)
557 : 0 : (&local_hdr->desc_ring);
558 : 0 : txq->tx_used_ring = (struct ntb_used *)
559 : 0 : (&remote_hdr->desc_ring[q_size]);
560 : 0 : txq->avail_cnt = &local_hdr->avail_cnt;
561 : 0 : txq->used_cnt = &remote_hdr->used_cnt;
562 : :
563 : : rte_wmb();
564 : 0 : *txq->used_cnt = 0;
565 : 0 : txq->last_used = 0;
566 : 0 : txq->last_avail = 0;
567 : 0 : txq->nb_tx_free = txq->nb_tx_desc - 1;
568 : :
569 : : /* Set per queue stats. */
570 [ # # ]: 0 : for (i = 0; i < NTB_XSTATS_NUM; i++) {
571 : 0 : hw->ntb_xstats[i + NTB_XSTATS_NUM * (qp_id + 1)] = 0;
572 : 0 : hw->ntb_xstats_off[i + NTB_XSTATS_NUM * (qp_id + 1)] = 0;
573 : : }
574 : :
575 : : return 0;
576 : : }
577 : :
578 : : static inline void
579 : 0 : ntb_enqueue_cleanup(struct ntb_tx_queue *txq)
580 : : {
581 : 0 : struct ntb_tx_entry *sw_ring = txq->sw_ring;
582 : 0 : uint16_t tx_free = txq->last_avail;
583 : : uint16_t nb_to_clean, i;
584 : :
585 : : /* avail_cnt + 1 represents where to rx next in the peer. */
586 : 0 : nb_to_clean = (*txq->avail_cnt - txq->last_avail + 1 +
587 : 0 : txq->nb_tx_desc) & (txq->nb_tx_desc - 1);
588 : 0 : nb_to_clean = RTE_MIN(nb_to_clean, txq->tx_free_thresh);
589 [ # # ]: 0 : for (i = 0; i < nb_to_clean; i++) {
590 [ # # ]: 0 : if (sw_ring[tx_free].mbuf)
591 : : rte_pktmbuf_free_seg(sw_ring[tx_free].mbuf);
592 : 0 : tx_free = (tx_free + 1) & (txq->nb_tx_desc - 1);
593 : : }
594 : :
595 : 0 : txq->nb_tx_free += nb_to_clean;
596 : 0 : txq->last_avail = tx_free;
597 : 0 : }
598 : :
599 : : static int
600 : 0 : ntb_enqueue_bufs(struct rte_rawdev *dev,
601 : : struct rte_rawdev_buf **buffers,
602 : : unsigned int count,
603 : : rte_rawdev_obj_t context)
604 : : {
605 : 0 : struct ntb_hw *hw = dev->dev_private;
606 : 0 : struct ntb_tx_queue *txq = hw->tx_queues[(size_t)context];
607 : 0 : struct ntb_tx_entry *sw_ring = txq->sw_ring;
608 : : struct rte_mbuf *txm;
609 : : struct ntb_used tx_used[NTB_MAX_DESC_SIZE];
610 : : volatile struct ntb_desc *tx_item;
611 : : uint16_t tx_last, nb_segs, off, last_used, avail_cnt;
612 : : uint16_t nb_mbufs = 0;
613 : : uint16_t nb_tx = 0;
614 : : uint64_t bytes = 0;
615 : : void *buf_addr;
616 : : int i;
617 : :
618 [ # # ]: 0 : if (unlikely(hw->ntb_ops->ioremap == NULL)) {
619 : 0 : NTB_LOG(ERR, "Ioremap not supported.");
620 : 0 : return nb_tx;
621 : : }
622 : :
623 [ # # # # ]: 0 : if (unlikely(dev->started == 0 || hw->peer_dev_up == 0)) {
624 : 0 : NTB_LOG(DEBUG, "Link is not up.");
625 : 0 : return nb_tx;
626 : : }
627 : :
628 [ # # ]: 0 : if (txq->nb_tx_free < txq->tx_free_thresh)
629 : 0 : ntb_enqueue_cleanup(txq);
630 : :
631 : 0 : off = NTB_XSTATS_NUM * ((size_t)context + 1);
632 : 0 : last_used = txq->last_used;
633 : 0 : avail_cnt = *txq->avail_cnt;/* Where to alloc next. */
634 [ # # ]: 0 : for (nb_tx = 0; nb_tx < count; nb_tx++) {
635 : 0 : txm = (struct rte_mbuf *)(buffers[nb_tx]->buf_addr);
636 [ # # # # ]: 0 : if (txm == NULL || txq->nb_tx_free < txm->nb_segs)
637 : : break;
638 : :
639 : 0 : tx_last = (txq->last_used + txm->nb_segs - 1) &
640 : 0 : (txq->nb_tx_desc - 1);
641 : : nb_segs = txm->nb_segs;
642 [ # # ]: 0 : for (i = 0; i < nb_segs; i++) {
643 : : /* Not enough ring space for tx. */
644 [ # # ]: 0 : if (txq->last_used == avail_cnt)
645 : 0 : goto end_of_tx;
646 : 0 : sw_ring[txq->last_used].mbuf = txm;
647 : 0 : tx_item = txq->tx_desc_ring + txq->last_used;
648 : :
649 [ # # ]: 0 : if (!tx_item->len) {
650 : 0 : (hw->ntb_xstats[NTB_TX_ERRS_ID + off])++;
651 : 0 : goto end_of_tx;
652 : : }
653 [ # # ]: 0 : if (txm->data_len > tx_item->len) {
654 : 0 : NTB_LOG(ERR, "Data length exceeds buf length."
655 : : " Only %u data would be transmitted.",
656 : : tx_item->len);
657 : 0 : txm->data_len = tx_item->len;
658 : : }
659 : :
660 : : /* translate remote virtual addr to bar virtual addr */
661 : 0 : buf_addr = (*hw->ntb_ops->ioremap)(dev, tx_item->addr);
662 [ # # ]: 0 : if (buf_addr == NULL) {
663 : 0 : (hw->ntb_xstats[NTB_TX_ERRS_ID + off])++;
664 : 0 : NTB_LOG(ERR, "Null remap addr.");
665 : 0 : goto end_of_tx;
666 : : }
667 : 0 : rte_memcpy(buf_addr, rte_pktmbuf_mtod(txm, void *),
668 [ # # ]: 0 : txm->data_len);
669 : :
670 : 0 : tx_used[nb_mbufs].len = txm->data_len;
671 : 0 : tx_used[nb_mbufs++].flags = (txq->last_used ==
672 : : tx_last) ?
673 : 0 : NTB_FLAG_EOP : 0;
674 : :
675 : : /* update stats */
676 : 0 : bytes += txm->data_len;
677 : :
678 : 0 : txm = txm->next;
679 : :
680 : 0 : sw_ring[txq->last_used].next_id = (txq->last_used + 1) &
681 : 0 : (txq->nb_tx_desc - 1);
682 : 0 : sw_ring[txq->last_used].last_id = tx_last;
683 : 0 : txq->last_used = (txq->last_used + 1) &
684 : : (txq->nb_tx_desc - 1);
685 : : }
686 : 0 : txq->nb_tx_free -= nb_segs;
687 : : }
688 : :
689 : 0 : end_of_tx:
690 [ # # ]: 0 : if (nb_tx) {
691 : : uint16_t nb1, nb2;
692 [ # # ]: 0 : if (nb_mbufs > txq->nb_tx_desc - last_used) {
693 : 0 : nb1 = txq->nb_tx_desc - last_used;
694 : 0 : nb2 = nb_mbufs - txq->nb_tx_desc + last_used;
695 : : } else {
696 : : nb1 = nb_mbufs;
697 : : nb2 = 0;
698 : : }
699 [ # # ]: 0 : rte_memcpy(txq->tx_used_ring + last_used, tx_used,
700 : : sizeof(struct ntb_used) * nb1);
701 [ # # ]: 0 : rte_memcpy(txq->tx_used_ring, tx_used + nb1,
702 : : sizeof(struct ntb_used) * nb2);
703 : : rte_wmb();
704 : 0 : *txq->used_cnt = txq->last_used;
705 : :
706 : : /* update queue stats */
707 : 0 : hw->ntb_xstats[NTB_TX_BYTES_ID + off] += bytes;
708 : 0 : hw->ntb_xstats[NTB_TX_PKTS_ID + off] += nb_tx;
709 : : }
710 : :
711 : 0 : return nb_tx;
712 : : }
713 : :
714 : : static int
715 : 0 : ntb_dequeue_bufs(struct rte_rawdev *dev,
716 : : struct rte_rawdev_buf **buffers,
717 : : unsigned int count,
718 : : rte_rawdev_obj_t context)
719 : : {
720 : 0 : struct ntb_hw *hw = dev->dev_private;
721 : 0 : struct ntb_rx_queue *rxq = hw->rx_queues[(size_t)context];
722 : 0 : struct ntb_rx_entry *sw_ring = rxq->sw_ring;
723 : : struct ntb_desc rx_desc[NTB_MAX_DESC_SIZE];
724 : : struct rte_mbuf *first, *rxm_t;
725 : : struct rte_mbuf *prev = NULL;
726 : : volatile struct ntb_used *rx_item;
727 : : uint16_t nb_mbufs = 0;
728 : : uint16_t nb_rx = 0;
729 : : uint64_t bytes = 0;
730 : : uint16_t off, last_avail, used_cnt, used_nb;
731 : : int i;
732 : :
733 [ # # # # ]: 0 : if (unlikely(dev->started == 0 || hw->peer_dev_up == 0)) {
734 : 0 : NTB_LOG(DEBUG, "Link is not up");
735 : 0 : return nb_rx;
736 : : }
737 : :
738 : 0 : used_cnt = *rxq->used_cnt;
739 : :
740 [ # # ]: 0 : if (rxq->last_used == used_cnt)
741 : : return nb_rx;
742 : :
743 : 0 : last_avail = rxq->last_avail;
744 : 0 : used_nb = (used_cnt - rxq->last_used) & (rxq->nb_rx_desc - 1);
745 : 0 : count = RTE_MIN(count, used_nb);
746 [ # # ]: 0 : for (nb_rx = 0; nb_rx < count; nb_rx++) {
747 : : i = 0;
748 : : while (true) {
749 : 0 : rx_item = rxq->rx_used_ring + rxq->last_used;
750 : 0 : rxm_t = sw_ring[rxq->last_used].mbuf;
751 : 0 : rxm_t->data_len = rx_item->len;
752 : 0 : rxm_t->data_off = RTE_PKTMBUF_HEADROOM;
753 : 0 : rxm_t->port = rxq->port_id;
754 : :
755 [ # # ]: 0 : if (!i) {
756 : 0 : rxm_t->nb_segs = 1;
757 : : first = rxm_t;
758 : 0 : first->pkt_len = 0;
759 : 0 : buffers[nb_rx]->buf_addr = rxm_t;
760 : : } else {
761 : 0 : prev->next = rxm_t;
762 : 0 : first->nb_segs++;
763 : : }
764 : :
765 : : prev = rxm_t;
766 : 0 : first->pkt_len += prev->data_len;
767 : 0 : rxq->last_used = (rxq->last_used + 1) &
768 : 0 : (rxq->nb_rx_desc - 1);
769 : :
770 : : /* alloc new mbuf */
771 : 0 : rxm_t = rte_mbuf_raw_alloc(rxq->mpool);
772 [ # # ]: 0 : if (unlikely(rxm_t == NULL)) {
773 : 0 : NTB_LOG(ERR, "recv alloc mbuf failed.");
774 : 0 : goto end_of_rx;
775 : : }
776 : 0 : rxm_t->port = rxq->port_id;
777 : 0 : sw_ring[rxq->last_avail].mbuf = rxm_t;
778 : 0 : i++;
779 : :
780 : : /* fill new desc */
781 : 0 : rx_desc[nb_mbufs].addr =
782 : 0 : rte_pktmbuf_mtod(rxm_t, size_t);
783 : 0 : rx_desc[nb_mbufs++].len = rxm_t->buf_len -
784 : : RTE_PKTMBUF_HEADROOM;
785 : 0 : rxq->last_avail = (rxq->last_avail + 1) &
786 : 0 : (rxq->nb_rx_desc - 1);
787 : :
788 [ # # ]: 0 : if (rx_item->flags & NTB_FLAG_EOP)
789 : : break;
790 : : }
791 : : /* update stats */
792 : 0 : bytes += first->pkt_len;
793 : : }
794 : :
795 : 0 : end_of_rx:
796 [ # # ]: 0 : if (nb_rx) {
797 : : uint16_t nb1, nb2;
798 [ # # ]: 0 : if (nb_mbufs > rxq->nb_rx_desc - last_avail) {
799 : 0 : nb1 = rxq->nb_rx_desc - last_avail;
800 : 0 : nb2 = nb_mbufs - rxq->nb_rx_desc + last_avail;
801 : : } else {
802 : : nb1 = nb_mbufs;
803 : : nb2 = 0;
804 : : }
805 [ # # ]: 0 : rte_memcpy(rxq->rx_desc_ring + last_avail, rx_desc,
806 : : sizeof(struct ntb_desc) * nb1);
807 [ # # ]: 0 : rte_memcpy(rxq->rx_desc_ring, rx_desc + nb1,
808 : : sizeof(struct ntb_desc) * nb2);
809 : : rte_wmb();
810 : 0 : *rxq->avail_cnt = rxq->last_avail;
811 : :
812 : : /* update queue stats */
813 : 0 : off = NTB_XSTATS_NUM * ((size_t)context + 1);
814 : 0 : hw->ntb_xstats[NTB_RX_BYTES_ID + off] += bytes;
815 : 0 : hw->ntb_xstats[NTB_RX_PKTS_ID + off] += nb_rx;
816 : 0 : hw->ntb_xstats[NTB_RX_MISS_ID + off] += (count - nb_rx);
817 : : }
818 : :
819 : 0 : return nb_rx;
820 : : }
821 : :
822 : : static int
823 : 0 : ntb_dev_info_get(struct rte_rawdev *dev, rte_rawdev_obj_t dev_info,
824 : : size_t dev_info_size)
825 : : {
826 : 0 : struct ntb_hw *hw = dev->dev_private;
827 : : struct ntb_dev_info *info = dev_info;
828 : :
829 [ # # ]: 0 : if (dev_info_size != sizeof(*info)) {
830 : 0 : NTB_LOG(ERR, "Invalid size parameter to %s", __func__);
831 : 0 : return -EINVAL;
832 : : }
833 : :
834 : 0 : info->mw_cnt = hw->mw_cnt;
835 : 0 : info->mw_size = hw->mw_size;
836 : :
837 : : /**
838 : : * Intel hardware requires that mapped memory base address should be
839 : : * aligned with EMBARSZ and needs continuous memzone.
840 : : */
841 : 0 : info->mw_size_align = (uint8_t)(hw->pci_dev->id.vendor_id ==
842 : : NTB_INTEL_VENDOR_ID);
843 : :
844 [ # # # # ]: 0 : if (!hw->queue_size || !hw->queue_pairs) {
845 : 0 : NTB_LOG(ERR, "No queue size and queue num assigned.");
846 : 0 : return -EAGAIN;
847 : : }
848 : :
849 : 0 : hw->hdr_size_per_queue = RTE_ALIGN(sizeof(struct ntb_header) +
850 : : hw->queue_size * sizeof(struct ntb_desc) +
851 : : hw->queue_size * sizeof(struct ntb_used),
852 : : RTE_CACHE_LINE_SIZE);
853 : 0 : info->ntb_hdr_size = hw->hdr_size_per_queue * hw->queue_pairs;
854 : :
855 : 0 : return 0;
856 : : }
857 : :
858 : : static int
859 : 0 : ntb_dev_configure(const struct rte_rawdev *dev, rte_rawdev_obj_t config,
860 : : size_t config_size)
861 : : {
862 : : struct ntb_dev_config *conf = config;
863 : 0 : struct ntb_hw *hw = dev->dev_private;
864 : : uint32_t xstats_num;
865 : : int ret;
866 : :
867 [ # # ]: 0 : if (conf == NULL || config_size != sizeof(*conf))
868 : : return -EINVAL;
869 : :
870 : 0 : hw->queue_pairs = conf->num_queues;
871 : 0 : hw->queue_size = conf->queue_size;
872 : 0 : hw->used_mw_num = conf->mz_num;
873 : 0 : hw->mz = conf->mz_list;
874 : 0 : hw->rx_queues = rte_zmalloc("ntb_rx_queues",
875 : 0 : sizeof(struct ntb_rx_queue *) * hw->queue_pairs, 0);
876 : 0 : hw->tx_queues = rte_zmalloc("ntb_tx_queues",
877 : 0 : sizeof(struct ntb_tx_queue *) * hw->queue_pairs, 0);
878 : : /* First total stats, then per queue stats. */
879 : 0 : xstats_num = (hw->queue_pairs + 1) * NTB_XSTATS_NUM;
880 : 0 : hw->ntb_xstats = rte_zmalloc("ntb_xstats", xstats_num *
881 : : sizeof(uint64_t), 0);
882 : 0 : hw->ntb_xstats_off = rte_zmalloc("ntb_xstats_off", xstats_num *
883 : : sizeof(uint64_t), 0);
884 : :
885 : : /* Start handshake with the peer. */
886 : 0 : ret = ntb_handshake_work(dev);
887 [ # # ]: 0 : if (ret < 0) {
888 : 0 : rte_free(hw->rx_queues);
889 : 0 : rte_free(hw->tx_queues);
890 : 0 : hw->rx_queues = NULL;
891 : 0 : hw->tx_queues = NULL;
892 : 0 : return ret;
893 : : }
894 : :
895 : : return 0;
896 : : }
897 : :
898 : : static int
899 : 0 : ntb_dev_start(struct rte_rawdev *dev)
900 : : {
901 : 0 : struct ntb_hw *hw = dev->dev_private;
902 : : uint32_t peer_base_l, peer_val;
903 : : uint64_t peer_base_h;
904 : : uint32_t i;
905 : : int ret;
906 : :
907 [ # # # # ]: 0 : if (!hw->link_status || !hw->peer_dev_up)
908 : : return -EINVAL;
909 : :
910 : : /* Set total stats. */
911 [ # # ]: 0 : for (i = 0; i < NTB_XSTATS_NUM; i++) {
912 : 0 : hw->ntb_xstats[i] = 0;
913 : 0 : hw->ntb_xstats_off[i] = 0;
914 : : }
915 : :
916 [ # # ]: 0 : for (i = 0; i < hw->queue_pairs; i++) {
917 : 0 : ret = ntb_queue_init(dev, i);
918 [ # # ]: 0 : if (ret) {
919 : 0 : NTB_LOG(ERR, "Failed to init queue.");
920 : 0 : goto err_q_init;
921 : : }
922 : : }
923 : :
924 : 0 : hw->peer_mw_base = rte_zmalloc("ntb_peer_mw_base", hw->mw_cnt *
925 : : sizeof(uint64_t), 0);
926 [ # # ]: 0 : if (hw->peer_mw_base == NULL) {
927 : 0 : NTB_LOG(ERR, "Cannot allocate memory for peer mw base.");
928 : : ret = -ENOMEM;
929 : 0 : goto err_q_init;
930 : : }
931 : :
932 [ # # ]: 0 : if (hw->ntb_ops->spad_read == NULL) {
933 : : ret = -ENOTSUP;
934 : 0 : goto err_up;
935 : : }
936 : :
937 : 0 : peer_val = (*hw->ntb_ops->spad_read)(dev, SPAD_Q_SZ, 0);
938 [ # # ]: 0 : if (peer_val != hw->queue_size) {
939 : 0 : NTB_LOG(ERR, "Inconsistent queue size! (local: %u peer: %u)",
940 : : hw->queue_size, peer_val);
941 : : ret = -EINVAL;
942 : 0 : goto err_up;
943 : : }
944 : :
945 : 0 : peer_val = (*hw->ntb_ops->spad_read)(dev, SPAD_NUM_QPS, 0);
946 [ # # ]: 0 : if (peer_val != hw->queue_pairs) {
947 : 0 : NTB_LOG(ERR, "Inconsistent number of queues! (local: %u peer:"
948 : : " %u)", hw->queue_pairs, peer_val);
949 : : ret = -EINVAL;
950 : 0 : goto err_up;
951 : : }
952 : :
953 : 0 : hw->peer_used_mws = (*hw->ntb_ops->spad_read)(dev, SPAD_USED_MWS, 0);
954 : :
955 [ # # ]: 0 : for (i = 0; i < hw->peer_used_mws; i++) {
956 : 0 : peer_base_h = (*hw->ntb_ops->spad_read)(dev,
957 : 0 : SPAD_MW0_BA_H + 2 * i, 0);
958 : 0 : peer_base_l = (*hw->ntb_ops->spad_read)(dev,
959 : 0 : SPAD_MW0_BA_L + 2 * i, 0);
960 : 0 : hw->peer_mw_base[i] = (peer_base_h << 32) + peer_base_l;
961 : : }
962 : :
963 : 0 : dev->started = 1;
964 : :
965 : 0 : return 0;
966 : :
967 : 0 : err_up:
968 : 0 : rte_free(hw->peer_mw_base);
969 : 0 : err_q_init:
970 [ # # ]: 0 : for (i = 0; i < hw->queue_pairs; i++) {
971 : 0 : ntb_rxq_release_mbufs(hw->rx_queues[i]);
972 : 0 : ntb_txq_release_mbufs(hw->tx_queues[i]);
973 : : }
974 : :
975 : : return ret;
976 : : }
977 : :
978 : : static void
979 : 0 : ntb_dev_stop(struct rte_rawdev *dev)
980 : : {
981 : 0 : struct ntb_hw *hw = dev->dev_private;
982 : : uint32_t time_out;
983 : : int status, i;
984 : :
985 [ # # ]: 0 : if (!hw->peer_dev_up)
986 : 0 : goto clean;
987 : :
988 : 0 : ntb_link_cleanup(dev);
989 : :
990 : : /* Notify the peer that device will be down. */
991 [ # # ]: 0 : if (hw->ntb_ops->peer_db_set == NULL) {
992 : 0 : NTB_LOG(ERR, "Peer doorbell setting is not supported.");
993 : 0 : return;
994 : : }
995 : 0 : status = (*hw->ntb_ops->peer_db_set)(dev, 1);
996 [ # # ]: 0 : if (status) {
997 : 0 : NTB_LOG(ERR, "Failed to tell peer device is down.");
998 : 0 : return;
999 : : }
1000 : :
1001 : : /*
1002 : : * Set time out as 1s in case that the peer is stopped accidently
1003 : : * without any notification.
1004 : : */
1005 : : time_out = 1000000;
1006 : :
1007 : : /* Wait for cleanup work down before db mask clear. */
1008 [ # # # # ]: 0 : while (hw->peer_dev_up && time_out) {
1009 : 0 : time_out -= 10;
1010 : 0 : rte_delay_us(10);
1011 : : }
1012 : :
1013 : 0 : clean:
1014 : : /* Clear doorbells mask. */
1015 [ # # ]: 0 : if (hw->ntb_ops->db_set_mask == NULL) {
1016 : 0 : NTB_LOG(ERR, "Doorbell mask setting is not supported.");
1017 : 0 : return;
1018 : : }
1019 : 0 : status = (*hw->ntb_ops->db_set_mask)(dev,
1020 : 0 : (((uint64_t)1 << hw->db_cnt) - 1));
1021 [ # # ]: 0 : if (status)
1022 : 0 : NTB_LOG(ERR, "Failed to clear doorbells.");
1023 : :
1024 [ # # ]: 0 : for (i = 0; i < hw->queue_pairs; i++) {
1025 : 0 : ntb_rxq_release_mbufs(hw->rx_queues[i]);
1026 : 0 : ntb_txq_release_mbufs(hw->tx_queues[i]);
1027 : : }
1028 : :
1029 : 0 : dev->started = 0;
1030 : : }
1031 : :
1032 : : static int
1033 : 0 : ntb_dev_close(struct rte_rawdev *dev)
1034 : : {
1035 : 0 : struct ntb_hw *hw = dev->dev_private;
1036 : : struct rte_intr_handle *intr_handle;
1037 : : int i;
1038 : :
1039 [ # # ]: 0 : if (dev->started)
1040 : 0 : ntb_dev_stop(dev);
1041 : :
1042 : : /* free queues */
1043 [ # # ]: 0 : for (i = 0; i < hw->queue_pairs; i++)
1044 : 0 : ntb_queue_release(dev, i);
1045 : 0 : hw->queue_pairs = 0;
1046 : :
1047 : 0 : intr_handle = hw->pci_dev->intr_handle;
1048 : : /* Disable interrupt only once */
1049 [ # # # # ]: 0 : if (!rte_intr_nb_efd_get(intr_handle) &&
1050 : 0 : !rte_intr_max_intr_get(intr_handle))
1051 : : return 0;
1052 : :
1053 : : /* Clean datapath event and vec mapping */
1054 : 0 : rte_intr_efd_disable(intr_handle);
1055 : 0 : rte_intr_vec_list_free(intr_handle);
1056 : : /* Disable uio intr before callback unregister */
1057 : 0 : rte_intr_disable(intr_handle);
1058 : :
1059 : : /* Unregister callback func to eal lib */
1060 : 0 : rte_intr_callback_unregister(intr_handle,
1061 : : ntb_dev_intr_handler, dev);
1062 : :
1063 : 0 : return 0;
1064 : : }
1065 : :
1066 : : static int
1067 : 0 : ntb_dev_reset(struct rte_rawdev *rawdev __rte_unused)
1068 : : {
1069 : 0 : return 0;
1070 : : }
1071 : :
1072 : : static int
1073 : 0 : ntb_attr_set(struct rte_rawdev *dev, const char *attr_name,
1074 : : uint64_t attr_value)
1075 : : {
1076 : : struct ntb_hw *hw;
1077 : : int index;
1078 : :
1079 [ # # ]: 0 : if (dev == NULL || attr_name == NULL) {
1080 : 0 : NTB_LOG(ERR, "Invalid arguments for setting attributes");
1081 : 0 : return -EINVAL;
1082 : : }
1083 : :
1084 : 0 : hw = dev->dev_private;
1085 : :
1086 [ # # ]: 0 : if (!strncmp(attr_name, NTB_SPAD_USER, NTB_SPAD_USER_LEN)) {
1087 [ # # ]: 0 : if (hw->ntb_ops->spad_write == NULL)
1088 : : return -ENOTSUP;
1089 : 0 : index = atoi(&attr_name[NTB_SPAD_USER_LEN]);
1090 [ # # ]: 0 : if (index < 0 || index >= NTB_SPAD_USER_MAX_NUM) {
1091 : 0 : NTB_LOG(ERR, "Invalid attribute (%s)", attr_name);
1092 : 0 : return -EINVAL;
1093 : : }
1094 : 0 : (*hw->ntb_ops->spad_write)(dev, hw->spad_user_list[index],
1095 : : 1, attr_value);
1096 : 0 : NTB_LOG(DEBUG, "Set attribute (%s) Value (%" PRIu64 ")",
1097 : : attr_name, attr_value);
1098 : 0 : return 0;
1099 : : }
1100 : :
1101 [ # # ]: 0 : if (!strncmp(attr_name, NTB_QUEUE_SZ_NAME, NTB_ATTR_NAME_LEN)) {
1102 : 0 : hw->queue_size = attr_value;
1103 : 0 : NTB_LOG(DEBUG, "Set attribute (%s) Value (%" PRIu64 ")",
1104 : : attr_name, attr_value);
1105 : 0 : return 0;
1106 : : }
1107 : :
1108 [ # # ]: 0 : if (!strncmp(attr_name, NTB_QUEUE_NUM_NAME, NTB_ATTR_NAME_LEN)) {
1109 : 0 : hw->queue_pairs = attr_value;
1110 : 0 : NTB_LOG(DEBUG, "Set attribute (%s) Value (%" PRIu64 ")",
1111 : : attr_name, attr_value);
1112 : 0 : return 0;
1113 : : }
1114 : :
1115 : : /* Attribute not found. */
1116 : 0 : NTB_LOG(ERR, "Attribute not found.");
1117 : 0 : return -EINVAL;
1118 : : }
1119 : :
1120 : : static int
1121 : 0 : ntb_attr_get(struct rte_rawdev *dev, const char *attr_name,
1122 : : uint64_t *attr_value)
1123 : : {
1124 : : struct ntb_hw *hw;
1125 : : int index;
1126 : :
1127 [ # # # # ]: 0 : if (dev == NULL || attr_name == NULL || attr_value == NULL) {
1128 : 0 : NTB_LOG(ERR, "Invalid arguments for getting attributes");
1129 : 0 : return -EINVAL;
1130 : : }
1131 : :
1132 : 0 : hw = dev->dev_private;
1133 : :
1134 [ # # ]: 0 : if (!strncmp(attr_name, NTB_TOPO_NAME, NTB_ATTR_NAME_LEN)) {
1135 : 0 : *attr_value = hw->topo;
1136 : 0 : NTB_LOG(DEBUG, "Attribute (%s) Value (%" PRIu64 ")",
1137 : : attr_name, *attr_value);
1138 : 0 : return 0;
1139 : : }
1140 : :
1141 [ # # ]: 0 : if (!strncmp(attr_name, NTB_LINK_STATUS_NAME, NTB_ATTR_NAME_LEN)) {
1142 : : /* hw->link_status only indicates hw link status. */
1143 [ # # # # ]: 0 : *attr_value = hw->link_status && hw->peer_dev_up;
1144 : 0 : NTB_LOG(DEBUG, "Attribute (%s) Value (%" PRIu64 ")",
1145 : : attr_name, *attr_value);
1146 : 0 : return 0;
1147 : : }
1148 : :
1149 [ # # ]: 0 : if (!strncmp(attr_name, NTB_SPEED_NAME, NTB_ATTR_NAME_LEN)) {
1150 : 0 : *attr_value = hw->link_speed;
1151 : 0 : NTB_LOG(DEBUG, "Attribute (%s) Value (%" PRIu64 ")",
1152 : : attr_name, *attr_value);
1153 : 0 : return 0;
1154 : : }
1155 : :
1156 [ # # ]: 0 : if (!strncmp(attr_name, NTB_WIDTH_NAME, NTB_ATTR_NAME_LEN)) {
1157 : 0 : *attr_value = hw->link_width;
1158 : 0 : NTB_LOG(DEBUG, "Attribute (%s) Value (%" PRIu64 ")",
1159 : : attr_name, *attr_value);
1160 : 0 : return 0;
1161 : : }
1162 : :
1163 [ # # ]: 0 : if (!strncmp(attr_name, NTB_MW_CNT_NAME, NTB_ATTR_NAME_LEN)) {
1164 : 0 : *attr_value = hw->mw_cnt;
1165 : 0 : NTB_LOG(DEBUG, "Attribute (%s) Value (%" PRIu64 ")",
1166 : : attr_name, *attr_value);
1167 : 0 : return 0;
1168 : : }
1169 : :
1170 [ # # ]: 0 : if (!strncmp(attr_name, NTB_DB_CNT_NAME, NTB_ATTR_NAME_LEN)) {
1171 : 0 : *attr_value = hw->db_cnt;
1172 : 0 : NTB_LOG(DEBUG, "Attribute (%s) Value (%" PRIu64 ")",
1173 : : attr_name, *attr_value);
1174 : 0 : return 0;
1175 : : }
1176 : :
1177 [ # # ]: 0 : if (!strncmp(attr_name, NTB_SPAD_CNT_NAME, NTB_ATTR_NAME_LEN)) {
1178 : 0 : *attr_value = hw->spad_cnt;
1179 : 0 : NTB_LOG(DEBUG, "Attribute (%s) Value (%" PRIu64 ")",
1180 : : attr_name, *attr_value);
1181 : 0 : return 0;
1182 : : }
1183 : :
1184 [ # # ]: 0 : if (!strncmp(attr_name, NTB_SPAD_USER, NTB_SPAD_USER_LEN)) {
1185 [ # # ]: 0 : if (hw->ntb_ops->spad_read == NULL)
1186 : : return -ENOTSUP;
1187 : 0 : index = atoi(&attr_name[NTB_SPAD_USER_LEN]);
1188 [ # # ]: 0 : if (index < 0 || index >= NTB_SPAD_USER_MAX_NUM) {
1189 : 0 : NTB_LOG(ERR, "Attribute (%s) out of range", attr_name);
1190 : 0 : return -EINVAL;
1191 : : }
1192 : 0 : *attr_value = (*hw->ntb_ops->spad_read)(dev,
1193 : : hw->spad_user_list[index], 0);
1194 : 0 : NTB_LOG(DEBUG, "Attribute (%s) Value (%" PRIu64 ")",
1195 : : attr_name, *attr_value);
1196 : 0 : return 0;
1197 : : }
1198 : :
1199 : : /* Attribute not found. */
1200 : 0 : NTB_LOG(ERR, "Attribute not found.");
1201 : 0 : return -EINVAL;
1202 : : }
1203 : :
1204 : : static inline uint64_t
1205 : : ntb_stats_update(uint64_t offset, uint64_t stat)
1206 : : {
1207 : 0 : if (stat >= offset)
1208 : 0 : return (stat - offset);
1209 : : else
1210 : 0 : return (uint64_t)(((uint64_t)-1) - offset + stat + 1);
1211 : : }
1212 : :
1213 : : static int
1214 : 0 : ntb_xstats_get(const struct rte_rawdev *dev,
1215 : : const unsigned int ids[],
1216 : : uint64_t values[],
1217 : : unsigned int n)
1218 : : {
1219 : 0 : struct ntb_hw *hw = dev->dev_private;
1220 : : uint32_t i, j, off, xstats_num;
1221 : :
1222 : : /* Calculate total stats of all queues. */
1223 [ # # ]: 0 : for (i = 0; i < NTB_XSTATS_NUM; i++) {
1224 : 0 : hw->ntb_xstats[i] = 0;
1225 [ # # ]: 0 : for (j = 0; j < hw->queue_pairs; j++) {
1226 : 0 : off = NTB_XSTATS_NUM * (j + 1) + i;
1227 : 0 : hw->ntb_xstats[i] +=
1228 : 0 : ntb_stats_update(hw->ntb_xstats_off[off],
1229 [ # # ]: 0 : hw->ntb_xstats[off]);
1230 : : }
1231 : : }
1232 : :
1233 : 0 : xstats_num = NTB_XSTATS_NUM * (hw->queue_pairs + 1);
1234 [ # # # # ]: 0 : for (i = 0; i < n && ids[i] < xstats_num; i++) {
1235 [ # # ]: 0 : if (ids[i] < NTB_XSTATS_NUM)
1236 : 0 : values[i] = hw->ntb_xstats[ids[i]];
1237 : : else
1238 : 0 : values[i] =
1239 : 0 : ntb_stats_update(hw->ntb_xstats_off[ids[i]],
1240 [ # # ]: 0 : hw->ntb_xstats[ids[i]]);
1241 : : }
1242 : :
1243 : 0 : return i;
1244 : : }
1245 : :
1246 : : static int
1247 : 0 : ntb_xstats_get_names(const struct rte_rawdev *dev,
1248 : : struct rte_rawdev_xstats_name *xstats_names,
1249 : : unsigned int size)
1250 : : {
1251 : 0 : struct ntb_hw *hw = dev->dev_private;
1252 : : uint32_t xstats_num, i, j, off;
1253 : :
1254 : 0 : xstats_num = NTB_XSTATS_NUM * (hw->queue_pairs + 1);
1255 [ # # ]: 0 : if (xstats_names == NULL || size < xstats_num)
1256 : 0 : return xstats_num;
1257 : :
1258 : : /* Total stats names */
1259 : : memcpy(xstats_names, ntb_xstats_names, sizeof(ntb_xstats_names));
1260 : :
1261 : : /* Queue stats names */
1262 [ # # ]: 0 : for (i = 0; i < hw->queue_pairs; i++) {
1263 [ # # ]: 0 : for (j = 0; j < NTB_XSTATS_NUM; j++) {
1264 : 0 : off = j + (i + 1) * NTB_XSTATS_NUM;
1265 : 0 : snprintf(xstats_names[off].name,
1266 : : sizeof(xstats_names[0].name),
1267 : 0 : "%s_q%u", ntb_xstats_names[j].name, i);
1268 : : }
1269 : : }
1270 : :
1271 : 0 : return xstats_num;
1272 : : }
1273 : :
1274 : : static uint64_t
1275 : 0 : ntb_xstats_get_by_name(const struct rte_rawdev *dev,
1276 : : const char *name, unsigned int *id)
1277 : : {
1278 : : struct rte_rawdev_xstats_name *xstats_names;
1279 : 0 : struct ntb_hw *hw = dev->dev_private;
1280 : : uint32_t xstats_num, i, j, off;
1281 : :
1282 [ # # ]: 0 : if (name == NULL)
1283 : : return -EINVAL;
1284 : :
1285 : 0 : xstats_num = NTB_XSTATS_NUM * (hw->queue_pairs + 1);
1286 : 0 : xstats_names = rte_zmalloc("ntb_stats_name",
1287 : : sizeof(struct rte_rawdev_xstats_name) *
1288 : : xstats_num, 0);
1289 : 0 : ntb_xstats_get_names(dev, xstats_names, xstats_num);
1290 : :
1291 : : /* Calculate total stats of all queues. */
1292 [ # # ]: 0 : for (i = 0; i < NTB_XSTATS_NUM; i++) {
1293 [ # # ]: 0 : for (j = 0; j < hw->queue_pairs; j++) {
1294 : 0 : off = NTB_XSTATS_NUM * (j + 1) + i;
1295 : 0 : hw->ntb_xstats[i] +=
1296 : 0 : ntb_stats_update(hw->ntb_xstats_off[off],
1297 [ # # ]: 0 : hw->ntb_xstats[off]);
1298 : : }
1299 : : }
1300 : :
1301 [ # # ]: 0 : for (i = 0; i < xstats_num; i++) {
1302 [ # # ]: 0 : if (!strncmp(name, xstats_names[i].name,
1303 : : RTE_RAW_DEV_XSTATS_NAME_SIZE)) {
1304 : 0 : *id = i;
1305 : 0 : rte_free(xstats_names);
1306 [ # # ]: 0 : if (i < NTB_XSTATS_NUM)
1307 : 0 : return hw->ntb_xstats[i];
1308 : : else
1309 : 0 : return ntb_stats_update(hw->ntb_xstats_off[i],
1310 [ # # ]: 0 : hw->ntb_xstats[i]);
1311 : : }
1312 : : }
1313 : :
1314 : 0 : NTB_LOG(ERR, "Cannot find the xstats name.");
1315 : :
1316 : 0 : return -EINVAL;
1317 : : }
1318 : :
1319 : : static int
1320 : 0 : ntb_xstats_reset(struct rte_rawdev *dev,
1321 : : const uint32_t ids[],
1322 : : uint32_t nb_ids)
1323 : : {
1324 : 0 : struct ntb_hw *hw = dev->dev_private;
1325 : : uint32_t i, j, off, xstats_num;
1326 : :
1327 : 0 : xstats_num = NTB_XSTATS_NUM * (hw->queue_pairs + 1);
1328 [ # # # # ]: 0 : for (i = 0; i < nb_ids && ids[i] < xstats_num; i++) {
1329 [ # # ]: 0 : if (ids[i] < NTB_XSTATS_NUM) {
1330 [ # # ]: 0 : for (j = 0; j < hw->queue_pairs; j++) {
1331 : 0 : off = NTB_XSTATS_NUM * (j + 1) + ids[i];
1332 : 0 : hw->ntb_xstats_off[off] = hw->ntb_xstats[off];
1333 : : }
1334 : : } else {
1335 : 0 : hw->ntb_xstats_off[ids[i]] = hw->ntb_xstats[ids[i]];
1336 : : }
1337 : : }
1338 : :
1339 : 0 : return i;
1340 : : }
1341 : :
1342 : : static const struct rte_rawdev_ops ntb_ops = {
1343 : : .dev_info_get = ntb_dev_info_get,
1344 : : .dev_configure = ntb_dev_configure,
1345 : : .dev_start = ntb_dev_start,
1346 : : .dev_stop = ntb_dev_stop,
1347 : : .dev_close = ntb_dev_close,
1348 : : .dev_reset = ntb_dev_reset,
1349 : :
1350 : : .queue_def_conf = ntb_queue_conf_get,
1351 : : .queue_setup = ntb_queue_setup,
1352 : : .queue_release = ntb_queue_release,
1353 : : .queue_count = ntb_queue_count,
1354 : :
1355 : : .enqueue_bufs = ntb_enqueue_bufs,
1356 : : .dequeue_bufs = ntb_dequeue_bufs,
1357 : :
1358 : : .attr_get = ntb_attr_get,
1359 : : .attr_set = ntb_attr_set,
1360 : :
1361 : : .xstats_get = ntb_xstats_get,
1362 : : .xstats_get_names = ntb_xstats_get_names,
1363 : : .xstats_get_by_name = ntb_xstats_get_by_name,
1364 : : .xstats_reset = ntb_xstats_reset,
1365 : : };
1366 : :
1367 : : static int
1368 : 0 : ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev)
1369 : : {
1370 : 0 : struct ntb_hw *hw = dev->dev_private;
1371 : : struct rte_intr_handle *intr_handle;
1372 : : int ret, i;
1373 : :
1374 : 0 : hw->pci_dev = pci_dev;
1375 : 0 : hw->peer_dev_up = 0;
1376 : 0 : hw->link_status = NTB_LINK_DOWN;
1377 : 0 : hw->link_speed = NTB_SPEED_NONE;
1378 : 0 : hw->link_width = NTB_WIDTH_NONE;
1379 : :
1380 [ # # ]: 0 : switch (pci_dev->id.device_id) {
1381 : 0 : case NTB_INTEL_DEV_ID_B2B_SKX:
1382 : : case NTB_INTEL_DEV_ID_B2B_ICX:
1383 : 0 : hw->ntb_ops = &intel_ntb_ops;
1384 : : break;
1385 : 0 : default:
1386 : 0 : NTB_LOG(ERR, "Not supported device.");
1387 : 0 : return -EINVAL;
1388 : : }
1389 : :
1390 [ # # ]: 0 : if (hw->ntb_ops->ntb_dev_init == NULL)
1391 : : return -ENOTSUP;
1392 : 0 : ret = (*hw->ntb_ops->ntb_dev_init)(dev);
1393 [ # # ]: 0 : if (ret) {
1394 : 0 : NTB_LOG(ERR, "Unable to init ntb dev.");
1395 : 0 : return ret;
1396 : : }
1397 : :
1398 [ # # ]: 0 : if (hw->ntb_ops->set_link == NULL)
1399 : : return -ENOTSUP;
1400 : 0 : ret = (*hw->ntb_ops->set_link)(dev, 1);
1401 [ # # ]: 0 : if (ret)
1402 : : return ret;
1403 : :
1404 : : /* Init doorbell. */
1405 : 0 : hw->db_valid_mask = RTE_LEN2MASK(hw->db_cnt, uint64_t);
1406 : : /* Clear all valid doorbell bits before registering intr handler */
1407 [ # # ]: 0 : if (hw->ntb_ops->db_clear == NULL)
1408 : : return -ENOTSUP;
1409 : 0 : (*hw->ntb_ops->db_clear)(dev, hw->db_valid_mask);
1410 : :
1411 : 0 : intr_handle = pci_dev->intr_handle;
1412 : : /* Register callback func to eal lib */
1413 : 0 : rte_intr_callback_register(intr_handle,
1414 : : ntb_dev_intr_handler, dev);
1415 : :
1416 : 0 : ret = rte_intr_efd_enable(intr_handle, hw->db_cnt);
1417 [ # # ]: 0 : if (ret)
1418 : : return ret;
1419 : :
1420 : : /* To clarify, the interrupt for each doorbell is already mapped
1421 : : * by default for intel gen3. They are mapped to msix vec 1-32,
1422 : : * and hardware intr is mapped to 0. Map all to 0 for uio.
1423 : : */
1424 [ # # ]: 0 : if (!rte_intr_cap_multiple(intr_handle)) {
1425 [ # # ]: 0 : for (i = 0; i < hw->db_cnt; i++) {
1426 [ # # ]: 0 : if (hw->ntb_ops->vector_bind == NULL)
1427 : : return -ENOTSUP;
1428 : 0 : ret = (*hw->ntb_ops->vector_bind)(dev, i, 0);
1429 [ # # ]: 0 : if (ret)
1430 : 0 : return ret;
1431 : : }
1432 : : }
1433 : :
1434 [ # # ]: 0 : if (hw->ntb_ops->db_set_mask == NULL ||
1435 [ # # ]: 0 : hw->ntb_ops->peer_db_set == NULL) {
1436 : 0 : NTB_LOG(ERR, "Doorbell is not supported.");
1437 : 0 : return -ENOTSUP;
1438 : : }
1439 : 0 : hw->db_mask = 0;
1440 : 0 : ret = (*hw->ntb_ops->db_set_mask)(dev, hw->db_mask);
1441 [ # # ]: 0 : if (ret) {
1442 : 0 : NTB_LOG(ERR, "Unable to enable intr for all dbs.");
1443 : 0 : return ret;
1444 : : }
1445 : :
1446 : : /* enable uio intr after callback register */
1447 : 0 : rte_intr_enable(intr_handle);
1448 : :
1449 : 0 : return ret;
1450 : : }
1451 : :
1452 : : static int
1453 : 0 : ntb_create(struct rte_pci_device *pci_dev, int socket_id)
1454 : : {
1455 : : char name[RTE_RAWDEV_NAME_MAX_LEN];
1456 : : struct rte_rawdev *rawdev = NULL;
1457 : : int ret;
1458 : :
1459 [ # # ]: 0 : if (pci_dev == NULL) {
1460 : 0 : NTB_LOG(ERR, "Invalid pci_dev.");
1461 : 0 : return -EINVAL;
1462 : : }
1463 : :
1464 : : memset(name, 0, sizeof(name));
1465 : 0 : snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "NTB:%x:%02x.%x",
1466 : 0 : pci_dev->addr.bus, pci_dev->addr.devid,
1467 : 0 : pci_dev->addr.function);
1468 : :
1469 : 0 : NTB_LOG(INFO, "Init %s on NUMA node %d", name, socket_id);
1470 : :
1471 : : /* Allocate device structure. */
1472 : 0 : rawdev = rte_rawdev_pmd_allocate(name, sizeof(struct ntb_hw),
1473 : : socket_id);
1474 [ # # ]: 0 : if (rawdev == NULL) {
1475 : 0 : NTB_LOG(ERR, "Unable to allocate rawdev.");
1476 : 0 : return -EINVAL;
1477 : : }
1478 : :
1479 : 0 : rawdev->dev_ops = &ntb_ops;
1480 : 0 : rawdev->device = &pci_dev->device;
1481 : 0 : rawdev->driver_name = pci_dev->driver->driver.name;
1482 : :
1483 : 0 : ret = ntb_init_hw(rawdev, pci_dev);
1484 [ # # ]: 0 : if (ret < 0) {
1485 : 0 : NTB_LOG(ERR, "Unable to init ntb hw.");
1486 : 0 : goto fail;
1487 : : }
1488 : :
1489 : : return ret;
1490 : :
1491 : : fail:
1492 : : if (rawdev != NULL)
1493 : 0 : rte_rawdev_pmd_release(rawdev);
1494 : :
1495 : 0 : return ret;
1496 : : }
1497 : :
1498 : : static int
1499 : 0 : ntb_destroy(struct rte_pci_device *pci_dev)
1500 : : {
1501 : : char name[RTE_RAWDEV_NAME_MAX_LEN];
1502 : : struct rte_rawdev *rawdev;
1503 : : int ret;
1504 : :
1505 [ # # ]: 0 : if (pci_dev == NULL) {
1506 : 0 : NTB_LOG(ERR, "Invalid pci_dev.");
1507 : : ret = -EINVAL;
1508 : 0 : return ret;
1509 : : }
1510 : :
1511 : : memset(name, 0, sizeof(name));
1512 : 0 : snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "NTB:%x:%02x.%x",
1513 : 0 : pci_dev->addr.bus, pci_dev->addr.devid,
1514 : 0 : pci_dev->addr.function);
1515 : :
1516 : 0 : NTB_LOG(INFO, "Closing %s on NUMA node %d", name, rte_socket_id());
1517 : :
1518 : 0 : rawdev = rte_rawdev_pmd_get_named_dev(name);
1519 [ # # ]: 0 : if (rawdev == NULL) {
1520 : 0 : NTB_LOG(ERR, "Invalid device name (%s)", name);
1521 : : ret = -EINVAL;
1522 : 0 : return ret;
1523 : : }
1524 : :
1525 : 0 : ret = rte_rawdev_pmd_release(rawdev);
1526 [ # # ]: 0 : if (ret)
1527 : 0 : NTB_LOG(ERR, "Failed to destroy ntb rawdev.");
1528 : :
1529 : : return ret;
1530 : : }
1531 : :
1532 : : static int
1533 : 0 : ntb_probe(struct rte_pci_driver *pci_drv __rte_unused,
1534 : : struct rte_pci_device *pci_dev)
1535 : : {
1536 : 0 : return ntb_create(pci_dev, rte_socket_id());
1537 : : }
1538 : :
1539 : : static int
1540 : 0 : ntb_remove(struct rte_pci_device *pci_dev)
1541 : : {
1542 : 0 : return ntb_destroy(pci_dev);
1543 : : }
1544 : :
1545 : :
1546 : : static struct rte_pci_driver rte_ntb_pmd = {
1547 : : .id_table = pci_id_ntb_map,
1548 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_WC_ACTIVATE,
1549 : : .probe = ntb_probe,
1550 : : .remove = ntb_remove,
1551 : : };
1552 : :
1553 : 251 : RTE_PMD_REGISTER_PCI(raw_ntb, rte_ntb_pmd);
1554 : : RTE_PMD_REGISTER_PCI_TABLE(raw_ntb, pci_id_ntb_map);
1555 : : RTE_PMD_REGISTER_KMOD_DEP(raw_ntb, "* igb_uio | uio_pci_generic | vfio-pci");
1556 [ - + ]: 251 : RTE_LOG_REGISTER_DEFAULT(ntb_logtype, INFO);
|