qlcnic: Enable Interrupt Coalescing for 83xx adapter
authorHimanshu Madhani <himanshu.madhani@qlogic.com>
Wed, 24 Apr 2013 12:42:42 +0000 (12:42 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 24 Apr 2013 23:34:05 +0000 (19:34 -0400)
Enable Interrupt coalescing through ethtool on 83xx adapter.

Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c

index f699ccee65dc8169d7f8ff010dda7023dcc3ca0c..767c683a4870322756220afbe9ce24fba054a426 100644 (file)
@@ -347,8 +347,14 @@ struct qlcnic_rx_buffer {
  * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
  * adjusted based on configured MTU.
  */
-#define QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US        3
-#define QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS        256
+#define QLCNIC_INTR_COAL_TYPE_RX               1
+#define QLCNIC_INTR_COAL_TYPE_TX               2
+
+#define QLCNIC_DEF_INTR_COALESCE_RX_TIME_US    3
+#define QLCNIC_DEF_INTR_COALESCE_RX_PACKETS    256
+
+#define QLCNIC_DEF_INTR_COALESCE_TX_TIME_US    64
+#define QLCNIC_DEF_INTR_COALESCE_TX_PACKETS    64
 
 #define QLCNIC_INTR_DEFAULT                    0x04
 #define QLCNIC_CONFIG_INTR_COALESCE            3
@@ -359,6 +365,8 @@ struct qlcnic_nic_intr_coalesce {
        u8      sts_ring_mask;
        u16     rx_packets;
        u16     rx_time_us;
+       u16     tx_packets;
+       u16     tx_time_us;
        u16     flag;
        u32     timer_out;
 };
index c40b077d43da92a04533c19a6b4cd20139ee833b..ea790a93ee7c0e79acedd062a1d1795fb413e8c4 100644 (file)
@@ -1937,7 +1937,7 @@ int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
 void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
 {
        int err;
-       u32 temp;
+       u16 temp;
        struct qlcnic_cmd_args cmd;
        struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
 
@@ -1945,10 +1945,18 @@ void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
                return;
 
        qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
-       cmd.req.arg[1] = 1 | (adapter->recv_ctx->context_id << 16);
+       if (coal->type == QLCNIC_INTR_COAL_TYPE_RX) {
+               temp = adapter->recv_ctx->context_id;
+               cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_RX | temp << 16;
+               temp = coal->rx_time_us;
+               cmd.req.arg[2] = coal->rx_packets | temp << 16;
+       } else if (coal->type == QLCNIC_INTR_COAL_TYPE_TX) {
+               temp = adapter->tx_ring->ctx_id;
+               cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_TX | temp << 16;
+               temp = coal->tx_time_us;
+               cmd.req.arg[2] = coal->tx_packets | temp << 16;
+       }
        cmd.req.arg[3] = coal->flag;
-       temp = coal->rx_time_us << 16;
-       cmd.req.arg[2] = coal->rx_packets | temp;
        err = qlcnic_issue_cmd(adapter, &cmd);
        if (err != QLCNIC_RCODE_SUCCESS)
                dev_info(&adapter->pdev->dev,
index 629d901637e13764af36b590d6a4eca6515b0a48..08efb463500723a268923617157b4864a4345878 100644 (file)
@@ -1303,6 +1303,9 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
                        struct ethtool_coalesce *ethcoal)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       struct qlcnic_nic_intr_coalesce *coal;
+       u32 rx_coalesce_usecs, rx_max_frames;
+       u32 tx_coalesce_usecs, tx_max_frames;
 
        if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
                return -EINVAL;
@@ -1313,8 +1316,8 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
        */
        if (ethcoal->rx_coalesce_usecs > 0xffff ||
                ethcoal->rx_max_coalesced_frames > 0xffff ||
-               ethcoal->tx_coalesce_usecs ||
-               ethcoal->tx_max_coalesced_frames ||
+               ethcoal->tx_coalesce_usecs > 0xffff ||
+               ethcoal->tx_max_coalesced_frames > 0xffff ||
                ethcoal->rx_coalesce_usecs_irq ||
                ethcoal->rx_max_coalesced_frames_irq ||
                ethcoal->tx_coalesce_usecs_irq ||
@@ -1334,18 +1337,55 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
                ethcoal->tx_max_coalesced_frames_high)
                return -EINVAL;
 
-       if (!ethcoal->rx_coalesce_usecs ||
-               !ethcoal->rx_max_coalesced_frames) {
-               adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
-               adapter->ahw->coal.rx_time_us =
-                       QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
-               adapter->ahw->coal.rx_packets =
-                       QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
+       coal = &adapter->ahw->coal;
+
+       if (qlcnic_83xx_check(adapter)) {
+               if (!ethcoal->tx_coalesce_usecs ||
+                   !ethcoal->tx_max_coalesced_frames ||
+                   !ethcoal->rx_coalesce_usecs ||
+                   !ethcoal->rx_max_coalesced_frames) {
+                       coal->flag = QLCNIC_INTR_DEFAULT;
+                       coal->type = QLCNIC_INTR_COAL_TYPE_RX;
+                       coal->rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
+                       coal->rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
+                       coal->tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US;
+                       coal->tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS;
+               } else {
+                       tx_coalesce_usecs = ethcoal->tx_coalesce_usecs;
+                       tx_max_frames = ethcoal->tx_max_coalesced_frames;
+                       rx_coalesce_usecs = ethcoal->rx_coalesce_usecs;
+                       rx_max_frames = ethcoal->rx_max_coalesced_frames;
+                       coal->flag = 0;
+
+                       if ((coal->rx_time_us == rx_coalesce_usecs) &&
+                           (coal->rx_packets == rx_max_frames)) {
+                               coal->type = QLCNIC_INTR_COAL_TYPE_TX;
+                               coal->tx_time_us = tx_coalesce_usecs;
+                               coal->tx_packets = tx_max_frames;
+                       } else if ((coal->tx_time_us == tx_coalesce_usecs) &&
+                                  (coal->tx_packets == tx_max_frames)) {
+                               coal->type = QLCNIC_INTR_COAL_TYPE_RX;
+                               coal->rx_time_us = rx_coalesce_usecs;
+                               coal->rx_packets = rx_max_frames;
+                       } else {
+                               coal->type = QLCNIC_INTR_COAL_TYPE_RX;
+                               coal->rx_time_us = rx_coalesce_usecs;
+                               coal->rx_packets = rx_max_frames;
+                               coal->tx_time_us = tx_coalesce_usecs;
+                               coal->tx_packets = tx_max_frames;
+                       }
+               }
        } else {
-               adapter->ahw->coal.flag = 0;
-               adapter->ahw->coal.rx_time_us = ethcoal->rx_coalesce_usecs;
-               adapter->ahw->coal.rx_packets =
-                       ethcoal->rx_max_coalesced_frames;
+               if (!ethcoal->rx_coalesce_usecs ||
+                   !ethcoal->rx_max_coalesced_frames) {
+                       coal->flag = QLCNIC_INTR_DEFAULT;
+                       coal->rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
+                       coal->rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
+               } else {
+                       coal->flag = 0;
+                       coal->rx_time_us = ethcoal->rx_coalesce_usecs;
+                       coal->rx_packets = ethcoal->rx_max_coalesced_frames;
+               }
        }
 
        qlcnic_config_intr_coalesce(adapter);
@@ -1363,6 +1403,8 @@ static int qlcnic_get_intr_coalesce(struct net_device *netdev,
 
        ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
        ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
+       ethcoal->tx_coalesce_usecs = adapter->ahw->coal.tx_time_us;
+       ethcoal->tx_max_coalesced_frames = adapter->ahw->coal.tx_packets;
 
        return 0;
 }
index 0052953a255d92ea1f7b5f165c11926dff79f339..4e0bcb17e209af4a7d02b68c8482105e77361950 100644 (file)
@@ -1587,7 +1587,9 @@ out:
 
 static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
 {
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
        int err = 0;
+
        adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
                                GFP_KERNEL);
        if (!adapter->recv_ctx) {
@@ -1595,9 +1597,14 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
                goto err_out;
        }
        /* Initialize interrupt coalesce parameters */
-       adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
-       adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
-       adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
+       ahw->coal.flag = QLCNIC_INTR_DEFAULT;
+       ahw->coal.type = QLCNIC_INTR_COAL_TYPE_RX;
+       ahw->coal.rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
+       ahw->coal.rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
+       if (qlcnic_83xx_check(adapter)) {
+               ahw->coal.tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US;
+               ahw->coal.tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS;
+       }
        /* clear stats */
        memset(&adapter->stats, 0, sizeof(adapter->stats));
 err_out: