Skip to content

Commit

Permalink
Merge branch 'nfp-ethtool-and-related-improvements'
Browse files Browse the repository at this point in the history
Simon Horman says:

====================
nfp: ethtool and related improvements

Dirk van der Merwe says:

This patch series throws a couple of loosely related items into a single
series.

Patch 1: Clang compilation fix reported by
  Matthias Kaehlcke <mka@chromium.org>

Patch 2: Driver can now do MAC reinit on load when there has been a
  media override set in the NSP.

Patch 3: Refactor the nfp_app_reprs_set API.

Patch 4: Similar to vNICs, representors must be able to deal with media
  override changes in the NSP.

Patch 5: Since representors can now handle media overrides, we can
  allocate the get/set link ndo's to them.

Patch 6 & 7: Add support for FEC mode modification.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
davem330 committed Nov 5, 2017
2 parents 1f25569 + 0d08709 commit bfe26ba
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 30 deletions.
16 changes: 4 additions & 12 deletions drivers/net/ethernet/netronome/nfp/flower/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ 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;
struct nfp_reprs *reprs;
const u8 queue = 0;
int i, err;

Expand Down Expand Up @@ -194,11 +194,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
reprs->reprs[i]->name);
}

old_reprs = nfp_app_reprs_set(app, repr_type, reprs);
if (IS_ERR(old_reprs)) {
err = PTR_ERR(old_reprs);
goto err_reprs_clean;
}
nfp_app_reprs_set(app, repr_type, reprs);

return 0;
err_reprs_clean:
Expand All @@ -222,8 +218,8 @@ static int
nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
{
struct nfp_eth_table *eth_tbl = app->pf->eth_tbl;
struct nfp_reprs *reprs, *old_reprs;
struct sk_buff *ctrl_skb;
struct nfp_reprs *reprs;
unsigned int i;
int err;

Expand Down Expand Up @@ -280,11 +276,7 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
phys_port, reprs->reprs[phys_port]->name);
}

old_reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
if (IS_ERR(old_reprs)) {
err = PTR_ERR(old_reprs);
goto err_reprs_clean;
}
nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);

/* The MAC_REPR control message should be sent after the MAC
* representors are registered using nfp_app_reprs_set(). This is
Expand Down
6 changes: 0 additions & 6 deletions drivers/net/ethernet/netronome/nfp/nfp_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,8 @@ nfp_app_reprs_set(struct nfp_app *app, enum nfp_repr_type type,

old = rcu_dereference_protected(app->reprs[type],
lockdep_is_held(&app->pf->lock));
if (reprs && old) {
old = ERR_PTR(-EBUSY);
goto exit_unlock;
}

rcu_assign_pointer(app->reprs[type], reprs);

exit_unlock:
return old;
}

Expand Down
28 changes: 27 additions & 1 deletion drivers/net/ethernet/netronome/nfp/nfp_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,32 @@ nfp_fw_load(struct pci_dev *pdev, struct nfp_pf *pf, struct nfp_nsp *nsp)
return err < 0 ? err : 1;
}

static void
nfp_nsp_init_ports(struct pci_dev *pdev, struct nfp_pf *pf,
struct nfp_nsp *nsp)
{
bool needs_reinit = false;
int i;

pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
if (!pf->eth_tbl)
return;

if (!nfp_nsp_has_mac_reinit(nsp))
return;

for (i = 0; i < pf->eth_tbl->count; i++)
needs_reinit |= pf->eth_tbl->ports[i].override_changed;
if (!needs_reinit)
return;

kfree(pf->eth_tbl);
if (nfp_nsp_mac_reinit(nsp))
dev_warn(&pdev->dev, "MAC reinit failed\n");

pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
}

static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
{
struct nfp_nsp *nsp;
Expand All @@ -366,7 +392,7 @@ static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
if (err < 0)
goto exit_close_nsp;

pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
nfp_nsp_init_ports(pdev, pf, nsp);

pf->nspi = __nfp_nsp_identify(nsp);
if (pf->nspi)
Expand Down
121 changes: 119 additions & 2 deletions drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,30 @@ nfp_app_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
nfp_get_drvinfo(app, app->pdev, "*", drvinfo);
}

static void
nfp_net_set_fec_link_mode(struct nfp_eth_table_port *eth_port,
struct ethtool_link_ksettings *c)
{
unsigned int modes;

ethtool_link_ksettings_add_link_mode(c, supported, FEC_NONE);
if (!nfp_eth_can_support_fec(eth_port)) {
ethtool_link_ksettings_add_link_mode(c, advertising, FEC_NONE);
return;
}

modes = nfp_eth_supported_fec_modes(eth_port);
if (modes & NFP_FEC_BASER) {
ethtool_link_ksettings_add_link_mode(c, supported, FEC_BASER);
ethtool_link_ksettings_add_link_mode(c, advertising, FEC_BASER);
}

if (modes & NFP_FEC_REED_SOLOMON) {
ethtool_link_ksettings_add_link_mode(c, supported, FEC_RS);
ethtool_link_ksettings_add_link_mode(c, advertising, FEC_RS);
}
}

/**
* nfp_net_get_link_ksettings - Get Link Speed settings
* @netdev: network interface device structure
Expand Down Expand Up @@ -278,9 +302,11 @@ nfp_net_get_link_ksettings(struct net_device *netdev,

port = nfp_port_from_netdev(netdev);
eth_port = nfp_port_get_eth_port(port);
if (eth_port)
if (eth_port) {
cmd->base.autoneg = eth_port->aneg != NFP_ANEG_DISABLED ?
AUTONEG_ENABLE : AUTONEG_DISABLE;
nfp_net_set_fec_link_mode(eth_port, cmd);
}

if (!netif_carrier_ok(netdev))
return 0;
Expand Down Expand Up @@ -328,7 +354,7 @@ nfp_net_set_link_ksettings(struct net_device *netdev,
return -EOPNOTSUPP;

if (netif_running(netdev)) {
netdev_warn(netdev, "Changing settings not allowed on an active interface. It may cause the port to be disabled until reboot.\n");
netdev_warn(netdev, "Changing settings not allowed on an active interface. It may cause the port to be disabled until driver reload.\n");
return -EBUSY;
}

Expand Down Expand Up @@ -686,6 +712,91 @@ static int nfp_port_get_sset_count(struct net_device *netdev, int sset)
}
}

static int nfp_port_fec_ethtool_to_nsp(u32 fec)
{
switch (fec) {
case ETHTOOL_FEC_AUTO:
return NFP_FEC_AUTO_BIT;
case ETHTOOL_FEC_OFF:
return NFP_FEC_DISABLED_BIT;
case ETHTOOL_FEC_RS:
return NFP_FEC_REED_SOLOMON_BIT;
case ETHTOOL_FEC_BASER:
return NFP_FEC_BASER_BIT;
default:
/* NSP only supports a single mode at a time */
return -EOPNOTSUPP;
}
}

static u32 nfp_port_fec_nsp_to_ethtool(u32 fec)
{
u32 result = 0;

if (fec & NFP_FEC_AUTO)
result |= ETHTOOL_FEC_AUTO;
if (fec & NFP_FEC_BASER)
result |= ETHTOOL_FEC_BASER;
if (fec & NFP_FEC_REED_SOLOMON)
result |= ETHTOOL_FEC_RS;
if (fec & NFP_FEC_DISABLED)
result |= ETHTOOL_FEC_OFF;

return result ?: ETHTOOL_FEC_NONE;
}

static int
nfp_port_get_fecparam(struct net_device *netdev,
struct ethtool_fecparam *param)
{
struct nfp_eth_table_port *eth_port;
struct nfp_port *port;

param->active_fec = ETHTOOL_FEC_NONE_BIT;
param->fec = ETHTOOL_FEC_NONE_BIT;

port = nfp_port_from_netdev(netdev);
eth_port = nfp_port_get_eth_port(port);
if (!eth_port)
return -EOPNOTSUPP;

if (!nfp_eth_can_support_fec(eth_port))
return 0;

param->fec = nfp_port_fec_nsp_to_ethtool(eth_port->fec_modes_supported);
param->active_fec = nfp_port_fec_nsp_to_ethtool(eth_port->fec);

return 0;
}

static int
nfp_port_set_fecparam(struct net_device *netdev,
struct ethtool_fecparam *param)
{
struct nfp_eth_table_port *eth_port;
struct nfp_port *port;
int err, fec;

port = nfp_port_from_netdev(netdev);
eth_port = nfp_port_get_eth_port(port);
if (!eth_port)
return -EOPNOTSUPP;

if (!nfp_eth_can_support_fec(eth_port))
return -EOPNOTSUPP;

fec = nfp_port_fec_ethtool_to_nsp(param->fec);
if (fec < 0)
return fec;

err = nfp_eth_set_fec(port->app->cpp, eth_port->index, fec);
if (!err)
/* Only refresh if we did something */
nfp_net_refresh_port_table(port);

return err < 0 ? err : 0;
}

/* RX network flow classification (RSS, filters, etc)
*/
static u32 ethtool_flow_to_nfp_flag(u32 flow_type)
Expand Down Expand Up @@ -1144,6 +1255,8 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
.set_channels = nfp_net_set_channels,
.get_link_ksettings = nfp_net_get_link_ksettings,
.set_link_ksettings = nfp_net_set_link_ksettings,
.get_fecparam = nfp_port_get_fecparam,
.set_fecparam = nfp_port_set_fecparam,
};

const struct ethtool_ops nfp_port_ethtool_ops = {
Expand All @@ -1155,6 +1268,10 @@ const struct ethtool_ops nfp_port_ethtool_ops = {
.set_dump = nfp_app_set_dump,
.get_dump_flag = nfp_app_get_dump_flag,
.get_dump_data = nfp_app_get_dump_data,
.get_link_ksettings = nfp_net_get_link_ksettings,
.set_link_ksettings = nfp_net_set_link_ksettings,
.get_fecparam = nfp_port_get_fecparam,
.set_fecparam = nfp_port_set_fecparam,
};

void nfp_net_set_ethtool_ops(struct net_device *netdev)
Expand Down
8 changes: 7 additions & 1 deletion drivers/net/ethernet/netronome/nfp/nfp_net_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,
return -EIO;
}
if (eth_port->override_changed) {
nfp_warn(cpp, "Port #%d config changed, unregistering. Reboot required before port will be operational again.\n", port->eth_id);
nfp_warn(cpp, "Port #%d config changed, unregistering. Driver reload required before port will be operational again.\n", port->eth_id);
port->type = NFP_PORT_INVALID;
}

Expand All @@ -611,6 +611,7 @@ int nfp_net_refresh_port_table_sync(struct nfp_pf *pf)
struct nfp_eth_table *eth_table;
struct nfp_net *nn, *next;
struct nfp_port *port;
int err;

lockdep_assert_held(&pf->lock);

Expand Down Expand Up @@ -640,6 +641,11 @@ int nfp_net_refresh_port_table_sync(struct nfp_pf *pf)

kfree(eth_table);

/* Resync repr state. This may cause reprs to be removed. */
err = nfp_reprs_resync_phys_ports(pf->app);
if (err)
return err;

/* Shoot off the ports which became invalid */
list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list) {
if (!nn->port || nn->port->type != NFP_PORT_INVALID)
Expand Down
47 changes: 47 additions & 0 deletions drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,50 @@ struct nfp_reprs *nfp_reprs_alloc(unsigned int num_reprs)

return reprs;
}

int nfp_reprs_resync_phys_ports(struct nfp_app *app)
{
struct nfp_reprs *reprs, *old_reprs;
struct nfp_repr *repr;
int i;

old_reprs =
rcu_dereference_protected(app->reprs[NFP_REPR_TYPE_PHYS_PORT],
lockdep_is_held(&app->pf->lock));
if (!old_reprs)
return 0;

reprs = nfp_reprs_alloc(old_reprs->num_reprs);
if (!reprs)
return -ENOMEM;

for (i = 0; i < old_reprs->num_reprs; i++) {
if (!old_reprs->reprs[i])
continue;

repr = netdev_priv(old_reprs->reprs[i]);
if (repr->port->type == NFP_PORT_INVALID)
continue;

reprs->reprs[i] = old_reprs->reprs[i];
}

old_reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
synchronize_rcu();

/* Now we free up removed representors */
for (i = 0; i < old_reprs->num_reprs; i++) {
if (!old_reprs->reprs[i])
continue;

repr = netdev_priv(old_reprs->reprs[i]);
if (repr->port->type != NFP_PORT_INVALID)
continue;

nfp_app_repr_stop(app, repr);
nfp_repr_clean(repr);
}

kfree(old_reprs);
return 0;
}
1 change: 1 addition & 0 deletions drivers/net/ethernet/netronome/nfp/nfp_net_repr.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,6 @@ void
nfp_reprs_clean_and_free_by_type(struct nfp_app *app,
enum nfp_repr_type type);
struct nfp_reprs *nfp_reprs_alloc(unsigned int num_reprs);
int nfp_reprs_resync_phys_ports(struct nfp_app *app);

#endif /* NFP_NET_REPR_H */
5 changes: 5 additions & 0 deletions drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,11 @@ int nfp_nsp_device_soft_reset(struct nfp_nsp *state)
return nfp_nsp_command(state, SPCODE_SOFT_RESET, 0, 0, 0);
}

int nfp_nsp_mac_reinit(struct nfp_nsp *state)
{
return nfp_nsp_command(state, SPCODE_MAC_INIT, 0, 0, 0);
}

int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw)
{
return nfp_nsp_command_buf(state, SPCODE_FW_LOAD, fw->size, fw->data,
Expand Down
Loading

0 comments on commit bfe26ba

Please sign in to comment.