nfp: make use of MAC reinit
authorJakub Kicinski <jakub.kicinski@netronome.com>
Sat, 4 Nov 2017 15:48:55 +0000 (16:48 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 5 Nov 2017 14:23:26 +0000 (23:23 +0900)
Recent management FW images can perform full reinit of MAC cores
without requiring a reboot.  When loading the driver check if there
are changes pending and if so call NSP MAC reinit.  Full application
FW reload is still required, and all MACs need to be reinited at the
same time (not only the ones which have been reconfigured, and thus
potentially causing disruption to unrelated netdevs) therefore for
now changing MAC config without reloading the driver still remains
future work.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Tested-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/netronome/nfp/nfp_main.c
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/netronome/nfp/nfp_net_main.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h

index f8fa63b66739dfcc081b623ff7de717bb5928445..35eaccbece3676561563a8e76748add7da44d71f 100644 (file)
@@ -346,6 +346,32 @@ exit_release_fw:
        return err < 0 ? err : 1;
 }
 
+static void
+nfp_nsp_init_ports(struct pci_dev *pdev, struct nfp_pf *pf,
+                  struct nfp_nsp *nsp)
+{
+       bool needs_reinit = false;
+       int i;
+
+       pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
+       if (!pf->eth_tbl)
+               return;
+
+       if (!nfp_nsp_has_mac_reinit(nsp))
+               return;
+
+       for (i = 0; i < pf->eth_tbl->count; i++)
+               needs_reinit |= pf->eth_tbl->ports[i].override_changed;
+       if (!needs_reinit)
+               return;
+
+       kfree(pf->eth_tbl);
+       if (nfp_nsp_mac_reinit(nsp))
+               dev_warn(&pdev->dev, "MAC reinit failed\n");
+
+       pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
+}
+
 static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
 {
        struct nfp_nsp *nsp;
@@ -366,7 +392,7 @@ static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
        if (err < 0)
                goto exit_close_nsp;
 
-       pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
+       nfp_nsp_init_ports(pdev, pf, nsp);
 
        pf->nspi = __nfp_nsp_identify(nsp);
        if (pf->nspi)
index c67b90c8d8b713d6ca0f35397373a9ea065ae4d4..0061097c271eb24c8b487bb19e11e99216eb48b9 100644 (file)
@@ -328,7 +328,7 @@ nfp_net_set_link_ksettings(struct net_device *netdev,
                return -EOPNOTSUPP;
 
        if (netif_running(netdev)) {
-               netdev_warn(netdev, "Changing settings not allowed on an active interface. It may cause the port to be disabled until reboot.\n");
+               netdev_warn(netdev, "Changing settings not allowed on an active interface. It may cause the port to be disabled until driver reload.\n");
                return -EBUSY;
        }
 
index ff373acd28f3fcf72bd17bc207486eaf9739337c..0beb9b21557b3c15b1b2cfe9c22836a4902b076f 100644 (file)
@@ -597,7 +597,7 @@ nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,
                return -EIO;
        }
        if (eth_port->override_changed) {
-               nfp_warn(cpp, "Port #%d config changed, unregistering. Reboot required before port will be operational again.\n", port->eth_id);
+               nfp_warn(cpp, "Port #%d config changed, unregistering. Driver reload required before port will be operational again.\n", port->eth_id);
                port->type = NFP_PORT_INVALID;
        }
 
index 37364555c42b3fe60438713c4b7ffd1ca3d4a9a6..14a6d1ba51a9419790fc3d37908aa7654dff6171 100644 (file)
@@ -477,6 +477,11 @@ int nfp_nsp_device_soft_reset(struct nfp_nsp *state)
        return nfp_nsp_command(state, SPCODE_SOFT_RESET, 0, 0, 0);
 }
 
+int nfp_nsp_mac_reinit(struct nfp_nsp *state)
+{
+       return nfp_nsp_command(state, SPCODE_MAC_INIT, 0, 0, 0);
+}
+
 int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw)
 {
        return nfp_nsp_command_buf(state, SPCODE_FW_LOAD, fw->size, fw->data,
index e2f028027c6fab4ca3ffb5bc8fd8aeb1abcb0541..47486d42f2d77a2726e2d11e46a8e2d8b1d6bac4 100644 (file)
@@ -48,6 +48,12 @@ u16 nfp_nsp_get_abi_ver_minor(struct nfp_nsp *state);
 int nfp_nsp_wait(struct nfp_nsp *state);
 int nfp_nsp_device_soft_reset(struct nfp_nsp *state);
 int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw);
+int nfp_nsp_mac_reinit(struct nfp_nsp *state);
+
+static inline bool nfp_nsp_has_mac_reinit(struct nfp_nsp *state)
+{
+       return nfp_nsp_get_abi_ver_minor(state) > 20;
+}
 
 enum nfp_eth_interface {
        NFP_INTERFACE_NONE      = 0,