2 * Copyright (C) 2017 Netronome Systems, Inc.
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
9 * The BSD 2-Clause License:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 #include <linux/bitfield.h>
35 #include <linux/errno.h>
36 #include <linux/etherdevice.h>
37 #include <linux/if_link.h>
38 #include <linux/if_ether.h>
40 #include "nfpcore/nfp_cpp.h"
43 #include "nfp_net_ctrl.h"
45 #include "nfp_net_sriov.h"
48 nfp_net_sriov_check(struct nfp_app
*app
, int vf
, u16 cap
, const char *msg
)
52 if (!app
|| !app
->pf
->vfcfg_tbl2
)
55 cap_vf
= readw(app
->pf
->vfcfg_tbl2
+ NFP_NET_VF_CFG_MB_CAP
);
56 if ((cap_vf
& cap
) != cap
) {
57 nfp_warn(app
->pf
->cpp
, "ndo_set_vf_%s not supported\n", msg
);
61 if (vf
< 0 || vf
>= app
->pf
->num_vfs
) {
62 nfp_warn(app
->pf
->cpp
, "invalid VF id %d\n", vf
);
70 nfp_net_sriov_update(struct nfp_app
*app
, int vf
, u16 update
, const char *msg
)
75 /* Write update info to mailbox in VF config symbol */
76 writeb(vf
, app
->pf
->vfcfg_tbl2
+ NFP_NET_VF_CFG_MB_VF_NUM
);
77 writew(update
, app
->pf
->vfcfg_tbl2
+ NFP_NET_VF_CFG_MB_UPD
);
79 nn
= list_first_entry(&app
->pf
->vnics
, struct nfp_net
, vnic_list
);
80 /* Signal VF reconfiguration */
81 ret
= nfp_net_reconfig(nn
, NFP_NET_CFG_UPDATE_VF
);
85 ret
= readw(app
->pf
->vfcfg_tbl2
+ NFP_NET_VF_CFG_MB_RET
);
87 nfp_warn(app
->pf
->cpp
,
88 "FW refused VF %s update with errno: %d\n", msg
, ret
);
92 int nfp_app_set_vf_mac(struct net_device
*netdev
, int vf
, u8
*mac
)
94 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
95 unsigned int vf_offset
;
98 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_MAC
, "mac");
102 if (is_multicast_ether_addr(mac
)) {
103 nfp_warn(app
->pf
->cpp
,
104 "invalid Ethernet address %pM for VF id %d\n",
109 /* Write MAC to VF entry in VF config symbol */
110 vf_offset
= NFP_NET_VF_CFG_MB_SZ
+ vf
* NFP_NET_VF_CFG_SZ
;
111 writel(get_unaligned_be32(mac
), app
->pf
->vfcfg_tbl2
+ vf_offset
);
112 writew(get_unaligned_be16(mac
+ 4),
113 app
->pf
->vfcfg_tbl2
+ vf_offset
+ NFP_NET_VF_CFG_MAC_LO
);
115 err
= nfp_net_sriov_update(app
, vf
, NFP_NET_VF_CFG_MB_UPD_MAC
, "MAC");
117 nfp_info(app
->pf
->cpp
,
118 "MAC %pM set on VF %d, reload the VF driver to make this change effective.\n",
124 int nfp_app_set_vf_vlan(struct net_device
*netdev
, int vf
, u16 vlan
, u8 qos
,
127 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
128 unsigned int vf_offset
;
132 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_VLAN
, "vlan");
136 if (vlan_proto
!= htons(ETH_P_8021Q
))
139 if (vlan
> 4095 || qos
> 7) {
140 nfp_warn(app
->pf
->cpp
,
141 "invalid vlan id or qos for VF id %d\n", vf
);
145 /* Write VLAN tag to VF entry in VF config symbol */
146 vlan_tci
= FIELD_PREP(NFP_NET_VF_CFG_VLAN_VID
, vlan
) |
147 FIELD_PREP(NFP_NET_VF_CFG_VLAN_QOS
, qos
);
148 vf_offset
= NFP_NET_VF_CFG_MB_SZ
+ vf
* NFP_NET_VF_CFG_SZ
;
149 writew(vlan_tci
, app
->pf
->vfcfg_tbl2
+ vf_offset
+ NFP_NET_VF_CFG_VLAN
);
151 return nfp_net_sriov_update(app
, vf
, NFP_NET_VF_CFG_MB_UPD_VLAN
,
155 int nfp_app_set_vf_spoofchk(struct net_device
*netdev
, int vf
, bool enable
)
157 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
158 unsigned int vf_offset
;
162 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_SPOOF
,
167 /* Write spoof check control bit to VF entry in VF config symbol */
168 vf_offset
= NFP_NET_VF_CFG_MB_SZ
+ vf
* NFP_NET_VF_CFG_SZ
+
170 vf_ctrl
= readb(app
->pf
->vfcfg_tbl2
+ vf_offset
);
171 vf_ctrl
&= ~NFP_NET_VF_CFG_CTRL_SPOOF
;
172 vf_ctrl
|= FIELD_PREP(NFP_NET_VF_CFG_CTRL_SPOOF
, enable
);
173 writeb(vf_ctrl
, app
->pf
->vfcfg_tbl2
+ vf_offset
);
175 return nfp_net_sriov_update(app
, vf
, NFP_NET_VF_CFG_MB_UPD_SPOOF
,
179 int nfp_app_set_vf_link_state(struct net_device
*netdev
, int vf
,
182 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
183 unsigned int vf_offset
;
187 err
= nfp_net_sriov_check(app
, vf
, NFP_NET_VF_CFG_MB_CAP_LINK_STATE
,
192 switch (link_state
) {
193 case IFLA_VF_LINK_STATE_AUTO
:
194 case IFLA_VF_LINK_STATE_ENABLE
:
195 case IFLA_VF_LINK_STATE_DISABLE
:
201 /* Write link state to VF entry in VF config symbol */
202 vf_offset
= NFP_NET_VF_CFG_MB_SZ
+ vf
* NFP_NET_VF_CFG_SZ
+
204 vf_ctrl
= readb(app
->pf
->vfcfg_tbl2
+ vf_offset
);
205 vf_ctrl
&= ~NFP_NET_VF_CFG_CTRL_LINK_STATE
;
206 vf_ctrl
|= FIELD_PREP(NFP_NET_VF_CFG_CTRL_LINK_STATE
, link_state
);
207 writeb(vf_ctrl
, app
->pf
->vfcfg_tbl2
+ vf_offset
);
209 return nfp_net_sriov_update(app
, vf
, NFP_NET_VF_CFG_MB_UPD_LINK_STATE
,
213 int nfp_app_get_vf_config(struct net_device
*netdev
, int vf
,
214 struct ifla_vf_info
*ivi
)
216 struct nfp_app
*app
= nfp_app_from_netdev(netdev
);
217 unsigned int vf_offset
;
224 err
= nfp_net_sriov_check(app
, vf
, 0, "");
228 vf_offset
= NFP_NET_VF_CFG_MB_SZ
+ vf
* NFP_NET_VF_CFG_SZ
;
230 mac_hi
= readl(app
->pf
->vfcfg_tbl2
+ vf_offset
);
231 mac_lo
= readw(app
->pf
->vfcfg_tbl2
+ vf_offset
+ NFP_NET_VF_CFG_MAC_LO
);
233 flags
= readb(app
->pf
->vfcfg_tbl2
+ vf_offset
+ NFP_NET_VF_CFG_CTRL
);
234 vlan_tci
= readw(app
->pf
->vfcfg_tbl2
+ vf_offset
+ NFP_NET_VF_CFG_VLAN
);
236 memset(ivi
, 0, sizeof(*ivi
));
239 put_unaligned_be32(mac_hi
, &ivi
->mac
[0]);
240 put_unaligned_be16(mac_lo
, &ivi
->mac
[4]);
242 ivi
->vlan
= FIELD_GET(NFP_NET_VF_CFG_VLAN_VID
, vlan_tci
);
243 ivi
->qos
= FIELD_GET(NFP_NET_VF_CFG_VLAN_QOS
, vlan_tci
);
245 ivi
->spoofchk
= FIELD_GET(NFP_NET_VF_CFG_CTRL_SPOOF
, flags
);
246 ivi
->linkstate
= FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE
, flags
);