Skip to content

Commit bfe26ba

Browse files
committed
Merge branch 'nfp-ethtool-and-related-improvements'
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 <[email protected]> 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 <[email protected]>
2 parents 1f25569 + 0d08709 commit bfe26ba

File tree

10 files changed

+325
-30
lines changed

10 files changed

+325
-30
lines changed

drivers/net/ethernet/netronome/nfp/flower/main.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
142142
{
143143
u8 nfp_pcie = nfp_cppcore_pcie_unit(app->pf->cpp);
144144
struct nfp_flower_priv *priv = app->priv;
145-
struct nfp_reprs *reprs, *old_reprs;
146145
enum nfp_port_type port_type;
146+
struct nfp_reprs *reprs;
147147
const u8 queue = 0;
148148
int i, err;
149149

@@ -194,11 +194,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
194194
reprs->reprs[i]->name);
195195
}
196196

197-
old_reprs = nfp_app_reprs_set(app, repr_type, reprs);
198-
if (IS_ERR(old_reprs)) {
199-
err = PTR_ERR(old_reprs);
200-
goto err_reprs_clean;
201-
}
197+
nfp_app_reprs_set(app, repr_type, reprs);
202198

203199
return 0;
204200
err_reprs_clean:
@@ -222,8 +218,8 @@ static int
222218
nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
223219
{
224220
struct nfp_eth_table *eth_tbl = app->pf->eth_tbl;
225-
struct nfp_reprs *reprs, *old_reprs;
226221
struct sk_buff *ctrl_skb;
222+
struct nfp_reprs *reprs;
227223
unsigned int i;
228224
int err;
229225

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

283-
old_reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
284-
if (IS_ERR(old_reprs)) {
285-
err = PTR_ERR(old_reprs);
286-
goto err_reprs_clean;
287-
}
279+
nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
288280

289281
/* The MAC_REPR control message should be sent after the MAC
290282
* representors are registered using nfp_app_reprs_set(). This is

drivers/net/ethernet/netronome/nfp/nfp_app.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,8 @@ nfp_app_reprs_set(struct nfp_app *app, enum nfp_repr_type type,
106106

107107
old = rcu_dereference_protected(app->reprs[type],
108108
lockdep_is_held(&app->pf->lock));
109-
if (reprs && old) {
110-
old = ERR_PTR(-EBUSY);
111-
goto exit_unlock;
112-
}
113-
114109
rcu_assign_pointer(app->reprs[type], reprs);
115110

116-
exit_unlock:
117111
return old;
118112
}
119113

drivers/net/ethernet/netronome/nfp/nfp_main.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,32 @@ nfp_fw_load(struct pci_dev *pdev, struct nfp_pf *pf, struct nfp_nsp *nsp)
346346
return err < 0 ? err : 1;
347347
}
348348

349+
static void
350+
nfp_nsp_init_ports(struct pci_dev *pdev, struct nfp_pf *pf,
351+
struct nfp_nsp *nsp)
352+
{
353+
bool needs_reinit = false;
354+
int i;
355+
356+
pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
357+
if (!pf->eth_tbl)
358+
return;
359+
360+
if (!nfp_nsp_has_mac_reinit(nsp))
361+
return;
362+
363+
for (i = 0; i < pf->eth_tbl->count; i++)
364+
needs_reinit |= pf->eth_tbl->ports[i].override_changed;
365+
if (!needs_reinit)
366+
return;
367+
368+
kfree(pf->eth_tbl);
369+
if (nfp_nsp_mac_reinit(nsp))
370+
dev_warn(&pdev->dev, "MAC reinit failed\n");
371+
372+
pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
373+
}
374+
349375
static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
350376
{
351377
struct nfp_nsp *nsp;
@@ -366,7 +392,7 @@ static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
366392
if (err < 0)
367393
goto exit_close_nsp;
368394

369-
pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
395+
nfp_nsp_init_ports(pdev, pf, nsp);
370396

371397
pf->nspi = __nfp_nsp_identify(nsp);
372398
if (pf->nspi)

drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,30 @@ nfp_app_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
244244
nfp_get_drvinfo(app, app->pdev, "*", drvinfo);
245245
}
246246

247+
static void
248+
nfp_net_set_fec_link_mode(struct nfp_eth_table_port *eth_port,
249+
struct ethtool_link_ksettings *c)
250+
{
251+
unsigned int modes;
252+
253+
ethtool_link_ksettings_add_link_mode(c, supported, FEC_NONE);
254+
if (!nfp_eth_can_support_fec(eth_port)) {
255+
ethtool_link_ksettings_add_link_mode(c, advertising, FEC_NONE);
256+
return;
257+
}
258+
259+
modes = nfp_eth_supported_fec_modes(eth_port);
260+
if (modes & NFP_FEC_BASER) {
261+
ethtool_link_ksettings_add_link_mode(c, supported, FEC_BASER);
262+
ethtool_link_ksettings_add_link_mode(c, advertising, FEC_BASER);
263+
}
264+
265+
if (modes & NFP_FEC_REED_SOLOMON) {
266+
ethtool_link_ksettings_add_link_mode(c, supported, FEC_RS);
267+
ethtool_link_ksettings_add_link_mode(c, advertising, FEC_RS);
268+
}
269+
}
270+
247271
/**
248272
* nfp_net_get_link_ksettings - Get Link Speed settings
249273
* @netdev: network interface device structure
@@ -278,9 +302,11 @@ nfp_net_get_link_ksettings(struct net_device *netdev,
278302

279303
port = nfp_port_from_netdev(netdev);
280304
eth_port = nfp_port_get_eth_port(port);
281-
if (eth_port)
305+
if (eth_port) {
282306
cmd->base.autoneg = eth_port->aneg != NFP_ANEG_DISABLED ?
283307
AUTONEG_ENABLE : AUTONEG_DISABLE;
308+
nfp_net_set_fec_link_mode(eth_port, cmd);
309+
}
284310

285311
if (!netif_carrier_ok(netdev))
286312
return 0;
@@ -328,7 +354,7 @@ nfp_net_set_link_ksettings(struct net_device *netdev,
328354
return -EOPNOTSUPP;
329355

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

@@ -686,6 +712,91 @@ static int nfp_port_get_sset_count(struct net_device *netdev, int sset)
686712
}
687713
}
688714

715+
static int nfp_port_fec_ethtool_to_nsp(u32 fec)
716+
{
717+
switch (fec) {
718+
case ETHTOOL_FEC_AUTO:
719+
return NFP_FEC_AUTO_BIT;
720+
case ETHTOOL_FEC_OFF:
721+
return NFP_FEC_DISABLED_BIT;
722+
case ETHTOOL_FEC_RS:
723+
return NFP_FEC_REED_SOLOMON_BIT;
724+
case ETHTOOL_FEC_BASER:
725+
return NFP_FEC_BASER_BIT;
726+
default:
727+
/* NSP only supports a single mode at a time */
728+
return -EOPNOTSUPP;
729+
}
730+
}
731+
732+
static u32 nfp_port_fec_nsp_to_ethtool(u32 fec)
733+
{
734+
u32 result = 0;
735+
736+
if (fec & NFP_FEC_AUTO)
737+
result |= ETHTOOL_FEC_AUTO;
738+
if (fec & NFP_FEC_BASER)
739+
result |= ETHTOOL_FEC_BASER;
740+
if (fec & NFP_FEC_REED_SOLOMON)
741+
result |= ETHTOOL_FEC_RS;
742+
if (fec & NFP_FEC_DISABLED)
743+
result |= ETHTOOL_FEC_OFF;
744+
745+
return result ?: ETHTOOL_FEC_NONE;
746+
}
747+
748+
static int
749+
nfp_port_get_fecparam(struct net_device *netdev,
750+
struct ethtool_fecparam *param)
751+
{
752+
struct nfp_eth_table_port *eth_port;
753+
struct nfp_port *port;
754+
755+
param->active_fec = ETHTOOL_FEC_NONE_BIT;
756+
param->fec = ETHTOOL_FEC_NONE_BIT;
757+
758+
port = nfp_port_from_netdev(netdev);
759+
eth_port = nfp_port_get_eth_port(port);
760+
if (!eth_port)
761+
return -EOPNOTSUPP;
762+
763+
if (!nfp_eth_can_support_fec(eth_port))
764+
return 0;
765+
766+
param->fec = nfp_port_fec_nsp_to_ethtool(eth_port->fec_modes_supported);
767+
param->active_fec = nfp_port_fec_nsp_to_ethtool(eth_port->fec);
768+
769+
return 0;
770+
}
771+
772+
static int
773+
nfp_port_set_fecparam(struct net_device *netdev,
774+
struct ethtool_fecparam *param)
775+
{
776+
struct nfp_eth_table_port *eth_port;
777+
struct nfp_port *port;
778+
int err, fec;
779+
780+
port = nfp_port_from_netdev(netdev);
781+
eth_port = nfp_port_get_eth_port(port);
782+
if (!eth_port)
783+
return -EOPNOTSUPP;
784+
785+
if (!nfp_eth_can_support_fec(eth_port))
786+
return -EOPNOTSUPP;
787+
788+
fec = nfp_port_fec_ethtool_to_nsp(param->fec);
789+
if (fec < 0)
790+
return fec;
791+
792+
err = nfp_eth_set_fec(port->app->cpp, eth_port->index, fec);
793+
if (!err)
794+
/* Only refresh if we did something */
795+
nfp_net_refresh_port_table(port);
796+
797+
return err < 0 ? err : 0;
798+
}
799+
689800
/* RX network flow classification (RSS, filters, etc)
690801
*/
691802
static u32 ethtool_flow_to_nfp_flag(u32 flow_type)
@@ -1144,6 +1255,8 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
11441255
.set_channels = nfp_net_set_channels,
11451256
.get_link_ksettings = nfp_net_get_link_ksettings,
11461257
.set_link_ksettings = nfp_net_set_link_ksettings,
1258+
.get_fecparam = nfp_port_get_fecparam,
1259+
.set_fecparam = nfp_port_set_fecparam,
11471260
};
11481261

11491262
const struct ethtool_ops nfp_port_ethtool_ops = {
@@ -1155,6 +1268,10 @@ const struct ethtool_ops nfp_port_ethtool_ops = {
11551268
.set_dump = nfp_app_set_dump,
11561269
.get_dump_flag = nfp_app_get_dump_flag,
11571270
.get_dump_data = nfp_app_get_dump_data,
1271+
.get_link_ksettings = nfp_net_get_link_ksettings,
1272+
.set_link_ksettings = nfp_net_set_link_ksettings,
1273+
.get_fecparam = nfp_port_get_fecparam,
1274+
.set_fecparam = nfp_port_set_fecparam,
11581275
};
11591276

11601277
void nfp_net_set_ethtool_ops(struct net_device *netdev)

drivers/net/ethernet/netronome/nfp/nfp_net_main.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,
597597
return -EIO;
598598
}
599599
if (eth_port->override_changed) {
600-
nfp_warn(cpp, "Port #%d config changed, unregistering. Reboot required before port will be operational again.\n", port->eth_id);
600+
nfp_warn(cpp, "Port #%d config changed, unregistering. Driver reload required before port will be operational again.\n", port->eth_id);
601601
port->type = NFP_PORT_INVALID;
602602
}
603603

@@ -611,6 +611,7 @@ int nfp_net_refresh_port_table_sync(struct nfp_pf *pf)
611611
struct nfp_eth_table *eth_table;
612612
struct nfp_net *nn, *next;
613613
struct nfp_port *port;
614+
int err;
614615

615616
lockdep_assert_held(&pf->lock);
616617

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

641642
kfree(eth_table);
642643

644+
/* Resync repr state. This may cause reprs to be removed. */
645+
err = nfp_reprs_resync_phys_ports(pf->app);
646+
if (err)
647+
return err;
648+
643649
/* Shoot off the ports which became invalid */
644650
list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list) {
645651
if (!nn->port || nn->port->type != NFP_PORT_INVALID)

drivers/net/ethernet/netronome/nfp/nfp_net_repr.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,50 @@ struct nfp_reprs *nfp_reprs_alloc(unsigned int num_reprs)
390390

391391
return reprs;
392392
}
393+
394+
int nfp_reprs_resync_phys_ports(struct nfp_app *app)
395+
{
396+
struct nfp_reprs *reprs, *old_reprs;
397+
struct nfp_repr *repr;
398+
int i;
399+
400+
old_reprs =
401+
rcu_dereference_protected(app->reprs[NFP_REPR_TYPE_PHYS_PORT],
402+
lockdep_is_held(&app->pf->lock));
403+
if (!old_reprs)
404+
return 0;
405+
406+
reprs = nfp_reprs_alloc(old_reprs->num_reprs);
407+
if (!reprs)
408+
return -ENOMEM;
409+
410+
for (i = 0; i < old_reprs->num_reprs; i++) {
411+
if (!old_reprs->reprs[i])
412+
continue;
413+
414+
repr = netdev_priv(old_reprs->reprs[i]);
415+
if (repr->port->type == NFP_PORT_INVALID)
416+
continue;
417+
418+
reprs->reprs[i] = old_reprs->reprs[i];
419+
}
420+
421+
old_reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
422+
synchronize_rcu();
423+
424+
/* Now we free up removed representors */
425+
for (i = 0; i < old_reprs->num_reprs; i++) {
426+
if (!old_reprs->reprs[i])
427+
continue;
428+
429+
repr = netdev_priv(old_reprs->reprs[i]);
430+
if (repr->port->type != NFP_PORT_INVALID)
431+
continue;
432+
433+
nfp_app_repr_stop(app, repr);
434+
nfp_repr_clean(repr);
435+
}
436+
437+
kfree(old_reprs);
438+
return 0;
439+
}

drivers/net/ethernet/netronome/nfp/nfp_net_repr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,6 @@ void
124124
nfp_reprs_clean_and_free_by_type(struct nfp_app *app,
125125
enum nfp_repr_type type);
126126
struct nfp_reprs *nfp_reprs_alloc(unsigned int num_reprs);
127+
int nfp_reprs_resync_phys_ports(struct nfp_app *app);
127128

128129
#endif /* NFP_NET_REPR_H */

drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,11 @@ int nfp_nsp_device_soft_reset(struct nfp_nsp *state)
477477
return nfp_nsp_command(state, SPCODE_SOFT_RESET, 0, 0, 0);
478478
}
479479

480+
int nfp_nsp_mac_reinit(struct nfp_nsp *state)
481+
{
482+
return nfp_nsp_command(state, SPCODE_MAC_INIT, 0, 0, 0);
483+
}
484+
480485
int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw)
481486
{
482487
return nfp_nsp_command_buf(state, SPCODE_FW_LOAD, fw->size, fw->data,

0 commit comments

Comments
 (0)