1 /* SPDX-License-Identifier: Apache-2.0
2 * Copyright (c) 2023 Cisco Systems, Inc.
6 #include <vnet/dev/dev.h>
7 #include <vnet/dev/pci.h>
8 #include <vnet/dev/counters.h>
9 #include <vppinfra/ring.h>
10 #include <dev_iavf/iavf.h>
11 #include <dev_iavf/virtchnl.h>
12 #include <dev_iavf/virtchnl_funcs.h>
13 #include <vnet/ethernet/ethernet.h>
14 #include <vnet/plugin/plugin.h>
15 #include <vpp/app/version.h>
17 VLIB_REGISTER_LOG_CLASS (iavf_log, static) = {
19 .subclass_name = "init",
22 #define IAVF_MAX_QPAIRS 32
24 static const u32 driver_cap_flags =
25 /**/ VIRTCHNL_VF_CAP_ADV_LINK_SPEED |
26 /**/ VIRTCHNL_VF_LARGE_NUM_QPAIRS |
27 /**/ VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF |
28 /**/ VIRTCHNL_VF_OFFLOAD_FDIR_PF |
29 /**/ VIRTCHNL_VF_OFFLOAD_L2 |
30 /**/ VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
31 /**/ VIRTCHNL_VF_OFFLOAD_RSS_PF |
32 /**/ VIRTCHNL_VF_OFFLOAD_RX_POLLING |
33 /**/ VIRTCHNL_VF_OFFLOAD_VLAN |
34 /**/ VIRTCHNL_VF_OFFLOAD_VLAN_V2 |
35 /**/ VIRTCHNL_VF_OFFLOAD_WB_ON_ITR |
38 static const virtchnl_version_info_t driver_virtchnl_version = {
39 .major = VIRTCHNL_VERSION_MAJOR,
40 .minor = VIRTCHNL_VERSION_MINOR,
43 #define _(f, n, s, d) \
44 { .name = #n, .desc = d, .severity = VL_COUNTER_SEVERITY_##s },
46 vlib_error_desc_t iavf_rx_node_counters[] = { foreach_iavf_rx_node_counter };
47 vlib_error_desc_t iavf_tx_node_counters[] = { foreach_iavf_tx_node_counter };
50 vnet_dev_node_t iavf_rx_node = {
51 .error_counters = iavf_rx_node_counters,
52 .n_error_counters = ARRAY_LEN (iavf_rx_node_counters),
53 .format_trace = format_iavf_rx_trace,
56 vnet_dev_node_t iavf_tx_node = {
57 .error_counters = iavf_tx_node_counters,
58 .n_error_counters = ARRAY_LEN (iavf_tx_node_counters),
65 } iavf_dev_types[] = {
66 { 0x1889, "Intel(R) Adaptive Virtual Function" },
67 { 0x154c, "Intel(R) X710 Virtual Function" },
68 { 0x37cd, "Intel(R) X722 Virtual Function" },
72 iavf_probe (vlib_main_t *vm, vnet_dev_bus_index_t bus_index, void *dev_info)
74 vnet_dev_bus_pci_device_info_t *di = dev_info;
76 if (di->vendor_id != 0x8086)
79 FOREACH_ARRAY_ELT (dt, iavf_dev_types)
81 if (dt->device_id == di->device_id)
82 return format (0, "%s", dt->desc);
89 iavf_reset (vlib_main_t *vm, vnet_dev_t *dev)
91 iavf_device_t *ad = vnet_dev_get_data (dev);
94 iavf_aq_init (vm, dev);
95 iavf_vc_op_reset_vf (vm, dev);
100 return VNET_DEV_ERR_TIMEOUT;
101 vlib_process_suspend (vm, 0.02);
103 while ((iavf_reg_read (ad, IAVF_VFGEN_RSTAT) & 3) != 2);
105 iavf_aq_init (vm, dev);
106 iavf_aq_poll_on (vm, dev);
107 return (VNET_DEV_OK);
111 iavf_alloc (vlib_main_t *vm, vnet_dev_t *dev)
113 log_debug (dev, "alloc");
114 return iavf_aq_alloc (vm, dev);
118 iavf_init (vlib_main_t *vm, vnet_dev_t *dev)
120 iavf_device_t *ad = vnet_dev_get_data (dev);
121 virtchnl_version_info_t ver;
122 virtchnl_vf_resource_t res;
123 u32 n_threads = vlib_get_n_threads ();
126 log_debug (dev, "init");
128 if ((rv = vnet_dev_pci_map_region (vm, dev, 0, &ad->bar0)))
131 if ((rv = vnet_dev_pci_bus_master_enable (vm, dev)))
134 if ((rv = iavf_reset (vm, dev)))
137 if ((rv = iavf_vc_op_version (vm, dev, &driver_virtchnl_version, &ver)))
140 if (ver.major != driver_virtchnl_version.major ||
141 ver.minor != driver_virtchnl_version.minor)
142 return VNET_DEV_ERR_UNSUPPORTED_DEVICE_VER;
144 if ((rv = iavf_vc_op_get_vf_resources (vm, dev, &driver_cap_flags, &res)))
147 if (res.num_vsis != 1 || res.vsi_res[0].vsi_type != VIRTCHNL_VSI_SRIOV)
148 return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
150 iavf_port_t iavf_port = {
151 .vf_cap_flags = res.vf_cap_flags,
152 .rss_key_size = res.rss_key_size,
153 .rss_lut_size = res.rss_lut_size,
154 .max_vectors = res.max_vectors,
155 .vsi_id = res.vsi_res[0].vsi_id,
156 .num_qp = clib_min (IAVF_MAX_QPAIRS, res.vsi_res[0].num_queue_pairs),
159 vnet_dev_port_add_args_t port_add_args = {
162 .type = VNET_DEV_PORT_TYPE_ETHERNET,
163 .max_rx_queues = clib_min (IAVF_MAX_QPAIRS, res.num_queue_pairs),
164 .max_tx_queues = clib_min (IAVF_MAX_QPAIRS, res.num_queue_pairs),
165 .max_supported_rx_frame_size = res.max_mtu,
166 .caps.change_max_rx_frame_size = 1,
169 .init = iavf_port_init,
170 .start = iavf_port_start,
171 .stop = iavf_port_stop,
172 .config_change = iavf_port_cfg_change,
173 .format_status = format_iavf_port_status,
175 .data_size = sizeof (iavf_port_t),
176 .initial_data = &iavf_port,
178 .rx_node = &iavf_rx_node,
179 .tx_node = &iavf_tx_node,
182 .data_size = sizeof (iavf_rxq_t),
187 .size_is_power_of_two = 1,
190 .alloc = iavf_rx_queue_alloc,
191 .free = iavf_rx_queue_free,
196 .data_size = sizeof (iavf_txq_t),
201 .size_is_power_of_two = 1,
204 .alloc = iavf_tx_queue_alloc,
205 .free = iavf_tx_queue_free,
210 vnet_dev_set_hw_addr_eth_mac (&port_add_args.port.attr.hw_addr,
211 res.vsi_res[0].default_mac_addr);
213 log_info (dev, "MAC address is %U", format_ethernet_address,
214 res.vsi_res[0].default_mac_addr);
216 if (n_threads <= vnet_dev_get_pci_n_msix_interrupts (dev) - 1)
218 port_add_args.port.attr.caps.interrupt_mode = 1;
219 iavf_port.n_rx_vectors = n_threads;
225 "number of threads (%u) bigger than number of interrupt lines "
226 "(%u), interrupt mode disabled",
227 vlib_get_n_threads (), res.max_vectors);
228 iavf_port.n_rx_vectors = 1;
231 if (res.vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF)
233 if (res.rss_key_size < IAVF_MAX_RSS_KEY_SIZE)
236 dev, "unsupported RSS config provided by device, RSS disabled");
240 port_add_args.port.attr.caps.rss = 1;
241 if (res.rss_lut_size > IAVF_MAX_RSS_LUT_SIZE)
242 log_notice (dev, "device supports bigger RSS LUT than driver");
246 return vnet_dev_port_add (vm, dev, 0, &port_add_args);
250 iavf_deinit (vlib_main_t *vm, vnet_dev_t *dev)
252 log_debug (dev, "deinit");
253 iavf_aq_poll_off (vm, dev);
254 iavf_aq_deinit (vm, dev);
255 iavf_aq_free (vm, dev);
259 iavf_free (vlib_main_t *vm, vnet_dev_t *dev)
261 log_debug (dev, "free");
262 iavf_aq_free (vm, dev);
265 VNET_DEV_REGISTER_DRIVER (avf) = {
268 .device_data_sz = sizeof (iavf_device_t),
269 .runtime_temp_space_sz = sizeof (iavf_rt_data_t),
273 .deinit = iavf_deinit,
279 VLIB_PLUGIN_REGISTER () = {
280 .version = VPP_BUILD_VER,
281 .description = "dev_iavf",