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  
17  static int
nfp_net_sriov_check(struct nfp_app * app,int vf,u16 cap,const char * msg,bool warn)18  nfp_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  
41  static int
nfp_net_sriov_update(struct nfp_app * app,int vf,u16 update,const char * msg)42  nfp_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  
nfp_app_set_vf_mac(struct net_device * netdev,int vf,u8 * mac)64  int 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  
nfp_app_set_vf_vlan(struct net_device * netdev,int vf,u16 vlan,u8 qos,__be16 vlan_proto)96  int 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  
nfp_app_set_vf_rate(struct net_device * netdev,int vf,int min_tx_rate,int max_tx_rate)147  int 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  
nfp_app_set_vf_spoofchk(struct net_device * netdev,int vf,bool enable)178  int 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  
nfp_app_set_vf_trust(struct net_device * netdev,int vf,bool enable)202  int 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  
nfp_app_set_vf_link_state(struct net_device * netdev,int vf,int link_state)226  int 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  
nfp_app_get_vf_config(struct net_device * netdev,int vf,struct ifla_vf_info * ivi)260  int 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  }
312