nfp_net_sriov.c (8919B)
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2/* Copyright (C) 2017-2019 Netronome Systems, Inc. */ 3 4#include <linux/bitfield.h> 5#include <linux/errno.h> 6#include <linux/etherdevice.h> 7#include <linux/if_link.h> 8#include <linux/if_ether.h> 9 10#include "nfpcore/nfp_cpp.h" 11#include "nfp_app.h" 12#include "nfp_main.h" 13#include "nfp_net_ctrl.h" 14#include "nfp_net.h" 15#include "nfp_net_sriov.h" 16 17static int 18nfp_net_sriov_check(struct nfp_app *app, int vf, u16 cap, const char *msg, bool warn) 19{ 20 u16 cap_vf; 21 22 if (!app || !app->pf->vfcfg_tbl2) 23 return -EOPNOTSUPP; 24 25 cap_vf = readw(app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_CAP); 26 if ((cap_vf & cap) != cap) { 27 if (warn) 28 nfp_warn(app->pf->cpp, "ndo_set_vf_%s not supported\n", msg); 29 return -EOPNOTSUPP; 30 } 31 32 if (vf < 0 || vf >= app->pf->num_vfs) { 33 if (warn) 34 nfp_warn(app->pf->cpp, "invalid VF id %d\n", vf); 35 return -EINVAL; 36 } 37 38 return 0; 39} 40 41static int 42nfp_net_sriov_update(struct nfp_app *app, int vf, u16 update, const char *msg) 43{ 44 struct nfp_net *nn; 45 int ret; 46 47 /* Write update info to mailbox in VF config symbol */ 48 writeb(vf, app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_VF_NUM); 49 writew(update, app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_UPD); 50 51 nn = list_first_entry(&app->pf->vnics, struct nfp_net, vnic_list); 52 /* Signal VF reconfiguration */ 53 ret = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_VF); 54 if (ret) 55 return ret; 56 57 ret = readw(app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_RET); 58 if (ret) 59 nfp_warn(app->pf->cpp, 60 "FW refused VF %s update with errno: %d\n", msg, ret); 61 return -ret; 62} 63 64int nfp_app_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) 65{ 66 struct nfp_app *app = nfp_app_from_netdev(netdev); 67 unsigned int vf_offset; 68 int err; 69 70 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_MAC, "mac", true); 71 if (err) 72 return err; 73 74 if (is_multicast_ether_addr(mac)) { 75 nfp_warn(app->pf->cpp, 76 "invalid Ethernet address %pM for VF id %d\n", 77 mac, vf); 78 return -EINVAL; 79 } 80 81 /* Write MAC to VF entry in VF config symbol */ 82 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ; 83 writel(get_unaligned_be32(mac), app->pf->vfcfg_tbl2 + vf_offset); 84 writew(get_unaligned_be16(mac + 4), 85 app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_MAC_LO); 86 87 err = nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_MAC, "MAC"); 88 if (!err) 89 nfp_info(app->pf->cpp, 90 "MAC %pM set on VF %d, reload the VF driver to make this change effective.\n", 91 mac, vf); 92 93 return err; 94} 95 96int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos, 97 __be16 vlan_proto) 98{ 99 struct nfp_app *app = nfp_app_from_netdev(netdev); 100 u16 update = NFP_NET_VF_CFG_MB_UPD_VLAN; 101 bool is_proto_sup = true; 102 unsigned int vf_offset; 103 u32 vlan_tag; 104 int err; 105 106 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_VLAN, "vlan", true); 107 if (err) 108 return err; 109 110 if (!eth_type_vlan(vlan_proto)) 111 return -EOPNOTSUPP; 112 113 if (vlan > 4095 || qos > 7) { 114 nfp_warn(app->pf->cpp, 115 "invalid vlan id or qos for VF id %d\n", vf); 116 return -EINVAL; 117 } 118 119 /* Check if fw supports or not */ 120 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_VLAN_PROTO, "vlan_proto", true); 121 if (err) 122 is_proto_sup = false; 123 124 if (vlan_proto != htons(ETH_P_8021Q)) { 125 if (!is_proto_sup) 126 return -EOPNOTSUPP; 127 update |= NFP_NET_VF_CFG_MB_UPD_VLAN_PROTO; 128 } 129 130 /* Write VLAN tag to VF entry in VF config symbol */ 131 vlan_tag = FIELD_PREP(NFP_NET_VF_CFG_VLAN_VID, vlan) | 132 FIELD_PREP(NFP_NET_VF_CFG_VLAN_QOS, qos); 133 134 /* vlan_tag of 0 means that the configuration should be cleared and in 135 * such circumstances setting the TPID has no meaning when 136 * configuring firmware. 137 */ 138 if (vlan_tag && is_proto_sup) 139 vlan_tag |= FIELD_PREP(NFP_NET_VF_CFG_VLAN_PROT, ntohs(vlan_proto)); 140 141 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ; 142 writel(vlan_tag, app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_VLAN); 143 144 return nfp_net_sriov_update(app, vf, update, "vlan"); 145} 146 147int nfp_app_set_vf_rate(struct net_device *netdev, int vf, 148 int min_tx_rate, int max_tx_rate) 149{ 150 struct nfp_app *app = nfp_app_from_netdev(netdev); 151 u32 vf_offset, ratevalue; 152 int err; 153 154 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate", true); 155 if (err) 156 return err; 157 158 if (max_tx_rate >= NFP_NET_VF_RATE_MAX || 159 min_tx_rate >= NFP_NET_VF_RATE_MAX) { 160 nfp_warn(app->cpp, "tx-rate exceeds %d.\n", 161 NFP_NET_VF_RATE_MAX); 162 return -EINVAL; 163 } 164 165 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ; 166 ratevalue = FIELD_PREP(NFP_NET_VF_CFG_MAX_RATE, 167 max_tx_rate ? max_tx_rate : 168 NFP_NET_VF_RATE_MAX) | 169 FIELD_PREP(NFP_NET_VF_CFG_MIN_RATE, min_tx_rate); 170 171 writel(ratevalue, 172 app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_RATE); 173 174 return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_RATE, 175 "rate"); 176} 177 178int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable) 179{ 180 struct nfp_app *app = nfp_app_from_netdev(netdev); 181 unsigned int vf_offset; 182 u8 vf_ctrl; 183 int err; 184 185 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_SPOOF, 186 "spoofchk", true); 187 if (err) 188 return err; 189 190 /* Write spoof check control bit to VF entry in VF config symbol */ 191 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ + 192 NFP_NET_VF_CFG_CTRL; 193 vf_ctrl = readb(app->pf->vfcfg_tbl2 + vf_offset); 194 vf_ctrl &= ~NFP_NET_VF_CFG_CTRL_SPOOF; 195 vf_ctrl |= FIELD_PREP(NFP_NET_VF_CFG_CTRL_SPOOF, enable); 196 writeb(vf_ctrl, app->pf->vfcfg_tbl2 + vf_offset); 197 198 return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_SPOOF, 199 "spoofchk"); 200} 201 202int nfp_app_set_vf_trust(struct net_device *netdev, int vf, bool enable) 203{ 204 struct nfp_app *app = nfp_app_from_netdev(netdev); 205 unsigned int vf_offset; 206 u8 vf_ctrl; 207 int err; 208 209 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_TRUST, 210 "trust", true); 211 if (err) 212 return err; 213 214 /* Write trust control bit to VF entry in VF config symbol */ 215 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ + 216 NFP_NET_VF_CFG_CTRL; 217 vf_ctrl = readb(app->pf->vfcfg_tbl2 + vf_offset); 218 vf_ctrl &= ~NFP_NET_VF_CFG_CTRL_TRUST; 219 vf_ctrl |= FIELD_PREP(NFP_NET_VF_CFG_CTRL_TRUST, enable); 220 writeb(vf_ctrl, app->pf->vfcfg_tbl2 + vf_offset); 221 222 return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_TRUST, 223 "trust"); 224} 225 226int nfp_app_set_vf_link_state(struct net_device *netdev, int vf, 227 int link_state) 228{ 229 struct nfp_app *app = nfp_app_from_netdev(netdev); 230 unsigned int vf_offset; 231 u8 vf_ctrl; 232 int err; 233 234 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_LINK_STATE, 235 "link_state", true); 236 if (err) 237 return err; 238 239 switch (link_state) { 240 case IFLA_VF_LINK_STATE_AUTO: 241 case IFLA_VF_LINK_STATE_ENABLE: 242 case IFLA_VF_LINK_STATE_DISABLE: 243 break; 244 default: 245 return -EINVAL; 246 } 247 248 /* Write link state to VF entry in VF config symbol */ 249 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ + 250 NFP_NET_VF_CFG_CTRL; 251 vf_ctrl = readb(app->pf->vfcfg_tbl2 + vf_offset); 252 vf_ctrl &= ~NFP_NET_VF_CFG_CTRL_LINK_STATE; 253 vf_ctrl |= FIELD_PREP(NFP_NET_VF_CFG_CTRL_LINK_STATE, link_state); 254 writeb(vf_ctrl, app->pf->vfcfg_tbl2 + vf_offset); 255 256 return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_LINK_STATE, 257 "link state"); 258} 259 260int nfp_app_get_vf_config(struct net_device *netdev, int vf, 261 struct ifla_vf_info *ivi) 262{ 263 struct nfp_app *app = nfp_app_from_netdev(netdev); 264 u32 vf_offset, mac_hi, rate; 265 u32 vlan_tag; 266 u16 mac_lo; 267 u8 flags; 268 int err; 269 270 err = nfp_net_sriov_check(app, vf, 0, "", true); 271 if (err) 272 return err; 273 274 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ; 275 276 mac_hi = readl(app->pf->vfcfg_tbl2 + vf_offset); 277 mac_lo = readw(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_MAC_LO); 278 279 flags = readb(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_CTRL); 280 vlan_tag = readl(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_VLAN); 281 282 memset(ivi, 0, sizeof(*ivi)); 283 ivi->vf = vf; 284 285 put_unaligned_be32(mac_hi, &ivi->mac[0]); 286 put_unaligned_be16(mac_lo, &ivi->mac[4]); 287 288 ivi->vlan = FIELD_GET(NFP_NET_VF_CFG_VLAN_VID, vlan_tag); 289 ivi->qos = FIELD_GET(NFP_NET_VF_CFG_VLAN_QOS, vlan_tag); 290 if (!nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_VLAN_PROTO, "vlan_proto", false)) 291 ivi->vlan_proto = htons(FIELD_GET(NFP_NET_VF_CFG_VLAN_PROT, vlan_tag)); 292 ivi->spoofchk = FIELD_GET(NFP_NET_VF_CFG_CTRL_SPOOF, flags); 293 ivi->trusted = FIELD_GET(NFP_NET_VF_CFG_CTRL_TRUST, flags); 294 ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE, flags); 295 296 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate", false); 297 if (!err) { 298 rate = readl(app->pf->vfcfg_tbl2 + vf_offset + 299 NFP_NET_VF_CFG_RATE); 300 301 ivi->max_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MAX_RATE, rate); 302 ivi->min_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MIN_RATE, rate); 303 304 if (ivi->max_tx_rate == NFP_NET_VF_RATE_MAX) 305 ivi->max_tx_rate = 0; 306 if (ivi->min_tx_rate == NFP_NET_VF_RATE_MAX) 307 ivi->min_tx_rate = 0; 308 } 309 310 return 0; 311}