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/etherdevice.h>
35 #include <linux/pci.h>
36 #include <linux/skbuff.h>
37 #include <net/devlink.h>
38 #include <net/dst_metadata.h>
40 #include "../nfpcore/nfp_cpp.h"
41 #include "../nfpcore/nfp_nsp.h"
42 #include "../nfp_app.h"
43 #include "../nfp_main.h"
44 #include "../nfp_net.h"
45 #include "../nfp_net_repr.h"
46 #include "../nfp_port.h"
50 * struct nfp_flower_priv - Flower APP per-vNIC priv data
51 * @nn: Pointer to vNIC
53 struct nfp_flower_priv
{
57 static const char *nfp_flower_extra_cap(struct nfp_app
*app
, struct nfp_net
*nn
)
62 static enum devlink_eswitch_mode
eswitch_mode_get(struct nfp_app
*app
)
64 return DEVLINK_ESWITCH_MODE_SWITCHDEV
;
67 static enum nfp_repr_type
68 nfp_flower_repr_get_type_and_port(struct nfp_app
*app
, u32 port_id
, u8
*port
)
70 switch (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE
, port_id
)) {
71 case NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT
:
72 *port
= FIELD_GET(NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM
,
74 return NFP_REPR_TYPE_PHYS_PORT
;
76 case NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT
:
77 *port
= FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC
, port_id
);
78 if (FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC_TYPE
, port_id
) ==
79 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF
)
80 return NFP_REPR_TYPE_PF
;
82 return NFP_REPR_TYPE_VF
;
85 return NFP_FLOWER_CMSG_PORT_TYPE_UNSPEC
;
88 static struct net_device
*
89 nfp_flower_repr_get(struct nfp_app
*app
, u32 port_id
)
91 enum nfp_repr_type repr_type
;
92 struct nfp_reprs
*reprs
;
95 repr_type
= nfp_flower_repr_get_type_and_port(app
, port_id
, &port
);
97 reprs
= rcu_dereference(app
->reprs
[repr_type
]);
101 if (port
>= reprs
->num_reprs
)
104 return reprs
->reprs
[port
];
108 nfp_flower_repr_netdev_get_stats64(struct net_device
*netdev
,
109 struct rtnl_link_stats64
*stats
)
111 struct nfp_repr
*repr
= netdev_priv(netdev
);
112 enum nfp_repr_type type
;
116 port_id
= repr
->dst
->u
.port_info
.port_id
;
117 type
= nfp_flower_repr_get_type_and_port(repr
->app
, port_id
, &port
);
118 nfp_repr_get_stats64(repr
->app
, type
, port
, stats
);
121 static int nfp_flower_repr_netdev_open(struct net_device
*netdev
)
125 err
= nfp_flower_cmsg_portmod(netdev
, true);
129 netif_carrier_on(netdev
);
130 netif_tx_wake_all_queues(netdev
);
135 static int nfp_flower_repr_netdev_stop(struct net_device
*netdev
)
137 netif_carrier_off(netdev
);
138 netif_tx_disable(netdev
);
140 return nfp_flower_cmsg_portmod(netdev
, false);
143 static const struct net_device_ops nfp_flower_repr_netdev_ops
= {
144 .ndo_open
= nfp_flower_repr_netdev_open
,
145 .ndo_stop
= nfp_flower_repr_netdev_stop
,
146 .ndo_start_xmit
= nfp_repr_xmit
,
147 .ndo_get_stats64
= nfp_flower_repr_netdev_get_stats64
,
148 .ndo_has_offload_stats
= nfp_repr_has_offload_stats
,
149 .ndo_get_offload_stats
= nfp_repr_get_offload_stats
,
152 static void nfp_flower_sriov_disable(struct nfp_app
*app
)
154 nfp_reprs_clean_and_free_by_type(app
, NFP_REPR_TYPE_VF
);
158 nfp_flower_spawn_vnic_reprs(struct nfp_app
*app
,
159 enum nfp_flower_cmsg_port_vnic_type vnic_type
,
160 enum nfp_repr_type repr_type
, unsigned int cnt
)
162 u8 nfp_pcie
= nfp_cppcore_pcie_unit(app
->pf
->cpp
);
163 struct nfp_flower_priv
*priv
= app
->priv
;
164 struct nfp_reprs
*reprs
, *old_reprs
;
165 enum nfp_port_type port_type
;
169 port_type
= repr_type
== NFP_REPR_TYPE_PF
? NFP_PORT_PF_PORT
:
172 reprs
= nfp_reprs_alloc(cnt
);
176 for (i
= 0; i
< cnt
; i
++) {
177 struct nfp_port
*port
;
180 reprs
->reprs
[i
] = nfp_repr_alloc(app
);
181 if (!reprs
->reprs
[i
]) {
183 goto err_reprs_clean
;
186 port
= nfp_port_alloc(app
, port_type
, reprs
->reprs
[i
]);
187 if (repr_type
== NFP_REPR_TYPE_PF
) {
190 port
->pf_id
= 0; /* For now we only support 1 PF */
194 eth_hw_addr_random(reprs
->reprs
[i
]);
196 port_id
= nfp_flower_cmsg_pcie_port(nfp_pcie
, vnic_type
,
198 err
= nfp_repr_init(app
, reprs
->reprs
[i
],
199 &nfp_flower_repr_netdev_ops
,
200 port_id
, port
, priv
->nn
->dp
.netdev
);
203 goto err_reprs_clean
;
206 nfp_info(app
->cpp
, "%s%d Representor(%s) created\n",
207 repr_type
== NFP_REPR_TYPE_PF
? "PF" : "VF", i
,
208 reprs
->reprs
[i
]->name
);
211 old_reprs
= nfp_app_reprs_set(app
, repr_type
, reprs
);
212 if (IS_ERR(old_reprs
)) {
213 err
= PTR_ERR(old_reprs
);
214 goto err_reprs_clean
;
219 nfp_reprs_clean_and_free(reprs
);
223 static int nfp_flower_sriov_enable(struct nfp_app
*app
, int num_vfs
)
225 return nfp_flower_spawn_vnic_reprs(app
,
226 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF
,
227 NFP_REPR_TYPE_VF
, num_vfs
);
230 static void nfp_flower_stop(struct nfp_app
*app
)
232 nfp_reprs_clean_and_free_by_type(app
, NFP_REPR_TYPE_PF
);
233 nfp_reprs_clean_and_free_by_type(app
, NFP_REPR_TYPE_PHYS_PORT
);
238 nfp_flower_spawn_phy_reprs(struct nfp_app
*app
, struct nfp_flower_priv
*priv
)
240 struct nfp_eth_table
*eth_tbl
= app
->pf
->eth_tbl
;
241 struct nfp_reprs
*reprs
, *old_reprs
;
245 reprs
= nfp_reprs_alloc(eth_tbl
->max_index
+ 1);
249 for (i
= 0; i
< eth_tbl
->count
; i
++) {
250 int phys_port
= eth_tbl
->ports
[i
].index
;
251 struct nfp_port
*port
;
254 reprs
->reprs
[phys_port
] = nfp_repr_alloc(app
);
255 if (!reprs
->reprs
[phys_port
]) {
257 goto err_reprs_clean
;
260 port
= nfp_port_alloc(app
, NFP_PORT_PHYS_PORT
,
261 reprs
->reprs
[phys_port
]);
264 goto err_reprs_clean
;
266 err
= nfp_port_init_phy_port(app
->pf
, app
, port
, i
);
269 goto err_reprs_clean
;
272 SET_NETDEV_DEV(reprs
->reprs
[phys_port
], &priv
->nn
->pdev
->dev
);
273 nfp_net_get_mac_addr(app
->pf
, port
,
274 eth_tbl
->ports
[i
].eth_index
);
276 cmsg_port_id
= nfp_flower_cmsg_phys_port(phys_port
);
277 err
= nfp_repr_init(app
, reprs
->reprs
[phys_port
],
278 &nfp_flower_repr_netdev_ops
,
279 cmsg_port_id
, port
, priv
->nn
->dp
.netdev
);
282 goto err_reprs_clean
;
285 nfp_info(app
->cpp
, "Phys Port %d Representor(%s) created\n",
286 phys_port
, reprs
->reprs
[phys_port
]->name
);
289 old_reprs
= nfp_app_reprs_set(app
, NFP_REPR_TYPE_PHYS_PORT
, reprs
);
290 if (IS_ERR(old_reprs
)) {
291 err
= PTR_ERR(old_reprs
);
292 goto err_reprs_clean
;
297 nfp_reprs_clean_and_free(reprs
);
301 static int nfp_flower_start(struct nfp_app
*app
)
305 err
= nfp_flower_spawn_phy_reprs(app
, app
->priv
);
309 return nfp_flower_spawn_vnic_reprs(app
,
310 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF
,
311 NFP_REPR_TYPE_PF
, 1);
314 static int nfp_flower_vnic_init(struct nfp_app
*app
, struct nfp_net
*nn
,
317 struct nfp_flower_priv
*priv
= app
->priv
;
320 nfp_warn(app
->cpp
, "FlowerNIC doesn't support more than one data vNIC\n");
321 goto err_invalid_port
;
326 eth_hw_addr_random(nn
->dp
.netdev
);
327 netif_keep_dst(nn
->dp
.netdev
);
332 nn
->port
= nfp_port_alloc(app
, NFP_PORT_INVALID
, nn
->dp
.netdev
);
333 return PTR_ERR_OR_ZERO(nn
->port
);
336 static int nfp_flower_init(struct nfp_app
*app
)
338 const struct nfp_pf
*pf
= app
->pf
;
341 nfp_warn(app
->cpp
, "FlowerNIC requires eth table\n");
345 if (!pf
->mac_stats_bar
) {
346 nfp_warn(app
->cpp
, "FlowerNIC requires mac_stats BAR\n");
350 if (!pf
->vf_cfg_bar
) {
351 nfp_warn(app
->cpp
, "FlowerNIC requires vf_cfg BAR\n");
355 app
->priv
= kzalloc(sizeof(struct nfp_flower_priv
), GFP_KERNEL
);
362 static void nfp_flower_clean(struct nfp_app
*app
)
368 const struct nfp_app_type app_flower
= {
369 .id
= NFP_APP_FLOWER_NIC
,
371 .ctrl_has_meta
= true,
373 .extra_cap
= nfp_flower_extra_cap
,
375 .init
= nfp_flower_init
,
376 .clean
= nfp_flower_clean
,
378 .vnic_init
= nfp_flower_vnic_init
,
380 .start
= nfp_flower_start
,
381 .stop
= nfp_flower_stop
,
383 .ctrl_msg_rx
= nfp_flower_cmsg_rx
,
385 .sriov_enable
= nfp_flower_sriov_enable
,
386 .sriov_disable
= nfp_flower_sriov_disable
,
388 .eswitch_mode_get
= eswitch_mode_get
,
389 .repr_get
= nfp_flower_repr_get
,