Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * 3 : : * Copyright(c) 2019-2021 Xilinx, Inc. 4 : : * Copyright(c) 2019 Solarflare Communications Inc. 5 : : * 6 : : * This software was jointly developed between OKTET Labs (under contract 7 : : * for Solarflare) and Solarflare Communications, Inc. 8 : : */ 9 : : 10 : : #include <rte_common.h> 11 : : #include <bus_pci_driver.h> 12 : : 13 : : #include "sfc.h" 14 : : #include "sfc_log.h" 15 : : 16 : : #include "efx.h" 17 : : 18 : : 19 : : /* 20 : : * Check if a MAC address is already assigned to one of previously 21 : : * configured vPorts (either PF itself or one of already configured VFs). 22 : : * 23 : : * Typically the first vPort which corresponds to PF has globally 24 : : * administered unicast address, but it still could be locally 25 : : * administered if user assigned it or in the case of unconfigured NIC. 26 : : * So, it is safer to include it as well in uniqueness check. 27 : : */ 28 : : static bool 29 : : sriov_mac_addr_assigned(const efx_vport_config_t *vport_config, 30 : : unsigned int num, const uint8_t *mac_addr) 31 : : { 32 : : unsigned int i; 33 : : 34 : : /* Check PF's MAC address as well as explained above */ 35 [ # # ]: 0 : for (i = 0; i < num; ++i) { 36 [ # # ]: 0 : if (memcmp(mac_addr, vport_config[i].evc_mac_addr, 37 : : sizeof(vport_config[i].evc_mac_addr)) == 0) 38 : : return true; 39 : : } 40 : : 41 : : return false; 42 : : } 43 : : 44 : : int 45 : 0 : sfc_sriov_attach(struct sfc_adapter *sa) 46 : : { 47 : 0 : const struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(sa->eth_dev); 48 : : struct sfc_sriov *sriov = &sa->sriov; 49 : : efx_vport_config_t *vport_config; 50 : : unsigned int i; 51 : : int rc; 52 : : 53 : 0 : sfc_log_init(sa, "entry"); 54 : : 55 : 0 : sriov->num_vfs = pci_dev->max_vfs; 56 [ # # # # ]: 0 : if (sa->switchdev || sriov->num_vfs == 0) 57 : 0 : goto done; 58 : : 59 : 0 : vport_config = calloc(sriov->num_vfs + 1, sizeof(*vport_config)); 60 [ # # ]: 0 : if (vport_config == NULL) { 61 : : rc = ENOMEM; 62 : 0 : goto fail_alloc_vport_config; 63 : : } 64 : : 65 : 0 : vport_config[0].evc_function = 0xffff; 66 : 0 : vport_config[0].evc_vid = EFX_VF_VID_DEFAULT; 67 : 0 : vport_config[0].evc_vlan_restrict = B_FALSE; 68 : : 69 [ # # ]: 0 : for (i = 1; i <= sriov->num_vfs; ++i) { 70 : 0 : vport_config[i].evc_function = i - 1; 71 : 0 : vport_config[i].evc_vid = EFX_VF_VID_DEFAULT; 72 : 0 : vport_config[i].evc_vlan_restrict = B_FALSE; 73 : : do { 74 : 0 : rte_eth_random_addr(vport_config[i].evc_mac_addr); 75 [ # # ]: 0 : } while (sriov_mac_addr_assigned(vport_config, i, 76 : : vport_config[i].evc_mac_addr)); 77 : : } 78 : : 79 : 0 : sriov->vport_config = vport_config; 80 : : 81 : 0 : done: 82 : 0 : sfc_log_init(sa, "done"); 83 : 0 : return 0; 84 : : 85 : : fail_alloc_vport_config: 86 : 0 : sriov->num_vfs = 0; 87 : 0 : return rc; 88 : : } 89 : : 90 : : void 91 : 0 : sfc_sriov_detach(struct sfc_adapter *sa) 92 : : { 93 : : struct sfc_sriov *sriov = &sa->sriov; 94 : : 95 : 0 : sfc_log_init(sa, "entry"); 96 : : 97 : 0 : free(sriov->vport_config); 98 : 0 : sriov->vport_config = NULL; 99 : 0 : sriov->num_vfs = 0; 100 : : 101 : 0 : sfc_log_init(sa, "done"); 102 : 0 : } 103 : : 104 : : int 105 : 0 : sfc_sriov_vswitch_create(struct sfc_adapter *sa) 106 : : { 107 : : struct sfc_sriov *sriov = &sa->sriov; 108 : 0 : efx_vport_config_t *vport_config = sriov->vport_config; 109 : : int rc; 110 : : 111 : 0 : sfc_log_init(sa, "entry"); 112 : : 113 [ # # ]: 0 : if (sa->switchdev) { 114 : 0 : sfc_log_init(sa, "don't create vswitch in switchdev mode"); 115 : 0 : goto done; 116 : : } 117 : : 118 [ # # ]: 0 : if (sriov->num_vfs == 0) { 119 : 0 : sfc_log_init(sa, "no VFs enabled"); 120 : 0 : goto done; 121 : : } 122 : : 123 : 0 : rc = efx_evb_init(sa->nic); 124 [ # # ]: 0 : if (rc != 0) { 125 : 0 : sfc_err(sa, "EVB init failed %d", rc); 126 : 0 : goto fail_evb_init; 127 : : } 128 : : 129 : : RTE_BUILD_BUG_ON(sizeof(sa->port.default_mac_addr) != 130 : : sizeof(vport_config[0].evc_mac_addr)); 131 : : rte_ether_addr_copy(&sa->port.default_mac_addr, 132 : : (struct rte_ether_addr *)vport_config[0].evc_mac_addr); 133 : : 134 : 0 : rc = efx_evb_vswitch_create(sa->nic, sriov->num_vfs + 1, 135 : : vport_config, &sriov->vswitch); 136 [ # # ]: 0 : if (rc != 0) { 137 : 0 : sfc_err(sa, "EVB vSwitch create failed %d", rc); 138 : 0 : goto fail_evb_vswitch_create; 139 : : } 140 : : 141 : 0 : done: 142 : 0 : sfc_log_init(sa, "done"); 143 : 0 : return 0; 144 : : 145 : : fail_evb_vswitch_create: 146 : 0 : efx_evb_fini(sa->nic); 147 : : 148 : : fail_evb_init: 149 : : return rc; 150 : : } 151 : : 152 : : void 153 : 0 : sfc_sriov_vswitch_destroy(struct sfc_adapter *sa) 154 : : { 155 : : struct sfc_sriov *sriov = &sa->sriov; 156 : : int rc; 157 : : 158 : 0 : sfc_log_init(sa, "entry"); 159 : : 160 [ # # # # ]: 0 : if (sa->switchdev || sriov->num_vfs == 0) 161 : 0 : goto done; 162 : : 163 : 0 : rc = efx_evb_vswitch_destroy(sa->nic, sriov->vswitch); 164 [ # # ]: 0 : if (rc != 0) 165 : 0 : sfc_err(sa, "efx_evb_vswitch_destroy() failed %d", rc); 166 : : 167 : 0 : sriov->vswitch = NULL; 168 : : 169 : 0 : efx_evb_fini(sa->nic); 170 : : 171 : 0 : done: 172 : 0 : sfc_log_init(sa, "done"); 173 : 0 : }