]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
nfp: propagate port speed from management firmware
authorYinjun Zhang <yinjun.zhang@corigine.com>
Thu, 25 Aug 2022 14:12:21 +0000 (16:12 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 30 Aug 2022 09:28:15 +0000 (11:28 +0200)
In future releases the NIC application firmware may be indifferent to port
speeds - not built for specific port speeds - and consequently it will not
be able to report VF port speeds to the driver without first learning them.
With this change, the driver will pass the speed of physical ports from
management firmware to application firmware, and the latter will copy the
speed of port 0 to all the active VFs. So that the driver can get VF port
speed as before.

The port speed of a VF may be requested from userspace using:

  ethtool <vf-intf>

Signed-off-by: Yinjun Zhang <yinjun.zhang@corigine.com>
Reviewed-by: Louis Peens <louis.peens@corigine.com>
Signed-off-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/netronome/nfp/nfp_main.h
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/netronome/nfp/nfp_net_main.c
drivers/net/ethernet/netronome/nfp/nfp_port.h

index f56ca11de13401d27b3bd74649794ee0b9dccbf4..be3746cbc58be3e2e27ddea2c2d5d7c5c3bc3c38 100644 (file)
@@ -190,4 +190,7 @@ int nfp_shared_buf_pool_set(struct nfp_pf *pf, unsigned int sb,
 
 int nfp_devlink_params_register(struct nfp_pf *pf);
 void nfp_devlink_params_unregister(struct nfp_pf *pf);
+
+unsigned int nfp_net_lr2speed(unsigned int linkrate);
+unsigned int nfp_net_speed2lr(unsigned int speed);
 #endif /* NFP_MAIN_H */
index cf4d6f1129fa29c0ca007bb3ecf0f8d246dfea85..fda3e77f28d2b60d913b5cb95554d7fc3bf296cd 100644 (file)
@@ -474,19 +474,22 @@ static void nfp_net_read_link_status(struct nfp_net *nn)
 {
        unsigned long flags;
        bool link_up;
-       u32 sts;
+       u16 sts;
 
        spin_lock_irqsave(&nn->link_status_lock, flags);
 
-       sts = nn_readl(nn, NFP_NET_CFG_STS);
+       sts = nn_readw(nn, NFP_NET_CFG_STS);
        link_up = !!(sts & NFP_NET_CFG_STS_LINK);
 
        if (nn->link_up == link_up)
                goto out;
 
        nn->link_up = link_up;
-       if (nn->port)
+       if (nn->port) {
                set_bit(NFP_PORT_CHANGED, &nn->port->flags);
+               if (nn->port->link_cb)
+                       nn->port->link_cb(nn->port);
+       }
 
        if (nn->link_up) {
                netif_carrier_on(nn->dp.netdev);
index ac05ec34d69ede56bf6ebb3b5d975b54b2236a69..91708527a47c6a659604c6c387fab4c1964757c1 100644 (file)
 #define   NFP_NET_CFG_STS_LINK_RATE_40G                  5
 #define   NFP_NET_CFG_STS_LINK_RATE_50G                  6
 #define   NFP_NET_CFG_STS_LINK_RATE_100G         7
+/* NSP Link rate is a 16-bit word. It's determined by NSP and
+ * written to CFG BAR by NFP driver.
+ */
+#define NFP_NET_CFG_STS_NSP_LINK_RATE  0x0036
 #define NFP_NET_CFG_CAP                        0x0038
 #define NFP_NET_CFG_MAX_TXRINGS                0x003c
 #define NFP_NET_CFG_MAX_RXRINGS                0x0040
index eeb1455a4e5dbb05069aba8c409cb9ecd3220c5d..cd2e67185e8c77b0eb35e03824db3eaf1e57414c 100644 (file)
@@ -273,20 +273,11 @@ static int
 nfp_net_get_link_ksettings(struct net_device *netdev,
                           struct ethtool_link_ksettings *cmd)
 {
-       static const u32 ls_to_ethtool[] = {
-               [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0,
-               [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN]     = SPEED_UNKNOWN,
-               [NFP_NET_CFG_STS_LINK_RATE_1G]          = SPEED_1000,
-               [NFP_NET_CFG_STS_LINK_RATE_10G]         = SPEED_10000,
-               [NFP_NET_CFG_STS_LINK_RATE_25G]         = SPEED_25000,
-               [NFP_NET_CFG_STS_LINK_RATE_40G]         = SPEED_40000,
-               [NFP_NET_CFG_STS_LINK_RATE_50G]         = SPEED_50000,
-               [NFP_NET_CFG_STS_LINK_RATE_100G]        = SPEED_100000,
-       };
        struct nfp_eth_table_port *eth_port;
        struct nfp_port *port;
        struct nfp_net *nn;
-       u32 sts, ls;
+       unsigned int speed;
+       u16 sts;
 
        /* Init to unknowns */
        ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
@@ -319,18 +310,15 @@ nfp_net_get_link_ksettings(struct net_device *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);
-       if (ls == NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED)
+       sts = nn_readw(nn, NFP_NET_CFG_STS);
+       speed = nfp_net_lr2speed(FIELD_GET(NFP_NET_CFG_STS_LINK_RATE, sts));
+       if (!speed)
                return -EOPNOTSUPP;
 
-       if (ls == NFP_NET_CFG_STS_LINK_RATE_UNKNOWN ||
-           ls >= ARRAY_SIZE(ls_to_ethtool))
-               return 0;
-
-       cmd->base.speed = ls_to_ethtool[ls];
-       cmd->base.duplex = DUPLEX_FULL;
+       if (speed != SPEED_UNKNOWN) {
+               cmd->base.speed = speed;
+               cmd->base.duplex = DUPLEX_FULL;
+       }
 
        return 0;
 }
index ca4e05650fe6446231d59b935c5f0d3ee70d6a59..dd668520851ed1c6559a97a40fc6abcf90cdefa8 100644 (file)
@@ -202,6 +202,9 @@ nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,
                        goto err_free_prev;
                }
 
+               if (nn->port)
+                       nn->port->link_cb = nfp_net_refresh_port_table;
+
                ctrl_bar += NFP_PF_CSR_SLICE_SIZE;
 
                /* Kill the vNIC if app init marked it as invalid */
@@ -523,6 +526,57 @@ err_unmap_ctrl:
        return err;
 }
 
+static const unsigned int lr_to_speed[] = {
+       [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0,
+       [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN]     = SPEED_UNKNOWN,
+       [NFP_NET_CFG_STS_LINK_RATE_1G]          = SPEED_1000,
+       [NFP_NET_CFG_STS_LINK_RATE_10G]         = SPEED_10000,
+       [NFP_NET_CFG_STS_LINK_RATE_25G]         = SPEED_25000,
+       [NFP_NET_CFG_STS_LINK_RATE_40G]         = SPEED_40000,
+       [NFP_NET_CFG_STS_LINK_RATE_50G]         = SPEED_50000,
+       [NFP_NET_CFG_STS_LINK_RATE_100G]        = SPEED_100000,
+};
+
+unsigned int nfp_net_lr2speed(unsigned int linkrate)
+{
+       if (linkrate < ARRAY_SIZE(lr_to_speed))
+               return lr_to_speed[linkrate];
+
+       return SPEED_UNKNOWN;
+}
+
+unsigned int nfp_net_speed2lr(unsigned int speed)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(lr_to_speed); i++) {
+               if (speed == lr_to_speed[i])
+                       return i;
+       }
+
+       return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN;
+}
+
+static void nfp_net_notify_port_speed(struct nfp_port *port)
+{
+       struct net_device *netdev = port->netdev;
+       struct nfp_net *nn;
+       u16 sts;
+
+       if (!nfp_netdev_is_nfp_net(netdev))
+               return;
+
+       nn = netdev_priv(netdev);
+       sts = nn_readw(nn, NFP_NET_CFG_STS);
+
+       if (!(sts & NFP_NET_CFG_STS_LINK)) {
+               nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, NFP_NET_CFG_STS_LINK_RATE_UNKNOWN);
+               return;
+       }
+
+       nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, nfp_net_speed2lr(port->eth_port->speed));
+}
+
 static int
 nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,
                        struct nfp_eth_table *eth_table)
@@ -544,6 +598,7 @@ nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,
        }
 
        memcpy(port->eth_port, eth_port, sizeof(*eth_port));
+       nfp_net_notify_port_speed(port);
 
        return 0;
 }
index d1ebe6c72f7fbc83b1ba82ac1fe337a28dfff59a..6793cdf9ff1158b48e5fa9e727fc6b9f73e0680e 100644 (file)
@@ -46,6 +46,7 @@ enum nfp_port_flags {
  * @tc_offload_cnt:    number of active TC offloads, how offloads are counted
  *                     is not defined, use as a boolean
  * @app:       backpointer to the app structure
+ * @link_cb:   callback when link status changed
  * @dl_port:   devlink port structure
  * @eth_id:    for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme
  * @eth_forced:        for %NFP_PORT_PHYS_PORT port is forced UP or DOWN, don't change
@@ -66,6 +67,7 @@ struct nfp_port {
        unsigned long tc_offload_cnt;
 
        struct nfp_app *app;
+       void (*link_cb)(struct nfp_port *port);
 
        struct devlink_port dl_port;