nfp: set config bit (ifup/ifdown) on netdev open/close

When a netdev (PF netdev or representor) is opened or closed, set the
physical port config bit appropriately - which powers UP/DOWN the PHY
module for the physical interface.

The PHY is powered first in the HW/FW configuration step when opening
the netdev and again last in the HW/FW configuration step when closing
the netdev.

This is only applicable when there is a physical port associated with
the netdev and if the NSP support this. Otherwise we silently ignore
this step.

The 'nfp_eth_set_configured' can actually return positive values -
updated the function documentation appropriately.

Signed-off-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Dirk van der Merwe 2017-07-25 00:51:08 -07:00 committed by David S. Miller
parent 81fc9b5ccf
commit 447e9ebfc1
5 changed files with 74 additions and 5 deletions

View file

@ -2658,6 +2658,7 @@ static int nfp_net_netdev_close(struct net_device *netdev)
/* Step 2: Tell NFP
*/
nfp_net_clear_config_and_disable(nn);
nfp_port_configure(netdev, false);
/* Step 3: Free resources
*/
@ -2775,16 +2776,21 @@ static int nfp_net_netdev_open(struct net_device *netdev)
goto err_free_all;
/* Step 2: Configure the NFP
* - Ifup the physical interface if it exists
* - Enable rings from 0 to tx_rings/rx_rings - 1.
* - Write MAC address (in case it changed)
* - Set the MTU
* - Set the Freelist buffer size
* - Enable the FW
*/
err = nfp_net_set_config_and_enable(nn);
err = nfp_port_configure(netdev, true);
if (err)
goto err_free_all;
err = nfp_net_set_config_and_enable(nn);
if (err)
goto err_port_disable;
/* Step 3: Enable for kernel
* - put some freelist descriptors on each RX ring
* - enable NAPI on each ring
@ -2795,6 +2801,8 @@ static int nfp_net_netdev_open(struct net_device *netdev)
return 0;
err_port_disable:
nfp_port_configure(netdev, false);
err_free_all:
nfp_net_close_free_all(nn);
return err;

View file

@ -239,15 +239,34 @@ static netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev)
static int nfp_repr_stop(struct net_device *netdev)
{
struct nfp_repr *repr = netdev_priv(netdev);
int err;
return nfp_app_repr_stop(repr->app, repr);
err = nfp_app_repr_stop(repr->app, repr);
if (err)
return err;
nfp_port_configure(netdev, false);
return 0;
}
static int nfp_repr_open(struct net_device *netdev)
{
struct nfp_repr *repr = netdev_priv(netdev);
int err;
return nfp_app_repr_open(repr->app, repr);
err = nfp_port_configure(netdev, true);
if (err)
return err;
err = nfp_app_repr_open(repr->app, repr);
if (err)
goto err_port_disable;
return 0;
err_port_disable:
nfp_port_configure(netdev, false);
return err;
}
const struct net_device_ops nfp_repr_netdev_ops = {

View file

@ -181,6 +181,33 @@ nfp_port_get_phys_port_name(struct net_device *netdev, char *name, size_t len)
return 0;
}
/**
* nfp_port_configure() - helper to set the interface configured bit
* @netdev: net_device instance
* @configed: Desired state
*
* Helper to set the ifup/ifdown state on the PHY only if there is a physical
* interface associated with the netdev.
*
* Return:
* 0 - configuration successful (or no change);
* -ERRNO - configuration failed.
*/
int nfp_port_configure(struct net_device *netdev, bool configed)
{
struct nfp_eth_table_port *eth_port;
struct nfp_port *port;
int err;
port = nfp_port_from_netdev(netdev);
eth_port = __nfp_port_get_eth_port(port);
if (!eth_port)
return 0;
err = nfp_eth_set_configured(port->app->cpp, eth_port->index, configed);
return err < 0 && err != -EOPNOTSUPP ? err : 0;
}
int nfp_port_init_phy_port(struct nfp_pf *pf, struct nfp_app *app,
struct nfp_port *port, unsigned int id)
{

View file

@ -120,6 +120,7 @@ struct nfp_eth_table_port *nfp_port_get_eth_port(struct nfp_port *port);
int
nfp_port_get_phys_port_name(struct net_device *netdev, char *name, size_t len);
int nfp_port_configure(struct net_device *netdev, bool configed);
struct nfp_port *
nfp_port_alloc(struct nfp_app *app, enum nfp_port_type type,

View file

@ -391,7 +391,10 @@ int nfp_eth_config_commit_end(struct nfp_nsp *nsp)
* Enable or disable PHY module (this usually means setting the TX lanes
* disable bits).
*
* Return: 0 or -ERRNO.
* Return:
* 0 - configuration successful;
* 1 - no changes were needed;
* -ERRNO - configuration failed.
*/
int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable)
{
@ -427,7 +430,10 @@ int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable)
*
* Set the ifup/ifdown state on the PHY.
*
* Return: 0 or -ERRNO.
* Return:
* 0 - configuration successful;
* 1 - no changes were needed;
* -ERRNO - configuration failed.
*/
int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed)
{
@ -439,6 +445,14 @@ int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed)
if (IS_ERR(nsp))
return PTR_ERR(nsp);
/* Older ABI versions did support this feature, however this has only
* been reliable since ABI 20.
*/
if (nfp_nsp_get_abi_ver_minor(nsp) < 20) {
nfp_eth_config_cleanup_end(nsp);
return -EOPNOTSUPP;
}
entries = nfp_nsp_config_entries(nsp);
/* Check if we are already in requested state */