netxen: support for ethtool set ringparam
authorAmit Kumar Salecha <amit@netxen.com>
Mon, 27 Jul 2009 18:15:54 +0000 (11:15 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 27 Jul 2009 18:15:54 +0000 (11:15 -0700)
Add support for ethtool -G to tune rx and tx ring sizes
per interface basis.

This is only supported for NX3031 based cards.

Signed-off-by: Amit Kumar Salecha <amit@netxen.com>
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ethtool.c
drivers/net/netxen/netxen_nic_main.c

index d01cc092450eb6f2d771a44a627d3b3c12cd6562..b68a70dc720e4269cc94930629eb0e09876e914b 100644 (file)
@@ -1427,6 +1427,9 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
 void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
                struct nx_host_tx_ring *tx_ring);
 
+/* Functions from netxen_nic_main.c */
+int netxen_nic_reset_context(struct netxen_adapter *);
+
 /*
  * NetXen Board information
  */
index 80d286db8eb47212550db915b739b9a3277766e1..39a308c363c72b246084745fa46c43e3d3b37f87 100644 (file)
@@ -490,7 +490,8 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 }
 
 static void
-netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
+netxen_nic_get_ringparam(struct net_device *dev,
+               struct ethtool_ringparam *ring)
 {
        struct netxen_adapter *adapter = netdev_priv(dev);
 
@@ -513,6 +514,62 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
        ring->rx_mini_pending = 0;
 }
 
+static u32
+netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
+{
+       u32 num_desc;
+       num_desc = max(val, min);
+       num_desc = min(num_desc, max);
+       num_desc = roundup_pow_of_two(num_desc);
+
+       if (val != num_desc) {
+               printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
+                      netxen_nic_driver_name, r_name, num_desc, val);
+       }
+
+       return num_desc;
+}
+
+static int
+netxen_nic_set_ringparam(struct net_device *dev,
+               struct ethtool_ringparam *ring)
+{
+       struct netxen_adapter *adapter = netdev_priv(dev);
+       u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;
+       u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+       u16 num_rxd, num_jumbo_rxd, num_txd;
+
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+               return -EOPNOTSUPP;
+
+       if (ring->rx_mini_pending)
+               return -EOPNOTSUPP;
+
+       if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
+               max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;
+               max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+       }
+
+       num_rxd = netxen_validate_ringparam(ring->rx_pending,
+                       MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");
+
+       num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,
+                       MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");
+
+       num_txd = netxen_validate_ringparam(ring->tx_pending,
+                       MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
+
+       if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
+                       num_jumbo_rxd == adapter->num_jumbo_rxd)
+               return 0;
+
+       adapter->num_rxd = num_rxd;
+       adapter->num_jumbo_rxd = num_jumbo_rxd;
+       adapter->num_txd = num_txd;
+
+       return netxen_nic_reset_context(adapter);
+}
+
 static void
 netxen_nic_get_pauseparam(struct net_device *dev,
                          struct ethtool_pauseparam *pause)
@@ -894,6 +951,7 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
        .get_eeprom_len = netxen_nic_get_eeprom_len,
        .get_eeprom = netxen_nic_get_eeprom,
        .get_ringparam = netxen_nic_get_ringparam,
+       .set_ringparam = netxen_nic_set_ringparam,
        .get_pauseparam = netxen_nic_get_pauseparam,
        .set_pauseparam = netxen_nic_set_pauseparam,
        .set_tx_csum = ethtool_op_set_tx_csum,
index ff7ee9c43ef5f61b5d138627ed83c3fdd7f34100..2bbefa6a37bc8f2a0f40765d8b641f875b87c9e2 100644 (file)
@@ -910,6 +910,9 @@ netxen_nic_attach(struct netxen_adapter *adapter)
        struct nx_host_rds_ring *rds_ring;
        struct nx_host_tx_ring *tx_ring;
 
+       if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
+               return 0;
+
        err = netxen_init_firmware(adapter);
        if (err != 0) {
                printk(KERN_ERR "Failed to init firmware\n");
@@ -973,6 +976,9 @@ err_out_free_sw:
 static void
 netxen_nic_detach(struct netxen_adapter *adapter)
 {
+       if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+               return;
+
        netxen_free_hw_resources(adapter);
        netxen_release_rx_buffers(adapter);
        netxen_nic_free_irq(adapter);
@@ -981,6 +987,30 @@ netxen_nic_detach(struct netxen_adapter *adapter)
        adapter->is_up = 0;
 }
 
+int
+netxen_nic_reset_context(struct netxen_adapter *adapter)
+{
+       int err = 0;
+       struct net_device *netdev = adapter->netdev;
+
+       if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
+
+               if (netif_running(netdev))
+                       netxen_nic_down(adapter, netdev);
+
+               netxen_nic_detach(adapter);
+
+               err = netxen_nic_attach(adapter);
+               if (err)
+                       goto done;
+
+               if (netif_running(netdev))
+                       err = netxen_nic_up(adapter, netdev);
+       }
+done:
+       return err;
+}
+
 static int
 netxen_setup_netdev(struct netxen_adapter *adapter,
                struct net_device *netdev)
@@ -1202,9 +1232,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
 
        unregister_netdev(netdev);
 
-       if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
-               netxen_nic_detach(adapter);
-       }
+       netxen_nic_detach(adapter);
 
        if (adapter->portnum == 0)
                netxen_free_dummy_dma(adapter);
@@ -1236,8 +1264,7 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
        if (netif_running(netdev))
                netxen_nic_down(adapter, netdev);
 
-       if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
-               netxen_nic_detach(adapter);
+       netxen_nic_detach(adapter);
 
        pci_save_state(pdev);
 
@@ -1298,11 +1325,9 @@ static int netxen_nic_open(struct net_device *netdev)
        if (adapter->driver_mismatch)
                return -EIO;
 
-       if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
-               err = netxen_nic_attach(adapter);
-               if (err)
-                       return err;
-       }
+       err = netxen_nic_attach(adapter);
+       if (err)
+               return err;
 
        err = netxen_nic_up(adapter, netdev);
        if (err)