]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'qlcnic'
authorDavid S. Miller <davem@davemloft.net>
Fri, 24 Jan 2014 00:13:39 +0000 (16:13 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 24 Jan 2014 00:13:39 +0000 (16:13 -0800)
Himanshu Madhani says:

====================
qlcnic: Refactoring and enhancements for all adapters.

This patch series contains following patches.

o Enhanced debug data collection when we are in Tx-timeout situation.
o Enhanced MSI-x vector calculation for defualt load path as well
  as for TSS/RSS ring change path.
o Refactored interrupt coalescing code for all adapters.
o Refactored interrupt handling as well as cleanup of poll controller
  code patch for all adapters.
o changed rx_mac_learn type to boolean.

Please apply to net-next.
====================

Signed-off-by: Zoltan Kiss <zoltan.kiss@citrix.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_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c

index 69a6ca086d5c78f0a0a6c1d3ca56361b3a1ee079..f19f81cde134ba1ed37807b460dc7ad4015b7707 100644 (file)
@@ -38,8 +38,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 3
-#define _QLCNIC_LINUX_SUBVERSION 54
-#define QLCNIC_LINUX_VERSIONID  "5.3.54"
+#define _QLCNIC_LINUX_SUBVERSION 55
+#define QLCNIC_LINUX_VERSIONID  "5.3.55"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
                 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
 #define QLCNIC_DEF_TX_RINGS            4
 #define QLCNIC_MAX_VNIC_TX_RINGS       4
 #define QLCNIC_MAX_VNIC_SDS_RINGS      4
+#define QLCNIC_83XX_MINIMUM_VECTOR     3
+#define QLCNIC_82XX_MINIMUM_VECTOR     2
 
 enum qlcnic_queue_type {
        QLCNIC_TX_QUEUE = 1,
@@ -369,6 +371,7 @@ struct qlcnic_rx_buffer {
  */
 #define QLCNIC_INTR_COAL_TYPE_RX               1
 #define QLCNIC_INTR_COAL_TYPE_TX               2
+#define QLCNIC_INTR_COAL_TYPE_RX_TX            3
 
 #define QLCNIC_DEF_INTR_COALESCE_RX_TIME_US    3
 #define QLCNIC_DEF_INTR_COALESCE_RX_PACKETS    256
@@ -961,6 +964,7 @@ struct qlcnic_ipaddr {
 #define QLCNIC_TX_INTR_SHARED          0x10000
 #define QLCNIC_APP_CHANGED_FLAGS       0x20000
 #define QLCNIC_HAS_PHYS_PORT_ID                0x40000
+#define QLCNIC_TSS_RSS                 0x80000
 
 #define QLCNIC_IS_MSI_FAMILY(adapter) \
        ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
@@ -1057,6 +1061,9 @@ struct qlcnic_adapter {
        u8 drv_tx_rings;  /* max tx rings supported by driver */
        u8 drv_sds_rings; /* max sds rings supported by driver */
 
+       u8 drv_tss_rings; /* tss ring input */
+       u8 drv_rss_rings; /* rss ring input */
+
        u8 rx_csum;
        u8 portnum;
 
@@ -1082,7 +1089,7 @@ struct qlcnic_adapter {
        u64 dev_rst_time;
        bool drv_mac_learn;
        bool fdb_mac_learn;
-       u8 rx_mac_learn;
+       bool rx_mac_learn;
        unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
        u8 flash_mfg_id;
        struct qlcnic_npar_info *npars;
@@ -1573,7 +1580,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int);
 netdev_tx_t qlcnic_xmit_frame(struct sk_buff *, struct net_device *);
 void qlcnic_set_tx_ring_count(struct qlcnic_adapter *, u8);
 void qlcnic_set_sds_ring_count(struct qlcnic_adapter *, u8);
-int qlcnic_setup_rings(struct qlcnic_adapter *, u8, u8);
+int qlcnic_setup_rings(struct qlcnic_adapter *);
 int qlcnic_validate_rings(struct qlcnic_adapter *, __u32, int);
 void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
 int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
@@ -1613,7 +1620,7 @@ void qlcnic_set_vlan_config(struct qlcnic_adapter *,
                            struct qlcnic_esw_func_cfg *);
 void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *,
                                      struct qlcnic_esw_func_cfg *);
-
+int qlcnic_setup_tss_rss_intr(struct qlcnic_adapter  *);
 void qlcnic_down(struct qlcnic_adapter *, struct net_device *);
 int qlcnic_up(struct qlcnic_adapter *, struct net_device *);
 void __qlcnic_down(struct qlcnic_adapter *, struct net_device *);
@@ -1670,11 +1677,8 @@ static inline int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter,
 
        err = netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);
        if (err)
-               dev_err(&adapter->pdev->dev, "failed to set %d Tx queues\n",
-                       adapter->drv_tx_rings);
-       else
-               dev_info(&adapter->pdev->dev, "Set %d Tx queues\n",
-                        adapter->drv_tx_rings);
+               netdev_err(netdev, "failed to set %d Tx queues\n",
+                          adapter->drv_tx_rings);
 
        return err;
 }
@@ -1740,7 +1744,8 @@ struct qlcnic_hardware_ops {
        int (*change_macvlan) (struct qlcnic_adapter *, u8*, u16, u8);
        void (*napi_enable) (struct qlcnic_adapter *);
        void (*napi_disable) (struct qlcnic_adapter *);
-       void (*config_intr_coal) (struct qlcnic_adapter *);
+       int (*config_intr_coal) (struct qlcnic_adapter *,
+                                struct ethtool_coalesce *);
        int (*config_rss) (struct qlcnic_adapter *, int);
        int (*config_hw_lro) (struct qlcnic_adapter *, int);
        int (*config_loopback) (struct qlcnic_adapter *, u8);
@@ -1756,6 +1761,14 @@ struct qlcnic_hardware_ops {
        pci_ers_result_t (*io_slot_reset) (struct pci_dev *);
        void (*io_resume) (struct pci_dev *);
        void (*get_beacon_state)(struct qlcnic_adapter *);
+       void (*enable_sds_intr) (struct qlcnic_adapter *,
+                                struct qlcnic_host_sds_ring *);
+       void (*disable_sds_intr) (struct qlcnic_adapter *,
+                                 struct qlcnic_host_sds_ring *);
+       void (*enable_tx_intr) (struct qlcnic_adapter *,
+                               struct qlcnic_host_tx_ring *);
+       void (*disable_tx_intr) (struct qlcnic_adapter *,
+                                struct qlcnic_host_tx_ring *);
 };
 
 extern struct qlcnic_nic_template qlcnic_vf_ops;
@@ -1928,9 +1941,10 @@ static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter)
        adapter->ahw->hw_ops->napi_disable(adapter);
 }
 
-static inline void qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
+static inline int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter,
+                                             struct ethtool_coalesce *ethcoal)
 {
-       adapter->ahw->hw_ops->config_intr_coal(adapter);
+       return adapter->ahw->hw_ops->config_intr_coal(adapter, ethcoal);
 }
 
 static inline int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
@@ -2029,6 +2043,54 @@ static inline bool qlcnic_check_multi_tx(struct qlcnic_adapter *adapter)
        return test_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state);
 }
 
+static inline void
+qlcnic_82xx_enable_tx_intr(struct qlcnic_adapter *adapter,
+                          struct qlcnic_host_tx_ring *tx_ring)
+{
+       if (qlcnic_check_multi_tx(adapter) &&
+           !adapter->ahw->diag_test)
+               writel(0x0, tx_ring->crb_intr_mask);
+}
+
+static inline void
+qlcnic_82xx_disable_tx_intr(struct qlcnic_adapter *adapter,
+                           struct qlcnic_host_tx_ring *tx_ring)
+{
+       if (qlcnic_check_multi_tx(adapter) &&
+           !adapter->ahw->diag_test)
+               writel(1, tx_ring->crb_intr_mask);
+}
+
+static inline void
+qlcnic_83xx_enable_tx_intr(struct qlcnic_adapter *adapter,
+                          struct qlcnic_host_tx_ring *tx_ring)
+{
+       writel(0, tx_ring->crb_intr_mask);
+}
+
+static inline void
+qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter,
+                           struct qlcnic_host_tx_ring *tx_ring)
+{
+       writel(1, tx_ring->crb_intr_mask);
+}
+
+/* Enable MSI-x and INT-x interrupts */
+static inline void
+qlcnic_83xx_enable_sds_intr(struct qlcnic_adapter *adapter,
+                           struct qlcnic_host_sds_ring *sds_ring)
+{
+       writel(0, sds_ring->crb_intr_mask);
+}
+
+/* Disable MSI-x and INT-x interrupts */
+static inline void
+qlcnic_83xx_disable_sds_intr(struct qlcnic_adapter *adapter,
+                            struct qlcnic_host_sds_ring *sds_ring)
+{
+       writel(1, sds_ring->crb_intr_mask);
+}
+
 static inline void qlcnic_disable_multi_tx(struct qlcnic_adapter *adapter)
 {
        test_and_clear_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state);
@@ -2038,10 +2100,10 @@ static inline void qlcnic_disable_multi_tx(struct qlcnic_adapter *adapter)
 /* When operating in a muti tx mode, driver needs to write 0x1
  * to src register, instead of 0x0 to disable receiving interrupt.
  */
-static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
+static inline void
+qlcnic_82xx_disable_sds_intr(struct qlcnic_adapter *adapter,
+                            struct qlcnic_host_sds_ring *sds_ring)
 {
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-
        if (qlcnic_check_multi_tx(adapter) &&
            !adapter->ahw->diag_test &&
            (adapter->flags & QLCNIC_MSIX_ENABLED))
@@ -2050,13 +2112,42 @@ static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
                writel(0, sds_ring->crb_intr_mask);
 }
 
+static inline void qlcnic_enable_sds_intr(struct qlcnic_adapter *adapter,
+                                         struct qlcnic_host_sds_ring *sds_ring)
+{
+       if (adapter->ahw->hw_ops->enable_sds_intr)
+               adapter->ahw->hw_ops->enable_sds_intr(adapter, sds_ring);
+}
+
+static inline void
+qlcnic_disable_sds_intr(struct qlcnic_adapter *adapter,
+                       struct qlcnic_host_sds_ring *sds_ring)
+{
+       if (adapter->ahw->hw_ops->disable_sds_intr)
+               adapter->ahw->hw_ops->disable_sds_intr(adapter, sds_ring);
+}
+
+static inline void qlcnic_enable_tx_intr(struct qlcnic_adapter *adapter,
+                                        struct qlcnic_host_tx_ring *tx_ring)
+{
+       if (adapter->ahw->hw_ops->enable_tx_intr)
+               adapter->ahw->hw_ops->enable_tx_intr(adapter, tx_ring);
+}
+
+static inline void qlcnic_disable_tx_intr(struct qlcnic_adapter *adapter,
+                                         struct qlcnic_host_tx_ring *tx_ring)
+{
+       if (adapter->ahw->hw_ops->disable_tx_intr)
+               adapter->ahw->hw_ops->disable_tx_intr(adapter, tx_ring);
+}
+
 /* When operating in a muti tx mode, driver needs to write 0x0
  * to src register, instead of 0x1 to enable receiving interrupts.
  */
-static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
+static inline void
+qlcnic_82xx_enable_sds_intr(struct qlcnic_adapter *adapter,
+                           struct qlcnic_host_sds_ring *sds_ring)
 {
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-
        if (qlcnic_check_multi_tx(adapter) &&
            !adapter->ahw->diag_test &&
            (adapter->flags & QLCNIC_MSIX_ENABLED))
index 294984584d1a50217fbe92a292e62e816eee680c..4146664d4d6a43978789081713b858b3f982de0e 100644 (file)
@@ -199,6 +199,11 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
        .io_slot_reset                  = qlcnic_83xx_io_slot_reset,
        .io_resume                      = qlcnic_83xx_io_resume,
        .get_beacon_state               = qlcnic_83xx_get_beacon_state,
+       .enable_sds_intr                = qlcnic_83xx_enable_sds_intr,
+       .disable_sds_intr               = qlcnic_83xx_disable_sds_intr,
+       .enable_tx_intr                 = qlcnic_83xx_enable_tx_intr,
+       .disable_tx_intr                = qlcnic_83xx_disable_tx_intr,
+
 };
 
 static struct qlcnic_nic_template qlcnic_83xx_ops = {
@@ -285,11 +290,22 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
        }
 }
 
-int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
+static void qlcnic_83xx_enable_legacy(struct qlcnic_adapter *adapter)
 {
-       int err, i, num_msix;
        struct qlcnic_hardware_context *ahw = adapter->ahw;
 
+       /* MSI-X enablement failed, use legacy interrupt */
+       adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR;
+       adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK;
+       adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR;
+       adapter->msix_entries[0].vector = adapter->pdev->irq;
+       dev_info(&adapter->pdev->dev, "using legacy interrupt\n");
+}
+
+static int qlcnic_83xx_calculate_msix_vector(struct qlcnic_adapter *adapter)
+{
+       int num_msix;
+
        num_msix = adapter->drv_sds_rings;
 
        /* account for AEN interrupt MSI-X based interrupts */
@@ -298,30 +314,44 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
        if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
                num_msix += adapter->drv_tx_rings;
 
-       err = qlcnic_enable_msix(adapter, num_msix);
-       if (err == -ENOMEM)
-               return err;
-       if (adapter->flags & QLCNIC_MSIX_ENABLED)
-               num_msix = adapter->ahw->num_msix;
-       else {
-               if (qlcnic_sriov_vf_check(adapter))
-                       return -EINVAL;
-               num_msix = 1;
-               adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
+       return num_msix;
+}
+
+int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       int err, i, num_msix;
+
+       if (adapter->flags & QLCNIC_TSS_RSS) {
+               err = qlcnic_setup_tss_rss_intr(adapter);
+               if (err < 0)
+                       return err;
+               num_msix = ahw->num_msix;
+       } else {
+               num_msix = qlcnic_83xx_calculate_msix_vector(adapter);
+
+               err = qlcnic_enable_msix(adapter, num_msix);
+               if (err == -ENOMEM)
+                       return err;
+
+               if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+                       num_msix = ahw->num_msix;
+               } else {
+                       if (qlcnic_sriov_vf_check(adapter))
+                               return -EINVAL;
+                       num_msix = 1;
+                       adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
+               }
        }
+
        /* setup interrupt mapping table for fw */
        ahw->intr_tbl = vzalloc(num_msix *
                                sizeof(struct qlcnic_intrpt_config));
        if (!ahw->intr_tbl)
                return -ENOMEM;
-       if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-               /* MSI-X enablement failed, use legacy interrupt */
-               adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR;
-               adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK;
-               adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR;
-               adapter->msix_entries[0].vector = adapter->pdev->irq;
-               dev_info(&adapter->pdev->dev, "using legacy interrupt\n");
-       }
+
+       if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
+               qlcnic_83xx_enable_legacy(adapter);
 
        for (i = 0; i < num_msix; i++) {
                if (adapter->flags & QLCNIC_MSIX_ENABLED)
@@ -331,6 +361,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
                ahw->intr_tbl[i].id = i;
                ahw->intr_tbl[i].src = 0;
        }
+
        return 0;
 }
 
@@ -345,20 +376,6 @@ static inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapt
                writel(1, adapter->tgt_mask_reg);
 }
 
-/* Enable MSI-x and INT-x interrupts */
-void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter,
-                            struct qlcnic_host_sds_ring *sds_ring)
-{
-       writel(0, sds_ring->crb_intr_mask);
-}
-
-/* Disable MSI-x and INT-x interrupts */
-void qlcnic_83xx_disable_intr(struct qlcnic_adapter *adapter,
-                             struct qlcnic_host_sds_ring *sds_ring)
-{
-       writel(1, sds_ring->crb_intr_mask);
-}
-
 static inline void qlcnic_83xx_enable_legacy_msix_mbx_intr(struct qlcnic_adapter
                                                    *adapter)
 {
@@ -496,7 +513,7 @@ irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data)
 
 done:
        adapter->ahw->diag_cnt++;
-       qlcnic_83xx_enable_intr(adapter, sds_ring);
+       qlcnic_enable_sds_intr(adapter, sds_ring);
 
        return IRQ_HANDLED;
 }
@@ -1295,8 +1312,8 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
        /* send the mailbox command*/
        err = qlcnic_issue_cmd(adapter, &cmd);
        if (err) {
-               dev_err(&adapter->pdev->dev,
-                       "Failed to create Tx ctx in firmware 0x%x\n", err);
+               netdev_err(adapter->netdev,
+                          "Failed to create Tx ctx in firmware 0x%x\n", err);
                goto out;
        }
        mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2];
@@ -1307,8 +1324,9 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
                intr_mask = ahw->intr_tbl[adapter->drv_sds_rings + ring].src;
                tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
        }
-       dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n",
-                tx->ctx_id, mbx_out->state);
+       netdev_info(adapter->netdev,
+                   "Tx Context[0x%x] Created, state:0x%x\n",
+                   tx->ctx_id, mbx_out->state);
 out:
        qlcnic_free_mbx_args(&cmd);
        return err;
@@ -1360,7 +1378,7 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
        if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
-                       qlcnic_83xx_enable_intr(adapter, sds_ring);
+                       qlcnic_enable_sds_intr(adapter, sds_ring);
                }
        }
 
@@ -1385,7 +1403,7 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
                for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
                        if (adapter->flags & QLCNIC_MSIX_ENABLED)
-                               qlcnic_83xx_disable_intr(adapter, sds_ring);
+                               qlcnic_disable_sds_intr(adapter, sds_ring);
                }
        }
 
@@ -1637,7 +1655,7 @@ static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,
        if (qlcnic_sriov_pf_check(adapter)) {
                qlcnic_alloc_lb_filters_mem(adapter);
                qlcnic_pf_set_interface_id_promisc(adapter, interface_id);
-               adapter->rx_mac_learn = 1;
+               adapter->rx_mac_learn = true;
        } else {
                if (!qlcnic_sriov_vf_check(adapter))
                        *interface_id = adapter->recv_ctx->context_id << 16;
@@ -2111,37 +2129,130 @@ int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac,
        return err;
 }
 
-void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
+static int qlcnic_83xx_set_rx_intr_coal(struct qlcnic_adapter *adapter)
 {
-       int err;
-       u16 temp;
-       struct qlcnic_cmd_args cmd;
        struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
+       struct qlcnic_cmd_args cmd;
+       u16 temp;
+       int err;
 
-       if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
-               return;
+       err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
+       if (err)
+               return err;
+
+       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;
+       cmd.req.arg[3] = coal->flag;
+
+       err = qlcnic_issue_cmd(adapter, &cmd);
+       if (err != QLCNIC_RCODE_SUCCESS)
+               netdev_err(adapter->netdev,
+                          "failed to set interrupt coalescing parameters\n");
+
+       qlcnic_free_mbx_args(&cmd);
+
+       return err;
+}
+
+static int qlcnic_83xx_set_tx_intr_coal(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
+       struct qlcnic_cmd_args cmd;
+       u16 temp;
+       int err;
 
        err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
        if (err)
-               return;
+               return err;
 
-       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;
-       }
+       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;
+
        err = qlcnic_issue_cmd(adapter, &cmd);
        if (err != QLCNIC_RCODE_SUCCESS)
-               dev_info(&adapter->pdev->dev,
-                        "Failed to send interrupt coalescence parameters\n");
+               netdev_err(adapter->netdev,
+                          "failed to set interrupt coalescing  parameters\n");
+
        qlcnic_free_mbx_args(&cmd);
+
+       return err;
+}
+
+int qlcnic_83xx_set_rx_tx_intr_coal(struct qlcnic_adapter *adapter)
+{
+       int err = 0;
+
+       err = qlcnic_83xx_set_rx_intr_coal(adapter);
+       if (err)
+               netdev_err(adapter->netdev,
+                          "failed to set Rx coalescing parameters\n");
+
+       err = qlcnic_83xx_set_tx_intr_coal(adapter);
+       if (err)
+               netdev_err(adapter->netdev,
+                          "failed to set Tx coalescing parameters\n");
+
+       return err;
+}
+
+int qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter,
+                                struct ethtool_coalesce *ethcoal)
+{
+       struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
+       u32 rx_coalesce_usecs, rx_max_frames;
+       u32 tx_coalesce_usecs, tx_max_frames;
+       int err;
+
+       if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
+               return -EIO;
+
+       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 = QLCNIC_INTR_DEFAULT;
+
+       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_TX;
+               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;
+       }
+
+       switch (coal->type) {
+       case QLCNIC_INTR_COAL_TYPE_RX:
+               err = qlcnic_83xx_set_rx_intr_coal(adapter);
+               break;
+       case QLCNIC_INTR_COAL_TYPE_TX:
+               err = qlcnic_83xx_set_tx_intr_coal(adapter);
+               break;
+       case QLCNIC_INTR_COAL_TYPE_RX_TX:
+               err = qlcnic_83xx_set_rx_tx_intr_coal(adapter);
+               break;
+       default:
+               err = -EINVAL;
+               netdev_err(adapter->netdev,
+                          "Invalid Interrupt coalescing type\n");
+               break;
+       }
+
+       return err;
 }
 
 static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
index a5ca3f460b2dab4c602a9d853857725a390b6e1d..f92485ca21d1131d989890f16f91a470847051c1 100644 (file)
@@ -547,7 +547,6 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32);
 int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32);
 int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *, int);
 int qlcnic_83xx_config_rss(struct qlcnic_adapter *, int);
-int qlcnic_83xx_config_intr_coalesce(struct qlcnic_adapter *);
 void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, u16);
 int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *);
 int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
@@ -577,17 +576,15 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *,
 void qlcnic_free_mbx_args(struct qlcnic_cmd_args *);
 void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *,
                          struct qlcnic_info *);
-void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *);
+int qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *,
+                                struct ethtool_coalesce *);
+int qlcnic_83xx_set_rx_tx_intr_coal(struct qlcnic_adapter *);
 int qlcnic_83xx_get_port_info(struct qlcnic_adapter *);
 void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *);
 void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *);
 irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *);
 irqreturn_t qlcnic_83xx_intr(int, void *);
 irqreturn_t qlcnic_83xx_tmp_intr(int, void *);
-void qlcnic_83xx_enable_intr(struct qlcnic_adapter *,
-                            struct qlcnic_host_sds_ring *);
-void qlcnic_83xx_disable_intr(struct qlcnic_adapter *,
-                            struct qlcnic_host_sds_ring *);
 void qlcnic_83xx_check_vf(struct qlcnic_adapter *,
                          const struct pci_device_id *);
 int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *);
index 6d7f6a170869d6d96a460ba0703adba410cc33ba..90a2dda351ec0eeba96930533402d5e6d098a2a8 100644 (file)
@@ -383,7 +383,7 @@ static int qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter *adapter)
        qlcnic_up(adapter, netdev);
        netif_device_attach(netdev);
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
-       dev_err(&adapter->pdev->dev, "%s:\n", __func__);
+       netdev_info(adapter->netdev, "%s: soft reset complete.\n", __func__);
 
        return 0;
 }
@@ -2217,7 +2217,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        int err = 0;
 
-       adapter->rx_mac_learn = 0;
+       adapter->rx_mac_learn = false;
        ahw->msix_supported = !!qlcnic_use_msi_x;
 
        qlcnic_83xx_init_rings(adapter);
index e26c49fa87ab2337511c6c85dc50bcf470c099a2..be7d7a62cc0d8c885c1f669f6c01f0f3a2259ea0 100644 (file)
@@ -227,10 +227,10 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
        if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) {
                adapter->flags |= QLCNIC_ESWITCH_ENABLED;
                if (adapter->drv_mac_learn)
-                       adapter->rx_mac_learn = 1;
+                       adapter->rx_mac_learn = true;
        } else {
                adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
-               adapter->rx_mac_learn = 0;
+               adapter->rx_mac_learn = false;
        }
 
        ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
index 45961e310194635cfeae014947d0f9693a472e81..acee1a5d80c6521095c755418eb8c46197d9cec7 100644 (file)
@@ -736,6 +736,7 @@ static int qlcnic_set_channels(struct net_device *dev,
                                   channel->rx_count);
                        return err;
                }
+               adapter->drv_rss_rings = channel->rx_count;
        }
 
        if (channel->tx_count) {
@@ -746,10 +747,12 @@ static int qlcnic_set_channels(struct net_device *dev,
                                   channel->tx_count);
                        return err;
                }
+               adapter->drv_tss_rings = channel->tx_count;
        }
 
-       err = qlcnic_setup_rings(adapter, channel->rx_count,
-                                channel->tx_count);
+       adapter->flags |= QLCNIC_TSS_RSS;
+
+       err = qlcnic_setup_rings(adapter);
        netdev_info(dev, "Allocated %d SDS rings and %d Tx rings\n",
                    adapter->drv_sds_rings, adapter->drv_tx_rings);
 
@@ -1495,9 +1498,7 @@ 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;
+       int err;
 
        if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
                return -EINVAL;
@@ -1507,82 +1508,31 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
        * unsupported parameters are set.
        */
        if (ethcoal->rx_coalesce_usecs > 0xffff ||
-               ethcoal->rx_max_coalesced_frames > 0xffff ||
-               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 ||
-               ethcoal->tx_max_coalesced_frames_irq ||
-               ethcoal->stats_block_coalesce_usecs ||
-               ethcoal->use_adaptive_rx_coalesce ||
-               ethcoal->use_adaptive_tx_coalesce ||
-               ethcoal->pkt_rate_low ||
-               ethcoal->rx_coalesce_usecs_low ||
-               ethcoal->rx_max_coalesced_frames_low ||
-               ethcoal->tx_coalesce_usecs_low ||
-               ethcoal->tx_max_coalesced_frames_low ||
-               ethcoal->pkt_rate_high ||
-               ethcoal->rx_coalesce_usecs_high ||
-               ethcoal->rx_max_coalesced_frames_high ||
-               ethcoal->tx_coalesce_usecs_high ||
-               ethcoal->tx_max_coalesced_frames_high)
+           ethcoal->rx_max_coalesced_frames > 0xffff ||
+           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 ||
+           ethcoal->tx_max_coalesced_frames_irq ||
+           ethcoal->stats_block_coalesce_usecs ||
+           ethcoal->use_adaptive_rx_coalesce ||
+           ethcoal->use_adaptive_tx_coalesce ||
+           ethcoal->pkt_rate_low ||
+           ethcoal->rx_coalesce_usecs_low ||
+           ethcoal->rx_max_coalesced_frames_low ||
+           ethcoal->tx_coalesce_usecs_low ||
+           ethcoal->tx_max_coalesced_frames_low ||
+           ethcoal->pkt_rate_high ||
+           ethcoal->rx_coalesce_usecs_high ||
+           ethcoal->rx_max_coalesced_frames_high ||
+           ethcoal->tx_coalesce_usecs_high ||
+           ethcoal->tx_max_coalesced_frames_high)
                return -EINVAL;
 
-       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 {
-               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);
+       err = qlcnic_config_intr_coalesce(adapter, ethcoal);
 
-       return 0;
+       return err;
 }
 
 static int qlcnic_get_intr_coalesce(struct net_device *netdev,
index e86147912922adc2bdff8e0a8b5f51a5d6a99567..03d18a0be6ce98cd8ab517d9623983de22a99672 100644 (file)
@@ -547,10 +547,10 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
                qlcnic_alloc_lb_filters_mem(adapter);
                adapter->drv_mac_learn = 1;
                if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
-                       adapter->rx_mac_learn = 1;
+                       adapter->rx_mac_learn = true;
        } else {
                adapter->drv_mac_learn = 0;
-               adapter->rx_mac_learn = 0;
+               adapter->rx_mac_learn = false;
        }
 
        qlcnic_nic_set_promisc(adapter, mode);
@@ -755,10 +755,7 @@ int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *adapter)
        return 0;
 }
 
-/*
- * Send the interrupt coalescing parameter set by ethtool to the card.
- */
-void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
+int qlcnic_82xx_set_rx_coalesce(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_nic_req req;
        int rv;
@@ -780,6 +777,28 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
        if (rv != 0)
                dev_err(&adapter->netdev->dev,
                        "Could not send interrupt coalescing parameters\n");
+
+       return rv;
+}
+
+/* Send the interrupt coalescing parameter set by ethtool to the card. */
+int qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter,
+                                    struct ethtool_coalesce *ethcoal)
+{
+       struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
+       int rv;
+
+       coal->flag = QLCNIC_INTR_DEFAULT;
+       coal->rx_time_us = ethcoal->rx_coalesce_usecs;
+       coal->rx_packets = ethcoal->rx_max_coalesced_frames;
+
+       rv = qlcnic_82xx_set_rx_coalesce(adapter);
+
+       if (rv)
+               netdev_err(adapter->netdev,
+                          "Failed to set Rx coalescing parametrs\n");
+
+       return rv;
 }
 
 #define QLCNIC_ENABLE_IPV4_LRO         BIT_0
index 17f563de90f1b66c9959d7066b7ba2b2557fe5c5..63d75617d445a2de9c6e9d998cc58d1a105f7b16 100644 (file)
@@ -171,7 +171,9 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
 void qlcnic_82xx_get_beacon_state(struct qlcnic_adapter *);
 void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter,
                               u64 *uaddr, u16 vlan_id);
-void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter);
+int qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *,
+                                    struct ethtool_coalesce *);
+int qlcnic_82xx_set_rx_coalesce(struct qlcnic_adapter *);
 int qlcnic_82xx_config_rss(struct qlcnic_adapter *adapter, int);
 void qlcnic_82xx_config_ipaddr(struct qlcnic_adapter *adapter,
                               __be32, int);
index 0df6988e42a967f757c8bf0385902a5dc653a490..30874cda84764996735d2a070ab45516311e8def 100644 (file)
@@ -131,35 +131,6 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *,
                                            struct qlcnic_host_rds_ring *,
                                            u16, u16);
 
-static inline void qlcnic_enable_tx_intr(struct qlcnic_adapter *adapter,
-                                 struct qlcnic_host_tx_ring *tx_ring)
-{
-       if (qlcnic_check_multi_tx(adapter) &&
-           !adapter->ahw->diag_test)
-               writel(0x0, tx_ring->crb_intr_mask);
-}
-
-
-static inline void qlcnic_disable_tx_int(struct qlcnic_adapter *adapter,
-                                        struct qlcnic_host_tx_ring *tx_ring)
-{
-       if (qlcnic_check_multi_tx(adapter) &&
-           !adapter->ahw->diag_test)
-               writel(1, tx_ring->crb_intr_mask);
-}
-
-static inline void qlcnic_83xx_enable_tx_intr(struct qlcnic_adapter *adapter,
-                                      struct qlcnic_host_tx_ring *tx_ring)
-{
-       writel(0, tx_ring->crb_intr_mask);
-}
-
-static inline void qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter,
-                                       struct qlcnic_host_tx_ring *tx_ring)
-{
-       writel(1, tx_ring->crb_intr_mask);
-}
-
 static inline u8 qlcnic_mac_hash(u64 mac, u16 vlan)
 {
        return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff) ^ (vlan & 0xff));
@@ -885,7 +856,7 @@ static int qlcnic_poll(struct napi_struct *napi, int budget)
        if ((work_done < budget) && tx_complete) {
                napi_complete(&sds_ring->napi);
                if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
-                       qlcnic_enable_int(sds_ring);
+                       qlcnic_enable_sds_intr(adapter, sds_ring);
                        qlcnic_enable_tx_intr(adapter, tx_ring);
                }
        }
@@ -926,7 +897,7 @@ static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
        if (work_done < budget) {
                napi_complete(&sds_ring->napi);
                if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
-                       qlcnic_enable_int(sds_ring);
+                       qlcnic_enable_sds_intr(adapter, sds_ring);
        }
 
        return work_done;
@@ -1557,7 +1528,7 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter)
        for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
                napi_enable(&sds_ring->napi);
-               qlcnic_enable_int(sds_ring);
+               qlcnic_enable_sds_intr(adapter, sds_ring);
        }
 
        if (qlcnic_check_multi_tx(adapter) &&
@@ -1583,7 +1554,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
 
        for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
-               qlcnic_disable_int(sds_ring);
+               qlcnic_disable_sds_intr(adapter, sds_ring);
                napi_synchronize(&sds_ring->napi);
                napi_disable(&sds_ring->napi);
        }
@@ -1593,7 +1564,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
            qlcnic_check_multi_tx(adapter)) {
                for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
                        tx_ring = &adapter->tx_ring[ring];
-                       qlcnic_disable_tx_int(adapter, tx_ring);
+                       qlcnic_disable_tx_intr(adapter, tx_ring);
                        napi_synchronize(&tx_ring->napi);
                        napi_disable(&tx_ring->napi);
                }
@@ -1856,7 +1827,7 @@ static int qlcnic_83xx_msix_sriov_vf_poll(struct napi_struct *napi, int budget)
        work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
        if ((work_done < budget) && tx_complete) {
                napi_complete(&sds_ring->napi);
-               qlcnic_83xx_enable_intr(adapter, sds_ring);
+               qlcnic_enable_sds_intr(adapter, sds_ring);
        }
 
        return work_done;
@@ -1879,7 +1850,7 @@ static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
        work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
        if ((work_done < budget) && tx_complete) {
                napi_complete(&sds_ring->napi);
-               qlcnic_83xx_enable_intr(adapter, sds_ring);
+               qlcnic_enable_sds_intr(adapter, sds_ring);
        }
 
        return work_done;
@@ -1898,7 +1869,7 @@ static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget)
        if (work_done) {
                napi_complete(&tx_ring->napi);
                if (test_bit(__QLCNIC_DEV_UP , &adapter->state))
-                       qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
+                       qlcnic_enable_tx_intr(adapter, tx_ring);
        }
 
        return work_done;
@@ -1916,7 +1887,7 @@ static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget)
        if (work_done < budget) {
                napi_complete(&sds_ring->napi);
                if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
-                       qlcnic_83xx_enable_intr(adapter, sds_ring);
+                       qlcnic_enable_sds_intr(adapter, sds_ring);
        }
 
        return work_done;
@@ -1936,7 +1907,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
                sds_ring = &recv_ctx->sds_rings[ring];
                napi_enable(&sds_ring->napi);
                if (adapter->flags & QLCNIC_MSIX_ENABLED)
-                       qlcnic_83xx_enable_intr(adapter, sds_ring);
+                       qlcnic_enable_sds_intr(adapter, sds_ring);
        }
 
        if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
@@ -1944,7 +1915,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
                for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
                        tx_ring = &adapter->tx_ring[ring];
                        napi_enable(&tx_ring->napi);
-                       qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
+                       qlcnic_enable_tx_intr(adapter, tx_ring);
                }
        }
 }
@@ -1962,7 +1933,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
        for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
                if (adapter->flags & QLCNIC_MSIX_ENABLED)
-                       qlcnic_83xx_disable_intr(adapter, sds_ring);
+                       qlcnic_disable_sds_intr(adapter, sds_ring);
                napi_synchronize(&sds_ring->napi);
                napi_disable(&sds_ring->napi);
        }
@@ -1971,7 +1942,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
            !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
                for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
                        tx_ring = &adapter->tx_ring[ring];
-                       qlcnic_83xx_disable_tx_intr(adapter, tx_ring);
+                       qlcnic_disable_tx_intr(adapter, tx_ring);
                        napi_synchronize(&tx_ring->napi);
                        napi_disable(&tx_ring->napi);
                }
index e2ee2bb5cd5c4d043df4b73a111a2e369a78e2a8..1f79d47c45fa3c9ec9b747958c71428cd0850ce5 100644 (file)
@@ -557,6 +557,10 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
        .io_slot_reset                  = qlcnic_82xx_io_slot_reset,
        .io_resume                      = qlcnic_82xx_io_resume,
        .get_beacon_state               = qlcnic_82xx_get_beacon_state,
+       .enable_sds_intr                = qlcnic_82xx_enable_sds_intr,
+       .disable_sds_intr               = qlcnic_82xx_disable_sds_intr,
+       .enable_tx_intr                 = qlcnic_82xx_enable_tx_intr,
+       .disable_tx_intr                = qlcnic_82xx_disable_tx_intr,
 };
 
 static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter)
@@ -599,9 +603,6 @@ void qlcnic_set_tx_ring_count(struct qlcnic_adapter *adapter, u8 tx_cnt)
                                                         QLCNIC_TX_QUEUE);
        else
                adapter->drv_tx_rings = tx_cnt;
-
-       dev_info(&adapter->pdev->dev, "Set %d Tx rings\n",
-                adapter->drv_tx_rings);
 }
 
 void qlcnic_set_sds_ring_count(struct qlcnic_adapter *adapter, u8 rx_cnt)
@@ -612,25 +613,79 @@ void qlcnic_set_sds_ring_count(struct qlcnic_adapter *adapter, u8 rx_cnt)
                                                          QLCNIC_RX_QUEUE);
        else
                adapter->drv_sds_rings = rx_cnt;
-
-       dev_info(&adapter->pdev->dev, "Set %d SDS rings\n",
-                adapter->drv_sds_rings);
 }
 
-int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
+int qlcnic_setup_tss_rss_intr(struct qlcnic_adapter *adapter)
 {
        struct pci_dev *pdev = adapter->pdev;
-       int drv_tx_rings, drv_sds_rings, tx_vector;
-       int err = -1, i;
+       int num_msix = 0, err = 0, vector;
+
+       adapter->flags &= ~QLCNIC_TSS_RSS;
+
+       if (adapter->drv_tss_rings > 0)
+               num_msix += adapter->drv_tss_rings;
+       else
+               num_msix += adapter->drv_tx_rings;
+
+       if (adapter->drv_rss_rings  > 0)
+               num_msix += adapter->drv_rss_rings;
+       else
+               num_msix += adapter->drv_sds_rings;
 
-       if (adapter->flags & QLCNIC_TX_INTR_SHARED) {
-               drv_tx_rings = 0;
-               tx_vector = 0;
+       if (qlcnic_83xx_check(adapter))
+               num_msix += 1;
+
+       if (!adapter->msix_entries) {
+               adapter->msix_entries = kcalloc(num_msix,
+                                               sizeof(struct msix_entry),
+                                               GFP_KERNEL);
+               if (!adapter->msix_entries)
+                       return -ENOMEM;
+       }
+
+restore:
+       for (vector = 0; vector < num_msix; vector++)
+               adapter->msix_entries[vector].entry = vector;
+
+       err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
+       if (err == 0) {
+               adapter->ahw->num_msix = num_msix;
+               if (adapter->drv_tss_rings > 0)
+                       adapter->drv_tx_rings = adapter->drv_tss_rings;
+
+               if (adapter->drv_rss_rings > 0)
+                       adapter->drv_sds_rings = adapter->drv_rss_rings;
        } else {
-               drv_tx_rings = adapter->drv_tx_rings;
-               tx_vector = 1;
+               netdev_info(adapter->netdev,
+                           "Unable to allocate %d MSI-X vectors, Available vectors %d\n",
+                           num_msix, err);
+
+               num_msix = adapter->drv_tx_rings + adapter->drv_sds_rings;
+
+               /* Set rings to 0 so we can restore original TSS/RSS count */
+               adapter->drv_tss_rings = 0;
+               adapter->drv_rss_rings = 0;
+
+               if (qlcnic_83xx_check(adapter))
+                       num_msix += 1;
+
+               netdev_info(adapter->netdev,
+                           "Restoring %d Tx, %d SDS rings for total %d vectors.\n",
+                           adapter->drv_tx_rings, adapter->drv_sds_rings,
+                           num_msix);
+               goto restore;
+
+               err = -EIO;
        }
 
+       return err;
+}
+
+int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
+{
+       struct pci_dev *pdev = adapter->pdev;
+       int err = -1, vector;
+
        if (!adapter->msix_entries) {
                adapter->msix_entries = kcalloc(num_msix,
                                                sizeof(struct msix_entry),
@@ -639,47 +694,43 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
                        return -ENOMEM;
        }
 
-       adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
        adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);
 
        if (adapter->ahw->msix_supported) {
- enable_msix:
-               for (i = 0; i < num_msix; i++)
-                       adapter->msix_entries[i].entry = i;
+enable_msix:
+               for (vector = 0; vector < num_msix; vector++)
+                       adapter->msix_entries[vector].entry = vector;
+
                err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
                if (err == 0) {
                        adapter->flags |= QLCNIC_MSIX_ENABLED;
-                       if (qlcnic_83xx_check(adapter)) {
-                               adapter->ahw->num_msix = num_msix;
-                               /* subtract mail box and tx ring vectors */
-                               adapter->drv_sds_rings = num_msix -
-                                                        drv_tx_rings - 1;
-                       } else {
-                               adapter->ahw->num_msix = num_msix;
-                               if (qlcnic_check_multi_tx(adapter) &&
-                                   !adapter->ahw->diag_test)
-                                       drv_sds_rings = num_msix - drv_tx_rings;
-                               else
-                                       drv_sds_rings = num_msix;
-
-                               adapter->drv_sds_rings = drv_sds_rings;
-                       }
+                       adapter->ahw->num_msix = num_msix;
                        dev_info(&pdev->dev, "using msi-x interrupts\n");
                        return err;
                } else if (err > 0) {
                        dev_info(&pdev->dev,
-                                "Unable to allocate %d MSI-X interrupt vectors\n",
-                                num_msix);
-                       if (qlcnic_83xx_check(adapter)) {
-                               if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector))
-                                       return err;
-                               err -= drv_tx_rings + 1;
+                                "Unable to allocate %d MSI-X vectors, Available vectors %d\n",
+                                num_msix, err);
+
+                       if (qlcnic_82xx_check(adapter)) {
                                num_msix = rounddown_pow_of_two(err);
-                               num_msix += drv_tx_rings + 1;
+                               if (err < QLCNIC_82XX_MINIMUM_VECTOR)
+                                       return -EIO;
                        } else {
-                               num_msix = rounddown_pow_of_two(err);
-                               if (qlcnic_check_multi_tx(adapter))
-                                       num_msix += drv_tx_rings;
+                               num_msix = rounddown_pow_of_two(err - 1);
+                               num_msix += 1;
+                               if (err < QLCNIC_83XX_MINIMUM_VECTOR)
+                                       return -EIO;
+                       }
+
+                       if (qlcnic_82xx_check(adapter) &&
+                           !qlcnic_check_multi_tx(adapter)) {
+                               adapter->drv_sds_rings = num_msix;
+                               adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
+                       } else {
+                               /* Distribute vectors equally */
+                               adapter->drv_tx_rings = num_msix / 2;
+                               adapter->drv_sds_rings = adapter->drv_tx_rings;
                        }
 
                        if (num_msix) {
@@ -690,14 +741,29 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
                        }
                } else {
                        dev_info(&pdev->dev,
-                                "Unable to allocate %d MSI-X interrupt vectors\n",
-                                num_msix);
+                                "Unable to allocate %d MSI-X vectors, err=%d\n",
+                                num_msix, err);
+                       return err;
                }
        }
 
        return err;
 }
 
+static int qlcnic_82xx_calculate_msix_vector(struct qlcnic_adapter *adapter)
+{
+       int num_msix;
+
+       num_msix = adapter->drv_sds_rings;
+
+       if (qlcnic_check_multi_tx(adapter))
+               num_msix += adapter->drv_tx_rings;
+       else
+               num_msix += QLCNIC_SINGLE_RING;
+
+       return num_msix;
+}
+
 static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
 {
        int err = 0;
@@ -736,21 +802,25 @@ static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter)
 {
        int num_msix, err = 0;
 
-       num_msix = adapter->drv_sds_rings;
-
-       if (qlcnic_check_multi_tx(adapter))
-               num_msix += adapter->drv_tx_rings;
+       if (adapter->flags & QLCNIC_TSS_RSS) {
+               err = qlcnic_setup_tss_rss_intr(adapter);
+               if (err < 0)
+                       return err;
+               num_msix = adapter->ahw->num_msix;
+       } else {
+               num_msix = qlcnic_82xx_calculate_msix_vector(adapter);
 
-       err = qlcnic_enable_msix(adapter, num_msix);
-       if (err == -ENOMEM)
-               return err;
+               err = qlcnic_enable_msix(adapter, num_msix);
+               if (err == -ENOMEM)
+                       return err;
 
-       if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-               qlcnic_disable_multi_tx(adapter);
+               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
+                       qlcnic_disable_multi_tx(adapter);
 
-               err = qlcnic_enable_msi_legacy(adapter);
-               if (!err)
-                       return err;
+                       err = qlcnic_enable_msi_legacy(adapter);
+                       if (!err)
+                               return err;
+               }
        }
 
        return 0;
@@ -1697,6 +1767,33 @@ static void qlcnic_get_lro_mss_capability(struct qlcnic_adapter *adapter)
        }
 }
 
+static int qlcnic_config_def_intr_coalesce(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       int err;
+
+       /* Initialize interrupt coalesce parameters */
+       ahw->coal.flag = QLCNIC_INTR_DEFAULT;
+
+       if (qlcnic_83xx_check(adapter)) {
+               ahw->coal.type = QLCNIC_INTR_COAL_TYPE_RX_TX;
+               ahw->coal.tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US;
+               ahw->coal.tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS;
+               ahw->coal.rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
+               ahw->coal.rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
+
+               err = qlcnic_83xx_set_rx_tx_intr_coal(adapter);
+       } else {
+               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;
+
+               err = qlcnic_82xx_set_rx_coalesce(adapter);
+       }
+
+       return err;
+}
+
 int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
 {
        int ring;
@@ -1729,7 +1826,7 @@ int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
        if (adapter->drv_sds_rings > 1)
                qlcnic_config_rss(adapter, 1);
 
-       qlcnic_config_intr_coalesce(adapter);
+       qlcnic_config_def_intr_coalesce(adapter);
 
        if (netdev->features & NETIF_F_LRO)
                qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
@@ -1874,7 +1971,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int drv_sds_rings)
        if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
-                       qlcnic_disable_int(sds_ring);
+                       qlcnic_disable_sds_intr(adapter, sds_ring);
                }
        }
 
@@ -1897,7 +1994,6 @@ 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),
@@ -1906,15 +2002,7 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
                err = -ENOMEM;
                goto err_out;
        }
-       /* Initialize interrupt coalesce parameters */
-       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:
@@ -1975,7 +2063,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
        if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
-                       qlcnic_enable_int(sds_ring);
+                       qlcnic_enable_sds_intr(adapter, sds_ring);
                }
        }
 
@@ -2007,7 +2095,7 @@ qlcnic_reset_hw_context(struct qlcnic_adapter *adapter)
        netif_device_attach(netdev);
 
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
-       dev_err(&adapter->pdev->dev, "%s:\n", __func__);
+       netdev_info(adapter->netdev, "%s: soft reset complete\n", __func__);
        return 0;
 }
 
@@ -2747,12 +2835,58 @@ int qlcnic_check_temp(struct qlcnic_adapter *adapter)
        return rv;
 }
 
-static void qlcnic_tx_timeout(struct net_device *netdev)
+static inline void dump_tx_ring_desc(struct qlcnic_host_tx_ring *tx_ring)
 {
-       struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       int i;
+       struct cmd_desc_type0 *tx_desc_info;
+
+       for (i = 0; i < tx_ring->num_desc; i++) {
+               tx_desc_info = &tx_ring->desc_head[i];
+               pr_info("TX Desc: %d\n", i);
+               print_hex_dump(KERN_INFO, "TX: ", DUMP_PREFIX_OFFSET, 16, 1,
+                              &tx_ring->desc_head[i],
+                              sizeof(struct cmd_desc_type0), true);
+       }
+}
+
+static void qlcnic_dump_tx_rings(struct qlcnic_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
        struct qlcnic_host_tx_ring *tx_ring;
        int ring;
 
+       if (!netdev || !netif_running(netdev))
+               return;
+
+       for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
+               tx_ring = &adapter->tx_ring[ring];
+               netdev_info(netdev, "Tx ring=%d Context Id=0x%x\n",
+                           ring, tx_ring->ctx_id);
+               netdev_info(netdev,
+                           "xmit_finished=%llu, xmit_called=%llu, xmit_on=%llu, xmit_off=%llu\n",
+                           tx_ring->tx_stats.xmit_finished,
+                           tx_ring->tx_stats.xmit_called,
+                           tx_ring->tx_stats.xmit_on,
+                           tx_ring->tx_stats.xmit_off);
+               netdev_info(netdev,
+                           "crb_intr_mask=%d, hw_producer=%d, sw_producer=%d sw_consumer=%d, hw_consumer=%d\n",
+                           readl(tx_ring->crb_intr_mask),
+                           readl(tx_ring->crb_cmd_producer),
+                           tx_ring->producer, tx_ring->sw_consumer,
+                           le32_to_cpu(*(tx_ring->hw_consumer)));
+
+               netdev_info(netdev, "Total desc=%d, Available desc=%d\n",
+                           tx_ring->num_desc, qlcnic_tx_avail(tx_ring));
+
+               if (netif_msg_tx_done(adapter->ahw))
+                       dump_tx_ring_desc(tx_ring);
+       }
+}
+
+static void qlcnic_tx_timeout(struct net_device *netdev)
+{
+       struct qlcnic_adapter *adapter = netdev_priv(netdev);
+
        if (test_bit(__QLCNIC_RESETTING, &adapter->state))
                return;
 
@@ -2765,22 +2899,7 @@ static void qlcnic_tx_timeout(struct net_device *netdev)
                                                      QLCNIC_FORCE_FW_DUMP_KEY);
        } else {
                netdev_info(netdev, "Tx timeout, reset adapter context.\n");
-               for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
-                       tx_ring = &adapter->tx_ring[ring];
-                       netdev_info(netdev, "Tx ring=%d\n", ring);
-                       netdev_info(netdev,
-                                   "crb_intr_mask=%d, producer=%d, sw_consumer=%d, hw_consumer=%d\n",
-                                   readl(tx_ring->crb_intr_mask),
-                                   readl(tx_ring->crb_cmd_producer),
-                                   tx_ring->sw_consumer,
-                                   le32_to_cpu(*(tx_ring->hw_consumer)));
-                       netdev_info(netdev,
-                                   "xmit_finished=%llu, xmit_called=%llu, xmit_on=%llu, xmit_off=%llu\n",
-                                   tx_ring->tx_stats.xmit_finished,
-                                   tx_ring->tx_stats.xmit_called,
-                                   tx_ring->tx_stats.xmit_on,
-                                   tx_ring->tx_stats.xmit_off);
-               }
+               qlcnic_dump_tx_rings(adapter);
                adapter->ahw->reset_context = 1;
        }
 }
@@ -2842,7 +2961,7 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
 
 done:
        adapter->ahw->diag_cnt++;
-       qlcnic_enable_int(sds_ring);
+       qlcnic_enable_sds_intr(adapter, sds_ring);
        return IRQ_HANDLED;
 }
 
@@ -2890,17 +3009,39 @@ static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void qlcnic_poll_controller(struct net_device *netdev)
 {
-       int ring;
-       struct qlcnic_host_sds_ring *sds_ring;
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
-       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+       struct qlcnic_host_sds_ring *sds_ring;
+       struct qlcnic_recv_context *recv_ctx;
+       struct qlcnic_host_tx_ring *tx_ring;
+       int ring;
+
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
+               return;
+
+       recv_ctx = adapter->recv_ctx;
 
-       disable_irq(adapter->irq);
        for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
-               qlcnic_intr(adapter->irq, sds_ring);
+               qlcnic_disable_sds_intr(adapter, sds_ring);
+               napi_schedule(&sds_ring->napi);
+       }
+
+       if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+               /* Only Multi-Tx queue capable devices need to
+                * schedule NAPI for TX rings
+                */
+               if ((qlcnic_83xx_check(adapter) &&
+                    (adapter->flags & QLCNIC_TX_INTR_SHARED)) ||
+                   (qlcnic_82xx_check(adapter) &&
+                    !qlcnic_check_multi_tx(adapter)))
+                       return;
+
+               for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
+                       tx_ring = &adapter->tx_ring[ring];
+                       qlcnic_disable_tx_intr(adapter, tx_ring);
+                       napi_schedule(&tx_ring->napi);
+               }
        }
-       enable_irq(adapter->irq);
 }
 #endif
 
@@ -3759,7 +3900,7 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt,
        return 0;
 }
 
-int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt)
+int qlcnic_setup_rings(struct qlcnic_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
        int err;
@@ -3780,12 +3921,6 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt)
 
        qlcnic_teardown_intr(adapter);
 
-       /* compute and set default and max tx/sds rings */
-       qlcnic_set_tx_ring_count(adapter, tx_cnt);
-       qlcnic_set_sds_ring_count(adapter, rx_cnt);
-
-       netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);
-
        err = qlcnic_setup_intr(adapter);
        if (err) {
                kfree(adapter->msix_entries);
@@ -3793,6 +3928,8 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt)
                return err;
        }
 
+       netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);
+
        if (qlcnic_83xx_check(adapter)) {
                qlcnic_83xx_initialize_nic(adapter, 1);
                err = qlcnic_83xx_setup_mbx_intr(adapter);
index db819e1b9469f346fef82415e6fd394fb02dcfc8..17a1ca2050f4eaa9f47f9394d43849ba6f97cfba 100644 (file)
@@ -71,6 +71,8 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
        .change_l2_filter               = qlcnic_83xx_change_l2_filter,
        .get_board_info                 = qlcnic_83xx_get_port_info,
        .free_mac_list                  = qlcnic_sriov_vf_free_mac_list,
+       .enable_sds_intr                = qlcnic_83xx_enable_sds_intr,
+       .disable_sds_intr               = qlcnic_83xx_disable_sds_intr,
 };
 
 static struct qlcnic_nic_template qlcnic_sriov_vf_ops = {