summaryrefslogtreecommitdiffstats
path: root/src/plugins/dev_iavf/iavf.c
blob: d1c2b9edc637c235983c7f4876e2da7ab53dff3b (plain)
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
---
project: 'vpp'
project_creation_date: '2015-12-08'
project_category: ''
lifecycle_state: 'Incubation'
project_lead: &vpp_ptl
    name: 'Damjan Marion'
    email: 'dmarion@me.com'
    id: 'dmarion'
    company: 'cisco'
    timezone: 'Europe/Zagreb'
primary_contact: *vpp_ptl
issue_tracking:
    type: 'jira'
    url: 'https://jira.fd.io/projects/vpp'
    key: 'VPP'
mailing_list:
    type: 'groups.io'
    url: 'https://lists.fd.io/g/vpp-dev'
    tag: '<[sub-project_name]>'
realtime_discussion:
    type: 'irc'
    server: 'freenode.net'
    channel: 'fdio-vpp'
meetings:
    - type: 'zoom'
      agenda: 'n/a'
      url: 'https://wiki.fd.io/view/VPP/Meeting'
      server: 'n/a'
      channel: 'fdio-vpp'
      repeats: 'weekly'
      time: '08:00 PT'
repositories:
    - 'vpp'
committers:
    - <<: *vpp_ptl
    - name: 'Dave Barach'
      company: 'cisco'
      email: 'openvpp@barachs.net'
      id: 'dbarach'
    - name: 'Florin Coras'
      company: 'cisco'
      email: 'florin.coras@gmail.com'
      id: 'florin.coras'
    - name: 'Benoit Ganne'
      company: 'cisco'
      email: 'bganne@cisco.com'
      id: 'bganne'
    - name: 'John Lo'
      company: 'cisco'
      email: 'loj@cisco.com'
      id: 'lojohn'
    - name: 'Chris Luke'
      company: 'comcast'
      email: 'chris_luke@comcast.com'
      id: 'chrisluke'
    - name: 'Neale Ranns'
      company: 'cisco'
      email: 'nranns@cisco.com'
      id: 'nranns'
    - name: 'Matthew Smith'
      company: 'netgate'
      email: 'mgsmith@netgate.com'
      id: 'mgsmith'
    - name: 'Ole Trøan'
      company: 'employees'
      email: 'otroan@employees.org'
      id: 'otroan'
    - name: 
/* SPDX-License-Identifier: Apache-2.0
 * Copyright (c) 2023 Cisco Systems, Inc.
 */

#include <vnet/vnet.h>
#include <vnet/dev/dev.h>
#include <vnet/dev/pci.h>
#include <vnet/dev/counters.h>
#include <vppinfra/ring.h>
#include <dev_iavf/iavf.h>
#include <dev_iavf/virtchnl.h>
#include <dev_iavf/virtchnl_funcs.h>
#include <vnet/ethernet/ethernet.h>
#include <vnet/plugin/plugin.h>
#include <vpp/app/version.h>

VLIB_REGISTER_LOG_CLASS (iavf_log, static) = {
  .class_name = "iavf",
  .subclass_name = "init",
};

#define IAVF_MAX_QPAIRS 32

static const u32 driver_cap_flags =
  /**/ VIRTCHNL_VF_CAP_ADV_LINK_SPEED |
  /**/ VIRTCHNL_VF_LARGE_NUM_QPAIRS |
  /**/ VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF |
  /**/ VIRTCHNL_VF_OFFLOAD_FDIR_PF |
  /**/ VIRTCHNL_VF_OFFLOAD_L2 |
  /**/ VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
  /**/ VIRTCHNL_VF_OFFLOAD_RSS_PF |
  /**/ VIRTCHNL_VF_OFFLOAD_RX_POLLING |
  /**/ VIRTCHNL_VF_OFFLOAD_VLAN |
  /**/ VIRTCHNL_VF_OFFLOAD_VLAN_V2 |
  /**/ VIRTCHNL_VF_OFFLOAD_WB_ON_ITR |
  /**/ 0;

static const virtchnl_version_info_t driver_virtchnl_version = 
  
= { foreach_iavf_tx_node_counter }; #undef _ vnet_dev_node_t iavf_rx_node = { .error_counters = iavf_rx_node_counters, .n_error_counters = ARRAY_LEN (iavf_rx_node_counters), .format_trace = format_iavf_rx_trace, }; vnet_dev_node_t iavf_tx_node = { .error_counters = iavf_tx_node_counters, .n_error_counters = ARRAY_LEN (iavf_tx_node_counters), }; static struct { u16 device_id; char *desc; } iavf_dev_types[] = { { 0x1889, "Intel(R) Adaptive Virtual Function" }, { 0x154c, "Intel(R) X710 Virtual Function" }, { 0x37cd, "Intel(R) X722 Virtual Function" }, }; static u8 * iavf_probe (vlib_main_t *vm, vnet_dev_bus_index_t bus_index, void *dev_info) { vnet_dev_bus_pci_device_info_t *di = dev_info; if (di->vendor_id != 0x8086) return 0; FOREACH_ARRAY_ELT (dt, iavf_dev_types) { if (dt->device_id == di->device_id) return format (0, "%s", dt->desc); } return 0; } static vnet_dev_rv_t iavf_reset (vlib_main_t *vm, vnet_dev_t *dev) { iavf_device_t *ad = vnet_dev_get_data (dev); u32 n_tries = 50; iavf_aq_init (vm, dev); iavf_vc_op_reset_vf (vm, dev); do { if (n_tries-- == 0) return VNET_DEV_ERR_TIMEOUT; vlib_process_suspend (vm, 0.02); } while ((iavf_reg_read (ad, IAVF_VFGEN_RSTAT) & 3) != 2); iavf_aq_init (vm, dev); iavf_aq_poll_on (vm, dev); return (VNET_DEV_OK); } static vnet_dev_rv_t iavf_alloc (vlib_main_t *vm, vnet_dev_t *dev) { log_debug (dev, "alloc"); return iavf_aq_alloc (vm, dev); } static vnet_dev_rv_t iavf_init (vlib_main_t *vm, vnet_dev_t *dev) { iavf_device_t *ad = vnet_dev_get_data (dev); virtchnl_version_info_t ver; virtchnl_vf_resource_t res; u32 n_threads = vlib_get_n_threads (); u16 max_frame_sz; vnet_dev_rv_t rv; log_debug (dev, "init"); if ((rv = vnet_dev_pci_map_region (vm, dev, 0, &ad->bar0))) return rv; if ((rv = vnet_dev_pci_bus_master_enable (vm, dev))) return rv; if ((rv = iavf_reset (vm, dev))) return rv; if ((rv = iavf_vc_op_version (vm, dev, &driver_virtchnl_version, &ver))) return rv; if (ver.major != driver_virtchnl_version.major || ver.minor != driver_virtchnl_version.minor) return VNET_DEV_ERR_UNSUPPORTED_DEVICE_VER; if ((rv = iavf_vc_op_get_vf_resources (vm, dev, &driver_cap_flags, &res))) return rv; if (res.num_vsis != 1 || res.vsi_res[0].vsi_type != VIRTCHNL_VSI_SRIOV) return VNET_DEV_ERR_UNSUPPORTED_DEVICE; if (res.max_mtu == 0) { log_warn (dev, "PF driver is reporting invalid value of 0 for max_mtu, " "consider upgrade"); max_frame_sz = ETHERNET_MAX_PACKET_BYTES; } else /* reverse of PF driver MTU calculation */ max_frame_sz = res.max_mtu + 14 /* ethernet header */ + 4 /* FCS */ + 2 * 4 /* two VLAN tags */; iavf_port_t iavf_port = { .vf_cap_flags = res.vf_cap_flags, .rss_key_size = res.rss_key_size, .rss_lut_size = res.rss_lut_size, .max_vectors = res.max_vectors, .vsi_id = res.vsi_res[0].vsi_id, .num_qp = clib_min (IAVF_MAX_QPAIRS, res.vsi_res[0].num_queue_pairs), }; vnet_dev_port_add_args_t port_add_args = { .port = { .attr = { .type = VNET_DEV_PORT_TYPE_ETHERNET, .max_rx_queues = clib_min (IAVF_MAX_QPAIRS, res.num_queue_pairs), .max_tx_queues = clib_min (IAVF_MAX_QPAIRS, res.num_queue_pairs), .max_supported_rx_frame_size = max_frame_sz, .caps = { .change_max_rx_frame_size = 1, .interrupt_mode = 1, .rss = 1, .mac_filter = 1, }, .rx_offloads = { .ip4_cksum = 1, }, .tx_offloads = { .ip4_cksum = 1, .tcp_gso = 1, }, }, .ops = { .init = iavf_port_init, .start = iavf_port_start, .stop = iavf_port_stop, .config_change = iavf_port_cfg_change, .config_change_validate = iavf_port_cfg_change_validate, .format_status = format_iavf_port_status, }, .data_size = sizeof (iavf_port_t), .initial_data = &iavf_port, }, .rx_node = &iavf_rx_node, .tx_node = &iavf_tx_node, .rx_queue = { .config = { .data_size = sizeof (iavf_rxq_t), .default_size = 512, .multiplier = 32, .min_size = 32, .max_size = 4096, .size_is_power_of_two = 1, }, .ops = { .alloc = iavf_rx_queue_alloc, .free = iavf_rx_queue_free, }, }, .tx_queue = { .config = { .data_size = sizeof (iavf_txq_t), .default_size = 512, .multiplier = 32, .min_size = 32, .max_size = 4096, .size_is_power_of_two = 1, }, .ops = { .alloc = iavf_tx_queue_alloc, .free = iavf_tx_queue_free, }, }, }; vnet_dev_set_hw_addr_eth_mac (&port_add_args.port.attr.hw_addr, res.vsi_res[0].default_mac_addr); log_info (dev, "MAC address is %U", format_ethernet_address, res.vsi_res[0].default_mac_addr); if (n_threads <= vnet_dev_get_pci_n_msix_interrupts (dev) - 1) { port_add_args.port.attr.caps.interrupt_mode = 1; iavf_port.n_rx_vectors = n_threads; } else { log_notice ( dev, "number of threads (%u) bigger than number of interrupt lines " "(%u), interrupt mode disabled", vlib_get_n_threads (), res.max_vectors); iavf_port.n_rx_vectors = 1; } if (res.vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) { if (res.rss_key_size < IAVF_MAX_RSS_KEY_SIZE) { log_notice ( dev, "unsupported RSS config provided by device, RSS disabled"); } else { port_add_args.port.attr.caps.rss = 1; if (res.rss_lut_size > IAVF_MAX_RSS_LUT_SIZE) log_notice (dev, "device supports bigger RSS LUT than driver"); } } return vnet_dev_port_add (vm, dev, 0, &port_add_args); } static void iavf_deinit (vlib_main_t *vm, vnet_dev_t *dev) { log_debug (dev, "deinit"); iavf_aq_poll_off (vm, dev); iavf_aq_deinit (vm, dev); iavf_aq_free (vm, dev); } static void iavf_free (vlib_main_t *vm, vnet_dev_t *dev) { log_debug (dev, "free"); iavf_aq_free (vm, dev); } VNET_DEV_REGISTER_DRIVER (avf) = { .name = "iavf", .bus = "pci", .device_data_sz = sizeof (iavf_device_t), .runtime_temp_space_sz = sizeof (iavf_rt_data_t), .ops = { .alloc = iavf_alloc, .init = iavf_init, .deinit = iavf_deinit, .free = iavf_free, .probe = iavf_probe, }, }; VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, .description = "dev_iavf", };