1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2019-2024 Advanced Micro Devices, Inc.
3 */
4
5 #include <stdint.h>
6 #include <stdlib.h>
7 #include <errno.h>
8
9 #include <rte_errno.h>
10 #include <rte_common.h>
11 #include <rte_log.h>
12 #include <rte_eal.h>
13 #include <bus_vdev_driver.h>
14 #include <rte_dev.h>
15 #include <rte_string_fns.h>
16 #include <rte_kvargs.h>
17
18 #include "ionic.h"
19 #include "ionic_common.h"
20 #include "ionic_logs.h"
21 #include "ionic_ethdev.h"
22
23 #define IONIC_VDEV_DEV_BAR 0
24 #define IONIC_VDEV_INTR_CTL_BAR 1
25 #define IONIC_VDEV_INTR_CFG_BAR 2
26 #define IONIC_VDEV_DB_BAR 3
27 #define IONIC_VDEV_BARS_MAX 4
28
29 #define IONIC_VDEV_DEV_INFO_REGS_OFFSET 0x0000
30 #define IONIC_VDEV_DEV_CMD_REGS_OFFSET 0x0800
31
32 #define IONIC_VDEV_FW_WAIT_US 1000 /* 1ms */
33 #define IONIC_VDEV_FW_WAIT_MAX 5000 /* 5s */
34
35 static int
ionic_vdev_setup(struct ionic_adapter * adapter)36 ionic_vdev_setup(struct ionic_adapter *adapter)
37 {
38 struct ionic_bars *bars = &adapter->bars;
39 struct ionic_dev *idev = &adapter->idev;
40 uint8_t *bar0_base;
41 uint32_t sig;
42 uint32_t fw_waits = 0;
43 uint8_t fw;
44
45 IONIC_PRINT_CALL();
46
47 /* BAR0: dev_cmd and interrupts */
48 if (bars->num_bars < 1) {
49 IONIC_PRINT(ERR, "No bars found, aborting");
50 return -EFAULT;
51 }
52
53 bar0_base = bars->bar[IONIC_VDEV_DEV_BAR].vaddr;
54 idev->dev_info = (union ionic_dev_info_regs *)
55 &bar0_base[IONIC_VDEV_DEV_INFO_REGS_OFFSET];
56 idev->dev_cmd = (union ionic_dev_cmd_regs *)
57 &bar0_base[IONIC_VDEV_DEV_CMD_REGS_OFFSET];
58 idev->intr_ctrl = (void *)bars->bar[IONIC_VDEV_INTR_CTL_BAR].vaddr;
59 idev->db_pages = (void *)bars->bar[IONIC_VDEV_DB_BAR].vaddr;
60
61 sig = ioread32(&idev->dev_info->signature);
62 if (sig != IONIC_DEV_INFO_SIGNATURE) {
63 IONIC_PRINT(ERR, "Incompatible firmware signature %x", sig);
64 return -EFAULT;
65 }
66
67 /* Wait for the FW to indicate readiness */
68 while (1) {
69 fw = ioread8(&idev->dev_info->fw_status);
70 if ((fw & IONIC_FW_STS_F_RUNNING) != 0)
71 break;
72
73 if (fw_waits > IONIC_VDEV_FW_WAIT_MAX) {
74 IONIC_PRINT(ERR, "Firmware readiness bit not set");
75 return -ETIMEDOUT;
76 }
77
78 fw_waits++;
79 rte_delay_us_block(IONIC_VDEV_FW_WAIT_US);
80 }
81 IONIC_PRINT(DEBUG, "Firmware ready (%u waits)", fw_waits);
82
83 adapter->name = rte_vdev_device_name(adapter->bus_dev);
84
85 return 0;
86 }
87
88 static void
ionic_vdev_poll(struct ionic_adapter * adapter)89 ionic_vdev_poll(struct ionic_adapter *adapter)
90 {
91 ionic_dev_interrupt_handler(adapter);
92 }
93
94 static void
ionic_vdev_unmap_bars(struct ionic_adapter * adapter)95 ionic_vdev_unmap_bars(struct ionic_adapter *adapter)
96 {
97 struct ionic_bars *bars = &adapter->bars;
98 uint32_t i;
99
100 for (i = 0; i < IONIC_VDEV_BARS_MAX; i++)
101 ionic_uio_rel_rsrc(adapter->name, i, &bars->bar[i]);
102 }
103
104 static const struct ionic_dev_intf ionic_vdev_intf = {
105 .setup = ionic_vdev_setup,
106 .poll = ionic_vdev_poll,
107 .unmap_bars = ionic_vdev_unmap_bars,
108 };
109
110 static int
eth_ionic_vdev_probe(struct rte_vdev_device * vdev)111 eth_ionic_vdev_probe(struct rte_vdev_device *vdev)
112 {
113 struct ionic_bars bars = {};
114 const char *name = rte_vdev_device_name(vdev);
115 unsigned int i;
116
117 IONIC_PRINT(NOTICE, "Initializing device %s",
118 rte_eal_process_type() == RTE_PROC_SECONDARY ?
119 "[SECONDARY]" : "");
120
121 ionic_uio_scan_mnet_devices();
122
123 for (i = 0; i < IONIC_VDEV_BARS_MAX; i++)
124 ionic_uio_get_rsrc(name, i, &bars.bar[i]);
125
126 bars.num_bars = IONIC_VDEV_BARS_MAX;
127
128 return eth_ionic_dev_probe((void *)vdev,
129 &vdev->device,
130 &bars,
131 &ionic_vdev_intf,
132 IONIC_DEV_ID_ETH_VF,
133 IONIC_PENSANDO_VENDOR_ID);
134 }
135
136 static int
eth_ionic_vdev_remove(struct rte_vdev_device * vdev)137 eth_ionic_vdev_remove(struct rte_vdev_device *vdev)
138 {
139 return eth_ionic_dev_remove(&vdev->device);
140 }
141
142 static struct rte_vdev_driver rte_vdev_ionic_pmd = {
143 .probe = eth_ionic_vdev_probe,
144 .remove = eth_ionic_vdev_remove,
145 };
146
147 RTE_PMD_REGISTER_VDEV(net_ionic, rte_vdev_ionic_pmd);
148