ar71xx: ag71xx: make ring sizes configurable via ethtool
authorGabor Juhos <juhosg@openwrt.org>
Tue, 31 May 2011 22:53:10 +0000 (22:53 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Tue, 31 May 2011 22:53:10 +0000 (22:53 +0000)
SVN-Revision: 27041

target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h
target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ethtool.c

index 64a82f1f251d395f02435a613bb801e848319134..1025bb4c491e3a61492f889490135f141e4057a8 100644 (file)
@@ -57,6 +57,9 @@
 #define AG71XX_TX_RING_SIZE_DEFAULT    64
 #define AG71XX_RX_RING_SIZE_DEFAULT    128
 
+#define AG71XX_TX_RING_SIZE_MAX                256
+#define AG71XX_RX_RING_SIZE_MAX                256
+
 #ifdef CONFIG_AG71XX_DEBUG
 #define DBG(fmt, args...)      printk(KERN_DEBUG fmt, ## args)
 #else
index 1f1c6aa77686c49bc1d01349c9b5dd81716c691c..498fbed1ff1d234b95eb32c7d5efcf6521f70318 100644 (file)
@@ -61,11 +61,64 @@ static void ag71xx_ethtool_set_msglevel(struct net_device *dev, u32 msg_level)
        ag->msg_enable = msg_level;
 }
 
+static void ag71xx_ethtool_get_ringparam(struct net_device *dev,
+                                        struct ethtool_ringparam *er)
+{
+       struct ag71xx *ag = netdev_priv(dev);
+
+       er->tx_max_pending = AG71XX_TX_RING_SIZE_MAX;
+       er->rx_max_pending = AG71XX_RX_RING_SIZE_MAX;
+       er->rx_mini_max_pending = 0;
+       er->rx_jumbo_max_pending = 0;
+
+       er->tx_pending = ag->tx_ring.size;
+       er->rx_pending = ag->rx_ring.size;
+       er->rx_mini_pending = 0;
+       er->rx_jumbo_pending = 0;
+}
+
+static int ag71xx_ethtool_set_ringparam(struct net_device *dev,
+                                       struct ethtool_ringparam *er)
+{
+       struct ag71xx *ag = netdev_priv(dev);
+       unsigned tx_size;
+       unsigned rx_size;
+       int err;
+
+       if (er->rx_mini_pending != 0||
+           er->rx_jumbo_pending != 0 ||
+           er->rx_pending == 0 ||
+           er->tx_pending == 0)
+               return -EINVAL;
+
+       tx_size = er->tx_pending < AG71XX_TX_RING_SIZE_MAX ?
+                 er->tx_pending : AG71XX_TX_RING_SIZE_MAX;
+
+       rx_size = er->rx_pending < AG71XX_RX_RING_SIZE_MAX ?
+                 er->rx_pending : AG71XX_RX_RING_SIZE_MAX;
+
+       if (netif_running(dev)) {
+               err = dev->netdev_ops->ndo_stop(dev);
+               if (err)
+                       return err;
+       }
+
+       ag->tx_ring.size = tx_size;
+       ag->rx_ring.size = rx_size;
+
+       if (netif_running(dev))
+               err = dev->netdev_ops->ndo_open(dev);
+
+       return err;
+}
+
 struct ethtool_ops ag71xx_ethtool_ops = {
        .set_settings   = ag71xx_ethtool_set_settings,
        .get_settings   = ag71xx_ethtool_get_settings,
        .get_drvinfo    = ag71xx_ethtool_get_drvinfo,
        .get_msglevel   = ag71xx_ethtool_get_msglevel,
        .set_msglevel   = ag71xx_ethtool_set_msglevel,
+       .get_ringparam  = ag71xx_ethtool_get_ringparam,
+       .set_ringparam  = ag71xx_ethtool_set_ringparam,
        .get_link       = ethtool_op_get_link,
 };