c83b8d964263d1b15d2c0e0d9023a0b064258374
[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_bus_pci.h>
16 #include <rte_memzone.h>
17 #include <rte_memcpy.h>
18 #include <rte_rawdev.h>
19 #include <rte_rawdev_pmd.h>
20
21 #include "ntb_hw_intel.h"
22 #include "ntb.h"
23
24 int ntb_logtype;
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         { .vendor_id = 0, /* sentinel */ },
29 };
30
31 static int
32 ntb_set_mw(struct rte_rawdev *dev, int mw_idx, uint64_t mw_size)
33 {
34         struct ntb_hw *hw = dev->dev_private;
35         char mw_name[RTE_MEMZONE_NAMESIZE];
36         const struct rte_memzone *mz;
37         int ret = 0;
38
39         if (hw->ntb_ops->mw_set_trans == NULL) {
40                 NTB_LOG(ERR, "Not supported to set mw.");
41                 return -ENOTSUP;
42         }
43
44         snprintf(mw_name, sizeof(mw_name), "ntb_%d_mw_%d",
45                  dev->dev_id, mw_idx);
46
47         mz = rte_memzone_lookup(mw_name);
48         if (mz)
49                 return 0;
50
51         /**
52          * Hardware requires that mapped memory base address should be
53          * aligned with EMBARSZ and needs continuous memzone.
54          */
55         mz = rte_memzone_reserve_aligned(mw_name, mw_size, dev->socket_id,
56                                 RTE_MEMZONE_IOVA_CONTIG, hw->mw_size[mw_idx]);
57         if (!mz) {
58                 NTB_LOG(ERR, "Cannot allocate aligned memzone.");
59                 return -EIO;
60         }
61         hw->mz[mw_idx] = mz;
62
63         ret = (*hw->ntb_ops->mw_set_trans)(dev, mw_idx, mz->iova, mw_size);
64         if (ret) {
65                 NTB_LOG(ERR, "Cannot set mw translation.");
66                 return ret;
67         }
68
69         return ret;
70 }
71
72 static void
73 ntb_link_cleanup(struct rte_rawdev *dev)
74 {
75         struct ntb_hw *hw = dev->dev_private;
76         int status, i;
77
78         if (hw->ntb_ops->spad_write == NULL ||
79             hw->ntb_ops->mw_set_trans == NULL) {
80                 NTB_LOG(ERR, "Not supported to clean up link.");
81                 return;
82         }
83
84         /* Clean spad registers. */
85         for (i = 0; i < hw->spad_cnt; i++) {
86                 status = (*hw->ntb_ops->spad_write)(dev, i, 0, 0);
87                 if (status)
88                         NTB_LOG(ERR, "Failed to clean local spad.");
89         }
90
91         /* Clear mw so that peer cannot access local memory.*/
92         for (i = 0; i < hw->mw_cnt; i++) {
93                 status = (*hw->ntb_ops->mw_set_trans)(dev, i, 0, 0);
94                 if (status)
95                         NTB_LOG(ERR, "Failed to clean mw.");
96         }
97 }
98
99 static void
100 ntb_dev_intr_handler(void *param)
101 {
102         struct rte_rawdev *dev = (struct rte_rawdev *)param;
103         struct ntb_hw *hw = dev->dev_private;
104         uint32_t mw_size_h, mw_size_l;
105         uint64_t db_bits = 0;
106         int i = 0;
107
108         if (hw->ntb_ops->db_read == NULL ||
109             hw->ntb_ops->db_clear == NULL ||
110             hw->ntb_ops->peer_db_set == NULL) {
111                 NTB_LOG(ERR, "Doorbell is not supported.");
112                 return;
113         }
114
115         db_bits = (*hw->ntb_ops->db_read)(dev);
116         if (!db_bits)
117                 NTB_LOG(ERR, "No doorbells");
118
119         /* Doorbell 0 is for peer device ready. */
120         if (db_bits & 1) {
121                 NTB_LOG(DEBUG, "DB0: Peer device is up.");
122                 /* Clear received doorbell. */
123                 (*hw->ntb_ops->db_clear)(dev, 1);
124
125                 /**
126                  * Peer dev is already up. All mw settings are already done.
127                  * Skip them.
128                  */
129                 if (hw->peer_dev_up)
130                         return;
131
132                 if (hw->ntb_ops->spad_read == NULL ||
133                     hw->ntb_ops->spad_write == NULL) {
134                         NTB_LOG(ERR, "Scratchpad is not supported.");
135                         return;
136                 }
137
138                 hw->peer_mw_cnt = (*hw->ntb_ops->spad_read)
139                                   (dev, SPAD_NUM_MWS, 0);
140                 hw->peer_mw_size = rte_zmalloc("uint64_t",
141                                    hw->peer_mw_cnt * sizeof(uint64_t), 0);
142                 for (i = 0; i < hw->mw_cnt; i++) {
143                         mw_size_h = (*hw->ntb_ops->spad_read)
144                                     (dev, SPAD_MW0_SZ_H + 2 * i, 0);
145                         mw_size_l = (*hw->ntb_ops->spad_read)
146                                     (dev, SPAD_MW0_SZ_L + 2 * i, 0);
147                         hw->peer_mw_size[i] = ((uint64_t)mw_size_h << 32) |
148                                               mw_size_l;
149                         NTB_LOG(DEBUG, "Peer %u mw size: 0x%"PRIx64"", i,
150                                         hw->peer_mw_size[i]);
151                 }
152
153                 hw->peer_dev_up = 1;
154
155                 /**
156                  * Handshake with peer. Spad_write only works when both
157                  * devices are up. So write spad again when db is received.
158                  * And set db again for the later device who may miss
159                  * the 1st db.
160                  */
161                 for (i = 0; i < hw->mw_cnt; i++) {
162                         (*hw->ntb_ops->spad_write)(dev, SPAD_NUM_MWS,
163                                                    1, hw->mw_cnt);
164                         mw_size_h = hw->mw_size[i] >> 32;
165                         (*hw->ntb_ops->spad_write)(dev, SPAD_MW0_SZ_H + 2 * i,
166                                                    1, mw_size_h);
167
168                         mw_size_l = hw->mw_size[i];
169                         (*hw->ntb_ops->spad_write)(dev, SPAD_MW0_SZ_L + 2 * i,
170                                                    1, mw_size_l);
171                 }
172                 (*hw->ntb_ops->peer_db_set)(dev, 0);
173
174                 /* To get the link info. */
175                 if (hw->ntb_ops->get_link_status == NULL) {
176                         NTB_LOG(ERR, "Not supported to get link status.");
177                         return;
178                 }
179                 (*hw->ntb_ops->get_link_status)(dev);
180                 NTB_LOG(INFO, "Link is up. Link speed: %u. Link width: %u",
181                         hw->link_speed, hw->link_width);
182                 return;
183         }
184
185         if (db_bits & (1 << 1)) {
186                 NTB_LOG(DEBUG, "DB1: Peer device is down.");
187                 /* Clear received doorbell. */
188                 (*hw->ntb_ops->db_clear)(dev, 2);
189
190                 /* Peer device will be down, So clean local side too. */
191                 ntb_link_cleanup(dev);
192
193                 hw->peer_dev_up = 0;
194                 /* Response peer's dev_stop request. */
195                 (*hw->ntb_ops->peer_db_set)(dev, 2);
196                 return;
197         }
198
199         if (db_bits & (1 << 2)) {
200                 NTB_LOG(DEBUG, "DB2: Peer device agrees dev to be down.");
201                 /* Clear received doorbell. */
202                 (*hw->ntb_ops->db_clear)(dev, (1 << 2));
203                 hw->peer_dev_up = 0;
204                 return;
205         }
206 }
207
208 static void
209 ntb_queue_conf_get(struct rte_rawdev *dev __rte_unused,
210                    uint16_t queue_id __rte_unused,
211                    rte_rawdev_obj_t queue_conf __rte_unused)
212 {
213 }
214
215 static int
216 ntb_queue_setup(struct rte_rawdev *dev __rte_unused,
217                 uint16_t queue_id __rte_unused,
218                 rte_rawdev_obj_t queue_conf __rte_unused)
219 {
220         return 0;
221 }
222
223 static int
224 ntb_queue_release(struct rte_rawdev *dev __rte_unused,
225                   uint16_t queue_id __rte_unused)
226 {
227         return 0;
228 }
229
230 static uint16_t
231 ntb_queue_count(struct rte_rawdev *dev)
232 {
233         struct ntb_hw *hw = dev->dev_private;
234         return hw->queue_pairs;
235 }
236
237 static int
238 ntb_enqueue_bufs(struct rte_rawdev *dev,
239                  struct rte_rawdev_buf **buffers,
240                  unsigned int count,
241                  rte_rawdev_obj_t context)
242 {
243         RTE_SET_USED(dev);
244         RTE_SET_USED(buffers);
245         RTE_SET_USED(count);
246         RTE_SET_USED(context);
247
248         return 0;
249 }
250
251 static int
252 ntb_dequeue_bufs(struct rte_rawdev *dev,
253                  struct rte_rawdev_buf **buffers,
254                  unsigned int count,
255                  rte_rawdev_obj_t context)
256 {
257         RTE_SET_USED(dev);
258         RTE_SET_USED(buffers);
259         RTE_SET_USED(count);
260         RTE_SET_USED(context);
261
262         return 0;
263 }
264
265 static void
266 ntb_dev_info_get(struct rte_rawdev *dev, rte_rawdev_obj_t dev_info)
267 {
268         struct ntb_hw *hw = dev->dev_private;
269         struct ntb_attr *ntb_attrs = dev_info;
270
271         strncpy(ntb_attrs[NTB_TOPO_ID].name, NTB_TOPO_NAME, NTB_ATTR_NAME_LEN);
272         switch (hw->topo) {
273         case NTB_TOPO_B2B_DSD:
274                 strncpy(ntb_attrs[NTB_TOPO_ID].value, "B2B DSD",
275                         NTB_ATTR_VAL_LEN);
276                 break;
277         case NTB_TOPO_B2B_USD:
278                 strncpy(ntb_attrs[NTB_TOPO_ID].value, "B2B USD",
279                         NTB_ATTR_VAL_LEN);
280                 break;
281         default:
282                 strncpy(ntb_attrs[NTB_TOPO_ID].value, "Unsupported",
283                         NTB_ATTR_VAL_LEN);
284         }
285
286         strncpy(ntb_attrs[NTB_LINK_STATUS_ID].name, NTB_LINK_STATUS_NAME,
287                 NTB_ATTR_NAME_LEN);
288         snprintf(ntb_attrs[NTB_LINK_STATUS_ID].value, NTB_ATTR_VAL_LEN,
289                  "%d", hw->link_status);
290
291         strncpy(ntb_attrs[NTB_SPEED_ID].name, NTB_SPEED_NAME,
292                 NTB_ATTR_NAME_LEN);
293         snprintf(ntb_attrs[NTB_SPEED_ID].value, NTB_ATTR_VAL_LEN,
294                  "%d", hw->link_speed);
295
296         strncpy(ntb_attrs[NTB_WIDTH_ID].name, NTB_WIDTH_NAME,
297                 NTB_ATTR_NAME_LEN);
298         snprintf(ntb_attrs[NTB_WIDTH_ID].value, NTB_ATTR_VAL_LEN,
299                  "%d", hw->link_width);
300
301         strncpy(ntb_attrs[NTB_MW_CNT_ID].name, NTB_MW_CNT_NAME,
302                 NTB_ATTR_NAME_LEN);
303         snprintf(ntb_attrs[NTB_MW_CNT_ID].value, NTB_ATTR_VAL_LEN,
304                  "%d", hw->mw_cnt);
305
306         strncpy(ntb_attrs[NTB_DB_CNT_ID].name, NTB_DB_CNT_NAME,
307                 NTB_ATTR_NAME_LEN);
308         snprintf(ntb_attrs[NTB_DB_CNT_ID].value, NTB_ATTR_VAL_LEN,
309                  "%d", hw->db_cnt);
310
311         strncpy(ntb_attrs[NTB_SPAD_CNT_ID].name, NTB_SPAD_CNT_NAME,
312                 NTB_ATTR_NAME_LEN);
313         snprintf(ntb_attrs[NTB_SPAD_CNT_ID].value, NTB_ATTR_VAL_LEN,
314                  "%d", hw->spad_cnt);
315 }
316
317 static int
318 ntb_dev_configure(const struct rte_rawdev *dev __rte_unused,
319                   rte_rawdev_obj_t config __rte_unused)
320 {
321         return 0;
322 }
323
324 static int
325 ntb_dev_start(struct rte_rawdev *dev)
326 {
327         struct ntb_hw *hw = dev->dev_private;
328         int ret, i;
329
330         /* TODO: init queues and start queues. */
331
332         /* Map memory of bar_size to remote. */
333         hw->mz = rte_zmalloc("struct rte_memzone *",
334                              hw->mw_cnt * sizeof(struct rte_memzone *), 0);
335         for (i = 0; i < hw->mw_cnt; i++) {
336                 ret = ntb_set_mw(dev, i, hw->mw_size[i]);
337                 if (ret) {
338                         NTB_LOG(ERR, "Fail to set mw.");
339                         return ret;
340                 }
341         }
342
343         dev->started = 1;
344
345         return 0;
346 }
347
348 static void
349 ntb_dev_stop(struct rte_rawdev *dev)
350 {
351         struct ntb_hw *hw = dev->dev_private;
352         uint32_t time_out;
353         int status;
354
355         /* TODO: stop rx/tx queues. */
356
357         if (!hw->peer_dev_up)
358                 goto clean;
359
360         ntb_link_cleanup(dev);
361
362         /* Notify the peer that device will be down. */
363         if (hw->ntb_ops->peer_db_set == NULL) {
364                 NTB_LOG(ERR, "Peer doorbell setting is not supported.");
365                 return;
366         }
367         status = (*hw->ntb_ops->peer_db_set)(dev, 1);
368         if (status) {
369                 NTB_LOG(ERR, "Failed to tell peer device is down.");
370                 return;
371         }
372
373         /*
374          * Set time out as 1s in case that the peer is stopped accidently
375          * without any notification.
376          */
377         time_out = 1000000;
378
379         /* Wait for cleanup work down before db mask clear. */
380         while (hw->peer_dev_up && time_out) {
381                 time_out -= 10;
382                 rte_delay_us(10);
383         }
384
385 clean:
386         /* Clear doorbells mask. */
387         if (hw->ntb_ops->db_set_mask == NULL) {
388                 NTB_LOG(ERR, "Doorbell mask setting is not supported.");
389                 return;
390         }
391         status = (*hw->ntb_ops->db_set_mask)(dev,
392                                 (((uint64_t)1 << hw->db_cnt) - 1));
393         if (status)
394                 NTB_LOG(ERR, "Failed to clear doorbells.");
395
396         dev->started = 0;
397 }
398
399 static int
400 ntb_dev_close(struct rte_rawdev *dev)
401 {
402         struct ntb_hw *hw = dev->dev_private;
403         struct rte_intr_handle *intr_handle;
404         int ret = 0;
405
406         if (dev->started)
407                 ntb_dev_stop(dev);
408
409         /* TODO: free queues. */
410
411         intr_handle = &hw->pci_dev->intr_handle;
412         /* Clean datapath event and vec mapping */
413         rte_intr_efd_disable(intr_handle);
414         if (intr_handle->intr_vec) {
415                 rte_free(intr_handle->intr_vec);
416                 intr_handle->intr_vec = NULL;
417         }
418         /* Disable uio intr before callback unregister */
419         rte_intr_disable(intr_handle);
420
421         /* Unregister callback func to eal lib */
422         rte_intr_callback_unregister(intr_handle,
423                                      ntb_dev_intr_handler, dev);
424
425         return ret;
426 }
427
428 static int
429 ntb_dev_reset(struct rte_rawdev *rawdev __rte_unused)
430 {
431         return 0;
432 }
433
434 static int
435 ntb_attr_set(struct rte_rawdev *dev, const char *attr_name,
436                                  uint64_t attr_value)
437 {
438         struct ntb_hw *hw = dev->dev_private;
439         int index = 0;
440
441         if (dev == NULL || attr_name == NULL) {
442                 NTB_LOG(ERR, "Invalid arguments for setting attributes");
443                 return -EINVAL;
444         }
445
446         if (!strncmp(attr_name, NTB_SPAD_USER, NTB_SPAD_USER_LEN)) {
447                 if (hw->ntb_ops->spad_write == NULL)
448                         return -ENOTSUP;
449                 index = atoi(&attr_name[NTB_SPAD_USER_LEN]);
450                 (*hw->ntb_ops->spad_write)(dev, hw->spad_user_list[index],
451                                            1, attr_value);
452                 NTB_LOG(INFO, "Set attribute (%s) Value (%" PRIu64 ")",
453                         attr_name, attr_value);
454                 return 0;
455         }
456
457         /* Attribute not found. */
458         NTB_LOG(ERR, "Attribute not found.");
459         return -EINVAL;
460 }
461
462 static int
463 ntb_attr_get(struct rte_rawdev *dev, const char *attr_name,
464                                  uint64_t *attr_value)
465 {
466         struct ntb_hw *hw = dev->dev_private;
467         int index = 0;
468
469         if (dev == NULL || attr_name == NULL || attr_value == NULL) {
470                 NTB_LOG(ERR, "Invalid arguments for getting attributes");
471                 return -EINVAL;
472         }
473
474         if (!strncmp(attr_name, NTB_TOPO_NAME, NTB_ATTR_NAME_LEN)) {
475                 *attr_value = hw->topo;
476                 NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
477                         attr_name, *attr_value);
478                 return 0;
479         }
480
481         if (!strncmp(attr_name, NTB_LINK_STATUS_NAME, NTB_ATTR_NAME_LEN)) {
482                 *attr_value = hw->link_status;
483                 NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
484                         attr_name, *attr_value);
485                 return 0;
486         }
487
488         if (!strncmp(attr_name, NTB_SPEED_NAME, NTB_ATTR_NAME_LEN)) {
489                 *attr_value = hw->link_speed;
490                 NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
491                         attr_name, *attr_value);
492                 return 0;
493         }
494
495         if (!strncmp(attr_name, NTB_WIDTH_NAME, NTB_ATTR_NAME_LEN)) {
496                 *attr_value = hw->link_width;
497                 NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
498                         attr_name, *attr_value);
499                 return 0;
500         }
501
502         if (!strncmp(attr_name, NTB_MW_CNT_NAME, NTB_ATTR_NAME_LEN)) {
503                 *attr_value = hw->mw_cnt;
504                 NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
505                         attr_name, *attr_value);
506                 return 0;
507         }
508
509         if (!strncmp(attr_name, NTB_DB_CNT_NAME, NTB_ATTR_NAME_LEN)) {
510                 *attr_value = hw->db_cnt;
511                 NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
512                         attr_name, *attr_value);
513                 return 0;
514         }
515
516         if (!strncmp(attr_name, NTB_SPAD_CNT_NAME, NTB_ATTR_NAME_LEN)) {
517                 *attr_value = hw->spad_cnt;
518                 NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
519                         attr_name, *attr_value);
520                 return 0;
521         }
522
523         if (!strncmp(attr_name, NTB_SPAD_USER, NTB_SPAD_USER_LEN)) {
524                 if (hw->ntb_ops->spad_read == NULL)
525                         return -ENOTSUP;
526                 index = atoi(&attr_name[NTB_SPAD_USER_LEN]);
527                 *attr_value = (*hw->ntb_ops->spad_read)(dev,
528                                 hw->spad_user_list[index], 0);
529                 NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
530                         attr_name, *attr_value);
531                 return 0;
532         }
533
534         /* Attribute not found. */
535         NTB_LOG(ERR, "Attribute not found.");
536         return -EINVAL;
537 }
538
539 static int
540 ntb_xstats_get(const struct rte_rawdev *dev __rte_unused,
541                const unsigned int ids[] __rte_unused,
542                uint64_t values[] __rte_unused,
543                unsigned int n __rte_unused)
544 {
545         return 0;
546 }
547
548 static int
549 ntb_xstats_get_names(const struct rte_rawdev *dev __rte_unused,
550                      struct rte_rawdev_xstats_name *xstats_names __rte_unused,
551                      unsigned int size __rte_unused)
552 {
553         return 0;
554 }
555
556 static uint64_t
557 ntb_xstats_get_by_name(const struct rte_rawdev *dev __rte_unused,
558                        const char *name __rte_unused,
559                        unsigned int *id __rte_unused)
560 {
561         return 0;
562 }
563
564 static int
565 ntb_xstats_reset(struct rte_rawdev *dev __rte_unused,
566                  const uint32_t ids[] __rte_unused,
567                  uint32_t nb_ids __rte_unused)
568 {
569         return 0;
570 }
571
572 static const struct rte_rawdev_ops ntb_ops = {
573         .dev_info_get         = ntb_dev_info_get,
574         .dev_configure        = ntb_dev_configure,
575         .dev_start            = ntb_dev_start,
576         .dev_stop             = ntb_dev_stop,
577         .dev_close            = ntb_dev_close,
578         .dev_reset            = ntb_dev_reset,
579
580         .queue_def_conf       = ntb_queue_conf_get,
581         .queue_setup          = ntb_queue_setup,
582         .queue_release        = ntb_queue_release,
583         .queue_count          = ntb_queue_count,
584
585         .enqueue_bufs         = ntb_enqueue_bufs,
586         .dequeue_bufs         = ntb_dequeue_bufs,
587
588         .attr_get             = ntb_attr_get,
589         .attr_set             = ntb_attr_set,
590
591         .xstats_get           = ntb_xstats_get,
592         .xstats_get_names     = ntb_xstats_get_names,
593         .xstats_get_by_name   = ntb_xstats_get_by_name,
594         .xstats_reset         = ntb_xstats_reset,
595 };
596
597 static int
598 ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev)
599 {
600         struct ntb_hw *hw = dev->dev_private;
601         struct rte_intr_handle *intr_handle;
602         uint32_t val;
603         int ret, i;
604
605         hw->pci_dev = pci_dev;
606         hw->peer_dev_up = 0;
607         hw->link_status = NTB_LINK_DOWN;
608         hw->link_speed = NTB_SPEED_NONE;
609         hw->link_width = NTB_WIDTH_NONE;
610
611         switch (pci_dev->id.device_id) {
612         case NTB_INTEL_DEV_ID_B2B_SKX:
613                 hw->ntb_ops = &intel_ntb_ops;
614                 break;
615         default:
616                 NTB_LOG(ERR, "Not supported device.");
617                 return -EINVAL;
618         }
619
620         if (hw->ntb_ops->ntb_dev_init == NULL)
621                 return -ENOTSUP;
622         ret = (*hw->ntb_ops->ntb_dev_init)(dev);
623         if (ret) {
624                 NTB_LOG(ERR, "Unable to init ntb dev.");
625                 return ret;
626         }
627
628         if (hw->ntb_ops->set_link == NULL)
629                 return -ENOTSUP;
630         ret = (*hw->ntb_ops->set_link)(dev, 1);
631         if (ret)
632                 return ret;
633
634         /* Init doorbell. */
635         hw->db_valid_mask = RTE_LEN2MASK(hw->db_cnt, uint64_t);
636
637         intr_handle = &pci_dev->intr_handle;
638         /* Register callback func to eal lib */
639         rte_intr_callback_register(intr_handle,
640                                    ntb_dev_intr_handler, dev);
641
642         ret = rte_intr_efd_enable(intr_handle, hw->db_cnt);
643         if (ret)
644                 return ret;
645
646         /* To clarify, the interrupt for each doorbell is already mapped
647          * by default for intel gen3. They are mapped to msix vec 1-32,
648          * and hardware intr is mapped to 0. Map all to 0 for uio.
649          */
650         if (!rte_intr_cap_multiple(intr_handle)) {
651                 for (i = 0; i < hw->db_cnt; i++) {
652                         if (hw->ntb_ops->vector_bind == NULL)
653                                 return -ENOTSUP;
654                         ret = (*hw->ntb_ops->vector_bind)(dev, i, 0);
655                         if (ret)
656                                 return ret;
657                 }
658         }
659
660         if (hw->ntb_ops->db_set_mask == NULL ||
661             hw->ntb_ops->peer_db_set == NULL) {
662                 NTB_LOG(ERR, "Doorbell is not supported.");
663                 return -ENOTSUP;
664         }
665         hw->db_mask = 0;
666         ret = (*hw->ntb_ops->db_set_mask)(dev, hw->db_mask);
667         if (ret) {
668                 NTB_LOG(ERR, "Unable to enable intr for all dbs.");
669                 return ret;
670         }
671
672         /* enable uio intr after callback register */
673         rte_intr_enable(intr_handle);
674
675         if (hw->ntb_ops->spad_write == NULL) {
676                 NTB_LOG(ERR, "Scratchpad is not supported.");
677                 return -ENOTSUP;
678         }
679         /* Tell peer the mw_cnt of local side. */
680         ret = (*hw->ntb_ops->spad_write)(dev, SPAD_NUM_MWS, 1, hw->mw_cnt);
681         if (ret) {
682                 NTB_LOG(ERR, "Failed to tell peer mw count.");
683                 return ret;
684         }
685
686         /* Tell peer each mw size on local side. */
687         for (i = 0; i < hw->mw_cnt; i++) {
688                 NTB_LOG(DEBUG, "Local %u mw size: 0x%"PRIx64"", i,
689                                 hw->mw_size[i]);
690                 val = hw->mw_size[i] >> 32;
691                 ret = (*hw->ntb_ops->spad_write)
692                                 (dev, SPAD_MW0_SZ_H + 2 * i, 1, val);
693                 if (ret) {
694                         NTB_LOG(ERR, "Failed to tell peer mw size.");
695                         return ret;
696                 }
697
698                 val = hw->mw_size[i];
699                 ret = (*hw->ntb_ops->spad_write)
700                                 (dev, SPAD_MW0_SZ_L + 2 * i, 1, val);
701                 if (ret) {
702                         NTB_LOG(ERR, "Failed to tell peer mw size.");
703                         return ret;
704                 }
705         }
706
707         /* Ring doorbell 0 to tell peer the device is ready. */
708         ret = (*hw->ntb_ops->peer_db_set)(dev, 0);
709         if (ret) {
710                 NTB_LOG(ERR, "Failed to tell peer device is probed.");
711                 return ret;
712         }
713
714         return ret;
715 }
716
717 static int
718 ntb_create(struct rte_pci_device *pci_dev, int socket_id)
719 {
720         char name[RTE_RAWDEV_NAME_MAX_LEN];
721         struct rte_rawdev *rawdev = NULL;
722         int ret;
723
724         if (pci_dev == NULL) {
725                 NTB_LOG(ERR, "Invalid pci_dev.");
726                 ret = -EINVAL;
727         }
728
729         memset(name, 0, sizeof(name));
730         snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "NTB:%x:%02x.%x",
731                  pci_dev->addr.bus, pci_dev->addr.devid,
732                  pci_dev->addr.function);
733
734         NTB_LOG(INFO, "Init %s on NUMA node %d", name, socket_id);
735
736         /* Allocate device structure. */
737         rawdev = rte_rawdev_pmd_allocate(name, sizeof(struct ntb_hw),
738                                          socket_id);
739         if (rawdev == NULL) {
740                 NTB_LOG(ERR, "Unable to allocate rawdev.");
741                 ret = -EINVAL;
742         }
743
744         rawdev->dev_ops = &ntb_ops;
745         rawdev->device = &pci_dev->device;
746         rawdev->driver_name = pci_dev->driver->driver.name;
747
748         ret = ntb_init_hw(rawdev, pci_dev);
749         if (ret < 0) {
750                 NTB_LOG(ERR, "Unable to init ntb hw.");
751                 goto fail;
752         }
753
754         return ret;
755
756 fail:
757         if (rawdev)
758                 rte_rawdev_pmd_release(rawdev);
759
760         return ret;
761 }
762
763 static int
764 ntb_destroy(struct rte_pci_device *pci_dev)
765 {
766         char name[RTE_RAWDEV_NAME_MAX_LEN];
767         struct rte_rawdev *rawdev;
768         int ret;
769
770         if (pci_dev == NULL) {
771                 NTB_LOG(ERR, "Invalid pci_dev.");
772                 ret = -EINVAL;
773                 return ret;
774         }
775
776         memset(name, 0, sizeof(name));
777         snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "NTB:%x:%02x.%x",
778                  pci_dev->addr.bus, pci_dev->addr.devid,
779                  pci_dev->addr.function);
780
781         NTB_LOG(INFO, "Closing %s on NUMA node %d", name, rte_socket_id());
782
783         rawdev = rte_rawdev_pmd_get_named_dev(name);
784         if (rawdev == NULL) {
785                 NTB_LOG(ERR, "Invalid device name (%s)", name);
786                 ret = -EINVAL;
787                 return ret;
788         }
789
790         ret = rte_rawdev_pmd_release(rawdev);
791         if (ret)
792                 NTB_LOG(ERR, "Failed to destroy ntb rawdev.");
793
794         return ret;
795 }
796
797 static int
798 ntb_probe(struct rte_pci_driver *pci_drv __rte_unused,
799         struct rte_pci_device *pci_dev)
800 {
801         return ntb_create(pci_dev, rte_socket_id());
802 }
803
804 static int
805 ntb_remove(struct rte_pci_device *pci_dev)
806 {
807         return ntb_destroy(pci_dev);
808 }
809
810
811 static struct rte_pci_driver rte_ntb_pmd = {
812         .id_table = pci_id_ntb_map,
813         .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
814         .probe = ntb_probe,
815         .remove = ntb_remove,
816 };
817
818 RTE_PMD_REGISTER_PCI(raw_ntb, rte_ntb_pmd);
819 RTE_PMD_REGISTER_PCI_TABLE(raw_ntb, pci_id_ntb_map);
820 RTE_PMD_REGISTER_KMOD_DEP(raw_ntb, "* igb_uio | uio_pci_generic | vfio-pci");
821
822 RTE_INIT(ntb_init_log)
823 {
824         ntb_logtype = rte_log_register("pmd.raw.ntb");
825         if (ntb_logtype >= 0)
826                 rte_log_set_level(ntb_logtype, RTE_LOG_DEBUG);
827 }