File: ionic_dev_vdev.c

package info (click to toggle)
dpdk 25.11-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 127,892 kB
  • sloc: ansic: 2,358,479; python: 16,426; sh: 4,474; makefile: 1,713; awk: 70
file content (147 lines) | stat: -rw-r--r-- 3,599 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright 2019-2024 Advanced Micro Devices, Inc.
 */

#include <stdint.h>
#include <stdlib.h>
#include <errno.h>

#include <rte_errno.h>
#include <rte_common.h>
#include <rte_log.h>
#include <rte_eal.h>
#include <bus_vdev_driver.h>
#include <rte_dev.h>
#include <rte_string_fns.h>
#include <rte_kvargs.h>

#include "ionic.h"
#include "ionic_common.h"
#include "ionic_logs.h"
#include "ionic_ethdev.h"

#define IONIC_VDEV_DEV_BAR          0
#define IONIC_VDEV_INTR_CTL_BAR     1
#define IONIC_VDEV_INTR_CFG_BAR     2
#define IONIC_VDEV_DB_BAR           3
#define IONIC_VDEV_BARS_MAX         4

#define IONIC_VDEV_DEV_INFO_REGS_OFFSET      0x0000
#define IONIC_VDEV_DEV_CMD_REGS_OFFSET       0x0800

#define IONIC_VDEV_FW_WAIT_US       1000     /* 1ms */
#define IONIC_VDEV_FW_WAIT_MAX      5000     /* 5s */

static int
ionic_vdev_setup(struct ionic_adapter *adapter)
{
	struct ionic_bars *bars = &adapter->bars;
	struct ionic_dev *idev = &adapter->idev;
	uint8_t *bar0_base;
	uint32_t sig;
	uint32_t fw_waits = 0;
	uint8_t fw;

	IONIC_PRINT_CALL();

	/* BAR0: dev_cmd and interrupts */
	if (bars->num_bars < 1) {
		IONIC_PRINT(ERR, "No bars found, aborting");
		return -EFAULT;
	}

	bar0_base = bars->bar[IONIC_VDEV_DEV_BAR].vaddr;
	idev->dev_info = (union ionic_dev_info_regs *)
		&bar0_base[IONIC_VDEV_DEV_INFO_REGS_OFFSET];
	idev->dev_cmd = (union ionic_dev_cmd_regs *)
		&bar0_base[IONIC_VDEV_DEV_CMD_REGS_OFFSET];
	idev->intr_ctrl = (void *)bars->bar[IONIC_VDEV_INTR_CTL_BAR].vaddr;
	idev->db_pages = (void *)bars->bar[IONIC_VDEV_DB_BAR].vaddr;

	sig = ioread32(&idev->dev_info->signature);
	if (sig != IONIC_DEV_INFO_SIGNATURE) {
		IONIC_PRINT(ERR, "Incompatible firmware signature %x", sig);
		return -EFAULT;
	}

	/* Wait for the FW to indicate readiness */
	while (1) {
		fw = ioread8(&idev->dev_info->fw_status);
		if ((fw & IONIC_FW_STS_F_RUNNING) != 0)
			break;

		if (fw_waits > IONIC_VDEV_FW_WAIT_MAX) {
			IONIC_PRINT(ERR, "Firmware readiness bit not set");
			return -ETIMEDOUT;
		}

		fw_waits++;
		rte_delay_us_block(IONIC_VDEV_FW_WAIT_US);
	}
	IONIC_PRINT(DEBUG, "Firmware ready (%u waits)", fw_waits);

	adapter->name = rte_vdev_device_name(adapter->bus_dev);

	return 0;
}

static void
ionic_vdev_poll(struct ionic_adapter *adapter)
{
	ionic_dev_interrupt_handler(adapter);
}

static void
ionic_vdev_unmap_bars(struct ionic_adapter *adapter)
{
	struct ionic_bars *bars = &adapter->bars;
	uint32_t i;

	for (i = 0; i < IONIC_VDEV_BARS_MAX; i++)
		ionic_uio_rel_rsrc(adapter->name, i, &bars->bar[i]);
}

static const struct ionic_dev_intf ionic_vdev_intf = {
	.setup = ionic_vdev_setup,
	.poll = ionic_vdev_poll,
	.unmap_bars = ionic_vdev_unmap_bars,
};

static int
eth_ionic_vdev_probe(struct rte_vdev_device *vdev)
{
	struct ionic_bars bars = {};
	const char *name = rte_vdev_device_name(vdev);
	unsigned int i;

	IONIC_PRINT(NOTICE, "Initializing device %s",
		rte_eal_process_type() == RTE_PROC_SECONDARY ?
			"[SECONDARY]" : "");

	ionic_uio_scan_mnet_devices();

	for (i = 0; i < IONIC_VDEV_BARS_MAX; i++)
		ionic_uio_get_rsrc(name, i, &bars.bar[i]);

	bars.num_bars = IONIC_VDEV_BARS_MAX;

	return eth_ionic_dev_probe((void *)vdev,
			&vdev->device,
			&bars,
			&ionic_vdev_intf,
			IONIC_DEV_ID_ETH_VF,
			IONIC_PENSANDO_VENDOR_ID);
}

static int
eth_ionic_vdev_remove(struct rte_vdev_device *vdev)
{
	return eth_ionic_dev_remove(&vdev->device);
}

static struct rte_vdev_driver rte_vdev_ionic_pmd = {
	.probe = eth_ionic_vdev_probe,
	.remove = eth_ionic_vdev_remove,
};

RTE_PMD_REGISTER_VDEV(net_ionic, rte_vdev_ionic_pmd);