0001
0002
0003
0004 #include <linux/bitfield.h>
0005 #include <linux/errno.h>
0006 #include <linux/etherdevice.h>
0007 #include <linux/if_link.h>
0008 #include <linux/if_ether.h>
0009
0010 #include "nfpcore/nfp_cpp.h"
0011 #include "nfp_app.h"
0012 #include "nfp_main.h"
0013 #include "nfp_net_ctrl.h"
0014 #include "nfp_net.h"
0015 #include "nfp_net_sriov.h"
0016
0017 static int
0018 nfp_net_sriov_check(struct nfp_app *app, int vf, u16 cap, const char *msg, bool warn)
0019 {
0020 u16 cap_vf;
0021
0022 if (!app || !app->pf->vfcfg_tbl2)
0023 return -EOPNOTSUPP;
0024
0025 cap_vf = readw(app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_CAP);
0026 if ((cap_vf & cap) != cap) {
0027 if (warn)
0028 nfp_warn(app->pf->cpp, "ndo_set_vf_%s not supported\n", msg);
0029 return -EOPNOTSUPP;
0030 }
0031
0032 if (vf < 0 || vf >= app->pf->num_vfs) {
0033 if (warn)
0034 nfp_warn(app->pf->cpp, "invalid VF id %d\n", vf);
0035 return -EINVAL;
0036 }
0037
0038 return 0;
0039 }
0040
0041 static int
0042 nfp_net_sriov_update(struct nfp_app *app, int vf, u16 update, const char *msg)
0043 {
0044 struct nfp_net *nn;
0045 int ret;
0046
0047
0048 writeb(vf, app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_VF_NUM);
0049 writew(update, app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_UPD);
0050
0051 nn = list_first_entry(&app->pf->vnics, struct nfp_net, vnic_list);
0052
0053 ret = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_VF);
0054 if (ret)
0055 return ret;
0056
0057 ret = readw(app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_RET);
0058 if (ret)
0059 nfp_warn(app->pf->cpp,
0060 "FW refused VF %s update with errno: %d\n", msg, ret);
0061 return -ret;
0062 }
0063
0064 int nfp_app_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
0065 {
0066 struct nfp_app *app = nfp_app_from_netdev(netdev);
0067 unsigned int vf_offset;
0068 int err;
0069
0070 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_MAC, "mac", true);
0071 if (err)
0072 return err;
0073
0074 if (is_multicast_ether_addr(mac)) {
0075 nfp_warn(app->pf->cpp,
0076 "invalid Ethernet address %pM for VF id %d\n",
0077 mac, vf);
0078 return -EINVAL;
0079 }
0080
0081
0082 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
0083 writel(get_unaligned_be32(mac), app->pf->vfcfg_tbl2 + vf_offset);
0084 writew(get_unaligned_be16(mac + 4),
0085 app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_MAC_LO);
0086
0087 err = nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_MAC, "MAC");
0088 if (!err)
0089 nfp_info(app->pf->cpp,
0090 "MAC %pM set on VF %d, reload the VF driver to make this change effective.\n",
0091 mac, vf);
0092
0093 return err;
0094 }
0095
0096 int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
0097 __be16 vlan_proto)
0098 {
0099 struct nfp_app *app = nfp_app_from_netdev(netdev);
0100 u16 update = NFP_NET_VF_CFG_MB_UPD_VLAN;
0101 bool is_proto_sup = true;
0102 unsigned int vf_offset;
0103 u32 vlan_tag;
0104 int err;
0105
0106 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_VLAN, "vlan", true);
0107 if (err)
0108 return err;
0109
0110 if (!eth_type_vlan(vlan_proto))
0111 return -EOPNOTSUPP;
0112
0113 if (vlan > 4095 || qos > 7) {
0114 nfp_warn(app->pf->cpp,
0115 "invalid vlan id or qos for VF id %d\n", vf);
0116 return -EINVAL;
0117 }
0118
0119
0120 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_VLAN_PROTO, "vlan_proto", true);
0121 if (err)
0122 is_proto_sup = false;
0123
0124 if (vlan_proto != htons(ETH_P_8021Q)) {
0125 if (!is_proto_sup)
0126 return -EOPNOTSUPP;
0127 update |= NFP_NET_VF_CFG_MB_UPD_VLAN_PROTO;
0128 }
0129
0130
0131 vlan_tag = FIELD_PREP(NFP_NET_VF_CFG_VLAN_VID, vlan) |
0132 FIELD_PREP(NFP_NET_VF_CFG_VLAN_QOS, qos);
0133
0134
0135
0136
0137
0138 if (vlan_tag && is_proto_sup)
0139 vlan_tag |= FIELD_PREP(NFP_NET_VF_CFG_VLAN_PROT, ntohs(vlan_proto));
0140
0141 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
0142 writel(vlan_tag, app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_VLAN);
0143
0144 return nfp_net_sriov_update(app, vf, update, "vlan");
0145 }
0146
0147 int nfp_app_set_vf_rate(struct net_device *netdev, int vf,
0148 int min_tx_rate, int max_tx_rate)
0149 {
0150 struct nfp_app *app = nfp_app_from_netdev(netdev);
0151 u32 vf_offset, ratevalue;
0152 int err;
0153
0154 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate", true);
0155 if (err)
0156 return err;
0157
0158 if (max_tx_rate >= NFP_NET_VF_RATE_MAX ||
0159 min_tx_rate >= NFP_NET_VF_RATE_MAX) {
0160 nfp_warn(app->cpp, "tx-rate exceeds %d.\n",
0161 NFP_NET_VF_RATE_MAX);
0162 return -EINVAL;
0163 }
0164
0165 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
0166 ratevalue = FIELD_PREP(NFP_NET_VF_CFG_MAX_RATE,
0167 max_tx_rate ? max_tx_rate :
0168 NFP_NET_VF_RATE_MAX) |
0169 FIELD_PREP(NFP_NET_VF_CFG_MIN_RATE, min_tx_rate);
0170
0171 writel(ratevalue,
0172 app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_RATE);
0173
0174 return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_RATE,
0175 "rate");
0176 }
0177
0178 int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
0179 {
0180 struct nfp_app *app = nfp_app_from_netdev(netdev);
0181 unsigned int vf_offset;
0182 u8 vf_ctrl;
0183 int err;
0184
0185 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_SPOOF,
0186 "spoofchk", true);
0187 if (err)
0188 return err;
0189
0190
0191 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ +
0192 NFP_NET_VF_CFG_CTRL;
0193 vf_ctrl = readb(app->pf->vfcfg_tbl2 + vf_offset);
0194 vf_ctrl &= ~NFP_NET_VF_CFG_CTRL_SPOOF;
0195 vf_ctrl |= FIELD_PREP(NFP_NET_VF_CFG_CTRL_SPOOF, enable);
0196 writeb(vf_ctrl, app->pf->vfcfg_tbl2 + vf_offset);
0197
0198 return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_SPOOF,
0199 "spoofchk");
0200 }
0201
0202 int nfp_app_set_vf_trust(struct net_device *netdev, int vf, bool enable)
0203 {
0204 struct nfp_app *app = nfp_app_from_netdev(netdev);
0205 unsigned int vf_offset;
0206 u8 vf_ctrl;
0207 int err;
0208
0209 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_TRUST,
0210 "trust", true);
0211 if (err)
0212 return err;
0213
0214
0215 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ +
0216 NFP_NET_VF_CFG_CTRL;
0217 vf_ctrl = readb(app->pf->vfcfg_tbl2 + vf_offset);
0218 vf_ctrl &= ~NFP_NET_VF_CFG_CTRL_TRUST;
0219 vf_ctrl |= FIELD_PREP(NFP_NET_VF_CFG_CTRL_TRUST, enable);
0220 writeb(vf_ctrl, app->pf->vfcfg_tbl2 + vf_offset);
0221
0222 return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_TRUST,
0223 "trust");
0224 }
0225
0226 int nfp_app_set_vf_link_state(struct net_device *netdev, int vf,
0227 int link_state)
0228 {
0229 struct nfp_app *app = nfp_app_from_netdev(netdev);
0230 unsigned int vf_offset;
0231 u8 vf_ctrl;
0232 int err;
0233
0234 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_LINK_STATE,
0235 "link_state", true);
0236 if (err)
0237 return err;
0238
0239 switch (link_state) {
0240 case IFLA_VF_LINK_STATE_AUTO:
0241 case IFLA_VF_LINK_STATE_ENABLE:
0242 case IFLA_VF_LINK_STATE_DISABLE:
0243 break;
0244 default:
0245 return -EINVAL;
0246 }
0247
0248
0249 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ +
0250 NFP_NET_VF_CFG_CTRL;
0251 vf_ctrl = readb(app->pf->vfcfg_tbl2 + vf_offset);
0252 vf_ctrl &= ~NFP_NET_VF_CFG_CTRL_LINK_STATE;
0253 vf_ctrl |= FIELD_PREP(NFP_NET_VF_CFG_CTRL_LINK_STATE, link_state);
0254 writeb(vf_ctrl, app->pf->vfcfg_tbl2 + vf_offset);
0255
0256 return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_LINK_STATE,
0257 "link state");
0258 }
0259
0260 int nfp_app_get_vf_config(struct net_device *netdev, int vf,
0261 struct ifla_vf_info *ivi)
0262 {
0263 struct nfp_app *app = nfp_app_from_netdev(netdev);
0264 u32 vf_offset, mac_hi, rate;
0265 u32 vlan_tag;
0266 u16 mac_lo;
0267 u8 flags;
0268 int err;
0269
0270 err = nfp_net_sriov_check(app, vf, 0, "", true);
0271 if (err)
0272 return err;
0273
0274 vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
0275
0276 mac_hi = readl(app->pf->vfcfg_tbl2 + vf_offset);
0277 mac_lo = readw(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_MAC_LO);
0278
0279 flags = readb(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_CTRL);
0280 vlan_tag = readl(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_VLAN);
0281
0282 memset(ivi, 0, sizeof(*ivi));
0283 ivi->vf = vf;
0284
0285 put_unaligned_be32(mac_hi, &ivi->mac[0]);
0286 put_unaligned_be16(mac_lo, &ivi->mac[4]);
0287
0288 ivi->vlan = FIELD_GET(NFP_NET_VF_CFG_VLAN_VID, vlan_tag);
0289 ivi->qos = FIELD_GET(NFP_NET_VF_CFG_VLAN_QOS, vlan_tag);
0290 if (!nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_VLAN_PROTO, "vlan_proto", false))
0291 ivi->vlan_proto = htons(FIELD_GET(NFP_NET_VF_CFG_VLAN_PROT, vlan_tag));
0292 ivi->spoofchk = FIELD_GET(NFP_NET_VF_CFG_CTRL_SPOOF, flags);
0293 ivi->trusted = FIELD_GET(NFP_NET_VF_CFG_CTRL_TRUST, flags);
0294 ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE, flags);
0295
0296 err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate", false);
0297 if (!err) {
0298 rate = readl(app->pf->vfcfg_tbl2 + vf_offset +
0299 NFP_NET_VF_CFG_RATE);
0300
0301 ivi->max_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MAX_RATE, rate);
0302 ivi->min_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MIN_RATE, rate);
0303
0304 if (ivi->max_tx_rate == NFP_NET_VF_RATE_MAX)
0305 ivi->max_tx_rate = 0;
0306 if (ivi->min_tx_rate == NFP_NET_VF_RATE_MAX)
0307 ivi->min_tx_rate = 0;
0308 }
0309
0310 return 0;
0311 }