Commit 9fac865d authored by David S. Miller's avatar David S. Miller

Merge branch 'qlcnic'

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: default avatarZoltan Kiss <zoltan.kiss@citrix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0681a282 18cae184
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
#define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 3 #define _QLCNIC_LINUX_MINOR 3
#define _QLCNIC_LINUX_SUBVERSION 54 #define _QLCNIC_LINUX_SUBVERSION 55
#define QLCNIC_LINUX_VERSIONID "5.3.54" #define QLCNIC_LINUX_VERSIONID "5.3.55"
#define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
...@@ -105,6 +105,8 @@ ...@@ -105,6 +105,8 @@
#define QLCNIC_DEF_TX_RINGS 4 #define QLCNIC_DEF_TX_RINGS 4
#define QLCNIC_MAX_VNIC_TX_RINGS 4 #define QLCNIC_MAX_VNIC_TX_RINGS 4
#define QLCNIC_MAX_VNIC_SDS_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 { enum qlcnic_queue_type {
QLCNIC_TX_QUEUE = 1, QLCNIC_TX_QUEUE = 1,
...@@ -369,6 +371,7 @@ struct qlcnic_rx_buffer { ...@@ -369,6 +371,7 @@ struct qlcnic_rx_buffer {
*/ */
#define QLCNIC_INTR_COAL_TYPE_RX 1 #define QLCNIC_INTR_COAL_TYPE_RX 1
#define QLCNIC_INTR_COAL_TYPE_TX 2 #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_TIME_US 3
#define QLCNIC_DEF_INTR_COALESCE_RX_PACKETS 256 #define QLCNIC_DEF_INTR_COALESCE_RX_PACKETS 256
...@@ -961,6 +964,7 @@ struct qlcnic_ipaddr { ...@@ -961,6 +964,7 @@ struct qlcnic_ipaddr {
#define QLCNIC_TX_INTR_SHARED 0x10000 #define QLCNIC_TX_INTR_SHARED 0x10000
#define QLCNIC_APP_CHANGED_FLAGS 0x20000 #define QLCNIC_APP_CHANGED_FLAGS 0x20000
#define QLCNIC_HAS_PHYS_PORT_ID 0x40000 #define QLCNIC_HAS_PHYS_PORT_ID 0x40000
#define QLCNIC_TSS_RSS 0x80000
#define QLCNIC_IS_MSI_FAMILY(adapter) \ #define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
...@@ -1057,6 +1061,9 @@ struct qlcnic_adapter { ...@@ -1057,6 +1061,9 @@ struct qlcnic_adapter {
u8 drv_tx_rings; /* max tx rings supported by driver */ u8 drv_tx_rings; /* max tx rings supported by driver */
u8 drv_sds_rings; /* max sds 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 rx_csum;
u8 portnum; u8 portnum;
...@@ -1082,7 +1089,7 @@ struct qlcnic_adapter { ...@@ -1082,7 +1089,7 @@ struct qlcnic_adapter {
u64 dev_rst_time; u64 dev_rst_time;
bool drv_mac_learn; bool drv_mac_learn;
bool fdb_mac_learn; bool fdb_mac_learn;
u8 rx_mac_learn; bool rx_mac_learn;
unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)]; unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
u8 flash_mfg_id; u8 flash_mfg_id;
struct qlcnic_npar_info *npars; struct qlcnic_npar_info *npars;
...@@ -1573,7 +1580,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int); ...@@ -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 *); 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_tx_ring_count(struct qlcnic_adapter *, u8);
void qlcnic_set_sds_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); int qlcnic_validate_rings(struct qlcnic_adapter *, __u32, int);
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
int qlcnic_enable_msix(struct qlcnic_adapter *, u32); int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
...@@ -1613,7 +1620,7 @@ void qlcnic_set_vlan_config(struct qlcnic_adapter *, ...@@ -1613,7 +1620,7 @@ void qlcnic_set_vlan_config(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *); struct qlcnic_esw_func_cfg *);
void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *, void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *); struct qlcnic_esw_func_cfg *);
int qlcnic_setup_tss_rss_intr(struct qlcnic_adapter *);
void qlcnic_down(struct qlcnic_adapter *, struct net_device *); void qlcnic_down(struct qlcnic_adapter *, struct net_device *);
int qlcnic_up(struct qlcnic_adapter *, struct net_device *); int qlcnic_up(struct qlcnic_adapter *, struct net_device *);
void __qlcnic_down(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, ...@@ -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); err = netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);
if (err) if (err)
dev_err(&adapter->pdev->dev, "failed to set %d Tx queues\n", netdev_err(netdev, "failed to set %d Tx queues\n",
adapter->drv_tx_rings); adapter->drv_tx_rings);
else
dev_info(&adapter->pdev->dev, "Set %d Tx queues\n",
adapter->drv_tx_rings);
return err; return err;
} }
...@@ -1740,7 +1744,8 @@ struct qlcnic_hardware_ops { ...@@ -1740,7 +1744,8 @@ struct qlcnic_hardware_ops {
int (*change_macvlan) (struct qlcnic_adapter *, u8*, u16, u8); int (*change_macvlan) (struct qlcnic_adapter *, u8*, u16, u8);
void (*napi_enable) (struct qlcnic_adapter *); void (*napi_enable) (struct qlcnic_adapter *);
void (*napi_disable) (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_rss) (struct qlcnic_adapter *, int);
int (*config_hw_lro) (struct qlcnic_adapter *, int); int (*config_hw_lro) (struct qlcnic_adapter *, int);
int (*config_loopback) (struct qlcnic_adapter *, u8); int (*config_loopback) (struct qlcnic_adapter *, u8);
...@@ -1756,6 +1761,14 @@ struct qlcnic_hardware_ops { ...@@ -1756,6 +1761,14 @@ struct qlcnic_hardware_ops {
pci_ers_result_t (*io_slot_reset) (struct pci_dev *); pci_ers_result_t (*io_slot_reset) (struct pci_dev *);
void (*io_resume) (struct pci_dev *); void (*io_resume) (struct pci_dev *);
void (*get_beacon_state)(struct qlcnic_adapter *); 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; extern struct qlcnic_nic_template qlcnic_vf_ops;
...@@ -1928,9 +1941,10 @@ static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter) ...@@ -1928,9 +1941,10 @@ static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter)
adapter->ahw->hw_ops->napi_disable(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) 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) ...@@ -2029,6 +2043,54 @@ static inline bool qlcnic_check_multi_tx(struct qlcnic_adapter *adapter)
return test_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state); 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) static inline void qlcnic_disable_multi_tx(struct qlcnic_adapter *adapter)
{ {
test_and_clear_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state); 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) ...@@ -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 /* When operating in a muti tx mode, driver needs to write 0x1
* to src register, instead of 0x0 to disable receiving interrupt. * 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) && if (qlcnic_check_multi_tx(adapter) &&
!adapter->ahw->diag_test && !adapter->ahw->diag_test &&
(adapter->flags & QLCNIC_MSIX_ENABLED)) (adapter->flags & QLCNIC_MSIX_ENABLED))
...@@ -2050,13 +2112,42 @@ static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) ...@@ -2050,13 +2112,42 @@ static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
writel(0, sds_ring->crb_intr_mask); 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 /* When operating in a muti tx mode, driver needs to write 0x0
* to src register, instead of 0x1 to enable receiving interrupts. * 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) && if (qlcnic_check_multi_tx(adapter) &&
!adapter->ahw->diag_test && !adapter->ahw->diag_test &&
(adapter->flags & QLCNIC_MSIX_ENABLED)) (adapter->flags & QLCNIC_MSIX_ENABLED))
......
...@@ -199,6 +199,11 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { ...@@ -199,6 +199,11 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
.io_slot_reset = qlcnic_83xx_io_slot_reset, .io_slot_reset = qlcnic_83xx_io_slot_reset,
.io_resume = qlcnic_83xx_io_resume, .io_resume = qlcnic_83xx_io_resume,
.get_beacon_state = qlcnic_83xx_get_beacon_state, .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 = { static struct qlcnic_nic_template qlcnic_83xx_ops = {
...@@ -285,11 +290,22 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr, ...@@ -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; 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; num_msix = adapter->drv_sds_rings;
/* account for AEN interrupt MSI-X based interrupts */ /* account for AEN interrupt MSI-X based interrupts */
...@@ -298,30 +314,44 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter) ...@@ -298,30 +314,44 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED)) if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
num_msix += adapter->drv_tx_rings; num_msix += adapter->drv_tx_rings;
err = qlcnic_enable_msix(adapter, num_msix); return num_msix;
if (err == -ENOMEM) }
return err;
if (adapter->flags & QLCNIC_MSIX_ENABLED) int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
num_msix = adapter->ahw->num_msix; {
else { struct qlcnic_hardware_context *ahw = adapter->ahw;
if (qlcnic_sriov_vf_check(adapter)) int err, i, num_msix;
return -EINVAL;
num_msix = 1; if (adapter->flags & QLCNIC_TSS_RSS) {
adapter->drv_tx_rings = QLCNIC_SINGLE_RING; 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 */ /* setup interrupt mapping table for fw */
ahw->intr_tbl = vzalloc(num_msix * ahw->intr_tbl = vzalloc(num_msix *
sizeof(struct qlcnic_intrpt_config)); sizeof(struct qlcnic_intrpt_config));
if (!ahw->intr_tbl) if (!ahw->intr_tbl)
return -ENOMEM; return -ENOMEM;
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
/* MSI-X enablement failed, use legacy interrupt */ if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR; qlcnic_83xx_enable_legacy(adapter);
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");
}
for (i = 0; i < num_msix; i++) { for (i = 0; i < num_msix; i++) {
if (adapter->flags & QLCNIC_MSIX_ENABLED) if (adapter->flags & QLCNIC_MSIX_ENABLED)
...@@ -331,6 +361,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter) ...@@ -331,6 +361,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
ahw->intr_tbl[i].id = i; ahw->intr_tbl[i].id = i;
ahw->intr_tbl[i].src = 0; ahw->intr_tbl[i].src = 0;
} }
return 0; return 0;
} }
...@@ -345,20 +376,6 @@ static inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapt ...@@ -345,20 +376,6 @@ static inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapt
writel(1, adapter->tgt_mask_reg); 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 static inline void qlcnic_83xx_enable_legacy_msix_mbx_intr(struct qlcnic_adapter
*adapter) *adapter)
{ {
...@@ -496,7 +513,7 @@ irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data) ...@@ -496,7 +513,7 @@ irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data)
done: done:
adapter->ahw->diag_cnt++; adapter->ahw->diag_cnt++;
qlcnic_83xx_enable_intr(adapter, sds_ring); qlcnic_enable_sds_intr(adapter, sds_ring);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1295,8 +1312,8 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, ...@@ -1295,8 +1312,8 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
/* send the mailbox command*/ /* send the mailbox command*/
err = qlcnic_issue_cmd(adapter, &cmd); err = qlcnic_issue_cmd(adapter, &cmd);
if (err) { if (err) {
dev_err(&adapter->pdev->dev, netdev_err(adapter->netdev,
"Failed to create Tx ctx in firmware 0x%x\n", err); "Failed to create Tx ctx in firmware 0x%x\n", err);
goto out; goto out;
} }
mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2]; 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, ...@@ -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; intr_mask = ahw->intr_tbl[adapter->drv_sds_rings + ring].src;
tx->crb_intr_mask = ahw->pci_base0 + intr_mask; tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
} }
dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n", netdev_info(adapter->netdev,
tx->ctx_id, mbx_out->state); "Tx Context[0x%x] Created, state:0x%x\n",
tx->ctx_id, mbx_out->state);
out: out:
qlcnic_free_mbx_args(&cmd); qlcnic_free_mbx_args(&cmd);
return err; return err;
...@@ -1360,7 +1378,7 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test, ...@@ -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) { if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->drv_sds_rings; ring++) { for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->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, ...@@ -1385,7 +1403,7 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
for (ring = 0; ring < adapter->drv_sds_rings; ring++) { for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring]; sds_ring = &adapter->recv_ctx->sds_rings[ring];
if (adapter->flags & QLCNIC_MSIX_ENABLED) 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, ...@@ -1637,7 +1655,7 @@ static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,
if (qlcnic_sriov_pf_check(adapter)) { if (qlcnic_sriov_pf_check(adapter)) {
qlcnic_alloc_lb_filters_mem(adapter); qlcnic_alloc_lb_filters_mem(adapter);
qlcnic_pf_set_interface_id_promisc(adapter, interface_id); qlcnic_pf_set_interface_id_promisc(adapter, interface_id);
adapter->rx_mac_learn = 1; adapter->rx_mac_learn = true;
} else { } else {
if (!qlcnic_sriov_vf_check(adapter)) if (!qlcnic_sriov_vf_check(adapter))
*interface_id = adapter->recv_ctx->context_id << 16; *interface_id = adapter->recv_ctx->context_id << 16;
...@@ -2111,37 +2129,130 @@ int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac, ...@@ -2111,37 +2129,130 @@ int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac,
return err; 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_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) err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
return; 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); err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
if (err) if (err)
return; return err;
if (coal->type == QLCNIC_INTR_COAL_TYPE_RX) { temp = adapter->tx_ring->ctx_id;
temp = adapter->recv_ctx->context_id; cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_TX | temp << 16;
cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_RX | temp << 16; temp = coal->tx_time_us;
temp = coal->rx_time_us; cmd.req.arg[2] = coal->tx_packets | temp << 16;
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; cmd.req.arg[3] = coal->flag;
err = qlcnic_issue_cmd(adapter, &cmd); err = qlcnic_issue_cmd(adapter, &cmd);
if (err != QLCNIC_RCODE_SUCCESS) if (err != QLCNIC_RCODE_SUCCESS)
dev_info(&adapter->pdev->dev, netdev_err(adapter->netdev,
"Failed to send interrupt coalescence parameters\n"); "failed to set interrupt coalescing parameters\n");
qlcnic_free_mbx_args(&cmd); 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, static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
......
...@@ -547,7 +547,6 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32); ...@@ -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_nic_set_promisc(struct qlcnic_adapter *, u32);
int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *, int); int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *, int);
int qlcnic_83xx_config_rss(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); 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_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *);
int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_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 *, ...@@ -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_free_mbx_args(struct qlcnic_cmd_args *);
void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *, void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *,
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 *); int qlcnic_83xx_get_port_info(struct qlcnic_adapter *);
void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *); void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *);
void qlcnic_83xx_disable_mbx_intr(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_clear_legacy_intr(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_intr(int, void *); irqreturn_t qlcnic_83xx_intr(int, void *);
irqreturn_t qlcnic_83xx_tmp_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 *, void qlcnic_83xx_check_vf(struct qlcnic_adapter *,
const struct pci_device_id *); const struct pci_device_id *);
int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *); int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *);
......
...@@ -383,7 +383,7 @@ static int qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter *adapter) ...@@ -383,7 +383,7 @@ static int qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter *adapter)
qlcnic_up(adapter, netdev); qlcnic_up(adapter, netdev);
netif_device_attach(netdev); netif_device_attach(netdev);
clear_bit(__QLCNIC_RESETTING, &adapter->state); 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; return 0;
} }
...@@ -2217,7 +2217,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) ...@@ -2217,7 +2217,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
int err = 0; int err = 0;
adapter->rx_mac_learn = 0; adapter->rx_mac_learn = false;
ahw->msix_supported = !!qlcnic_use_msi_x; ahw->msix_supported = !!qlcnic_use_msi_x;
qlcnic_83xx_init_rings(adapter); qlcnic_83xx_init_rings(adapter);
......
...@@ -227,10 +227,10 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) ...@@ -227,10 +227,10 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) { if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) {
adapter->flags |= QLCNIC_ESWITCH_ENABLED; adapter->flags |= QLCNIC_ESWITCH_ENABLED;
if (adapter->drv_mac_learn) if (adapter->drv_mac_learn)
adapter->rx_mac_learn = 1; adapter->rx_mac_learn = true;
} else { } else {
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
adapter->rx_mac_learn = 0; adapter->rx_mac_learn = false;
} }
ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER; ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
......
...@@ -736,6 +736,7 @@ static int qlcnic_set_channels(struct net_device *dev, ...@@ -736,6 +736,7 @@ static int qlcnic_set_channels(struct net_device *dev,
channel->rx_count); channel->rx_count);
return err; return err;
} }
adapter->drv_rss_rings = channel->rx_count;
} }
if (channel->tx_count) { if (channel->tx_count) {
...@@ -746,10 +747,12 @@ static int qlcnic_set_channels(struct net_device *dev, ...@@ -746,10 +747,12 @@ static int qlcnic_set_channels(struct net_device *dev,
channel->tx_count); channel->tx_count);
return err; return err;
} }
adapter->drv_tss_rings = channel->tx_count;
} }
err = qlcnic_setup_rings(adapter, channel->rx_count, adapter->flags |= QLCNIC_TSS_RSS;
channel->tx_count);
err = qlcnic_setup_rings(adapter);
netdev_info(dev, "Allocated %d SDS rings and %d Tx rings\n", netdev_info(dev, "Allocated %d SDS rings and %d Tx rings\n",
adapter->drv_sds_rings, adapter->drv_tx_rings); adapter->drv_sds_rings, adapter->drv_tx_rings);
...@@ -1495,9 +1498,7 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev, ...@@ -1495,9 +1498,7 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ethcoal) struct ethtool_coalesce *ethcoal)
{ {
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_nic_intr_coalesce *coal; int err;
u32 rx_coalesce_usecs, rx_max_frames;
u32 tx_coalesce_usecs, tx_max_frames;
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
return -EINVAL; return -EINVAL;
...@@ -1507,82 +1508,31 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev, ...@@ -1507,82 +1508,31 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
* unsupported parameters are set. * unsupported parameters are set.
*/ */
if (ethcoal->rx_coalesce_usecs > 0xffff || if (ethcoal->rx_coalesce_usecs > 0xffff ||
ethcoal->rx_max_coalesced_frames > 0xffff || ethcoal->rx_max_coalesced_frames > 0xffff ||
ethcoal->tx_coalesce_usecs > 0xffff || ethcoal->tx_coalesce_usecs > 0xffff ||
ethcoal->tx_max_coalesced_frames > 0xffff || ethcoal->tx_max_coalesced_frames > 0xffff ||
ethcoal->rx_coalesce_usecs_irq || ethcoal->rx_coalesce_usecs_irq ||
ethcoal->rx_max_coalesced_frames_irq || ethcoal->rx_max_coalesced_frames_irq ||
ethcoal->tx_coalesce_usecs_irq || ethcoal->tx_coalesce_usecs_irq ||
ethcoal->tx_max_coalesced_frames_irq || ethcoal->tx_max_coalesced_frames_irq ||
ethcoal->stats_block_coalesce_usecs || ethcoal->stats_block_coalesce_usecs ||
ethcoal->use_adaptive_rx_coalesce || ethcoal->use_adaptive_rx_coalesce ||
ethcoal->use_adaptive_tx_coalesce || ethcoal->use_adaptive_tx_coalesce ||
ethcoal->pkt_rate_low || ethcoal->pkt_rate_low ||
ethcoal->rx_coalesce_usecs_low || ethcoal->rx_coalesce_usecs_low ||
ethcoal->rx_max_coalesced_frames_low || ethcoal->rx_max_coalesced_frames_low ||
ethcoal->tx_coalesce_usecs_low || ethcoal->tx_coalesce_usecs_low ||
ethcoal->tx_max_coalesced_frames_low || ethcoal->tx_max_coalesced_frames_low ||
ethcoal->pkt_rate_high || ethcoal->pkt_rate_high ||
ethcoal->rx_coalesce_usecs_high || ethcoal->rx_coalesce_usecs_high ||
ethcoal->rx_max_coalesced_frames_high || ethcoal->rx_max_coalesced_frames_high ||
ethcoal->tx_coalesce_usecs_high || ethcoal->tx_coalesce_usecs_high ||
ethcoal->tx_max_coalesced_frames_high) ethcoal->tx_max_coalesced_frames_high)
return -EINVAL; return -EINVAL;
coal = &adapter->ahw->coal; err = qlcnic_config_intr_coalesce(adapter, ethcoal);
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);
return 0; return err;
} }
static int qlcnic_get_intr_coalesce(struct net_device *netdev, static int qlcnic_get_intr_coalesce(struct net_device *netdev,
......
...@@ -547,10 +547,10 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) ...@@ -547,10 +547,10 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
qlcnic_alloc_lb_filters_mem(adapter); qlcnic_alloc_lb_filters_mem(adapter);
adapter->drv_mac_learn = 1; adapter->drv_mac_learn = 1;
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
adapter->rx_mac_learn = 1; adapter->rx_mac_learn = true;
} else { } else {
adapter->drv_mac_learn = 0; adapter->drv_mac_learn = 0;
adapter->rx_mac_learn = 0; adapter->rx_mac_learn = false;
} }
qlcnic_nic_set_promisc(adapter, mode); qlcnic_nic_set_promisc(adapter, mode);
...@@ -755,10 +755,7 @@ int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *adapter) ...@@ -755,10 +755,7 @@ int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *adapter)
return 0; return 0;
} }
/* int qlcnic_82xx_set_rx_coalesce(struct qlcnic_adapter *adapter)
* Send the interrupt coalescing parameter set by ethtool to the card.
*/
void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
int rv; int rv;
...@@ -780,6 +777,28 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter) ...@@ -780,6 +777,28 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
if (rv != 0) if (rv != 0)
dev_err(&adapter->netdev->dev, dev_err(&adapter->netdev->dev,
"Could not send interrupt coalescing parameters\n"); "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 #define QLCNIC_ENABLE_IPV4_LRO BIT_0
......
...@@ -171,7 +171,9 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, ...@@ -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_get_beacon_state(struct qlcnic_adapter *);
void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter,
u64 *uaddr, u16 vlan_id); 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); int qlcnic_82xx_config_rss(struct qlcnic_adapter *adapter, int);
void qlcnic_82xx_config_ipaddr(struct qlcnic_adapter *adapter, void qlcnic_82xx_config_ipaddr(struct qlcnic_adapter *adapter,
__be32, int); __be32, int);
......
...@@ -131,35 +131,6 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *, ...@@ -131,35 +131,6 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *,
struct qlcnic_host_rds_ring *, struct qlcnic_host_rds_ring *,
u16, u16); 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) static inline u8 qlcnic_mac_hash(u64 mac, u16 vlan)
{ {
return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff) ^ (vlan & 0xff)); return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff) ^ (vlan & 0xff));
...@@ -885,7 +856,7 @@ static int qlcnic_poll(struct napi_struct *napi, int budget) ...@@ -885,7 +856,7 @@ static int qlcnic_poll(struct napi_struct *napi, int budget)
if ((work_done < budget) && tx_complete) { if ((work_done < budget) && tx_complete) {
napi_complete(&sds_ring->napi); napi_complete(&sds_ring->napi);
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { 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); qlcnic_enable_tx_intr(adapter, tx_ring);
} }
} }
...@@ -926,7 +897,7 @@ static int qlcnic_rx_poll(struct napi_struct *napi, int budget) ...@@ -926,7 +897,7 @@ static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
if (work_done < budget) { if (work_done < budget) {
napi_complete(&sds_ring->napi); napi_complete(&sds_ring->napi);
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
qlcnic_enable_int(sds_ring); qlcnic_enable_sds_intr(adapter, sds_ring);
} }
return work_done; return work_done;
...@@ -1557,7 +1528,7 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter) ...@@ -1557,7 +1528,7 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->drv_sds_rings; ring++) { for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring]; sds_ring = &recv_ctx->sds_rings[ring];
napi_enable(&sds_ring->napi); napi_enable(&sds_ring->napi);
qlcnic_enable_int(sds_ring); qlcnic_enable_sds_intr(adapter, sds_ring);
} }
if (qlcnic_check_multi_tx(adapter) && if (qlcnic_check_multi_tx(adapter) &&
...@@ -1583,7 +1554,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter) ...@@ -1583,7 +1554,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->drv_sds_rings; ring++) { for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &recv_ctx->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_synchronize(&sds_ring->napi);
napi_disable(&sds_ring->napi); napi_disable(&sds_ring->napi);
} }
...@@ -1593,7 +1564,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter) ...@@ -1593,7 +1564,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
qlcnic_check_multi_tx(adapter)) { qlcnic_check_multi_tx(adapter)) {
for (ring = 0; ring < adapter->drv_tx_rings; ring++) { for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[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_synchronize(&tx_ring->napi);
napi_disable(&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) ...@@ -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); work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
if ((work_done < budget) && tx_complete) { if ((work_done < budget) && tx_complete) {
napi_complete(&sds_ring->napi); napi_complete(&sds_ring->napi);
qlcnic_83xx_enable_intr(adapter, sds_ring); qlcnic_enable_sds_intr(adapter, sds_ring);
} }
return work_done; return work_done;
...@@ -1879,7 +1850,7 @@ static int qlcnic_83xx_poll(struct napi_struct *napi, int budget) ...@@ -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); work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
if ((work_done < budget) && tx_complete) { if ((work_done < budget) && tx_complete) {
napi_complete(&sds_ring->napi); napi_complete(&sds_ring->napi);
qlcnic_83xx_enable_intr(adapter, sds_ring); qlcnic_enable_sds_intr(adapter, sds_ring);
} }
return work_done; return work_done;
...@@ -1898,7 +1869,7 @@ static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget) ...@@ -1898,7 +1869,7 @@ static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget)
if (work_done) { if (work_done) {
napi_complete(&tx_ring->napi); napi_complete(&tx_ring->napi);
if (test_bit(__QLCNIC_DEV_UP , &adapter->state)) 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; return work_done;
...@@ -1916,7 +1887,7 @@ static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget) ...@@ -1916,7 +1887,7 @@ static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget)
if (work_done < budget) { if (work_done < budget) {
napi_complete(&sds_ring->napi); napi_complete(&sds_ring->napi);
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) 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; return work_done;
...@@ -1936,7 +1907,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter) ...@@ -1936,7 +1907,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
sds_ring = &recv_ctx->sds_rings[ring]; sds_ring = &recv_ctx->sds_rings[ring];
napi_enable(&sds_ring->napi); napi_enable(&sds_ring->napi);
if (adapter->flags & QLCNIC_MSIX_ENABLED) 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) && if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
...@@ -1944,7 +1915,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter) ...@@ -1944,7 +1915,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->drv_tx_rings; ring++) { for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring]; tx_ring = &adapter->tx_ring[ring];
napi_enable(&tx_ring->napi); 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) ...@@ -1962,7 +1933,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->drv_sds_rings; ring++) { for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring]; sds_ring = &recv_ctx->sds_rings[ring];
if (adapter->flags & QLCNIC_MSIX_ENABLED) 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_synchronize(&sds_ring->napi);
napi_disable(&sds_ring->napi); napi_disable(&sds_ring->napi);
} }
...@@ -1971,7 +1942,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter) ...@@ -1971,7 +1942,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) { !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
for (ring = 0; ring < adapter->drv_tx_rings; ring++) { for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[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_synchronize(&tx_ring->napi);
napi_disable(&tx_ring->napi); napi_disable(&tx_ring->napi);
} }
......
...@@ -557,6 +557,10 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { ...@@ -557,6 +557,10 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
.io_slot_reset = qlcnic_82xx_io_slot_reset, .io_slot_reset = qlcnic_82xx_io_slot_reset,
.io_resume = qlcnic_82xx_io_resume, .io_resume = qlcnic_82xx_io_resume,
.get_beacon_state = qlcnic_82xx_get_beacon_state, .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) 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) ...@@ -599,9 +603,6 @@ void qlcnic_set_tx_ring_count(struct qlcnic_adapter *adapter, u8 tx_cnt)
QLCNIC_TX_QUEUE); QLCNIC_TX_QUEUE);
else else
adapter->drv_tx_rings = tx_cnt; 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) 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) ...@@ -612,25 +613,79 @@ void qlcnic_set_sds_ring_count(struct qlcnic_adapter *adapter, u8 rx_cnt)
QLCNIC_RX_QUEUE); QLCNIC_RX_QUEUE);
else else
adapter->drv_sds_rings = rx_cnt; 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; struct pci_dev *pdev = adapter->pdev;
int drv_tx_rings, drv_sds_rings, tx_vector; int num_msix = 0, err = 0, vector;
int err = -1, i;
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) { if (qlcnic_83xx_check(adapter))
drv_tx_rings = 0; num_msix += 1;
tx_vector = 0;
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 { } else {
drv_tx_rings = adapter->drv_tx_rings; netdev_info(adapter->netdev,
tx_vector = 1; "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) { if (!adapter->msix_entries) {
adapter->msix_entries = kcalloc(num_msix, adapter->msix_entries = kcalloc(num_msix,
sizeof(struct msix_entry), sizeof(struct msix_entry),
...@@ -639,47 +694,43 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) ...@@ -639,47 +694,43 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
return -ENOMEM; return -ENOMEM;
} }
adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);
if (adapter->ahw->msix_supported) { if (adapter->ahw->msix_supported) {
enable_msix: enable_msix:
for (i = 0; i < num_msix; i++) for (vector = 0; vector < num_msix; vector++)
adapter->msix_entries[i].entry = i; adapter->msix_entries[vector].entry = vector;
err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
if (err == 0) { if (err == 0) {
adapter->flags |= QLCNIC_MSIX_ENABLED; adapter->flags |= QLCNIC_MSIX_ENABLED;
if (qlcnic_83xx_check(adapter)) { adapter->ahw->num_msix = num_msix;
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;
}
dev_info(&pdev->dev, "using msi-x interrupts\n"); dev_info(&pdev->dev, "using msi-x interrupts\n");
return err; return err;
} else if (err > 0) { } else if (err > 0) {
dev_info(&pdev->dev, dev_info(&pdev->dev,
"Unable to allocate %d MSI-X interrupt vectors\n", "Unable to allocate %d MSI-X vectors, Available vectors %d\n",
num_msix); num_msix, err);
if (qlcnic_83xx_check(adapter)) {
if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector)) if (qlcnic_82xx_check(adapter)) {
return err;
err -= drv_tx_rings + 1;
num_msix = rounddown_pow_of_two(err); num_msix = rounddown_pow_of_two(err);
num_msix += drv_tx_rings + 1; if (err < QLCNIC_82XX_MINIMUM_VECTOR)
return -EIO;
} else { } else {
num_msix = rounddown_pow_of_two(err); num_msix = rounddown_pow_of_two(err - 1);
if (qlcnic_check_multi_tx(adapter)) num_msix += 1;
num_msix += drv_tx_rings; 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) { if (num_msix) {
...@@ -690,14 +741,29 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) ...@@ -690,14 +741,29 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
} }
} else { } else {
dev_info(&pdev->dev, dev_info(&pdev->dev,
"Unable to allocate %d MSI-X interrupt vectors\n", "Unable to allocate %d MSI-X vectors, err=%d\n",
num_msix); num_msix, err);
return 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) static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
{ {
int err = 0; int err = 0;
...@@ -736,21 +802,25 @@ static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter) ...@@ -736,21 +802,25 @@ static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter)
{ {
int num_msix, err = 0; int num_msix, err = 0;
num_msix = adapter->drv_sds_rings; if (adapter->flags & QLCNIC_TSS_RSS) {
err = qlcnic_setup_tss_rss_intr(adapter);
if (qlcnic_check_multi_tx(adapter)) if (err < 0)
num_msix += adapter->drv_tx_rings; return err;
num_msix = adapter->ahw->num_msix;
} else {
num_msix = qlcnic_82xx_calculate_msix_vector(adapter);
err = qlcnic_enable_msix(adapter, num_msix); err = qlcnic_enable_msix(adapter, num_msix);
if (err == -ENOMEM) if (err == -ENOMEM)
return err; return err;
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
qlcnic_disable_multi_tx(adapter); qlcnic_disable_multi_tx(adapter);
err = qlcnic_enable_msi_legacy(adapter); err = qlcnic_enable_msi_legacy(adapter);
if (!err) if (!err)
return err; return err;
}
} }
return 0; return 0;
...@@ -1697,6 +1767,33 @@ static void qlcnic_get_lro_mss_capability(struct qlcnic_adapter *adapter) ...@@ -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 __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
{ {
int ring; int ring;
...@@ -1729,7 +1826,7 @@ int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) ...@@ -1729,7 +1826,7 @@ int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
if (adapter->drv_sds_rings > 1) if (adapter->drv_sds_rings > 1)
qlcnic_config_rss(adapter, 1); qlcnic_config_rss(adapter, 1);
qlcnic_config_intr_coalesce(adapter); qlcnic_config_def_intr_coalesce(adapter);
if (netdev->features & NETIF_F_LRO) if (netdev->features & NETIF_F_LRO)
qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED); 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) ...@@ -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) { if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->drv_sds_rings; ring++) { for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->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 @@ void qlcnic_diag_free_res(struct net_device *netdev, int drv_sds_rings) ...@@ -1897,7 +1994,6 @@ void qlcnic_diag_free_res(struct net_device *netdev, int drv_sds_rings)
static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
int err = 0; int err = 0;
adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context), adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
...@@ -1906,15 +2002,7 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) ...@@ -1906,15 +2002,7 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
err = -ENOMEM; err = -ENOMEM;
goto err_out; 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 */ /* clear stats */
memset(&adapter->stats, 0, sizeof(adapter->stats)); memset(&adapter->stats, 0, sizeof(adapter->stats));
err_out: err_out:
...@@ -1975,7 +2063,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) ...@@ -1975,7 +2063,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->drv_sds_rings; ring++) { for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->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) ...@@ -2007,7 +2095,7 @@ qlcnic_reset_hw_context(struct qlcnic_adapter *adapter)
netif_device_attach(netdev); netif_device_attach(netdev);
clear_bit(__QLCNIC_RESETTING, &adapter->state); 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; return 0;
} }
...@@ -2747,12 +2835,58 @@ int qlcnic_check_temp(struct qlcnic_adapter *adapter) ...@@ -2747,12 +2835,58 @@ int qlcnic_check_temp(struct qlcnic_adapter *adapter)
return rv; 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; struct qlcnic_host_tx_ring *tx_ring;
int 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)) if (test_bit(__QLCNIC_RESETTING, &adapter->state))
return; return;
...@@ -2765,22 +2899,7 @@ static void qlcnic_tx_timeout(struct net_device *netdev) ...@@ -2765,22 +2899,7 @@ static void qlcnic_tx_timeout(struct net_device *netdev)
QLCNIC_FORCE_FW_DUMP_KEY); QLCNIC_FORCE_FW_DUMP_KEY);
} else { } else {
netdev_info(netdev, "Tx timeout, reset adapter context.\n"); netdev_info(netdev, "Tx timeout, reset adapter context.\n");
for (ring = 0; ring < adapter->drv_tx_rings; ring++) { qlcnic_dump_tx_rings(adapter);
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);
}
adapter->ahw->reset_context = 1; adapter->ahw->reset_context = 1;
} }
} }
...@@ -2842,7 +2961,7 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data) ...@@ -2842,7 +2961,7 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
done: done:
adapter->ahw->diag_cnt++; adapter->ahw->diag_cnt++;
qlcnic_enable_int(sds_ring); qlcnic_enable_sds_intr(adapter, sds_ring);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2890,17 +3009,39 @@ static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data) ...@@ -2890,17 +3009,39 @@ static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data)
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev) 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_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++) { for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &recv_ctx->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 #endif
...@@ -3759,7 +3900,7 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt, ...@@ -3759,7 +3900,7 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt,
return 0; 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; struct net_device *netdev = adapter->netdev;
int err; int err;
...@@ -3780,12 +3921,6 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt) ...@@ -3780,12 +3921,6 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt)
qlcnic_teardown_intr(adapter); 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); err = qlcnic_setup_intr(adapter);
if (err) { if (err) {
kfree(adapter->msix_entries); kfree(adapter->msix_entries);
...@@ -3793,6 +3928,8 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt) ...@@ -3793,6 +3928,8 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt)
return err; return err;
} }
netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);
if (qlcnic_83xx_check(adapter)) { if (qlcnic_83xx_check(adapter)) {
qlcnic_83xx_initialize_nic(adapter, 1); qlcnic_83xx_initialize_nic(adapter, 1);
err = qlcnic_83xx_setup_mbx_intr(adapter); err = qlcnic_83xx_setup_mbx_intr(adapter);
......
...@@ -71,6 +71,8 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { ...@@ -71,6 +71,8 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
.change_l2_filter = qlcnic_83xx_change_l2_filter, .change_l2_filter = qlcnic_83xx_change_l2_filter,
.get_board_info = qlcnic_83xx_get_port_info, .get_board_info = qlcnic_83xx_get_port_info,
.free_mac_list = qlcnic_sriov_vf_free_mac_list, .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 = { static struct qlcnic_nic_template qlcnic_sriov_vf_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment