]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
eth: fbnic: support ring channel get and set while down
authorJakub Kicinski <kuba@kernel.org>
Fri, 20 Dec 2024 02:52:40 +0000 (18:52 -0800)
committerJakub Kicinski <kuba@kernel.org>
Mon, 23 Dec 2024 18:35:56 +0000 (10:35 -0800)
Trivial implementation of ethtool channel get and set. Set is only
supported when device is closed, next patch will add code for
live reconfig.

Asymmetric configurations are supported (combined + extra Tx or Rx),
so are configurations with independent IRQs for Rx and Tx.
Having all 3 NAPI types (combined, Tx, Rx) is not supported.

We used to only call fbnic_reset_indir_tbl() during init.
Now that we call it after device had been register must
be careful not to override user config.

Link: https://patch.msgid.link/20241220025241.1522781-10-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
drivers/net/ethernet/meta/fbnic/fbnic_rpc.c

index d1be8fc304046500c8e47285951dc00cdd6aa618..d2fe97ae6a7161cd410065e9e9c08cd67aa34b62 100644 (file)
@@ -304,6 +304,68 @@ fbnic_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh,
        return 0;
 }
 
+static void fbnic_get_channels(struct net_device *netdev,
+                              struct ethtool_channels *ch)
+{
+       struct fbnic_net *fbn = netdev_priv(netdev);
+       struct fbnic_dev *fbd = fbn->fbd;
+
+       ch->max_rx = fbd->max_num_queues;
+       ch->max_tx = fbd->max_num_queues;
+       ch->max_combined = min(ch->max_rx, ch->max_tx);
+       ch->max_other = FBNIC_NON_NAPI_VECTORS;
+
+       if (fbn->num_rx_queues > fbn->num_napi ||
+           fbn->num_tx_queues > fbn->num_napi)
+               ch->combined_count = min(fbn->num_rx_queues,
+                                        fbn->num_tx_queues);
+       else
+               ch->combined_count =
+                       fbn->num_rx_queues + fbn->num_tx_queues - fbn->num_napi;
+       ch->rx_count = fbn->num_rx_queues - ch->combined_count;
+       ch->tx_count = fbn->num_tx_queues - ch->combined_count;
+       ch->other_count = FBNIC_NON_NAPI_VECTORS;
+}
+
+static void fbnic_set_queues(struct fbnic_net *fbn, struct ethtool_channels *ch,
+                            unsigned int max_napis)
+{
+       fbn->num_rx_queues = ch->rx_count + ch->combined_count;
+       fbn->num_tx_queues = ch->tx_count + ch->combined_count;
+       fbn->num_napi = min(ch->rx_count + ch->tx_count + ch->combined_count,
+                           max_napis);
+}
+
+static int fbnic_set_channels(struct net_device *netdev,
+                             struct ethtool_channels *ch)
+{
+       struct fbnic_net *fbn = netdev_priv(netdev);
+       unsigned int max_napis, standalone;
+       struct fbnic_dev *fbd = fbn->fbd;
+
+       max_napis = fbd->num_irqs - FBNIC_NON_NAPI_VECTORS;
+       standalone = ch->rx_count + ch->tx_count;
+
+       /* Limits for standalone queues:
+        *  - each queue has it's own NAPI (num_napi >= rx + tx + combined)
+        *  - combining queues (combined not 0, rx or tx must be 0)
+        */
+       if ((ch->rx_count && ch->tx_count && ch->combined_count) ||
+           (standalone && standalone + ch->combined_count > max_napis) ||
+           ch->rx_count + ch->combined_count > fbd->max_num_queues ||
+           ch->tx_count + ch->combined_count > fbd->max_num_queues ||
+           ch->other_count != FBNIC_NON_NAPI_VECTORS)
+               return -EINVAL;
+
+       if (!netif_running(netdev)) {
+               fbnic_set_queues(fbn, ch, max_napis);
+               fbnic_reset_indir_tbl(fbn);
+               return 0;
+       }
+
+       return -EBUSY;
+}
+
 static int
 fbnic_get_ts_info(struct net_device *netdev,
                  struct kernel_ethtool_ts_info *tsinfo)
@@ -417,6 +479,8 @@ static const struct ethtool_ops fbnic_ethtool_ops = {
        .get_rxfh_indir_size    = fbnic_get_rxfh_indir_size,
        .get_rxfh               = fbnic_get_rxfh,
        .set_rxfh               = fbnic_set_rxfh,
+       .get_channels           = fbnic_get_channels,
+       .set_channels           = fbnic_set_channels,
        .get_ts_info            = fbnic_get_ts_info,
        .get_ts_stats           = fbnic_get_ts_stats,
        .get_eth_mac_stats      = fbnic_get_eth_mac_stats,
index b99c890ac43f6ebc7b7b074a63f17d5a76379b8e..c25bd300b9024792132c466926d7677adb63561c 100644 (file)
@@ -13,6 +13,9 @@ void fbnic_reset_indir_tbl(struct fbnic_net *fbn)
        unsigned int num_rx = fbn->num_rx_queues;
        unsigned int i;
 
+       if (netif_is_rxfh_configured(fbn->netdev))
+               return;
+
        for (i = 0; i < FBNIC_RPC_RSS_TBL_SIZE; i++)
                fbn->indir_tbl[0][i] = ethtool_rxfh_indir_default(i, num_rx);
 }