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