Skip to content

Commit

Permalink
Merge branch 'nfp-get_phys_port_name-for-representors-and-SR-IOV-reor…
Browse files Browse the repository at this point in the history
…der'

Jakub Kicinski says:

====================
nfp: get_phys_port_name for representors and SR-IOV reorder

This series starts by making the error message if FW cannot be located
easier to understand.  Then I move some functions from PCI probe files
into library code (nfpcore) where they belong, and remove one function
which is never used.

Next few patches equip representors with nfp_port structure and make
their NDOs fully shared (not defined in apps), thanks to which we can
easily determine which netdevs are NFP's by comparing the NDO pointers.

10th patch makes use of the shared NDOs and nfp_ports to deliver
netdev-type independent .ndo_get_phys_port_name() implementation.

Patches 11 and 12 reorder the nfp_app SR-IOV callbacks with enabling
SR-IOV VFs.  Unfortunately due to how PCI subsystem works we can't
guarantee being able to disable SR-IOV at exit or that it will be
disabled when we first probe...  We must therefore make sure FW is
able to deal with being loaded while SR-IOV is already on.

Patch 13 fixes potential deadlock when enabling SR-IOV happens at
the same time as port state refresh.  Note that this can't happen
at this point, since Flower doesn't refresh ports... but lockdep
doesn't know about such details and we will have to deal with this
sooner or later anyway.

Last but not least a new Kconfig is added to make sure those who
don't care about flower offloads have a way of not including the
code in their kernels.  Thanks to nfp_app separation this costs us
a single ifdef and excluding flower files from the build.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 27, 2017
2 parents ed9208b + 57ae676 commit 2ee87db
Show file tree
Hide file tree
Showing 19 changed files with 388 additions and 226 deletions.
10 changes: 10 additions & 0 deletions drivers/net/ethernet/netronome/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ config NFP
cards working as a advanced Ethernet NIC. It works with both
SR-IOV physical and virtual functions.

config NFP_APP_FLOWER
bool "NFP4000/NFP6000 TC Flower offload support"
depends on NFP
depends on NET_SWITCHDEV
---help---
Enable driver support for TC Flower offload on NFP4000 and NFP6000.
Say Y, if you are planning to make use of TC Flower offload
either directly, with Open vSwitch, or any other way. Note that
TC Flower offload requires specific FW to work.

config NFP_DEBUG
bool "Debug support for Netronome(R) NFP4000/NFP6000 NIC drivers"
depends on NFP
Expand Down
8 changes: 6 additions & 2 deletions drivers/net/ethernet/netronome/nfp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@ nfp-objs := \
nfp_port.o \
bpf/main.o \
bpf/offload.o \
flower/cmsg.o \
flower/main.o \
nic/main.o

ifeq ($(CONFIG_NFP_APP_FLOWER),y)
nfp-objs += \
flower/cmsg.o \
flower/main.o
endif

ifeq ($(CONFIG_BPF_SYSCALL),y)
nfp-objs += \
bpf/verifier.o \
Expand Down
5 changes: 2 additions & 3 deletions drivers/net/ethernet/netronome/nfp/flower/cmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@ nfp_flower_cmsg_alloc(struct nfp_app *app, unsigned int size,
return skb;
}

int nfp_flower_cmsg_portmod(struct net_device *netdev, bool carrier_ok)
int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok)
{
struct nfp_repr *repr = netdev_priv(netdev);
struct nfp_flower_cmsg_portmod *msg;
struct sk_buff *skb;

Expand All @@ -94,7 +93,7 @@ int nfp_flower_cmsg_portmod(struct net_device *netdev, bool carrier_ok)
msg->portnum = cpu_to_be32(repr->dst->u.port_info.port_id);
msg->reserved = 0;
msg->info = carrier_ok;
msg->mtu = cpu_to_be16(netdev->mtu);
msg->mtu = cpu_to_be16(repr->netdev->mtu);

nfp_ctrl_tx(repr->app->ctrl, skb);

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/netronome/nfp/flower/cmsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ nfp_flower_cmsg_pcie_port(u8 nfp_pcie, enum nfp_flower_cmsg_port_vnic_type type,
NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT);
}

int nfp_flower_cmsg_portmod(struct net_device *netdev, bool carrier_ok);
int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok);
void nfp_flower_cmsg_rx(struct nfp_app *app, struct sk_buff *skb);

#endif
89 changes: 42 additions & 47 deletions drivers/net/ethernet/netronome/nfp/flower/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,51 +104,30 @@ nfp_flower_repr_get(struct nfp_app *app, u32 port_id)
return reprs->reprs[port];
}

static void
nfp_flower_repr_netdev_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats)
{
struct nfp_repr *repr = netdev_priv(netdev);
enum nfp_repr_type type;
u32 port_id;
u8 port = 0;

port_id = repr->dst->u.port_info.port_id;
type = nfp_flower_repr_get_type_and_port(repr->app, port_id, &port);
nfp_repr_get_stats64(repr->app, type, port, stats);
}

static int nfp_flower_repr_netdev_open(struct net_device *netdev)
static int
nfp_flower_repr_netdev_open(struct nfp_app *app, struct nfp_repr *repr)
{
int err;

err = nfp_flower_cmsg_portmod(netdev, true);
err = nfp_flower_cmsg_portmod(repr, true);
if (err)
return err;

netif_carrier_on(netdev);
netif_tx_wake_all_queues(netdev);
netif_carrier_on(repr->netdev);
netif_tx_wake_all_queues(repr->netdev);

return 0;
}

static int nfp_flower_repr_netdev_stop(struct net_device *netdev)
static int
nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr)
{
netif_carrier_off(netdev);
netif_tx_disable(netdev);
netif_carrier_off(repr->netdev);
netif_tx_disable(repr->netdev);

return nfp_flower_cmsg_portmod(netdev, false);
return nfp_flower_cmsg_portmod(repr, false);
}

static const struct net_device_ops nfp_flower_repr_netdev_ops = {
.ndo_open = nfp_flower_repr_netdev_open,
.ndo_stop = nfp_flower_repr_netdev_stop,
.ndo_start_xmit = nfp_repr_xmit,
.ndo_get_stats64 = nfp_flower_repr_netdev_get_stats64,
.ndo_has_offload_stats = nfp_repr_has_offload_stats,
.ndo_get_offload_stats = nfp_repr_get_offload_stats,
};

static void nfp_flower_sriov_disable(struct nfp_app *app)
{
nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
Expand All @@ -162,14 +141,19 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
u8 nfp_pcie = nfp_cppcore_pcie_unit(app->pf->cpp);
struct nfp_flower_priv *priv = app->priv;
struct nfp_reprs *reprs, *old_reprs;
enum nfp_port_type port_type;
const u8 queue = 0;
int i, err;

port_type = repr_type == NFP_REPR_TYPE_PF ? NFP_PORT_PF_PORT :
NFP_PORT_VF_PORT;

reprs = nfp_reprs_alloc(cnt);
if (!reprs)
return -ENOMEM;

for (i = 0; i < cnt; i++) {
struct nfp_port *port;
u32 port_id;

reprs->reprs[i] = nfp_repr_alloc(app);
Expand All @@ -178,15 +162,24 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
goto err_reprs_clean;
}

port = nfp_port_alloc(app, port_type, reprs->reprs[i]);
if (repr_type == NFP_REPR_TYPE_PF) {
port->pf_id = i;
} else {
port->pf_id = 0; /* For now we only support 1 PF */
port->vf_id = i;
}

eth_hw_addr_random(reprs->reprs[i]);

port_id = nfp_flower_cmsg_pcie_port(nfp_pcie, vnic_type,
i, queue);
err = nfp_repr_init(app, reprs->reprs[i],
&nfp_flower_repr_netdev_ops,
port_id, NULL, priv->nn->dp.netdev);
if (err)
port_id, port, priv->nn->dp.netdev);
if (err) {
nfp_port_free(port);
goto err_reprs_clean;
}

nfp_info(app->cpp, "%s%d Representor(%s) created\n",
repr_type == NFP_REPR_TYPE_PF ? "PF" : "VF", i,
Expand Down Expand Up @@ -260,7 +253,6 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)

cmsg_port_id = nfp_flower_cmsg_phys_port(phys_port);
err = nfp_repr_init(app, reprs->reprs[phys_port],
&nfp_flower_repr_netdev_ops,
cmsg_port_id, port, priv->nn->dp.netdev);
if (err) {
nfp_port_free(port);
Expand Down Expand Up @@ -296,26 +288,16 @@ static int nfp_flower_start(struct nfp_app *app)
NFP_REPR_TYPE_PF, 1);
}

static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
{
kfree(app->priv);
app->priv = NULL;
}

static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn,
unsigned int id)
{
struct nfp_flower_priv *priv;
struct nfp_flower_priv *priv = app->priv;

if (id > 0) {
nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n");
goto err_invalid_port;
}

priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
app->priv = priv;
priv->nn = nn;

eth_hw_addr_random(nn->dp.netdev);
Expand Down Expand Up @@ -347,9 +329,19 @@ static int nfp_flower_init(struct nfp_app *app)
return -EINVAL;
}

app->priv = kzalloc(sizeof(struct nfp_flower_priv), GFP_KERNEL);
if (!app->priv)
return -ENOMEM;

return 0;
}

static void nfp_flower_clean(struct nfp_app *app)
{
kfree(app->priv);
app->priv = NULL;
}

const struct nfp_app_type app_flower = {
.id = NFP_APP_FLOWER_NIC,
.name = "flower",
Expand All @@ -358,9 +350,12 @@ const struct nfp_app_type app_flower = {
.extra_cap = nfp_flower_extra_cap,

.init = nfp_flower_init,
.clean = nfp_flower_clean,

.vnic_init = nfp_flower_vnic_init,
.vnic_clean = nfp_flower_vnic_clean,

.repr_open = nfp_flower_repr_netdev_open,
.repr_stop = nfp_flower_repr_netdev_stop,

.start = nfp_flower_start,
.stop = nfp_flower_stop,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/netronome/nfp/nfp_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@
static const struct nfp_app_type *apps[] = {
&app_nic,
&app_bpf,
#ifdef CONFIG_NFP_APP_FLOWER
&app_flower,
#endif
};

const char *nfp_app_mip_name(struct nfp_app *app)
Expand Down
30 changes: 29 additions & 1 deletion drivers/net/ethernet/netronome/nfp/nfp_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct sk_buff;
struct nfp_app;
struct nfp_cpp;
struct nfp_pf;
struct nfp_repr;
struct nfp_net;

enum nfp_app_id {
Expand All @@ -66,10 +67,13 @@ extern const struct nfp_app_type app_flower;
* @ctrl_has_meta: control messages have prepend of type:5/port:CTRL
*
* Callbacks
* @init: perform basic app checks
* @init: perform basic app checks and init
* @clean: clean app state
* @extra_cap: extra capabilities string
* @vnic_init: init vNICs (assign port types, etc.)
* @vnic_clean: clean up app's vNIC state
* @repr_open: representor netdev open callback
* @repr_stop: representor netdev stop callback
* @start: start application logic
* @stop: stop application logic
* @ctrl_msg_rx: control message handler
Expand All @@ -88,13 +92,17 @@ struct nfp_app_type {
bool ctrl_has_meta;

int (*init)(struct nfp_app *app);
void (*clean)(struct nfp_app *app);

const char *(*extra_cap)(struct nfp_app *app, struct nfp_net *nn);

int (*vnic_init)(struct nfp_app *app, struct nfp_net *nn,
unsigned int id);
void (*vnic_clean)(struct nfp_app *app, struct nfp_net *nn);

int (*repr_open)(struct nfp_app *app, struct nfp_repr *repr);
int (*repr_stop)(struct nfp_app *app, struct nfp_repr *repr);

int (*start)(struct nfp_app *app);
void (*stop)(struct nfp_app *app);

Expand Down Expand Up @@ -144,6 +152,12 @@ static inline int nfp_app_init(struct nfp_app *app)
return app->type->init(app);
}

static inline void nfp_app_clean(struct nfp_app *app)
{
if (app->type->clean)
app->type->clean(app);
}

static inline int nfp_app_vnic_init(struct nfp_app *app, struct nfp_net *nn,
unsigned int id)
{
Expand All @@ -156,6 +170,20 @@ static inline void nfp_app_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
app->type->vnic_clean(app, nn);
}

static inline int nfp_app_repr_open(struct nfp_app *app, struct nfp_repr *repr)
{
if (!app->type->repr_open)
return -EINVAL;
return app->type->repr_open(app, repr);
}

static inline int nfp_app_repr_stop(struct nfp_app *app, struct nfp_repr *repr)
{
if (!app->type->repr_stop)
return -EINVAL;
return app->type->repr_stop(app, repr);
}

static inline int nfp_app_start(struct nfp_app *app, struct nfp_net *ctrl)
{
app->ctrl = ctrl;
Expand Down
Loading

0 comments on commit 2ee87db

Please sign in to comment.