Commit 447e9ebf authored by Dirk van der Merwe's avatar Dirk van der Merwe Committed by David S. Miller

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: default avatarDirk van der Merwe <dirk.vandermerwe@netronome.com>
Reviewed-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 81fc9b5c
...@@ -2658,6 +2658,7 @@ static int nfp_net_netdev_close(struct net_device *netdev) ...@@ -2658,6 +2658,7 @@ static int nfp_net_netdev_close(struct net_device *netdev)
/* Step 2: Tell NFP /* Step 2: Tell NFP
*/ */
nfp_net_clear_config_and_disable(nn); nfp_net_clear_config_and_disable(nn);
nfp_port_configure(netdev, false);
/* Step 3: Free resources /* Step 3: Free resources
*/ */
...@@ -2775,16 +2776,21 @@ static int nfp_net_netdev_open(struct net_device *netdev) ...@@ -2775,16 +2776,21 @@ static int nfp_net_netdev_open(struct net_device *netdev)
goto err_free_all; goto err_free_all;
/* Step 2: Configure the NFP /* Step 2: Configure the NFP
* - Ifup the physical interface if it exists
* - Enable rings from 0 to tx_rings/rx_rings - 1. * - Enable rings from 0 to tx_rings/rx_rings - 1.
* - Write MAC address (in case it changed) * - Write MAC address (in case it changed)
* - Set the MTU * - Set the MTU
* - Set the Freelist buffer size * - Set the Freelist buffer size
* - Enable the FW * - Enable the FW
*/ */
err = nfp_net_set_config_and_enable(nn); err = nfp_port_configure(netdev, true);
if (err) if (err)
goto err_free_all; goto err_free_all;
err = nfp_net_set_config_and_enable(nn);
if (err)
goto err_port_disable;
/* Step 3: Enable for kernel /* Step 3: Enable for kernel
* - put some freelist descriptors on each RX ring * - put some freelist descriptors on each RX ring
* - enable NAPI on each ring * - enable NAPI on each ring
...@@ -2795,6 +2801,8 @@ static int nfp_net_netdev_open(struct net_device *netdev) ...@@ -2795,6 +2801,8 @@ static int nfp_net_netdev_open(struct net_device *netdev)
return 0; return 0;
err_port_disable:
nfp_port_configure(netdev, false);
err_free_all: err_free_all:
nfp_net_close_free_all(nn); nfp_net_close_free_all(nn);
return err; return err;
......
...@@ -239,15 +239,34 @@ static netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -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) static int nfp_repr_stop(struct net_device *netdev)
{ {
struct nfp_repr *repr = netdev_priv(netdev); struct nfp_repr *repr = netdev_priv(netdev);
int err;
err = nfp_app_repr_stop(repr->app, repr);
if (err)
return err;
return nfp_app_repr_stop(repr->app, repr); nfp_port_configure(netdev, false);
return 0;
} }
static int nfp_repr_open(struct net_device *netdev) static int nfp_repr_open(struct net_device *netdev)
{ {
struct nfp_repr *repr = netdev_priv(netdev); struct nfp_repr *repr = netdev_priv(netdev);
int err;
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 nfp_app_repr_open(repr->app, repr); return 0;
err_port_disable:
nfp_port_configure(netdev, false);
return err;
} }
const struct net_device_ops nfp_repr_netdev_ops = { const struct net_device_ops nfp_repr_netdev_ops = {
......
...@@ -181,6 +181,33 @@ nfp_port_get_phys_port_name(struct net_device *netdev, char *name, size_t len) ...@@ -181,6 +181,33 @@ nfp_port_get_phys_port_name(struct net_device *netdev, char *name, size_t len)
return 0; 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, int nfp_port_init_phy_port(struct nfp_pf *pf, struct nfp_app *app,
struct nfp_port *port, unsigned int id) struct nfp_port *port, unsigned int id)
{ {
......
...@@ -120,6 +120,7 @@ struct nfp_eth_table_port *nfp_port_get_eth_port(struct nfp_port *port); ...@@ -120,6 +120,7 @@ struct nfp_eth_table_port *nfp_port_get_eth_port(struct nfp_port *port);
int int
nfp_port_get_phys_port_name(struct net_device *netdev, char *name, size_t len); 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 * struct nfp_port *
nfp_port_alloc(struct nfp_app *app, enum nfp_port_type type, nfp_port_alloc(struct nfp_app *app, enum nfp_port_type type,
......
...@@ -391,7 +391,10 @@ int nfp_eth_config_commit_end(struct nfp_nsp *nsp) ...@@ -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 * Enable or disable PHY module (this usually means setting the TX lanes
* disable bits). * 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) 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) ...@@ -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. * 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) 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) ...@@ -439,6 +445,14 @@ int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed)
if (IS_ERR(nsp)) if (IS_ERR(nsp))
return PTR_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); entries = nfp_nsp_config_entries(nsp);
/* Check if we are already in requested state */ /* Check if we are already in requested state */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment