cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}