|
@@ -11,6 +11,7 @@
|
|
|
|
|
|
#include "aq_ethtool.h"
|
|
#include "aq_ethtool.h"
|
|
#include "aq_nic.h"
|
|
#include "aq_nic.h"
|
|
|
|
+#include "aq_vec.h"
|
|
|
|
|
|
static void aq_ethtool_get_regs(struct net_device *ndev,
|
|
static void aq_ethtool_get_regs(struct net_device *ndev,
|
|
struct ethtool_regs *regs, void *p)
|
|
struct ethtool_regs *regs, void *p)
|
|
@@ -284,6 +285,64 @@ static int aq_ethtool_set_coalesce(struct net_device *ndev,
|
|
return aq_nic_update_interrupt_moderation_settings(aq_nic);
|
|
return aq_nic_update_interrupt_moderation_settings(aq_nic);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void aq_get_ringparam(struct net_device *ndev,
|
|
|
|
+ struct ethtool_ringparam *ring)
|
|
|
|
+{
|
|
|
|
+ struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
|
|
|
+ struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
|
|
|
|
+
|
|
|
|
+ ring->rx_pending = aq_nic_cfg->rxds;
|
|
|
|
+ ring->tx_pending = aq_nic_cfg->txds;
|
|
|
|
+
|
|
|
|
+ ring->rx_max_pending = aq_nic_cfg->aq_hw_caps->rxds_max;
|
|
|
|
+ ring->tx_max_pending = aq_nic_cfg->aq_hw_caps->txds_max;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int aq_set_ringparam(struct net_device *ndev,
|
|
|
|
+ struct ethtool_ringparam *ring)
|
|
|
|
+{
|
|
|
|
+ int err = 0;
|
|
|
|
+ bool ndev_running = false;
|
|
|
|
+ struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
|
|
|
+ struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
|
|
|
|
+ const struct aq_hw_caps_s *hw_caps = aq_nic_cfg->aq_hw_caps;
|
|
|
|
+
|
|
|
|
+ if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
|
|
|
|
+ err = -EOPNOTSUPP;
|
|
|
|
+ goto err_exit;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (netif_running(ndev)) {
|
|
|
|
+ ndev_running = true;
|
|
|
|
+ dev_close(ndev);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ aq_nic_free_vectors(aq_nic);
|
|
|
|
+
|
|
|
|
+ aq_nic_cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
|
|
|
|
+ aq_nic_cfg->rxds = min(aq_nic_cfg->rxds, hw_caps->rxds_max);
|
|
|
|
+ aq_nic_cfg->rxds = ALIGN(aq_nic_cfg->rxds, AQ_HW_RXD_MULTIPLE);
|
|
|
|
+
|
|
|
|
+ aq_nic_cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
|
|
|
|
+ aq_nic_cfg->txds = min(aq_nic_cfg->txds, hw_caps->txds_max);
|
|
|
|
+ aq_nic_cfg->txds = ALIGN(aq_nic_cfg->txds, AQ_HW_TXD_MULTIPLE);
|
|
|
|
+
|
|
|
|
+ for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < aq_nic_cfg->vecs;
|
|
|
|
+ aq_nic->aq_vecs++) {
|
|
|
|
+ aq_nic->aq_vec[aq_nic->aq_vecs] =
|
|
|
|
+ aq_vec_alloc(aq_nic, aq_nic->aq_vecs, aq_nic_cfg);
|
|
|
|
+ if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) {
|
|
|
|
+ err = -ENOMEM;
|
|
|
|
+ goto err_exit;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (ndev_running)
|
|
|
|
+ err = dev_open(ndev);
|
|
|
|
+
|
|
|
|
+err_exit:
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
const struct ethtool_ops aq_ethtool_ops = {
|
|
const struct ethtool_ops aq_ethtool_ops = {
|
|
.get_link = aq_ethtool_get_link,
|
|
.get_link = aq_ethtool_get_link,
|
|
.get_regs_len = aq_ethtool_get_regs_len,
|
|
.get_regs_len = aq_ethtool_get_regs_len,
|
|
@@ -291,6 +350,8 @@ const struct ethtool_ops aq_ethtool_ops = {
|
|
.get_drvinfo = aq_ethtool_get_drvinfo,
|
|
.get_drvinfo = aq_ethtool_get_drvinfo,
|
|
.get_strings = aq_ethtool_get_strings,
|
|
.get_strings = aq_ethtool_get_strings,
|
|
.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
|
|
.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
|
|
|
|
+ .get_ringparam = aq_get_ringparam,
|
|
|
|
+ .set_ringparam = aq_set_ringparam,
|
|
.get_rxfh_key_size = aq_ethtool_get_rss_key_size,
|
|
.get_rxfh_key_size = aq_ethtool_get_rss_key_size,
|
|
.get_rxfh = aq_ethtool_get_rss,
|
|
.get_rxfh = aq_ethtool_get_rss,
|
|
.get_rxnfc = aq_ethtool_get_rxnfc,
|
|
.get_rxnfc = aq_ethtool_get_rxnfc,
|