diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 8132dd31a6dd78b360ee843c618ab80db1de7c93..7882d260483546def792e06d8bcd5c56abc5b453 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -543,7 +543,6 @@ struct nfp_net_dp { * @reconfig_sync_present: Some thread is performing synchronous reconfig * @reconfig_timer: Timer for async reading of reconfig results * @link_up: Is the link up? - * @link_changed: Has link state changes since last port refresh? * @link_status_lock: Protects @link_* and ensures atomicity with BAR reading * @rx_coalesce_usecs: RX interrupt moderation usecs delay parameter * @rx_coalesce_max_frames: RX interrupt moderation frame count parameter @@ -601,7 +600,6 @@ struct nfp_net { u32 me_freq_mhz; bool link_up; - bool link_changed; spinlock_t link_status_lock; spinlock_t reconfig_lock; @@ -842,8 +840,6 @@ struct nfp_net_dp *nfp_net_clone_dp(struct nfp_net *nn); int nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_dp *new, struct netlink_ext_ack *extack); -bool nfp_net_link_changed_read_clear(struct nfp_net *nn); - #ifdef CONFIG_NFP_DEBUG void nfp_net_debugfs_create(void); void nfp_net_debugfs_destroy(void); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 15ef45a05c1e5e338c72ad968c752d2227a84ecf..b3f5c8af678939c101f9e545ea157975bafa630a 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -392,19 +392,6 @@ static irqreturn_t nfp_net_irq_rxtx(int irq, void *data) return IRQ_HANDLED; } -bool nfp_net_link_changed_read_clear(struct nfp_net *nn) -{ - unsigned long flags; - bool ret; - - spin_lock_irqsave(&nn->link_status_lock, flags); - ret = nn->link_changed; - nn->link_changed = false; - spin_unlock_irqrestore(&nn->link_status_lock, flags); - - return ret; -} - /** * nfp_net_read_link_status() - Reread link status from control BAR * @nn: NFP Network structure @@ -424,7 +411,8 @@ static void nfp_net_read_link_status(struct nfp_net *nn) goto out; nn->link_up = link_up; - nn->link_changed = true; + if (nn->port) + set_bit(NFP_PORT_CHANGED, &nn->port->flags); if (nn->link_up) { netif_carrier_on(nn->dp.netdev); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index 334020347ff26229a388d14ba1c6a4be85b15231..23f9ea0f89822ecc58cc3ffe1f8bc35e60f0d7d1 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -217,15 +217,11 @@ nfp_net_get_link_ksettings(struct net_device *netdev, if (!netif_carrier_ok(netdev)) return 0; - if (!nfp_netdev_is_nfp_net(netdev)) - return -EOPNOTSUPP; - nn = netdev_priv(netdev); - /* Use link speed from ETH table if available, otherwise try the BAR */ if (eth_port) { int err; - if (nfp_net_link_changed_read_clear(nn)) { + if (test_bit(NFP_PORT_CHANGED, &port->flags)) { err = nfp_net_refresh_eth_port(port); if (err) return err; @@ -237,6 +233,10 @@ nfp_net_get_link_ksettings(struct net_device *netdev, return 0; } + if (!nfp_netdev_is_nfp_net(netdev)) + return -EOPNOTSUPP; + nn = netdev_priv(netdev); + sts = nn_readl(nn, NFP_NET_CFG_STS); ls = FIELD_GET(NFP_NET_CFG_STS_LINK_RATE, sts); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c index 92037e3624ad3b659ec5a8703c998feab498ba2a..e8d54b9b9b97bbb29b6d5de891dbf2d06412c7b0 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c @@ -555,16 +555,19 @@ static void nfp_net_refresh_vnics(struct work_struct *work) if (list_empty(&pf->vnics)) goto out; + /* Update state of all ports */ + rtnl_lock(); list_for_each_entry(nn, &pf->vnics, vnic_list) - nfp_net_link_changed_read_clear(nn); + if (nn->port) + clear_bit(NFP_PORT_CHANGED, &nn->port->flags); eth_table = nfp_eth_read_ports(pf->cpp); if (!eth_table) { + rtnl_unlock(); nfp_err(pf->cpp, "Error refreshing port config!\n"); goto out; } - rtnl_lock(); list_for_each_entry(nn, &pf->vnics, vnic_list) { if (!__nfp_port_get_eth_port(nn->port)) continue; @@ -575,6 +578,7 @@ static void nfp_net_refresh_vnics(struct work_struct *work) kfree(eth_table); + /* 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) continue; @@ -604,6 +608,8 @@ int nfp_net_refresh_eth_port(struct nfp_port *port) struct nfp_eth_table *eth_table; int ret; + clear_bit(NFP_PORT_CHANGED, &port->flags); + eth_table = nfp_eth_read_ports(cpp); if (!eth_table) { nfp_err(cpp, "Error refreshing port state table!\n"); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.h b/drivers/net/ethernet/netronome/nfp/nfp_port.h index 341e7e128233e4d365bd11086a5846e0632a2d9c..47adacf885572b7b73d16071cb6aaebec9d66f99 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_port.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_port.h @@ -50,10 +50,21 @@ enum nfp_port_type { NFP_PORT_PHYS_PORT, }; +/** + * enum nfp_port_flags - port flags (can be type-specific) + * @NFP_PORT_CHANGED: port state has changed since last eth table refresh; + * for NFP_PORT_PHYS_PORT, never set otherwise; must hold + * rtnl_lock to clear + */ +enum nfp_port_flags { + NFP_PORT_CHANGED = 0, +}; + /** * struct nfp_port - structure representing NFP port * @netdev: backpointer to associated netdev * @type: what port type does the entity represent + * @flags: port flags * @app: backpointer to the app structure * @eth_id: for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme * @eth_port: for %NFP_PORT_PHYS_PORT translated ETH Table port entry @@ -62,6 +73,8 @@ struct nfp_port { struct net_device *netdev; enum nfp_port_type type; + unsigned long flags; + struct nfp_app *app; unsigned int eth_id;