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