1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017-2019 Netronome Systems, Inc. */
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>
10 #include "nfpcore/nfp_cpp.h"
13 #include "nfp_net_ctrl.h"
15 #include "nfp_net_sriov.h"
18 nfp_net_sriov_check(struct nfp_app
*app
, int vf
, u16 cap
, const char *msg
, bool warn
)
22 if (!app
|| !app
->pf
->vfcfg_tbl2
)
25 cap_vf
= readw(app
->pf
->vfcfg_tbl2
+ NFP_NET_VF_CFG_MB_CAP
);
26 if ((cap_vf
& cap
) != cap
) {
28 nfp_warn(app
->pf
->cpp
, "ndo_set_vf_%s not supported\n", msg
);
32 if (vf
< 0 || vf
>= app
->pf
->num_vfs
) {
34 nfp_warn(app
->pf
->cpp
, "invalid VF id %d\n", vf
);
42 nfp_net_sriov_update(struct nfp_app
*app
, int vf
, u16 update
, const char *msg
)
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
);
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
);
57 ret
= readw(app
->pf
->vfcfg_tbl2
+ NFP_NET_VF_CFG_MB_RET
);
59 nfp_warn(app
->pf
->cpp
,
60 "FW refused VF %s update with errno: %d\n", msg
, ret
);
64 int nfp_app_set_vf_mac(struct net_device
*netdev
, int vf
, u8
*mac
)
66 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
67 unsigned int vf_offset
;
70 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_MAC
, "mac", true);
74 if (is_multicast_ether_addr(mac
)) {
75 nfp_warn(app
->pf
->cpp
,
76 "invalid Ethernet address %pM for VF id %d\n",
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
);
87 err
= nfp_net_sriov_update(app
, vf
, NFP_NET_VF_CFG_MB_UPD_MAC
, "MAC");
89 nfp_info(app
->pf
->cpp
,
90 "MAC %pM set on VF %d, reload the VF driver to make this change effective.\n",
96 int nfp_app_set_vf_vlan(struct net_device
*netdev
, int vf
, u16 vlan
, u8 qos
,
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
;
106 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_VLAN
, "vlan", true);
110 if (!eth_type_vlan(vlan_proto
))
113 if (vlan
> 4095 || qos
> 7) {
114 nfp_warn(app
->pf
->cpp
,
115 "invalid vlan id or qos for VF id %d\n", vf
);
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);
122 is_proto_sup
= false;
124 if (vlan_proto
!= htons(ETH_P_8021Q
)) {
127 update
|= NFP_NET_VF_CFG_MB_UPD_VLAN_PROTO
;
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
);
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.
138 if (vlan_tag
&& is_proto_sup
)
139 vlan_tag
|= FIELD_PREP(NFP_NET_VF_CFG_VLAN_PROT
, ntohs(vlan_proto
));
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
);
144 return nfp_net_sriov_update(app
, vf
, update
, "vlan");
147 int nfp_app_set_vf_rate(struct net_device
*netdev
, int vf
,
148 int min_tx_rate
, int max_tx_rate
)
150 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
151 u32 vf_offset
, ratevalue
;
154 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_RATE
, "rate", true);
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
);
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
);
172 app
->pf
->vfcfg_tbl2
+ vf_offset
+ NFP_NET_VF_CFG_RATE
);
174 return nfp_net_sriov_update(app
, vf
, NFP_NET_VF_CFG_MB_UPD_RATE
,
178 int nfp_app_set_vf_spoofchk(struct net_device
*netdev
, int vf
, bool enable
)
180 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
181 unsigned int vf_offset
;
185 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_SPOOF
,
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
+
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
);
198 return nfp_net_sriov_update(app
, vf
, NFP_NET_VF_CFG_MB_UPD_SPOOF
,
202 int nfp_app_set_vf_trust(struct net_device
*netdev
, int vf
, bool enable
)
204 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
205 unsigned int vf_offset
;
209 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_TRUST
,
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
+
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
);
222 return nfp_net_sriov_update(app
, vf
, NFP_NET_VF_CFG_MB_UPD_TRUST
,
226 int nfp_app_set_vf_link_state(struct net_device
*netdev
, int vf
,
229 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
230 unsigned int vf_offset
;
234 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_LINK_STATE
,
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
:
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
+
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
);
256 return nfp_net_sriov_update(app
, vf
, NFP_NET_VF_CFG_MB_UPD_LINK_STATE
,
260 int nfp_app_get_vf_config(struct net_device
*netdev
, int vf
,
261 struct ifla_vf_info
*ivi
)
263 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
264 u32 vf_offset
, mac_hi
, rate
;
270 err
= nfp_net_sriov_check(app
, vf
, 0, "", true);
274 vf_offset
= NFP_NET_VF_CFG_MB_SZ
+ vf
* NFP_NET_VF_CFG_SZ
;
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
);
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
);
282 memset(ivi
, 0, sizeof(*ivi
));
285 put_unaligned_be32(mac_hi
, &ivi
->mac
[0]);
286 put_unaligned_be16(mac_lo
, &ivi
->mac
[4]);
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
);
296 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_RATE
, "rate", false);
298 rate
= readl(app
->pf
->vfcfg_tbl2
+ vf_offset
+
299 NFP_NET_VF_CFG_RATE
);
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
);
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;