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: Zoltan Kiss <zoltan.kiss@citrix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
9fac865db0
@ -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))
|
||||
@ -105,6 +105,8 @@
|
||||
#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))
|
||||
|
@ -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;
|
||||
|
||||
if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
|
||||
return;
|
||||
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->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)
|
||||
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;
|
||||
}
|
||||
|
||||
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 err;
|
||||
|
||||
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)
|
||||
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,
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,24 +613,78 @@ 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;
|
||||
|
||||
if (adapter->flags & QLCNIC_TX_INTR_SHARED) {
|
||||
drv_tx_rings = 0;
|
||||
tx_vector = 0;
|
||||
} else {
|
||||
drv_tx_rings = adapter->drv_tx_rings;
|
||||
tx_vector = 1;
|
||||
}
|
||||
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 (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 {
|
||||
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,
|
||||
@ -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;
|
||||
|
||||
err = qlcnic_enable_msix(adapter, num_msix);
|
||||
if (err == -ENOMEM)
|
||||
return err;
|
||||
|
||||
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
|
||||
qlcnic_disable_multi_tx(adapter);
|
||||
|
||||
err = qlcnic_enable_msi_legacy(adapter);
|
||||
if (!err)
|
||||
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;
|
||||
|
||||
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
|
||||
qlcnic_disable_multi_tx(adapter);
|
||||
|
||||
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,11 +2835,57 @@ int qlcnic_check_temp(struct qlcnic_adapter *adapter)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline void dump_tx_ring_desc(struct qlcnic_host_tx_ring *tx_ring)
|
||||
{
|
||||
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);
|
||||
struct qlcnic_host_tx_ring *tx_ring;
|
||||
int ring;
|
||||
|
||||
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);
|
||||
|
@ -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 = {
|
||||
|
Loading…
Reference in New Issue
Block a user