nfp: set config bit (ifup/ifdown) on netdev open/close
authorDirk van der Merwe <dirk.vandermerwe@netronome.com>
Tue, 25 Jul 2017 07:51:08 +0000 (00:51 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 25 Jul 2017 19:29:45 +0000 (12:29 -0700)
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>
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
drivers/net/ethernet/netronome/nfp/nfp_port.c
drivers/net/ethernet/netronome/nfp/nfp_port.h
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c

index 18750ff0ede6262d1a5fd50b8acc808c12a50756..ea471604450ee12574476a0b116d3286ece2de00 100644 (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;
index 8ec5474f4b186f46baadafa33a4cab18cabea95d..47daad30756cc098e9e1a1df2bfd50d37339ecf2 100644 (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;
+
+       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)
 {
        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 = {
index e42644dbb86523cef20379a2c93be98a1fdb84b7..d16a7b78ba9b877653ee88ccee2dcdf3025bd33d 100644 (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)
 {
index a33d22e18f94f80fbccc3e66e0ef9fb342ebecf7..56c76926c82a8c8e7b8d6f93c1034d800fb21b96 100644 (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,
index c2bc36e8649f7b65f9f0f5b0f279cbfad9febe87..f6f7c085f8e087a3b36a93e01e94f7f0744b24c5 100644 (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 */