Merge branch 'qlcnic'
Himanshu Madhani says: ==================== qlcnic: Multiple Tx queue support and code refactoring This Patch series contains following changes o Refactored code to calculate, validate and assign Tx/SDS rings for various modes of driver. o Enhanced ethtool statistics for multi Tx queue on all supported adapters. o Enable multiple Tx queue for 83xx and 84xx Series adapters. o Register netdev for failed device state. changes from v1 -> v2 o Dropped patch to replace inappropriate usage of kzalloc() with vzalloc(). Please apply to net-next. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
96635fbd0b
|
@ -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 51
|
#define _QLCNIC_LINUX_SUBVERSION 52
|
||||||
#define QLCNIC_LINUX_VERSIONID "5.3.51"
|
#define QLCNIC_LINUX_VERSIONID "5.3.52"
|
||||||
#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))
|
||||||
|
@ -98,8 +98,22 @@
|
||||||
#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
|
#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
|
||||||
+ MGMT_CMD_DESC_RESV)
|
+ MGMT_CMD_DESC_RESV)
|
||||||
#define QLCNIC_MAX_TX_TIMEOUTS 2
|
#define QLCNIC_MAX_TX_TIMEOUTS 2
|
||||||
#define QLCNIC_MAX_TX_RINGS 8
|
|
||||||
#define QLCNIC_MAX_SDS_RINGS 8
|
/* Driver will use 1 Tx ring in INT-x/MSI/SRIOV mode. */
|
||||||
|
#define QLCNIC_SINGLE_RING 1
|
||||||
|
#define QLCNIC_DEF_SDS_RINGS 4
|
||||||
|
#define QLCNIC_DEF_TX_RINGS 4
|
||||||
|
#define QLCNIC_MAX_VNIC_TX_RINGS 4
|
||||||
|
#define QLCNIC_MAX_VNIC_SDS_RINGS 4
|
||||||
|
|
||||||
|
enum qlcnic_queue_type {
|
||||||
|
QLCNIC_TX_QUEUE = 1,
|
||||||
|
QLCNIC_RX_QUEUE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Operational mode for driver */
|
||||||
|
#define QLCNIC_VNIC_MODE 0xFF
|
||||||
|
#define QLCNIC_DEFAULT_MODE 0x0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Following are the states of the Phantom. Phantom will set them and
|
* Following are the states of the Phantom. Phantom will set them and
|
||||||
|
@ -533,6 +547,14 @@ struct qlcnic_host_sds_ring {
|
||||||
char name[IFNAMSIZ + 12];
|
char name[IFNAMSIZ + 12];
|
||||||
} ____cacheline_internodealigned_in_smp;
|
} ____cacheline_internodealigned_in_smp;
|
||||||
|
|
||||||
|
struct qlcnic_tx_queue_stats {
|
||||||
|
u64 xmit_on;
|
||||||
|
u64 xmit_off;
|
||||||
|
u64 xmit_called;
|
||||||
|
u64 xmit_finished;
|
||||||
|
u64 tx_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
struct qlcnic_host_tx_ring {
|
struct qlcnic_host_tx_ring {
|
||||||
int irq;
|
int irq;
|
||||||
void __iomem *crb_intr_mask;
|
void __iomem *crb_intr_mask;
|
||||||
|
@ -544,10 +566,7 @@ struct qlcnic_host_tx_ring {
|
||||||
u32 sw_consumer;
|
u32 sw_consumer;
|
||||||
u32 num_desc;
|
u32 num_desc;
|
||||||
|
|
||||||
u64 xmit_on;
|
struct qlcnic_tx_queue_stats tx_stats;
|
||||||
u64 xmit_off;
|
|
||||||
u64 xmit_called;
|
|
||||||
u64 xmit_finished;
|
|
||||||
|
|
||||||
void __iomem *crb_cmd_producer;
|
void __iomem *crb_cmd_producer;
|
||||||
struct cmd_desc_type0 *desc_head;
|
struct cmd_desc_type0 *desc_head;
|
||||||
|
@ -940,8 +959,6 @@ struct qlcnic_ipaddr {
|
||||||
#define QLCNIC_BEACON_EANBLE 0xC
|
#define QLCNIC_BEACON_EANBLE 0xC
|
||||||
#define QLCNIC_BEACON_DISABLE 0xD
|
#define QLCNIC_BEACON_DISABLE 0xD
|
||||||
|
|
||||||
#define QLCNIC_DEF_NUM_STS_DESC_RINGS 4
|
|
||||||
#define QLCNIC_DEF_NUM_TX_RINGS 4
|
|
||||||
#define QLCNIC_MSIX_TBL_SPACE 8192
|
#define QLCNIC_MSIX_TBL_SPACE 8192
|
||||||
#define QLCNIC_PCI_REG_MSIX_TBL 0x44
|
#define QLCNIC_PCI_REG_MSIX_TBL 0x44
|
||||||
#define QLCNIC_MSIX_TBL_PGSIZE 4096
|
#define QLCNIC_MSIX_TBL_PGSIZE 4096
|
||||||
|
@ -961,6 +978,7 @@ struct qlcnic_ipaddr {
|
||||||
#define __QLCNIC_SRIOV_CAPABLE 11
|
#define __QLCNIC_SRIOV_CAPABLE 11
|
||||||
#define __QLCNIC_MBX_POLL_ENABLE 12
|
#define __QLCNIC_MBX_POLL_ENABLE 12
|
||||||
#define __QLCNIC_DIAG_MODE 13
|
#define __QLCNIC_DIAG_MODE 13
|
||||||
|
#define __QLCNIC_MAINTENANCE_MODE 16
|
||||||
|
|
||||||
#define QLCNIC_INTERRUPT_TEST 1
|
#define QLCNIC_INTERRUPT_TEST 1
|
||||||
#define QLCNIC_LOOPBACK_TEST 2
|
#define QLCNIC_LOOPBACK_TEST 2
|
||||||
|
@ -1011,7 +1029,6 @@ struct qlcnic_adapter {
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
|
|
||||||
int max_drv_tx_rings;
|
|
||||||
u16 num_txd;
|
u16 num_txd;
|
||||||
u16 num_rxd;
|
u16 num_rxd;
|
||||||
u16 num_jumbo_rxd;
|
u16 num_jumbo_rxd;
|
||||||
|
@ -1019,7 +1036,13 @@ struct qlcnic_adapter {
|
||||||
u16 max_jumbo_rxd;
|
u16 max_jumbo_rxd;
|
||||||
|
|
||||||
u8 max_rds_rings;
|
u8 max_rds_rings;
|
||||||
u8 max_sds_rings;
|
|
||||||
|
u8 max_sds_rings; /* max sds rings supported by adapter */
|
||||||
|
u8 max_tx_rings; /* max tx rings supported by adapter */
|
||||||
|
|
||||||
|
u8 drv_tx_rings; /* max tx rings supported by driver */
|
||||||
|
u8 drv_sds_rings; /* max sds rings supported by driver */
|
||||||
|
|
||||||
u8 rx_csum;
|
u8 rx_csum;
|
||||||
u8 portnum;
|
u8 portnum;
|
||||||
|
|
||||||
|
@ -1542,12 +1565,13 @@ int qlcnic_loopback_test(struct net_device *, u8);
|
||||||
|
|
||||||
/* Functions from qlcnic_main.c */
|
/* Functions from qlcnic_main.c */
|
||||||
int qlcnic_reset_context(struct qlcnic_adapter *);
|
int qlcnic_reset_context(struct qlcnic_adapter *);
|
||||||
void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
|
void qlcnic_diag_free_res(struct net_device *netdev, int);
|
||||||
int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
|
int qlcnic_diag_alloc_res(struct net_device *netdev, int);
|
||||||
netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
|
netdev_tx_t qlcnic_xmit_frame(struct sk_buff *, struct net_device *);
|
||||||
int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, int);
|
void qlcnic_set_tx_ring_count(struct qlcnic_adapter *, u8);
|
||||||
int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32);
|
void qlcnic_set_sds_ring_count(struct qlcnic_adapter *, u8);
|
||||||
int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *, u32 txq);
|
int qlcnic_setup_rings(struct qlcnic_adapter *, u8, u8);
|
||||||
|
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);
|
||||||
void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
|
void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
|
||||||
int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
|
int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
|
||||||
|
@ -1640,19 +1664,18 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
|
||||||
static inline int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter,
|
static inline int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter,
|
||||||
struct net_device *netdev)
|
struct net_device *netdev)
|
||||||
{
|
{
|
||||||
int err, tx_q;
|
int err;
|
||||||
|
|
||||||
tx_q = adapter->max_drv_tx_rings;
|
netdev->num_tx_queues = adapter->drv_tx_rings;
|
||||||
|
netdev->real_num_tx_queues = adapter->drv_tx_rings;
|
||||||
|
|
||||||
netdev->num_tx_queues = tx_q;
|
err = netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);
|
||||||
netdev->real_num_tx_queues = tx_q;
|
|
||||||
|
|
||||||
err = netif_set_real_num_tx_queues(netdev, tx_q);
|
|
||||||
if (err)
|
if (err)
|
||||||
dev_err(&adapter->pdev->dev, "failed to set %d Tx queues\n",
|
dev_err(&adapter->pdev->dev, "failed to set %d Tx queues\n",
|
||||||
tx_q);
|
adapter->drv_tx_rings);
|
||||||
else
|
else
|
||||||
dev_info(&adapter->pdev->dev, "set %d Tx queues\n", tx_q);
|
dev_info(&adapter->pdev->dev, "Set %d Tx queues\n",
|
||||||
|
adapter->drv_tx_rings);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1694,7 +1717,7 @@ struct qlcnic_hardware_ops {
|
||||||
int (*write_reg) (struct qlcnic_adapter *, ulong, u32);
|
int (*write_reg) (struct qlcnic_adapter *, ulong, u32);
|
||||||
void (*get_ocm_win) (struct qlcnic_hardware_context *);
|
void (*get_ocm_win) (struct qlcnic_hardware_context *);
|
||||||
int (*get_mac_address) (struct qlcnic_adapter *, u8 *, u8);
|
int (*get_mac_address) (struct qlcnic_adapter *, u8 *, u8);
|
||||||
int (*setup_intr) (struct qlcnic_adapter *, u8, int);
|
int (*setup_intr) (struct qlcnic_adapter *);
|
||||||
int (*alloc_mbx_args)(struct qlcnic_cmd_args *,
|
int (*alloc_mbx_args)(struct qlcnic_cmd_args *,
|
||||||
struct qlcnic_adapter *, u32);
|
struct qlcnic_adapter *, u32);
|
||||||
int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
|
int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
|
||||||
|
@ -1765,10 +1788,9 @@ static inline int qlcnic_get_mac_address(struct qlcnic_adapter *adapter,
|
||||||
return adapter->ahw->hw_ops->get_mac_address(adapter, mac, function);
|
return adapter->ahw->hw_ops->get_mac_address(adapter, mac, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter,
|
static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter)
|
||||||
u8 num_intr, int txq)
|
|
||||||
{
|
{
|
||||||
return adapter->ahw->hw_ops->setup_intr(adapter, num_intr, txq);
|
return adapter->ahw->hw_ops->setup_intr(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
|
static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
|
||||||
|
@ -2004,7 +2026,7 @@ static inline bool qlcnic_check_multi_tx(struct qlcnic_adapter *adapter)
|
||||||
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);
|
||||||
adapter->max_drv_tx_rings = 1;
|
adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When operating in a muti tx mode, driver needs to write 0x1
|
/* When operating in a muti tx mode, driver needs to write 0x1
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/aer.h>
|
#include <linux/aer.h>
|
||||||
|
|
||||||
#define QLCNIC_MAX_TX_QUEUES 1
|
|
||||||
#define RSS_HASHTYPE_IP_TCP 0x3
|
#define RSS_HASHTYPE_IP_TCP 0x3
|
||||||
#define QLC_83XX_FW_MBX_CMD 0
|
#define QLC_83XX_FW_MBX_CMD 0
|
||||||
|
|
||||||
|
@ -268,20 +267,18 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr, int txq)
|
int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
int err, i, num_msix;
|
int err, i, num_msix;
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
|
||||||
if (!num_intr)
|
num_msix = adapter->drv_sds_rings;
|
||||||
num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
|
|
||||||
num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
|
|
||||||
num_intr));
|
|
||||||
/* account for AEN interrupt MSI-X based interrupts */
|
/* account for AEN interrupt MSI-X based interrupts */
|
||||||
num_msix += 1;
|
num_msix += 1;
|
||||||
|
|
||||||
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
|
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
|
||||||
num_msix += adapter->max_drv_tx_rings;
|
num_msix += adapter->drv_tx_rings;
|
||||||
|
|
||||||
err = qlcnic_enable_msix(adapter, num_msix);
|
err = qlcnic_enable_msix(adapter, num_msix);
|
||||||
if (err == -ENOMEM)
|
if (err == -ENOMEM)
|
||||||
|
@ -325,7 +322,8 @@ inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
|
inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
writel(1, adapter->tgt_mask_reg);
|
if (adapter->tgt_mask_reg)
|
||||||
|
writel(1, adapter->tgt_mask_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable MSI-x and INT-x interrupts */
|
/* Enable MSI-x and INT-x interrupts */
|
||||||
|
@ -498,8 +496,11 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
|
||||||
num_msix = 0;
|
num_msix = 0;
|
||||||
|
|
||||||
msleep(20);
|
msleep(20);
|
||||||
synchronize_irq(adapter->msix_entries[num_msix].vector);
|
|
||||||
free_irq(adapter->msix_entries[num_msix].vector, adapter);
|
if (adapter->msix_entries) {
|
||||||
|
synchronize_irq(adapter->msix_entries[num_msix].vector);
|
||||||
|
free_irq(adapter->msix_entries[num_msix].vector, adapter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
|
int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
|
||||||
|
@ -760,6 +761,9 @@ int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *adapter,
|
||||||
int cmd_type, err, opcode;
|
int cmd_type, err, opcode;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
|
if (!mbx)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
opcode = LSW(cmd->req.arg[0]);
|
opcode = LSW(cmd->req.arg[0]);
|
||||||
cmd_type = cmd->type;
|
cmd_type = cmd->type;
|
||||||
err = mbx->ops->enqueue_cmd(adapter, cmd, &timeout);
|
err = mbx->ops->enqueue_cmd(adapter, cmd, &timeout);
|
||||||
|
@ -979,14 +983,14 @@ static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
|
sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
|
||||||
context_id = recv_ctx->context_id;
|
context_id = recv_ctx->context_id;
|
||||||
num_sds = (adapter->max_sds_rings - QLCNIC_MAX_RING_SETS);
|
num_sds = adapter->drv_sds_rings - QLCNIC_MAX_SDS_RINGS;
|
||||||
ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
|
ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
|
||||||
QLCNIC_CMD_ADD_RCV_RINGS);
|
QLCNIC_CMD_ADD_RCV_RINGS);
|
||||||
cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
|
cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
|
||||||
|
|
||||||
/* set up status rings, mbx 2-81 */
|
/* set up status rings, mbx 2-81 */
|
||||||
index = 2;
|
index = 2;
|
||||||
for (i = 8; i < adapter->max_sds_rings; i++) {
|
for (i = 8; i < adapter->drv_sds_rings; i++) {
|
||||||
memset(&sds_mbx, 0, sds_mbx_size);
|
memset(&sds_mbx, 0, sds_mbx_size);
|
||||||
sds = &recv_ctx->sds_rings[i];
|
sds = &recv_ctx->sds_rings[i];
|
||||||
sds->consumer = 0;
|
sds->consumer = 0;
|
||||||
|
@ -1021,7 +1025,7 @@ static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
|
||||||
mbx_out = (struct qlcnic_add_rings_mbx_out *)&cmd.rsp.arg[1];
|
mbx_out = (struct qlcnic_add_rings_mbx_out *)&cmd.rsp.arg[1];
|
||||||
index = 0;
|
index = 0;
|
||||||
/* status descriptor ring */
|
/* status descriptor ring */
|
||||||
for (i = 8; i < adapter->max_sds_rings; i++) {
|
for (i = 8; i < adapter->drv_sds_rings; i++) {
|
||||||
sds = &recv_ctx->sds_rings[i];
|
sds = &recv_ctx->sds_rings[i];
|
||||||
sds->crb_sts_consumer = ahw->pci_base0 +
|
sds->crb_sts_consumer = ahw->pci_base0 +
|
||||||
mbx_out->host_csmr[index];
|
mbx_out->host_csmr[index];
|
||||||
|
@ -1079,10 +1083,10 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
num_rds = adapter->max_rds_rings;
|
num_rds = adapter->max_rds_rings;
|
||||||
|
|
||||||
if (adapter->max_sds_rings <= QLCNIC_MAX_RING_SETS)
|
if (adapter->drv_sds_rings <= QLCNIC_MAX_SDS_RINGS)
|
||||||
num_sds = adapter->max_sds_rings;
|
num_sds = adapter->drv_sds_rings;
|
||||||
else
|
else
|
||||||
num_sds = QLCNIC_MAX_RING_SETS;
|
num_sds = QLCNIC_MAX_SDS_RINGS;
|
||||||
|
|
||||||
sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
|
sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
|
||||||
rds_mbx_size = sizeof(struct qlcnic_rds_mbx);
|
rds_mbx_size = sizeof(struct qlcnic_rds_mbx);
|
||||||
|
@ -1183,7 +1187,7 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
|
||||||
sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
|
sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adapter->max_sds_rings > QLCNIC_MAX_RING_SETS)
|
if (adapter->drv_sds_rings > QLCNIC_MAX_SDS_RINGS)
|
||||||
err = qlcnic_83xx_add_rings(adapter);
|
err = qlcnic_83xx_add_rings(adapter);
|
||||||
out:
|
out:
|
||||||
qlcnic_free_mbx_args(&cmd);
|
qlcnic_free_mbx_args(&cmd);
|
||||||
|
@ -1239,9 +1243,9 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
|
||||||
mbx.size = tx->num_desc;
|
mbx.size = tx->num_desc;
|
||||||
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
||||||
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
|
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
|
||||||
msix_vector = adapter->max_sds_rings + ring;
|
msix_vector = adapter->drv_sds_rings + ring;
|
||||||
else
|
else
|
||||||
msix_vector = adapter->max_sds_rings - 1;
|
msix_vector = adapter->drv_sds_rings - 1;
|
||||||
msix_id = ahw->intr_tbl[msix_vector].id;
|
msix_id = ahw->intr_tbl[msix_vector].id;
|
||||||
} else {
|
} else {
|
||||||
msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
|
msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
|
||||||
|
@ -1264,7 +1268,8 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
|
||||||
qlcnic_pf_set_interface_id_create_tx_ctx(adapter, &temp);
|
qlcnic_pf_set_interface_id_create_tx_ctx(adapter, &temp);
|
||||||
|
|
||||||
cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT;
|
cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT;
|
||||||
cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES | temp;
|
cmd.req.arg[5] = QLCNIC_SINGLE_RING | temp;
|
||||||
|
|
||||||
buf = &cmd.req.arg[6];
|
buf = &cmd.req.arg[6];
|
||||||
memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx));
|
memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx));
|
||||||
/* send the mailbox command*/
|
/* send the mailbox command*/
|
||||||
|
@ -1279,7 +1284,7 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
|
||||||
tx->ctx_id = mbx_out->ctx_id;
|
tx->ctx_id = mbx_out->ctx_id;
|
||||||
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
intr_mask = ahw->intr_tbl[adapter->max_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",
|
dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n",
|
||||||
|
@ -1290,7 +1295,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
|
static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
|
||||||
int num_sds_ring)
|
u8 num_sds_ring)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct qlcnic_host_sds_ring *sds_ring;
|
struct qlcnic_host_sds_ring *sds_ring;
|
||||||
|
@ -1306,7 +1311,7 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
|
||||||
|
|
||||||
qlcnic_detach(adapter);
|
qlcnic_detach(adapter);
|
||||||
|
|
||||||
adapter->max_sds_rings = 1;
|
adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
|
||||||
adapter->ahw->diag_test = test;
|
adapter->ahw->diag_test = test;
|
||||||
adapter->ahw->linkup = 0;
|
adapter->ahw->linkup = 0;
|
||||||
|
|
||||||
|
@ -1320,7 +1325,7 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
|
||||||
if (ret) {
|
if (ret) {
|
||||||
qlcnic_detach(adapter);
|
qlcnic_detach(adapter);
|
||||||
if (adapter_state == QLCNIC_ADAPTER_UP_MAGIC) {
|
if (adapter_state == QLCNIC_ADAPTER_UP_MAGIC) {
|
||||||
adapter->max_sds_rings = num_sds_ring;
|
adapter->drv_sds_rings = num_sds_ring;
|
||||||
qlcnic_attach(adapter);
|
qlcnic_attach(adapter);
|
||||||
}
|
}
|
||||||
netif_device_attach(netdev);
|
netif_device_attach(netdev);
|
||||||
|
@ -1333,7 +1338,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->max_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_83xx_enable_intr(adapter, sds_ring);
|
||||||
}
|
}
|
||||||
|
@ -1354,7 +1359,7 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
|
static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
|
||||||
int max_sds_rings)
|
u8 drv_sds_rings)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct qlcnic_host_sds_ring *sds_ring;
|
struct qlcnic_host_sds_ring *sds_ring;
|
||||||
|
@ -1362,7 +1367,7 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
|
||||||
|
|
||||||
clear_bit(__QLCNIC_DEV_UP, &adapter->state);
|
clear_bit(__QLCNIC_DEV_UP, &adapter->state);
|
||||||
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
||||||
for (ring = 0; ring < adapter->max_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_disable_intr(adapter, sds_ring);
|
qlcnic_83xx_disable_intr(adapter, sds_ring);
|
||||||
if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
|
if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
|
||||||
|
@ -1386,7 +1391,7 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
adapter->ahw->diag_test = 0;
|
adapter->ahw->diag_test = 0;
|
||||||
adapter->max_sds_rings = max_sds_rings;
|
adapter->drv_sds_rings = drv_sds_rings;
|
||||||
|
|
||||||
if (qlcnic_attach(adapter))
|
if (qlcnic_attach(adapter))
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1648,7 +1653,9 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings;
|
u8 drv_sds_rings = adapter->drv_sds_rings;
|
||||||
|
u8 drv_tx_rings = adapter->drv_tx_rings;
|
||||||
|
int ret = 0, loop = 0;
|
||||||
|
|
||||||
if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
|
if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
|
||||||
netdev_warn(netdev,
|
netdev_warn(netdev,
|
||||||
|
@ -1670,7 +1677,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
|
||||||
mode == QLCNIC_ILB_MODE ? "internal" : "external");
|
mode == QLCNIC_ILB_MODE ? "internal" : "external");
|
||||||
|
|
||||||
ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST,
|
ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST,
|
||||||
max_sds_rings);
|
drv_sds_rings);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail_diag_alloc;
|
goto fail_diag_alloc;
|
||||||
|
|
||||||
|
@ -1708,10 +1715,11 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
|
||||||
qlcnic_83xx_clear_lb_mode(adapter, mode);
|
qlcnic_83xx_clear_lb_mode(adapter, mode);
|
||||||
|
|
||||||
free_diag_res:
|
free_diag_res:
|
||||||
qlcnic_83xx_diag_free_res(netdev, max_sds_rings);
|
qlcnic_83xx_diag_free_res(netdev, drv_sds_rings);
|
||||||
|
|
||||||
fail_diag_alloc:
|
fail_diag_alloc:
|
||||||
adapter->max_sds_rings = max_sds_rings;
|
adapter->drv_sds_rings = drv_sds_rings;
|
||||||
|
adapter->drv_tx_rings = drv_tx_rings;
|
||||||
qlcnic_release_diag_lock(adapter);
|
qlcnic_release_diag_lock(adapter);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3049,11 +3057,14 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
|
||||||
int status = 0;
|
int status = 0;
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
|
||||||
/* Get port configuration info */
|
if (!test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
|
||||||
status = qlcnic_83xx_get_port_info(adapter);
|
/* Get port configuration info */
|
||||||
/* Get Link Status related info */
|
status = qlcnic_83xx_get_port_info(adapter);
|
||||||
config = qlcnic_83xx_test_link(adapter);
|
/* Get Link Status related info */
|
||||||
ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
|
config = qlcnic_83xx_test_link(adapter);
|
||||||
|
ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
|
||||||
|
}
|
||||||
|
|
||||||
/* hard code until there is a way to get it from flash */
|
/* hard code until there is a way to get it from flash */
|
||||||
ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
|
ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
|
||||||
|
|
||||||
|
@ -3293,10 +3304,11 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
struct qlcnic_cmd_args cmd;
|
struct qlcnic_cmd_args cmd;
|
||||||
|
u8 val, drv_sds_rings = adapter->drv_sds_rings;
|
||||||
|
u8 drv_tx_rings = adapter->drv_tx_rings;
|
||||||
u32 data;
|
u32 data;
|
||||||
u16 intrpt_id, id;
|
u16 intrpt_id, id;
|
||||||
u8 val;
|
int ret;
|
||||||
int ret, max_sds_rings = adapter->max_sds_rings;
|
|
||||||
|
|
||||||
if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
|
if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
|
||||||
netdev_info(netdev, "Device is resetting\n");
|
netdev_info(netdev, "Device is resetting\n");
|
||||||
|
@ -3309,7 +3321,7 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST,
|
ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST,
|
||||||
max_sds_rings);
|
drv_sds_rings);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail_diag_irq;
|
goto fail_diag_irq;
|
||||||
|
|
||||||
|
@ -3346,10 +3358,11 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
|
||||||
|
|
||||||
done:
|
done:
|
||||||
qlcnic_free_mbx_args(&cmd);
|
qlcnic_free_mbx_args(&cmd);
|
||||||
qlcnic_83xx_diag_free_res(netdev, max_sds_rings);
|
qlcnic_83xx_diag_free_res(netdev, drv_sds_rings);
|
||||||
|
|
||||||
fail_diag_irq:
|
fail_diag_irq:
|
||||||
adapter->max_sds_rings = max_sds_rings;
|
adapter->drv_sds_rings = drv_sds_rings;
|
||||||
|
adapter->drv_tx_rings = drv_tx_rings;
|
||||||
qlcnic_release_diag_lock(adapter);
|
qlcnic_release_diag_lock(adapter);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3503,7 +3516,7 @@ int qlcnic_83xx_resume(struct qlcnic_adapter *adapter)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) {
|
if (ahw->nic_mode == QLCNIC_VNIC_MODE) {
|
||||||
if (ahw->op_mode == QLCNIC_MGMT_FUNC) {
|
if (ahw->op_mode == QLCNIC_MGMT_FUNC) {
|
||||||
qlcnic_83xx_set_vnic_opmode(adapter);
|
qlcnic_83xx_set_vnic_opmode(adapter);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3530,6 +3543,9 @@ void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx)
|
||||||
|
|
||||||
void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx)
|
void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx)
|
||||||
{
|
{
|
||||||
|
if (!mbx)
|
||||||
|
return;
|
||||||
|
|
||||||
destroy_workqueue(mbx->work_q);
|
destroy_workqueue(mbx->work_q);
|
||||||
kfree(mbx);
|
kfree(mbx);
|
||||||
}
|
}
|
||||||
|
@ -3650,6 +3666,9 @@ void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
|
struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
|
||||||
|
|
||||||
|
if (!mbx)
|
||||||
|
return;
|
||||||
|
|
||||||
clear_bit(QLC_83XX_MBX_READY, &mbx->status);
|
clear_bit(QLC_83XX_MBX_READY, &mbx->status);
|
||||||
complete(&mbx->completion);
|
complete(&mbx->completion);
|
||||||
cancel_work_sync(&mbx->work);
|
cancel_work_sync(&mbx->work);
|
||||||
|
|
|
@ -61,7 +61,6 @@
|
||||||
#define QLC_83XX_HOST_SDS_MBX_IDX 8
|
#define QLC_83XX_HOST_SDS_MBX_IDX 8
|
||||||
|
|
||||||
#define QLCNIC_HOST_RDS_MBX_IDX 88
|
#define QLCNIC_HOST_RDS_MBX_IDX 88
|
||||||
#define QLCNIC_MAX_RING_SETS 8
|
|
||||||
|
|
||||||
/* Pause control registers */
|
/* Pause control registers */
|
||||||
#define QLC_83XX_SRE_SHIM_REG 0x0D200284
|
#define QLC_83XX_SRE_SHIM_REG 0x0D200284
|
||||||
|
@ -183,8 +182,8 @@ struct qlcnic_rcv_mbx_out {
|
||||||
u8 num_pci_func;
|
u8 num_pci_func;
|
||||||
u8 state;
|
u8 state;
|
||||||
#endif
|
#endif
|
||||||
u32 host_csmr[QLCNIC_MAX_RING_SETS];
|
u32 host_csmr[QLCNIC_MAX_SDS_RINGS];
|
||||||
struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
|
struct __host_producer_mbx host_prod[QLCNIC_MAX_SDS_RINGS];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct qlcnic_add_rings_mbx_out {
|
struct qlcnic_add_rings_mbx_out {
|
||||||
|
@ -197,8 +196,8 @@ struct qlcnic_add_rings_mbx_out {
|
||||||
u8 sts_num;
|
u8 sts_num;
|
||||||
u8 rcv_num;
|
u8 rcv_num;
|
||||||
#endif
|
#endif
|
||||||
u32 host_csmr[QLCNIC_MAX_RING_SETS];
|
u32 host_csmr[QLCNIC_MAX_SDS_RINGS];
|
||||||
struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
|
struct __host_producer_mbx host_prod[QLCNIC_MAX_SDS_RINGS];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/* Transmit context mailbox inbox registers
|
/* Transmit context mailbox inbox registers
|
||||||
|
@ -415,8 +414,6 @@ enum qlcnic_83xx_states {
|
||||||
#define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000)
|
#define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000)
|
||||||
#define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val) (val & 0x20000)
|
#define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val) (val & 0x20000)
|
||||||
#define QLC_83XX_ESWITCH_CAPABILITY BIT_23
|
#define QLC_83XX_ESWITCH_CAPABILITY BIT_23
|
||||||
#define QLC_83XX_VIRTUAL_NIC_MODE 0xFF
|
|
||||||
#define QLC_83XX_DEFAULT_MODE 0x0
|
|
||||||
#define QLC_83XX_SRIOV_MODE 0x1
|
#define QLC_83XX_SRIOV_MODE 0x1
|
||||||
#define QLCNIC_BRDTYPE_83XX_10G 0x0083
|
#define QLCNIC_BRDTYPE_83XX_10G 0x0083
|
||||||
|
|
||||||
|
@ -524,7 +521,7 @@ enum qlc_83xx_ext_regs {
|
||||||
/* 83xx funcitons */
|
/* 83xx funcitons */
|
||||||
int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
|
int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
|
||||||
int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
|
int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
|
||||||
int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8, int);
|
int qlcnic_83xx_setup_intr(struct qlcnic_adapter *);
|
||||||
void qlcnic_83xx_get_func_no(struct qlcnic_adapter *);
|
void qlcnic_83xx_get_func_no(struct qlcnic_adapter *);
|
||||||
int qlcnic_83xx_cam_lock(struct qlcnic_adapter *);
|
int qlcnic_83xx_cam_lock(struct qlcnic_adapter *);
|
||||||
void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *);
|
void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *);
|
||||||
|
|
|
@ -902,7 +902,7 @@ static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)
|
||||||
qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
|
qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
|
||||||
set_bit(__QLCNIC_RESETTING, &adapter->state);
|
set_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||||
clear_bit(QLC_83XX_MBX_READY, &mbx->status);
|
clear_bit(QLC_83XX_MBX_READY, &mbx->status);
|
||||||
if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE)
|
if (adapter->ahw->nic_mode == QLCNIC_VNIC_MODE)
|
||||||
qlcnic_83xx_disable_vnic_mode(adapter, 1);
|
qlcnic_83xx_disable_vnic_mode(adapter, 1);
|
||||||
|
|
||||||
if (qlcnic_check_diag_status(adapter)) {
|
if (qlcnic_check_diag_status(adapter)) {
|
||||||
|
@ -2033,6 +2033,8 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
|
||||||
ahw->max_mac_filters = nic_info.max_mac_filters;
|
ahw->max_mac_filters = nic_info.max_mac_filters;
|
||||||
ahw->max_mtu = nic_info.max_mtu;
|
ahw->max_mtu = nic_info.max_mtu;
|
||||||
|
|
||||||
|
adapter->max_tx_rings = ahw->max_tx_ques;
|
||||||
|
adapter->max_sds_rings = ahw->max_rx_ques;
|
||||||
/* eSwitch capability indicates vNIC mode.
|
/* eSwitch capability indicates vNIC mode.
|
||||||
* vNIC and SRIOV are mutually exclusive operational modes.
|
* vNIC and SRIOV are mutually exclusive operational modes.
|
||||||
* If SR-IOV capability is detected, SR-IOV physical function
|
* If SR-IOV capability is detected, SR-IOV physical function
|
||||||
|
@ -2045,7 +2047,7 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
|
||||||
return QLC_83XX_DEFAULT_OPMODE;
|
return QLC_83XX_DEFAULT_OPMODE;
|
||||||
|
|
||||||
if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
|
if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
|
||||||
return QLC_83XX_VIRTUAL_NIC_MODE;
|
return QLCNIC_VNIC_MODE;
|
||||||
|
|
||||||
return QLC_83XX_DEFAULT_OPMODE;
|
return QLC_83XX_DEFAULT_OPMODE;
|
||||||
}
|
}
|
||||||
|
@ -2059,15 +2061,20 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
|
||||||
if (ret == -EIO)
|
if (ret == -EIO)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (ret == QLC_83XX_VIRTUAL_NIC_MODE) {
|
if (ret == QLCNIC_VNIC_MODE) {
|
||||||
ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE;
|
ahw->nic_mode = QLCNIC_VNIC_MODE;
|
||||||
|
|
||||||
if (qlcnic_83xx_config_vnic_opmode(adapter))
|
if (qlcnic_83xx_config_vnic_opmode(adapter))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
adapter->max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;
|
||||||
|
adapter->max_tx_rings = QLCNIC_MAX_VNIC_TX_RINGS;
|
||||||
} else if (ret == QLC_83XX_DEFAULT_OPMODE) {
|
} else if (ret == QLC_83XX_DEFAULT_OPMODE) {
|
||||||
ahw->nic_mode = QLC_83XX_DEFAULT_MODE;
|
ahw->nic_mode = QLCNIC_DEFAULT_MODE;
|
||||||
adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
|
adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
|
||||||
ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
|
ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
|
||||||
|
adapter->max_sds_rings = ahw->max_rx_ques;
|
||||||
|
adapter->max_tx_rings = ahw->max_tx_ques;
|
||||||
} else {
|
} else {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -2170,6 +2177,23 @@ static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qlcnic_83xx_init_rings(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
u8 rx_cnt = QLCNIC_DEF_SDS_RINGS;
|
||||||
|
u8 tx_cnt = QLCNIC_DEF_TX_RINGS;
|
||||||
|
|
||||||
|
adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
|
||||||
|
adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
|
||||||
|
|
||||||
|
if (!adapter->ahw->msix_supported) {
|
||||||
|
rx_cnt = QLCNIC_SINGLE_RING;
|
||||||
|
tx_cnt = QLCNIC_SINGLE_RING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compute and set drv sds rings */
|
||||||
|
qlcnic_set_tx_ring_count(adapter, tx_cnt);
|
||||||
|
qlcnic_set_sds_ring_count(adapter, rx_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
|
int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
|
||||||
{
|
{
|
||||||
|
@ -2178,6 +2202,9 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
ahw->msix_supported = !!qlcnic_use_msi_x;
|
ahw->msix_supported = !!qlcnic_use_msi_x;
|
||||||
|
|
||||||
|
qlcnic_83xx_init_rings(adapter);
|
||||||
|
|
||||||
err = qlcnic_83xx_init_mailbox_work(adapter);
|
err = qlcnic_83xx_init_mailbox_work(adapter);
|
||||||
if (err)
|
if (err)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -2190,22 +2217,26 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qlcnic_83xx_read_flash_descriptor_table(adapter) ||
|
||||||
|
qlcnic_83xx_read_flash_mfg_id(adapter)) {
|
||||||
|
dev_err(&adapter->pdev->dev, "Failed reading flash mfg id\n");
|
||||||
|
err = -ENOTRECOVERABLE;
|
||||||
|
goto detach_mbx;
|
||||||
|
}
|
||||||
|
|
||||||
err = qlcnic_83xx_check_hw_status(adapter);
|
err = qlcnic_83xx_check_hw_status(adapter);
|
||||||
if (err)
|
if (err)
|
||||||
goto detach_mbx;
|
goto detach_mbx;
|
||||||
|
|
||||||
if (!qlcnic_83xx_read_flash_descriptor_table(adapter))
|
|
||||||
qlcnic_83xx_read_flash_mfg_id(adapter);
|
|
||||||
|
|
||||||
err = qlcnic_83xx_get_fw_info(adapter);
|
err = qlcnic_83xx_get_fw_info(adapter);
|
||||||
if (err)
|
if (err)
|
||||||
goto detach_mbx;
|
goto detach_mbx;
|
||||||
|
|
||||||
err = qlcnic_83xx_idc_init(adapter);
|
err = qlcnic_83xx_idc_init(adapter);
|
||||||
if (err)
|
if (err)
|
||||||
goto clear_fw_info;
|
goto detach_mbx;
|
||||||
|
|
||||||
err = qlcnic_setup_intr(adapter, 0, 0);
|
err = qlcnic_setup_intr(adapter);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
|
dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
|
||||||
goto disable_intr;
|
goto disable_intr;
|
||||||
|
@ -2227,6 +2258,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
|
||||||
if (err)
|
if (err)
|
||||||
goto disable_mbx_intr;
|
goto disable_mbx_intr;
|
||||||
|
|
||||||
|
|
||||||
/* Perform operating mode specific initialization */
|
/* Perform operating mode specific initialization */
|
||||||
err = adapter->nic_ops->init_driver(adapter);
|
err = adapter->nic_ops->init_driver(adapter);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -2247,12 +2279,10 @@ disable_mbx_intr:
|
||||||
disable_intr:
|
disable_intr:
|
||||||
qlcnic_teardown_intr(adapter);
|
qlcnic_teardown_intr(adapter);
|
||||||
|
|
||||||
clear_fw_info:
|
|
||||||
kfree(ahw->fw_info);
|
|
||||||
|
|
||||||
detach_mbx:
|
detach_mbx:
|
||||||
qlcnic_83xx_detach_mailbox_work(adapter);
|
qlcnic_83xx_detach_mailbox_work(adapter);
|
||||||
qlcnic_83xx_free_mailbox(ahw->mailbox);
|
qlcnic_83xx_free_mailbox(ahw->mailbox);
|
||||||
|
ahw->mailbox = NULL;
|
||||||
exit:
|
exit:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -2265,7 +2295,7 @@ void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter)
|
||||||
clear_bit(QLC_83XX_MBX_READY, &idc->status);
|
clear_bit(QLC_83XX_MBX_READY, &idc->status);
|
||||||
cancel_delayed_work_sync(&adapter->fw_work);
|
cancel_delayed_work_sync(&adapter->fw_work);
|
||||||
|
|
||||||
if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE)
|
if (ahw->nic_mode == QLCNIC_VNIC_MODE)
|
||||||
qlcnic_83xx_disable_vnic_mode(adapter, 1);
|
qlcnic_83xx_disable_vnic_mode(adapter, 1);
|
||||||
|
|
||||||
qlcnic_83xx_idc_detach_driver(adapter);
|
qlcnic_83xx_idc_detach_driver(adapter);
|
||||||
|
|
|
@ -270,7 +270,7 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
nrds_rings = adapter->max_rds_rings;
|
nrds_rings = adapter->max_rds_rings;
|
||||||
nsds_rings = adapter->max_sds_rings;
|
nsds_rings = adapter->drv_sds_rings;
|
||||||
|
|
||||||
rq_size = SIZEOF_HOSTRQ_RX(struct qlcnic_hostrq_rx_ctx, nrds_rings,
|
rq_size = SIZEOF_HOSTRQ_RX(struct qlcnic_hostrq_rx_ctx, nrds_rings,
|
||||||
nsds_rings);
|
nsds_rings);
|
||||||
|
@ -475,7 +475,7 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
|
||||||
|
|
||||||
if (qlcnic_check_multi_tx(adapter) &&
|
if (qlcnic_check_multi_tx(adapter) &&
|
||||||
!adapter->ahw->diag_test) {
|
!adapter->ahw->diag_test) {
|
||||||
temp_nsds_rings = adapter->max_sds_rings;
|
temp_nsds_rings = adapter->drv_sds_rings;
|
||||||
index = temp_nsds_rings + ring;
|
index = temp_nsds_rings + ring;
|
||||||
msix_id = ahw->intr_tbl[index].id;
|
msix_id = ahw->intr_tbl[index].id;
|
||||||
prq->msi_index = cpu_to_le16(msix_id);
|
prq->msi_index = cpu_to_le16(msix_id);
|
||||||
|
@ -512,7 +512,7 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *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)) {
|
||||||
index = adapter->max_sds_rings + ring;
|
index = adapter->drv_sds_rings + ring;
|
||||||
intr_mask = ahw->intr_tbl[index].src;
|
intr_mask = ahw->intr_tbl[index].src;
|
||||||
tx_ring->crb_intr_mask = ahw->pci_base0 + intr_mask;
|
tx_ring->crb_intr_mask = ahw->pci_base0 + intr_mask;
|
||||||
}
|
}
|
||||||
|
@ -582,7 +582,7 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
recv_ctx = adapter->recv_ctx;
|
recv_ctx = adapter->recv_ctx;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
ptr = (__le32 *)dma_alloc_coherent(&pdev->dev, sizeof(u32),
|
ptr = (__le32 *)dma_alloc_coherent(&pdev->dev, sizeof(u32),
|
||||||
&tx_ring->hw_cons_phys_addr,
|
&tx_ring->hw_cons_phys_addr,
|
||||||
|
@ -616,7 +616,7 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
|
|
||||||
addr = dma_alloc_coherent(&adapter->pdev->dev,
|
addr = dma_alloc_coherent(&adapter->pdev->dev,
|
||||||
|
@ -664,7 +664,7 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev)
|
||||||
if (err)
|
if (err)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
for (ring = 0; ring < dev->max_drv_tx_rings; ring++) {
|
for (ring = 0; ring < dev->drv_tx_rings; ring++) {
|
||||||
err = qlcnic_fw_cmd_create_tx_ctx(dev,
|
err = qlcnic_fw_cmd_create_tx_ctx(dev,
|
||||||
&dev->tx_ring[ring],
|
&dev->tx_ring[ring],
|
||||||
ring);
|
ring);
|
||||||
|
@ -703,7 +703,7 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
|
if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
|
||||||
qlcnic_fw_cmd_del_rx_ctx(adapter);
|
qlcnic_fw_cmd_del_rx_ctx(adapter);
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
|
for (ring = 0; ring < adapter->drv_tx_rings; ring++)
|
||||||
qlcnic_fw_cmd_del_tx_ctx(adapter,
|
qlcnic_fw_cmd_del_tx_ctx(adapter,
|
||||||
&adapter->tx_ring[ring]);
|
&adapter->tx_ring[ring]);
|
||||||
|
|
||||||
|
@ -733,7 +733,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
recv_ctx = adapter->recv_ctx;
|
recv_ctx = adapter->recv_ctx;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
if (tx_ring->hw_consumer != NULL) {
|
if (tx_ring->hw_consumer != NULL) {
|
||||||
dma_free_coherent(&adapter->pdev->dev, sizeof(u32),
|
dma_free_coherent(&adapter->pdev->dev, sizeof(u32),
|
||||||
|
@ -764,7 +764,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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 (sds_ring->desc_head != NULL) {
|
if (sds_ring->desc_head != NULL) {
|
||||||
|
@ -895,6 +895,8 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
|
||||||
npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
|
npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
|
||||||
npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
|
npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
|
||||||
npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
|
npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
|
||||||
|
adapter->max_tx_rings = npar_info->max_tx_ques;
|
||||||
|
adapter->max_sds_rings = npar_info->max_rx_ques;
|
||||||
}
|
}
|
||||||
|
|
||||||
qlcnic_free_mbx_args(&cmd);
|
qlcnic_free_mbx_args(&cmd);
|
||||||
|
|
|
@ -27,43 +27,36 @@ static const u32 qlcnic_fw_dump_level[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
|
static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
|
||||||
{"xmit_called", QLC_SIZEOF(stats.xmitcalled),
|
|
||||||
QLC_OFF(stats.xmitcalled)},
|
|
||||||
{"xmit_finished", QLC_SIZEOF(stats.xmitfinished),
|
|
||||||
QLC_OFF(stats.xmitfinished)},
|
|
||||||
{"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
|
|
||||||
{"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
|
|
||||||
{"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
|
|
||||||
{"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
|
|
||||||
{"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
|
|
||||||
{"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
|
|
||||||
{"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
|
|
||||||
{"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
|
|
||||||
{"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
|
|
||||||
{"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
|
{"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
|
||||||
{"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
|
{"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
|
||||||
|
{"xmit_called", QLC_SIZEOF(stats.xmitcalled),
|
||||||
|
QLC_OFF(stats.xmitcalled)},
|
||||||
|
{"xmit_finished", QLC_SIZEOF(stats.xmitfinished),
|
||||||
|
QLC_OFF(stats.xmitfinished)},
|
||||||
|
{"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
|
||||||
|
QLC_OFF(stats.tx_dma_map_error)},
|
||||||
|
{"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
|
||||||
|
{"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
|
||||||
|
{"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
|
||||||
|
QLC_OFF(stats.rx_dma_map_error)},
|
||||||
|
{"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
|
||||||
|
{"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
|
||||||
|
{"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
|
||||||
|
{"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
|
||||||
|
{"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
|
||||||
|
{"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
|
||||||
|
{"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
|
||||||
|
{"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
|
||||||
{"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
|
{"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
|
||||||
QLC_OFF(stats.skb_alloc_failure)},
|
QLC_OFF(stats.skb_alloc_failure)},
|
||||||
{"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
|
|
||||||
{"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
|
|
||||||
QLC_OFF(stats.rx_dma_map_error)},
|
|
||||||
{"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
|
|
||||||
QLC_OFF(stats.tx_dma_map_error)},
|
|
||||||
{"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun),
|
{"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun),
|
||||||
QLC_OFF(stats.mac_filter_limit_overrun)},
|
QLC_OFF(stats.mac_filter_limit_overrun)},
|
||||||
{"spurious intr", QLC_SIZEOF(stats.spurious_intr),
|
{"spurious intr", QLC_SIZEOF(stats.spurious_intr),
|
||||||
QLC_OFF(stats.spurious_intr)},
|
QLC_OFF(stats.spurious_intr)},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
|
static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
|
||||||
"rx unicast frames",
|
|
||||||
"rx multicast frames",
|
|
||||||
"rx broadcast frames",
|
|
||||||
"rx dropped frames",
|
|
||||||
"rx errors",
|
|
||||||
"rx local frames",
|
|
||||||
"rx numbytes",
|
|
||||||
"tx unicast frames",
|
"tx unicast frames",
|
||||||
"tx multicast frames",
|
"tx multicast frames",
|
||||||
"tx broadcast frames",
|
"tx broadcast frames",
|
||||||
|
@ -71,6 +64,13 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
|
||||||
"tx errors",
|
"tx errors",
|
||||||
"tx local frames",
|
"tx local frames",
|
||||||
"tx numbytes",
|
"tx numbytes",
|
||||||
|
"rx unicast frames",
|
||||||
|
"rx multicast frames",
|
||||||
|
"rx broadcast frames",
|
||||||
|
"rx dropped frames",
|
||||||
|
"rx errors",
|
||||||
|
"rx local frames",
|
||||||
|
"rx numbytes",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
|
static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
|
||||||
|
@ -126,13 +126,16 @@ static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
|
||||||
|
|
||||||
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
|
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
|
||||||
|
|
||||||
static const char qlcnic_tx_ring_stats_strings[][ETH_GSTRING_LEN] = {
|
static const char qlcnic_tx_queue_stats_strings[][ETH_GSTRING_LEN] = {
|
||||||
"xmit_on",
|
"xmit_on",
|
||||||
"xmit_off",
|
"xmit_off",
|
||||||
"xmit_called",
|
"xmit_called",
|
||||||
"xmit_finished",
|
"xmit_finished",
|
||||||
|
"tx_bytes",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define QLCNIC_TX_STATS_LEN ARRAY_SIZE(qlcnic_tx_queue_stats_strings)
|
||||||
|
|
||||||
static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
|
static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
|
||||||
"ctx_rx_bytes",
|
"ctx_rx_bytes",
|
||||||
"ctx_rx_pkts",
|
"ctx_rx_pkts",
|
||||||
|
@ -223,9 +226,9 @@ static const u32 ext_diag_registers[] = {
|
||||||
|
|
||||||
static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter)
|
static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
int ring_regs_cnt = (adapter->max_drv_tx_rings * 5) +
|
int ring_regs_cnt = (adapter->drv_tx_rings * 5) +
|
||||||
(adapter->max_rds_rings * 2) +
|
(adapter->max_rds_rings * 2) +
|
||||||
(adapter->max_sds_rings * 3) + 5;
|
(adapter->drv_sds_rings * 3) + 5;
|
||||||
return ring_regs_cnt * sizeof(u32);
|
return ring_regs_cnt * sizeof(u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,8 +530,8 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
|
||||||
/* Marker btw regs and TX ring count */
|
/* Marker btw regs and TX ring count */
|
||||||
regs_buff[i++] = 0xFFEFCDAB;
|
regs_buff[i++] = 0xFFEFCDAB;
|
||||||
|
|
||||||
regs_buff[i++] = adapter->max_drv_tx_rings; /* No. of TX ring */
|
regs_buff[i++] = adapter->drv_tx_rings; /* No. of TX ring */
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
regs_buff[i++] = le32_to_cpu(*(tx_ring->hw_consumer));
|
regs_buff[i++] = le32_to_cpu(*(tx_ring->hw_consumer));
|
||||||
regs_buff[i++] = tx_ring->sw_consumer;
|
regs_buff[i++] = tx_ring->sw_consumer;
|
||||||
|
@ -547,8 +550,8 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
|
||||||
regs_buff[i++] = rds_rings->producer;
|
regs_buff[i++] = rds_rings->producer;
|
||||||
}
|
}
|
||||||
|
|
||||||
regs_buff[i++] = adapter->max_sds_rings; /* No. of SDS ring */
|
regs_buff[i++] = adapter->drv_sds_rings; /* No. of SDS ring */
|
||||||
for (ring = 0; ring < adapter->max_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]);
|
||||||
regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
|
regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
|
||||||
regs_buff[i++] = sds_ring->consumer;
|
regs_buff[i++] = sds_ring->consumer;
|
||||||
|
@ -661,46 +664,88 @@ qlcnic_set_ringparam(struct net_device *dev,
|
||||||
return qlcnic_reset_context(adapter);
|
return qlcnic_reset_context(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
|
||||||
|
u8 rx_ring, u8 tx_ring)
|
||||||
|
{
|
||||||
|
if (rx_ring != 0) {
|
||||||
|
if (rx_ring > adapter->max_sds_rings) {
|
||||||
|
netdev_err(adapter->netdev, "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
|
||||||
|
rx_ring, adapter->max_sds_rings);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx_ring != 0) {
|
||||||
|
if (qlcnic_82xx_check(adapter) &&
|
||||||
|
(tx_ring > adapter->max_tx_rings)) {
|
||||||
|
netdev_err(adapter->netdev,
|
||||||
|
"Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
|
||||||
|
tx_ring, adapter->max_tx_rings);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter) &&
|
||||||
|
(tx_ring > QLCNIC_SINGLE_RING)) {
|
||||||
|
netdev_err(adapter->netdev,
|
||||||
|
"Invalid ring count, Tx ring count %d should not be greater than %d driver Tx rings.\n",
|
||||||
|
tx_ring, QLCNIC_SINGLE_RING);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void qlcnic_get_channels(struct net_device *dev,
|
static void qlcnic_get_channels(struct net_device *dev,
|
||||||
struct ethtool_channels *channel)
|
struct ethtool_channels *channel)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
int min;
|
|
||||||
|
|
||||||
min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus());
|
channel->max_rx = adapter->max_sds_rings;
|
||||||
channel->max_rx = rounddown_pow_of_two(min);
|
channel->max_tx = adapter->max_tx_rings;
|
||||||
channel->max_tx = min_t(int, QLCNIC_MAX_TX_RINGS, num_online_cpus());
|
channel->rx_count = adapter->drv_sds_rings;
|
||||||
|
channel->tx_count = adapter->drv_tx_rings;
|
||||||
channel->rx_count = adapter->max_sds_rings;
|
|
||||||
channel->tx_count = adapter->max_drv_tx_rings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qlcnic_set_channels(struct net_device *dev,
|
static int qlcnic_set_channels(struct net_device *dev,
|
||||||
struct ethtool_channels *channel)
|
struct ethtool_channels *channel)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
int err;
|
int err;
|
||||||
int txq = 0;
|
|
||||||
|
|
||||||
if (channel->other_count || channel->combined_count)
|
if (channel->other_count || channel->combined_count)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
err = qlcnic_validate_ring_count(adapter, channel->rx_count,
|
||||||
|
channel->tx_count);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (channel->rx_count) {
|
if (channel->rx_count) {
|
||||||
err = qlcnic_validate_max_rss(adapter, channel->rx_count);
|
err = qlcnic_validate_rings(adapter, channel->rx_count,
|
||||||
if (err)
|
QLCNIC_RX_QUEUE);
|
||||||
|
if (err) {
|
||||||
|
netdev_err(dev, "Unable to configure %u SDS rings\n",
|
||||||
|
channel->rx_count);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qlcnic_82xx_check(adapter) && channel->tx_count) {
|
if (channel->tx_count) {
|
||||||
err = qlcnic_validate_max_tx_rings(adapter, channel->tx_count);
|
err = qlcnic_validate_rings(adapter, channel->tx_count,
|
||||||
if (err)
|
QLCNIC_TX_QUEUE);
|
||||||
|
if (err) {
|
||||||
|
netdev_err(dev, "Unable to configure %u Tx rings\n",
|
||||||
|
channel->tx_count);
|
||||||
return err;
|
return err;
|
||||||
txq = channel->tx_count;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = qlcnic_set_max_rss(adapter, channel->rx_count, txq);
|
err = qlcnic_setup_rings(adapter, channel->rx_count,
|
||||||
netdev_info(dev, "allocated 0x%x sds rings and 0x%x tx rings\n",
|
channel->tx_count);
|
||||||
adapter->max_sds_rings, adapter->max_drv_tx_rings);
|
netdev_info(dev, "Allocated %d SDS rings and %d Tx rings\n",
|
||||||
|
adapter->drv_sds_rings, adapter->drv_tx_rings);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -902,7 +947,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
struct qlcnic_cmd_args cmd;
|
struct qlcnic_cmd_args cmd;
|
||||||
int ret, max_sds_rings = adapter->max_sds_rings;
|
int ret, drv_sds_rings = adapter->drv_sds_rings;
|
||||||
|
|
||||||
if (qlcnic_83xx_check(adapter))
|
if (qlcnic_83xx_check(adapter))
|
||||||
return qlcnic_83xx_interrupt_test(netdev);
|
return qlcnic_83xx_interrupt_test(netdev);
|
||||||
|
@ -931,10 +976,10 @@ done:
|
||||||
qlcnic_free_mbx_args(&cmd);
|
qlcnic_free_mbx_args(&cmd);
|
||||||
|
|
||||||
free_diag_res:
|
free_diag_res:
|
||||||
qlcnic_diag_free_res(netdev, max_sds_rings);
|
qlcnic_diag_free_res(netdev, drv_sds_rings);
|
||||||
|
|
||||||
clear_diag_irq:
|
clear_diag_irq:
|
||||||
adapter->max_sds_rings = max_sds_rings;
|
adapter->drv_sds_rings = drv_sds_rings;
|
||||||
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1010,8 +1055,8 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
|
||||||
int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
int max_drv_tx_rings = adapter->max_drv_tx_rings;
|
int drv_tx_rings = adapter->drv_tx_rings;
|
||||||
int max_sds_rings = adapter->max_sds_rings;
|
int drv_sds_rings = adapter->drv_sds_rings;
|
||||||
struct qlcnic_host_sds_ring *sds_ring;
|
struct qlcnic_host_sds_ring *sds_ring;
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
int loop = 0;
|
int loop = 0;
|
||||||
|
@ -1066,11 +1111,11 @@ int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
||||||
qlcnic_clear_lb_mode(adapter, mode);
|
qlcnic_clear_lb_mode(adapter, mode);
|
||||||
|
|
||||||
free_res:
|
free_res:
|
||||||
qlcnic_diag_free_res(netdev, max_sds_rings);
|
qlcnic_diag_free_res(netdev, drv_sds_rings);
|
||||||
|
|
||||||
clear_it:
|
clear_it:
|
||||||
adapter->max_sds_rings = max_sds_rings;
|
adapter->drv_sds_rings = drv_sds_rings;
|
||||||
adapter->max_drv_tx_rings = max_drv_tx_rings;
|
adapter->drv_tx_rings = drv_tx_rings;
|
||||||
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1123,11 +1168,11 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
|
||||||
QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
|
QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
|
||||||
break;
|
break;
|
||||||
case ETH_SS_STATS:
|
case ETH_SS_STATS:
|
||||||
num_stats = ARRAY_SIZE(qlcnic_tx_ring_stats_strings);
|
num_stats = ARRAY_SIZE(qlcnic_tx_queue_stats_strings);
|
||||||
for (i = 0; i < adapter->max_drv_tx_rings; i++) {
|
for (i = 0; i < adapter->drv_tx_rings; i++) {
|
||||||
for (index = 0; index < num_stats; index++) {
|
for (index = 0; index < num_stats; index++) {
|
||||||
sprintf(data, "tx_ring_%d %s", i,
|
sprintf(data, "tx_queue_%d %s", i,
|
||||||
qlcnic_tx_ring_stats_strings[index]);
|
qlcnic_tx_queue_stats_strings[index]);
|
||||||
data += ETH_GSTRING_LEN;
|
data += ETH_GSTRING_LEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1225,6 +1270,36 @@ static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qlcnic_update_stats(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
|
int ring;
|
||||||
|
|
||||||
|
for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
|
||||||
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
|
adapter->stats.xmit_on += tx_ring->tx_stats.xmit_on;
|
||||||
|
adapter->stats.xmit_off += tx_ring->tx_stats.xmit_off;
|
||||||
|
adapter->stats.xmitcalled += tx_ring->tx_stats.xmit_called;
|
||||||
|
adapter->stats.xmitfinished += tx_ring->tx_stats.xmit_finished;
|
||||||
|
adapter->stats.txbytes += tx_ring->tx_stats.tx_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 *qlcnic_fill_tx_queue_stats(u64 *data, void *stats)
|
||||||
|
{
|
||||||
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
|
|
||||||
|
tx_ring = (struct qlcnic_host_tx_ring *)stats;
|
||||||
|
|
||||||
|
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_on);
|
||||||
|
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_off);
|
||||||
|
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_called);
|
||||||
|
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_finished);
|
||||||
|
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.tx_bytes);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
static void qlcnic_get_ethtool_stats(struct net_device *dev,
|
static void qlcnic_get_ethtool_stats(struct net_device *dev,
|
||||||
struct ethtool_stats *stats, u64 *data)
|
struct ethtool_stats *stats, u64 *data)
|
||||||
{
|
{
|
||||||
|
@ -1232,19 +1307,20 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev,
|
||||||
struct qlcnic_host_tx_ring *tx_ring;
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
struct qlcnic_esw_statistics port_stats;
|
struct qlcnic_esw_statistics port_stats;
|
||||||
struct qlcnic_mac_statistics mac_stats;
|
struct qlcnic_mac_statistics mac_stats;
|
||||||
int index, ret, length, size, ring;
|
int index, ret, length, size, tx_size, ring;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
memset(data, 0, adapter->max_drv_tx_rings * 4 * sizeof(u64));
|
tx_size = adapter->drv_tx_rings * QLCNIC_TX_STATS_LEN;
|
||||||
for (ring = 0, index = 0; ring < adapter->max_drv_tx_rings; ring++) {
|
|
||||||
|
memset(data, 0, tx_size * sizeof(u64));
|
||||||
|
for (ring = 0, index = 0; ring < adapter->drv_tx_rings; ring++) {
|
||||||
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
|
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
*data++ = tx_ring->xmit_on;
|
data = qlcnic_fill_tx_queue_stats(data, tx_ring);
|
||||||
*data++ = tx_ring->xmit_off;
|
qlcnic_update_stats(adapter);
|
||||||
*data++ = tx_ring->xmit_called;
|
|
||||||
*data++ = tx_ring->xmit_finished;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(data, 0, stats->n_stats * sizeof(u64));
|
memset(data, 0, stats->n_stats * sizeof(u64));
|
||||||
length = QLCNIC_STATS_LEN;
|
length = QLCNIC_STATS_LEN;
|
||||||
for (index = 0; index < length; index++) {
|
for (index = 0; index < length; index++) {
|
||||||
|
@ -1286,7 +1362,7 @@ static int qlcnic_set_led(struct net_device *dev,
|
||||||
enum ethtool_phys_id_state state)
|
enum ethtool_phys_id_state state)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
int max_sds_rings = adapter->max_sds_rings;
|
int drv_sds_rings = adapter->drv_sds_rings;
|
||||||
int err = -EIO, active = 1;
|
int err = -EIO, active = 1;
|
||||||
|
|
||||||
if (qlcnic_83xx_check(adapter))
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
@ -1344,7 +1420,7 @@ static int qlcnic_set_led(struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
|
if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
|
||||||
qlcnic_diag_free_res(dev, max_sds_rings);
|
qlcnic_diag_free_res(dev, drv_sds_rings);
|
||||||
|
|
||||||
if (!active || err)
|
if (!active || err)
|
||||||
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
|
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
|
||||||
|
@ -1685,7 +1761,6 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
|
||||||
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
|
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
|
||||||
bool valid_mask = false;
|
bool valid_mask = false;
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
u32 state;
|
|
||||||
|
|
||||||
switch (val->flag) {
|
switch (val->flag) {
|
||||||
case QLCNIC_FORCE_FW_DUMP_KEY:
|
case QLCNIC_FORCE_FW_DUMP_KEY:
|
||||||
|
@ -1738,9 +1813,8 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
|
||||||
|
|
||||||
case QLCNIC_SET_QUIESCENT:
|
case QLCNIC_SET_QUIESCENT:
|
||||||
case QLCNIC_RESET_QUIESCENT:
|
case QLCNIC_RESET_QUIESCENT:
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
|
||||||
if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
|
netdev_info(netdev, "Device is in non-operational state\n");
|
||||||
netdev_info(netdev, "Device in FAILED state\n");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -146,6 +146,12 @@ struct qlcnic_mailbox_metadata {
|
||||||
#define QLCNIC_MBX_PORT_RSP_OK 0x1a
|
#define QLCNIC_MBX_PORT_RSP_OK 0x1a
|
||||||
#define QLCNIC_MBX_ASYNC_EVENT BIT_15
|
#define QLCNIC_MBX_ASYNC_EVENT BIT_15
|
||||||
|
|
||||||
|
/* Set HW Tx ring limit for 82xx adapter. */
|
||||||
|
#define QLCNIC_MAX_HW_TX_RINGS 8
|
||||||
|
#define QLCNIC_MAX_HW_VNIC_TX_RINGS 4
|
||||||
|
#define QLCNIC_MAX_TX_RINGS 8
|
||||||
|
#define QLCNIC_MAX_SDS_RINGS 8
|
||||||
|
|
||||||
struct qlcnic_pci_info;
|
struct qlcnic_pci_info;
|
||||||
struct qlcnic_info;
|
struct qlcnic_info;
|
||||||
struct qlcnic_cmd_args;
|
struct qlcnic_cmd_args;
|
||||||
|
@ -176,7 +182,7 @@ int qlcnic_82xx_set_lb_mode(struct qlcnic_adapter *, u8);
|
||||||
void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
|
void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
|
||||||
void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
|
void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
|
||||||
void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *, u32);
|
void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *, u32);
|
||||||
int qlcnic_82xx_setup_intr(struct qlcnic_adapter *, u8, int);
|
int qlcnic_82xx_setup_intr(struct qlcnic_adapter *);
|
||||||
irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *);
|
irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *);
|
||||||
int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
|
int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
|
||||||
struct qlcnic_cmd_args *);
|
struct qlcnic_cmd_args *);
|
||||||
|
|
|
@ -236,7 +236,7 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
|
||||||
spin_lock_init(&rds_ring->lock);
|
spin_lock_init(&rds_ring->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
sds_ring->irq = adapter->msix_entries[ring].vector;
|
sds_ring->irq = adapter->msix_entries[ring].vector;
|
||||||
sds_ring->adapter = adapter;
|
sds_ring->adapter = adapter;
|
||||||
|
|
|
@ -581,10 +581,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
||||||
goto drop_packet;
|
goto drop_packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qlcnic_check_multi_tx(adapter))
|
tx_ring = &adapter->tx_ring[skb_get_queue_mapping(skb)];
|
||||||
tx_ring = &adapter->tx_ring[skb_get_queue_mapping(skb)];
|
|
||||||
else
|
|
||||||
tx_ring = &adapter->tx_ring[0];
|
|
||||||
num_txd = tx_ring->num_desc;
|
num_txd = tx_ring->num_desc;
|
||||||
|
|
||||||
frag_count = skb_shinfo(skb)->nr_frags + 1;
|
frag_count = skb_shinfo(skb)->nr_frags + 1;
|
||||||
|
@ -607,8 +604,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
||||||
if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
|
if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
|
||||||
netif_tx_start_queue(tx_ring->txq);
|
netif_tx_start_queue(tx_ring->txq);
|
||||||
} else {
|
} else {
|
||||||
adapter->stats.xmit_off++;
|
tx_ring->tx_stats.xmit_off++;
|
||||||
tx_ring->xmit_off++;
|
|
||||||
return NETDEV_TX_BUSY;
|
return NETDEV_TX_BUSY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -669,9 +665,8 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
||||||
if (adapter->drv_mac_learn)
|
if (adapter->drv_mac_learn)
|
||||||
qlcnic_send_filter(adapter, first_desc, skb);
|
qlcnic_send_filter(adapter, first_desc, skb);
|
||||||
|
|
||||||
adapter->stats.txbytes += skb->len;
|
tx_ring->tx_stats.tx_bytes += skb->len;
|
||||||
adapter->stats.xmitcalled++;
|
tx_ring->tx_stats.xmit_called++;
|
||||||
tx_ring->xmit_called++;
|
|
||||||
|
|
||||||
qlcnic_update_cmd_producer(tx_ring);
|
qlcnic_update_cmd_producer(tx_ring);
|
||||||
|
|
||||||
|
@ -789,6 +784,9 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
|
||||||
struct net_device *netdev = adapter->netdev;
|
struct net_device *netdev = adapter->netdev;
|
||||||
struct qlcnic_skb_frag *frag;
|
struct qlcnic_skb_frag *frag;
|
||||||
|
|
||||||
|
if (!spin_trylock(&adapter->tx_clean_lock))
|
||||||
|
return 1;
|
||||||
|
|
||||||
sw_consumer = tx_ring->sw_consumer;
|
sw_consumer = tx_ring->sw_consumer;
|
||||||
hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
|
hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
|
||||||
|
|
||||||
|
@ -805,8 +803,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
|
||||||
PCI_DMA_TODEVICE);
|
PCI_DMA_TODEVICE);
|
||||||
frag->dma = 0ULL;
|
frag->dma = 0ULL;
|
||||||
}
|
}
|
||||||
adapter->stats.xmitfinished++;
|
tx_ring->tx_stats.xmit_finished++;
|
||||||
tx_ring->xmit_finished++;
|
|
||||||
dev_kfree_skb_any(buffer->skb);
|
dev_kfree_skb_any(buffer->skb);
|
||||||
buffer->skb = NULL;
|
buffer->skb = NULL;
|
||||||
}
|
}
|
||||||
|
@ -823,8 +820,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
|
||||||
netif_carrier_ok(netdev)) {
|
netif_carrier_ok(netdev)) {
|
||||||
if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
|
if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
|
||||||
netif_tx_wake_queue(tx_ring->txq);
|
netif_tx_wake_queue(tx_ring->txq);
|
||||||
adapter->stats.xmit_on++;
|
tx_ring->tx_stats.xmit_on++;
|
||||||
tx_ring->xmit_on++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
adapter->tx_timeo_cnt = 0;
|
adapter->tx_timeo_cnt = 0;
|
||||||
|
@ -844,6 +840,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
|
||||||
*/
|
*/
|
||||||
hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
|
hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
|
||||||
done = (sw_consumer == hw_consumer);
|
done = (sw_consumer == hw_consumer);
|
||||||
|
spin_unlock(&adapter->tx_clean_lock);
|
||||||
|
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
@ -1463,18 +1460,18 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
|
||||||
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
||||||
struct qlcnic_host_tx_ring *tx_ring;
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
|
|
||||||
if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
|
if (qlcnic_alloc_sds_rings(recv_ctx, adapter->drv_sds_rings))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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 (qlcnic_check_multi_tx(adapter) &&
|
if (qlcnic_check_multi_tx(adapter) &&
|
||||||
!adapter->ahw->diag_test &&
|
!adapter->ahw->diag_test &&
|
||||||
(adapter->max_drv_tx_rings > 1)) {
|
(adapter->drv_tx_rings > QLCNIC_SINGLE_RING)) {
|
||||||
netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll,
|
netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll,
|
||||||
NAPI_POLL_WEIGHT);
|
NAPI_POLL_WEIGHT);
|
||||||
} else {
|
} else {
|
||||||
if (ring == (adapter->max_sds_rings - 1))
|
if (ring == (adapter->drv_sds_rings - 1))
|
||||||
netif_napi_add(netdev, &sds_ring->napi,
|
netif_napi_add(netdev, &sds_ring->napi,
|
||||||
qlcnic_poll,
|
qlcnic_poll,
|
||||||
NAPI_POLL_WEIGHT);
|
NAPI_POLL_WEIGHT);
|
||||||
|
@ -1491,7 +1488,7 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) {
|
if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) {
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
netif_napi_add(netdev, &tx_ring->napi, qlcnic_tx_poll,
|
netif_napi_add(netdev, &tx_ring->napi, qlcnic_tx_poll,
|
||||||
NAPI_POLL_WEIGHT);
|
NAPI_POLL_WEIGHT);
|
||||||
|
@ -1508,7 +1505,7 @@ void qlcnic_82xx_napi_del(struct qlcnic_adapter *adapter)
|
||||||
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
||||||
struct qlcnic_host_tx_ring *tx_ring;
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
netif_napi_del(&sds_ring->napi);
|
netif_napi_del(&sds_ring->napi);
|
||||||
}
|
}
|
||||||
|
@ -1516,7 +1513,7 @@ void qlcnic_82xx_napi_del(struct qlcnic_adapter *adapter)
|
||||||
qlcnic_free_sds_rings(adapter->recv_ctx);
|
qlcnic_free_sds_rings(adapter->recv_ctx);
|
||||||
|
|
||||||
if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) {
|
if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) {
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
netif_napi_del(&tx_ring->napi);
|
netif_napi_del(&tx_ring->napi);
|
||||||
}
|
}
|
||||||
|
@ -1535,7 +1532,7 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter)
|
||||||
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
|
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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_int(sds_ring);
|
||||||
|
@ -1544,8 +1541,8 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter)
|
||||||
if (qlcnic_check_multi_tx(adapter) &&
|
if (qlcnic_check_multi_tx(adapter) &&
|
||||||
(adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
(adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
!adapter->ahw->diag_test &&
|
!adapter->ahw->diag_test &&
|
||||||
(adapter->max_drv_tx_rings > 1)) {
|
(adapter->drv_tx_rings > QLCNIC_SINGLE_RING)) {
|
||||||
for (ring = 0; ring < adapter->max_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_enable_tx_intr(adapter, tx_ring);
|
qlcnic_enable_tx_intr(adapter, tx_ring);
|
||||||
|
@ -1563,7 +1560,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
|
||||||
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
|
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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_int(sds_ring);
|
||||||
napi_synchronize(&sds_ring->napi);
|
napi_synchronize(&sds_ring->napi);
|
||||||
|
@ -1573,7 +1570,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
|
||||||
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
!adapter->ahw->diag_test &&
|
!adapter->ahw->diag_test &&
|
||||||
qlcnic_check_multi_tx(adapter)) {
|
qlcnic_check_multi_tx(adapter)) {
|
||||||
for (ring = 0; ring < adapter->max_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_int(adapter, tx_ring);
|
||||||
napi_synchronize(&tx_ring->napi);
|
napi_synchronize(&tx_ring->napi);
|
||||||
|
@ -1911,7 +1908,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
|
||||||
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
|
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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);
|
||||||
if (adapter->flags & QLCNIC_MSIX_ENABLED)
|
if (adapter->flags & QLCNIC_MSIX_ENABLED)
|
||||||
|
@ -1920,7 +1917,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
for (ring = 0; ring < adapter->max_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_83xx_enable_tx_intr(adapter, tx_ring);
|
||||||
|
@ -1938,7 +1935,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
|
||||||
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
|
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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_83xx_disable_intr(adapter, sds_ring);
|
||||||
|
@ -1948,7 +1945,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
for (ring = 0; ring < adapter->max_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_83xx_disable_tx_intr(adapter, tx_ring);
|
||||||
napi_synchronize(&tx_ring->napi);
|
napi_synchronize(&tx_ring->napi);
|
||||||
|
@ -1965,10 +1962,10 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
|
||||||
struct qlcnic_host_tx_ring *tx_ring;
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
||||||
|
|
||||||
if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
|
if (qlcnic_alloc_sds_rings(recv_ctx, adapter->drv_sds_rings))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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) {
|
||||||
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
|
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
|
||||||
|
@ -1994,7 +1991,7 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
|
||||||
|
|
||||||
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
netif_napi_add(netdev, &tx_ring->napi,
|
netif_napi_add(netdev, &tx_ring->napi,
|
||||||
qlcnic_83xx_msix_tx_poll,
|
qlcnic_83xx_msix_tx_poll,
|
||||||
|
@ -2012,7 +2009,7 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter)
|
||||||
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
||||||
struct qlcnic_host_tx_ring *tx_ring;
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
netif_napi_del(&sds_ring->napi);
|
netif_napi_del(&sds_ring->napi);
|
||||||
}
|
}
|
||||||
|
@ -2021,7 +2018,7 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
netif_napi_del(&tx_ring->napi);
|
netif_napi_del(&tx_ring->napi);
|
||||||
}
|
}
|
||||||
|
|
|
@ -548,36 +548,75 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
|
||||||
.io_resume = qlcnic_82xx_io_resume,
|
.io_resume = qlcnic_82xx_io_resume,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void qlcnic_get_multiq_capability(struct qlcnic_adapter *adapter)
|
static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
int num_tx_q;
|
|
||||||
|
|
||||||
if (ahw->msix_supported &&
|
if (qlcnic_82xx_check(adapter) &&
|
||||||
(ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_MULTI_TX)) {
|
(ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_MULTI_TX)) {
|
||||||
num_tx_q = min_t(int, QLCNIC_DEF_NUM_TX_RINGS,
|
test_and_set_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state);
|
||||||
num_online_cpus());
|
return 0;
|
||||||
if (num_tx_q > 1) {
|
|
||||||
test_and_set_bit(__QLCNIC_MULTI_TX_UNIQUE,
|
|
||||||
&adapter->state);
|
|
||||||
adapter->max_drv_tx_rings = num_tx_q;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
adapter->max_drv_tx_rings = 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qlcnic_max_rings(struct qlcnic_adapter *adapter, u8 ring_cnt,
|
||||||
|
int queue_type)
|
||||||
|
{
|
||||||
|
int num_rings, max_rings = QLCNIC_MAX_SDS_RINGS;
|
||||||
|
|
||||||
|
if (queue_type == QLCNIC_RX_QUEUE)
|
||||||
|
max_rings = adapter->max_sds_rings;
|
||||||
|
else if (queue_type == QLCNIC_TX_QUEUE)
|
||||||
|
max_rings = adapter->max_tx_rings;
|
||||||
|
|
||||||
|
num_rings = rounddown_pow_of_two(min_t(int, num_online_cpus(),
|
||||||
|
max_rings));
|
||||||
|
|
||||||
|
if (ring_cnt > num_rings)
|
||||||
|
return num_rings;
|
||||||
|
else
|
||||||
|
return ring_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qlcnic_set_tx_ring_count(struct qlcnic_adapter *adapter, u8 tx_cnt)
|
||||||
|
{
|
||||||
|
/* 83xx adapter does not have max_tx_rings intialized in probe */
|
||||||
|
if (adapter->max_tx_rings)
|
||||||
|
adapter->drv_tx_rings = qlcnic_max_rings(adapter, 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)
|
||||||
|
{
|
||||||
|
/* 83xx adapter does not have max_sds_rings intialized in probe */
|
||||||
|
if (adapter->max_sds_rings)
|
||||||
|
adapter->drv_sds_rings = qlcnic_max_rings(adapter, 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_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = adapter->pdev;
|
struct pci_dev *pdev = adapter->pdev;
|
||||||
int max_tx_rings, max_sds_rings, tx_vector;
|
int drv_tx_rings, drv_sds_rings, tx_vector;
|
||||||
int err = -1, i;
|
int err = -1, i;
|
||||||
|
|
||||||
if (adapter->flags & QLCNIC_TX_INTR_SHARED) {
|
if (adapter->flags & QLCNIC_TX_INTR_SHARED) {
|
||||||
max_tx_rings = 0;
|
drv_tx_rings = 0;
|
||||||
tx_vector = 0;
|
tx_vector = 0;
|
||||||
} else {
|
} else {
|
||||||
max_tx_rings = adapter->max_drv_tx_rings;
|
drv_tx_rings = adapter->drv_tx_rings;
|
||||||
tx_vector = 1;
|
tx_vector = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,7 +628,7 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter->max_sds_rings = 1;
|
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) {
|
||||||
|
@ -602,18 +641,18 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
|
||||||
if (qlcnic_83xx_check(adapter)) {
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
adapter->ahw->num_msix = num_msix;
|
adapter->ahw->num_msix = num_msix;
|
||||||
/* subtract mail box and tx ring vectors */
|
/* subtract mail box and tx ring vectors */
|
||||||
adapter->max_sds_rings = num_msix -
|
adapter->drv_sds_rings = num_msix -
|
||||||
max_tx_rings - 1;
|
drv_tx_rings - 1;
|
||||||
} else {
|
} else {
|
||||||
adapter->ahw->num_msix = num_msix;
|
adapter->ahw->num_msix = num_msix;
|
||||||
if (qlcnic_check_multi_tx(adapter) &&
|
if (qlcnic_check_multi_tx(adapter) &&
|
||||||
!adapter->ahw->diag_test &&
|
!adapter->ahw->diag_test &&
|
||||||
(adapter->max_drv_tx_rings > 1))
|
(adapter->drv_tx_rings > 1))
|
||||||
max_sds_rings = num_msix - max_tx_rings;
|
drv_sds_rings = num_msix - drv_tx_rings;
|
||||||
else
|
else
|
||||||
max_sds_rings = num_msix;
|
drv_sds_rings = num_msix;
|
||||||
|
|
||||||
adapter->max_sds_rings = max_sds_rings;
|
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;
|
||||||
|
@ -624,13 +663,13 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
|
||||||
if (qlcnic_83xx_check(adapter)) {
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector))
|
if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector))
|
||||||
return err;
|
return err;
|
||||||
err -= (max_tx_rings + 1);
|
err -= drv_tx_rings + 1;
|
||||||
num_msix = rounddown_pow_of_two(err);
|
num_msix = rounddown_pow_of_two(err);
|
||||||
num_msix += (max_tx_rings + 1);
|
num_msix += drv_tx_rings + 1;
|
||||||
} else {
|
} else {
|
||||||
num_msix = rounddown_pow_of_two(err);
|
num_msix = rounddown_pow_of_two(err);
|
||||||
if (qlcnic_check_multi_tx(adapter))
|
if (qlcnic_check_multi_tx(adapter))
|
||||||
num_msix += max_tx_rings;
|
num_msix += drv_tx_rings;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_msix) {
|
if (num_msix) {
|
||||||
|
@ -683,25 +722,14 @@ static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr, int txq)
|
int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
|
||||||
int num_msix, err = 0;
|
int num_msix, err = 0;
|
||||||
|
|
||||||
if (!num_intr)
|
num_msix = adapter->drv_sds_rings;
|
||||||
num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
|
|
||||||
|
|
||||||
if (ahw->msix_supported) {
|
if (qlcnic_check_multi_tx(adapter))
|
||||||
num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
|
num_msix += adapter->drv_tx_rings;
|
||||||
num_intr));
|
|
||||||
if (qlcnic_check_multi_tx(adapter)) {
|
|
||||||
if (txq)
|
|
||||||
adapter->max_drv_tx_rings = txq;
|
|
||||||
num_msix += adapter->max_drv_tx_rings;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
num_msix = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = qlcnic_enable_msix(adapter, num_msix);
|
err = qlcnic_enable_msix(adapter, num_msix);
|
||||||
if (err == -ENOMEM)
|
if (err == -ENOMEM)
|
||||||
|
@ -1140,14 +1168,18 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
|
||||||
adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
|
adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
|
||||||
adapter->ahw->max_mtu = nic_info.max_mtu;
|
adapter->ahw->max_mtu = nic_info.max_mtu;
|
||||||
|
|
||||||
/* Disable NPAR for 83XX */
|
if (adapter->ahw->capabilities & BIT_6) {
|
||||||
if (qlcnic_83xx_check(adapter))
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (adapter->ahw->capabilities & BIT_6)
|
|
||||||
adapter->flags |= QLCNIC_ESWITCH_ENABLED;
|
adapter->flags |= QLCNIC_ESWITCH_ENABLED;
|
||||||
else
|
adapter->ahw->nic_mode = QLCNIC_VNIC_MODE;
|
||||||
|
adapter->max_tx_rings = QLCNIC_MAX_HW_VNIC_TX_RINGS;
|
||||||
|
adapter->max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;
|
||||||
|
|
||||||
|
dev_info(&adapter->pdev->dev, "vNIC mode enabled.\n");
|
||||||
|
} else {
|
||||||
|
adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
|
||||||
|
adapter->max_tx_rings = QLCNIC_MAX_HW_TX_RINGS;
|
||||||
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
|
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1295,6 +1327,8 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
|
||||||
"HAL Version: %d, Privileged function\n",
|
"HAL Version: %d, Privileged function\n",
|
||||||
adapter->ahw->fw_hal_version);
|
adapter->ahw->fw_hal_version);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
|
adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
|
||||||
|
@ -1554,7 +1588,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
|
||||||
if (qlcnic_82xx_check(adapter) ||
|
if (qlcnic_82xx_check(adapter) ||
|
||||||
(qlcnic_83xx_check(adapter) &&
|
(qlcnic_83xx_check(adapter) &&
|
||||||
(adapter->flags & QLCNIC_MSIX_ENABLED))) {
|
(adapter->flags & QLCNIC_MSIX_ENABLED))) {
|
||||||
num_sds_rings = adapter->max_sds_rings;
|
num_sds_rings = adapter->drv_sds_rings;
|
||||||
for (ring = 0; ring < num_sds_rings; ring++) {
|
for (ring = 0; ring < num_sds_rings; ring++) {
|
||||||
sds_ring = &recv_ctx->sds_rings[ring];
|
sds_ring = &recv_ctx->sds_rings[ring];
|
||||||
if (qlcnic_82xx_check(adapter) &&
|
if (qlcnic_82xx_check(adapter) &&
|
||||||
|
@ -1588,7 +1622,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
|
||||||
(adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
(adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
!(adapter->flags & QLCNIC_TX_INTR_SHARED))) {
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED))) {
|
||||||
handler = qlcnic_msix_tx_intr;
|
handler = qlcnic_msix_tx_intr;
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings;
|
for (ring = 0; ring < adapter->drv_tx_rings;
|
||||||
ring++) {
|
ring++) {
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
snprintf(tx_ring->name, sizeof(tx_ring->name),
|
snprintf(tx_ring->name, sizeof(tx_ring->name),
|
||||||
|
@ -1616,7 +1650,7 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter)
|
||||||
if (qlcnic_82xx_check(adapter) ||
|
if (qlcnic_82xx_check(adapter) ||
|
||||||
(qlcnic_83xx_check(adapter) &&
|
(qlcnic_83xx_check(adapter) &&
|
||||||
(adapter->flags & QLCNIC_MSIX_ENABLED))) {
|
(adapter->flags & QLCNIC_MSIX_ENABLED))) {
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
free_irq(sds_ring->irq, sds_ring);
|
free_irq(sds_ring->irq, sds_ring);
|
||||||
}
|
}
|
||||||
|
@ -1625,7 +1659,7 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter)
|
||||||
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) ||
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) ||
|
||||||
(qlcnic_82xx_check(adapter) &&
|
(qlcnic_82xx_check(adapter) &&
|
||||||
qlcnic_check_multi_tx(adapter))) {
|
qlcnic_check_multi_tx(adapter))) {
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings;
|
for (ring = 0; ring < adapter->drv_tx_rings;
|
||||||
ring++) {
|
ring++) {
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
if (tx_ring->irq)
|
if (tx_ring->irq)
|
||||||
|
@ -1679,7 +1713,7 @@ int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
|
||||||
|
|
||||||
adapter->ahw->linkup = 0;
|
adapter->ahw->linkup = 0;
|
||||||
|
|
||||||
if (adapter->max_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_intr_coalesce(adapter);
|
||||||
|
@ -1721,6 +1755,7 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
|
||||||
if (qlcnic_sriov_vf_check(adapter))
|
if (qlcnic_sriov_vf_check(adapter))
|
||||||
qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
|
qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
|
||||||
smp_mb();
|
smp_mb();
|
||||||
|
spin_lock(&adapter->tx_clean_lock);
|
||||||
netif_carrier_off(netdev);
|
netif_carrier_off(netdev);
|
||||||
adapter->ahw->linkup = 0;
|
adapter->ahw->linkup = 0;
|
||||||
netif_tx_disable(netdev);
|
netif_tx_disable(netdev);
|
||||||
|
@ -1739,8 +1774,9 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
|
||||||
|
|
||||||
qlcnic_reset_rx_buffers_list(adapter);
|
qlcnic_reset_rx_buffers_list(adapter);
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
|
for (ring = 0; ring < adapter->drv_tx_rings; ring++)
|
||||||
qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]);
|
qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]);
|
||||||
|
spin_unlock(&adapter->tx_clean_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Usage: During suspend and firmware recovery module */
|
/* Usage: During suspend and firmware recovery module */
|
||||||
|
@ -1816,16 +1852,16 @@ void qlcnic_detach(struct qlcnic_adapter *adapter)
|
||||||
adapter->is_up = 0;
|
adapter->is_up = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
|
void qlcnic_diag_free_res(struct net_device *netdev, int drv_sds_rings)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct qlcnic_host_sds_ring *sds_ring;
|
struct qlcnic_host_sds_ring *sds_ring;
|
||||||
int max_tx_rings = adapter->max_drv_tx_rings;
|
int drv_tx_rings = adapter->drv_tx_rings;
|
||||||
int ring;
|
int ring;
|
||||||
|
|
||||||
clear_bit(__QLCNIC_DEV_UP, &adapter->state);
|
clear_bit(__QLCNIC_DEV_UP, &adapter->state);
|
||||||
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
||||||
for (ring = 0; ring < adapter->max_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_int(sds_ring);
|
||||||
}
|
}
|
||||||
|
@ -1836,8 +1872,8 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
|
||||||
qlcnic_detach(adapter);
|
qlcnic_detach(adapter);
|
||||||
|
|
||||||
adapter->ahw->diag_test = 0;
|
adapter->ahw->diag_test = 0;
|
||||||
adapter->max_sds_rings = max_sds_rings;
|
adapter->drv_sds_rings = drv_sds_rings;
|
||||||
adapter->max_drv_tx_rings = max_tx_rings;
|
adapter->drv_tx_rings = drv_tx_rings;
|
||||||
|
|
||||||
if (qlcnic_attach(adapter))
|
if (qlcnic_attach(adapter))
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1903,10 +1939,10 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
|
||||||
|
|
||||||
qlcnic_detach(adapter);
|
qlcnic_detach(adapter);
|
||||||
|
|
||||||
adapter->max_sds_rings = 1;
|
adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
|
||||||
|
adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
|
||||||
adapter->ahw->diag_test = test;
|
adapter->ahw->diag_test = test;
|
||||||
adapter->ahw->linkup = 0;
|
adapter->ahw->linkup = 0;
|
||||||
adapter->max_drv_tx_rings = 1;
|
|
||||||
|
|
||||||
ret = qlcnic_attach(adapter);
|
ret = qlcnic_attach(adapter);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -1927,7 +1963,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->max_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_int(sds_ring);
|
||||||
}
|
}
|
||||||
|
@ -2100,7 +2136,7 @@ void qlcnic_free_tx_rings(struct qlcnic_adapter *adapter)
|
||||||
int ring;
|
int ring;
|
||||||
struct qlcnic_host_tx_ring *tx_ring;
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
if (tx_ring && tx_ring->cmd_buf_arr != NULL) {
|
if (tx_ring && tx_ring->cmd_buf_arr != NULL) {
|
||||||
vfree(tx_ring->cmd_buf_arr);
|
vfree(tx_ring->cmd_buf_arr);
|
||||||
|
@ -2118,14 +2154,14 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
|
||||||
struct qlcnic_host_tx_ring *tx_ring;
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
struct qlcnic_cmd_buffer *cmd_buf_arr;
|
struct qlcnic_cmd_buffer *cmd_buf_arr;
|
||||||
|
|
||||||
tx_ring = kcalloc(adapter->max_drv_tx_rings,
|
tx_ring = kcalloc(adapter->drv_tx_rings,
|
||||||
sizeof(struct qlcnic_host_tx_ring), GFP_KERNEL);
|
sizeof(struct qlcnic_host_tx_ring), GFP_KERNEL);
|
||||||
if (tx_ring == NULL)
|
if (tx_ring == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
adapter->tx_ring = tx_ring;
|
adapter->tx_ring = tx_ring;
|
||||||
|
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
tx_ring->num_desc = adapter->num_txd;
|
tx_ring->num_desc = adapter->num_txd;
|
||||||
tx_ring->txq = netdev_get_tx_queue(netdev, ring);
|
tx_ring->txq = netdev_get_tx_queue(netdev, ring);
|
||||||
|
@ -2140,11 +2176,11 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
|
||||||
|
|
||||||
if (qlcnic_83xx_check(adapter) ||
|
if (qlcnic_83xx_check(adapter) ||
|
||||||
(qlcnic_82xx_check(adapter) && qlcnic_check_multi_tx(adapter))) {
|
(qlcnic_82xx_check(adapter) && qlcnic_check_multi_tx(adapter))) {
|
||||||
for (ring = 0; ring < adapter->max_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];
|
||||||
tx_ring->adapter = adapter;
|
tx_ring->adapter = adapter;
|
||||||
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
||||||
index = adapter->max_sds_rings + ring;
|
index = adapter->drv_sds_rings + ring;
|
||||||
vector = adapter->msix_entries[index].vector;
|
vector = adapter->msix_entries[index].vector;
|
||||||
tx_ring->irq = vector;
|
tx_ring->irq = vector;
|
||||||
}
|
}
|
||||||
|
@ -2263,6 +2299,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
rwlock_init(&adapter->ahw->crb_lock);
|
rwlock_init(&adapter->ahw->crb_lock);
|
||||||
mutex_init(&adapter->ahw->mem_lock);
|
mutex_init(&adapter->ahw->mem_lock);
|
||||||
|
|
||||||
|
spin_lock_init(&adapter->tx_clean_lock);
|
||||||
INIT_LIST_HEAD(&adapter->mac_list);
|
INIT_LIST_HEAD(&adapter->mac_list);
|
||||||
|
|
||||||
qlcnic_register_dcb(adapter);
|
qlcnic_register_dcb(adapter);
|
||||||
|
@ -2277,20 +2314,21 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
goto err_out_maintenance_mode;
|
goto err_out_maintenance_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
qlcnic_get_multiq_capability(adapter);
|
/* compute and set default and max tx/sds rings */
|
||||||
|
if (adapter->ahw->msix_supported) {
|
||||||
if ((adapter->ahw->act_pci_func > 2) &&
|
if (qlcnic_check_multi_tx_capability(adapter) == 1)
|
||||||
qlcnic_check_multi_tx(adapter)) {
|
qlcnic_set_tx_ring_count(adapter,
|
||||||
adapter->max_drv_tx_rings = QLCNIC_DEF_NUM_TX_RINGS;
|
QLCNIC_SINGLE_RING);
|
||||||
dev_info(&adapter->pdev->dev,
|
else
|
||||||
"vNIC mode enabled, Set max TX rings = %d\n",
|
qlcnic_set_tx_ring_count(adapter,
|
||||||
adapter->max_drv_tx_rings);
|
QLCNIC_DEF_TX_RINGS);
|
||||||
|
qlcnic_set_sds_ring_count(adapter,
|
||||||
|
QLCNIC_DEF_SDS_RINGS);
|
||||||
|
} else {
|
||||||
|
qlcnic_set_tx_ring_count(adapter, QLCNIC_SINGLE_RING);
|
||||||
|
qlcnic_set_sds_ring_count(adapter, QLCNIC_SINGLE_RING);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qlcnic_check_multi_tx(adapter)) {
|
|
||||||
clear_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state);
|
|
||||||
adapter->max_drv_tx_rings = 1;
|
|
||||||
}
|
|
||||||
err = qlcnic_setup_idc_param(adapter);
|
err = qlcnic_setup_idc_param(adapter);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_out_free_hw;
|
goto err_out_free_hw;
|
||||||
|
@ -2301,16 +2339,26 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
|
|
||||||
if (dcb && qlcnic_dcb_attach(dcb))
|
if (dcb && qlcnic_dcb_attach(dcb))
|
||||||
qlcnic_clear_dcb_ops(dcb);
|
qlcnic_clear_dcb_ops(dcb);
|
||||||
|
|
||||||
} else if (qlcnic_83xx_check(adapter)) {
|
} else if (qlcnic_83xx_check(adapter)) {
|
||||||
adapter->max_drv_tx_rings = 1;
|
|
||||||
qlcnic_83xx_check_vf(adapter, ent);
|
qlcnic_83xx_check_vf(adapter, ent);
|
||||||
adapter->portnum = adapter->ahw->pci_func;
|
adapter->portnum = adapter->ahw->pci_func;
|
||||||
err = qlcnic_83xx_init(adapter, pci_using_dac);
|
err = qlcnic_83xx_init(adapter, pci_using_dac);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "%s: failed\n", __func__);
|
switch (err) {
|
||||||
goto err_out_free_hw;
|
case -ENOTRECOVERABLE:
|
||||||
|
dev_err(&pdev->dev, "Adapter initialization failed due to a faulty hardware. Please reboot\n");
|
||||||
|
dev_err(&pdev->dev, "If reboot doesn't help, please replace the adapter with new one and return the faulty adapter for repair\n");
|
||||||
|
goto err_out_free_hw;
|
||||||
|
case -ENOMEM:
|
||||||
|
dev_err(&pdev->dev, "Adapter initialization failed. Please reboot\n");
|
||||||
|
goto err_out_free_hw;
|
||||||
|
default:
|
||||||
|
dev_err(&pdev->dev, "Adapter initialization failed. A reboot may be required to recover from this failure\n");
|
||||||
|
dev_err(&pdev->dev, "If reboot does not help to recover from this failure, try a flash update of the adapter\n");
|
||||||
|
goto err_out_maintenance_mode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qlcnic_sriov_vf_check(adapter))
|
if (qlcnic_sriov_vf_check(adapter))
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2338,7 +2386,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
"Device does not support MSI interrupts\n");
|
"Device does not support MSI interrupts\n");
|
||||||
|
|
||||||
if (qlcnic_82xx_check(adapter)) {
|
if (qlcnic_82xx_check(adapter)) {
|
||||||
err = qlcnic_setup_intr(adapter, 0, 0);
|
err = qlcnic_setup_intr(adapter);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "Failed to setup interrupt\n");
|
dev_err(&pdev->dev, "Failed to setup interrupt\n");
|
||||||
goto err_out_disable_msi;
|
goto err_out_disable_msi;
|
||||||
|
@ -2412,8 +2460,16 @@ err_out_disable_pdev:
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err_out_maintenance_mode:
|
err_out_maintenance_mode:
|
||||||
|
set_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state);
|
||||||
netdev->netdev_ops = &qlcnic_netdev_failed_ops;
|
netdev->netdev_ops = &qlcnic_netdev_failed_ops;
|
||||||
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
|
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
|
||||||
|
ahw->port_type = QLCNIC_XGBE;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
adapter->tgt_status_reg = NULL;
|
||||||
|
else
|
||||||
|
ahw->board_type = QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS;
|
||||||
|
|
||||||
err = register_netdev(netdev);
|
err = register_netdev(netdev);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -2535,12 +2591,11 @@ static int qlcnic_resume(struct pci_dev *pdev)
|
||||||
static int qlcnic_open(struct net_device *netdev)
|
static int qlcnic_open(struct net_device *netdev)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
u32 state;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
|
||||||
if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD) {
|
netdev_err(netdev, "%s: Device is in non-operational state\n",
|
||||||
netdev_err(netdev, "%s: Device is in FAILED state\n", __func__);
|
__func__);
|
||||||
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -2702,24 +2757,21 @@ 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");
|
||||||
if (qlcnic_82xx_check(adapter)) {
|
for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings;
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
ring++) {
|
netdev_info(netdev, "Tx ring=%d\n", ring);
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
netdev_info(netdev,
|
||||||
dev_info(&netdev->dev, "ring=%d\n", ring);
|
"crb_intr_mask=%d, producer=%d, sw_consumer=%d, hw_consumer=%d\n",
|
||||||
dev_info(&netdev->dev, "crb_intr_mask=%d\n",
|
readl(tx_ring->crb_intr_mask),
|
||||||
readl(tx_ring->crb_intr_mask));
|
readl(tx_ring->crb_cmd_producer),
|
||||||
dev_info(&netdev->dev, "producer=%d\n",
|
tx_ring->sw_consumer,
|
||||||
readl(tx_ring->crb_cmd_producer));
|
le32_to_cpu(*(tx_ring->hw_consumer)));
|
||||||
dev_info(&netdev->dev, "sw_consumer = %d\n",
|
netdev_info(netdev,
|
||||||
tx_ring->sw_consumer);
|
"xmit_finished=%llu, xmit_called=%llu, xmit_on=%llu, xmit_off=%llu\n",
|
||||||
dev_info(&netdev->dev, "hw_consumer = %d\n",
|
tx_ring->tx_stats.xmit_finished,
|
||||||
le32_to_cpu(*(tx_ring->hw_consumer)));
|
tx_ring->tx_stats.xmit_called,
|
||||||
dev_info(&netdev->dev, "xmit-on=%llu\n",
|
tx_ring->tx_stats.xmit_on,
|
||||||
tx_ring->xmit_on);
|
tx_ring->tx_stats.xmit_off);
|
||||||
dev_info(&netdev->dev, "xmit-off=%llu\n",
|
|
||||||
tx_ring->xmit_off);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
adapter->ahw->reset_context = 1;
|
adapter->ahw->reset_context = 1;
|
||||||
}
|
}
|
||||||
|
@ -2833,7 +2885,7 @@ static void qlcnic_poll_controller(struct net_device *netdev)
|
||||||
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
||||||
|
|
||||||
disable_irq(adapter->irq);
|
disable_irq(adapter->irq);
|
||||||
for (ring = 0; ring < adapter->max_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_intr(adapter->irq, sds_ring);
|
||||||
}
|
}
|
||||||
|
@ -3253,8 +3305,9 @@ void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
||||||
if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD) {
|
|
||||||
netdev_err(adapter->netdev, "%s: Device is in FAILED state\n",
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
|
||||||
|
netdev_err(adapter->netdev, "%s: Device is in non-operational state\n",
|
||||||
__func__);
|
__func__);
|
||||||
qlcnic_api_unlock(adapter);
|
qlcnic_api_unlock(adapter);
|
||||||
|
|
||||||
|
@ -3499,7 +3552,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
|
||||||
qlcnic_clr_drv_state(adapter);
|
qlcnic_clr_drv_state(adapter);
|
||||||
kfree(adapter->msix_entries);
|
kfree(adapter->msix_entries);
|
||||||
adapter->msix_entries = NULL;
|
adapter->msix_entries = NULL;
|
||||||
err = qlcnic_setup_intr(adapter, 0, 0);
|
err = qlcnic_setup_intr(adapter);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
kfree(adapter->msix_entries);
|
kfree(adapter->msix_entries);
|
||||||
|
@ -3644,130 +3697,90 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *adapter, u32 txq)
|
int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt,
|
||||||
|
int queue_type)
|
||||||
{
|
{
|
||||||
struct net_device *netdev = adapter->netdev;
|
struct net_device *netdev = adapter->netdev;
|
||||||
u8 max_hw = QLCNIC_MAX_TX_RINGS;
|
u8 max_hw_rings = 0;
|
||||||
u32 max_allowed;
|
char buf[8];
|
||||||
|
int cur_rings;
|
||||||
|
|
||||||
|
if (queue_type == QLCNIC_RX_QUEUE) {
|
||||||
|
max_hw_rings = adapter->max_sds_rings;
|
||||||
|
cur_rings = adapter->drv_sds_rings;
|
||||||
|
strcpy(buf, "SDS");
|
||||||
|
} else if (queue_type == QLCNIC_TX_QUEUE) {
|
||||||
|
max_hw_rings = adapter->max_tx_rings;
|
||||||
|
cur_rings = adapter->drv_tx_rings;
|
||||||
|
strcpy(buf, "Tx");
|
||||||
|
}
|
||||||
|
|
||||||
if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
|
if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
|
||||||
netdev_err(netdev, "No Multi TX-Q support in INT-x mode\n");
|
netdev_err(netdev, "No RSS/TSS support in INT-x mode\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qlcnic_check_multi_tx(adapter)) {
|
if (adapter->flags & QLCNIC_MSI_ENABLED) {
|
||||||
netdev_err(netdev, "No Multi TX-Q support\n");
|
netdev_err(netdev, "No RSS/TSS support in MSI mode\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txq > QLCNIC_MAX_TX_RINGS) {
|
if (ring_cnt < 2) {
|
||||||
netdev_err(netdev, "Invalid ring count\n");
|
netdev_err(netdev,
|
||||||
|
"%s rings value should not be lower than 2\n", buf);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
max_allowed = rounddown_pow_of_two(min_t(int, max_hw,
|
if (!is_power_of_2(ring_cnt)) {
|
||||||
num_online_cpus()));
|
netdev_err(netdev, "%s rings value should be a power of 2\n",
|
||||||
if ((txq > max_allowed) || !is_power_of_2(txq)) {
|
buf);
|
||||||
if (!is_power_of_2(txq))
|
return -EINVAL;
|
||||||
netdev_err(netdev,
|
}
|
||||||
"TX queue should be a power of 2\n");
|
|
||||||
if (txq > num_online_cpus())
|
if (qlcnic_82xx_check(adapter) && (queue_type == QLCNIC_TX_QUEUE) &&
|
||||||
netdev_err(netdev,
|
!qlcnic_check_multi_tx(adapter)) {
|
||||||
"Tx queue should not be higher than [%u], number of online CPUs in the system\n",
|
netdev_err(netdev, "No Multi Tx queue support\n");
|
||||||
num_online_cpus());
|
return -EINVAL;
|
||||||
netdev_err(netdev, "Unable to configure %u Tx rings\n", txq);
|
}
|
||||||
|
|
||||||
|
if (ring_cnt > num_online_cpus()) {
|
||||||
|
netdev_err(netdev,
|
||||||
|
"%s value[%u] should not be higher than, number of online CPUs\n",
|
||||||
|
buf, num_online_cpus());
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter,
|
int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt)
|
||||||
__u32 val)
|
|
||||||
{
|
{
|
||||||
struct net_device *netdev = adapter->netdev;
|
struct net_device *netdev = adapter->netdev;
|
||||||
u8 max_hw = adapter->ahw->max_rx_ques;
|
|
||||||
u32 max_allowed;
|
|
||||||
|
|
||||||
if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
|
|
||||||
netdev_err(netdev, "No RSS support in INT-x mode\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (val > QLCNIC_MAX_SDS_RINGS) {
|
|
||||||
netdev_err(netdev, "RSS value should not be higher than %u\n",
|
|
||||||
QLCNIC_MAX_SDS_RINGS);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
max_allowed = rounddown_pow_of_two(min_t(int, max_hw,
|
|
||||||
num_online_cpus()));
|
|
||||||
if ((val > max_allowed) || (val < 2) || !is_power_of_2(val)) {
|
|
||||||
if (!is_power_of_2(val))
|
|
||||||
netdev_err(netdev, "RSS value should be a power of 2\n");
|
|
||||||
|
|
||||||
if (val < 2)
|
|
||||||
netdev_err(netdev, "RSS value should not be lower than 2\n");
|
|
||||||
|
|
||||||
if (val > max_hw)
|
|
||||||
netdev_err(netdev,
|
|
||||||
"RSS value should not be higher than[%u], the max RSS rings supported by the adapter\n",
|
|
||||||
max_hw);
|
|
||||||
|
|
||||||
if (val > num_online_cpus())
|
|
||||||
netdev_err(netdev,
|
|
||||||
"RSS value should not be higher than[%u], number of online CPUs in the system\n",
|
|
||||||
num_online_cpus());
|
|
||||||
|
|
||||||
netdev_err(netdev, "Unable to configure %u RSS rings\n", val);
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, int txq)
|
|
||||||
{
|
|
||||||
int err;
|
int err;
|
||||||
struct net_device *netdev = adapter->netdev;
|
|
||||||
int num_msix;
|
|
||||||
|
|
||||||
if (test_bit(__QLCNIC_RESETTING, &adapter->state))
|
if (test_bit(__QLCNIC_RESETTING, &adapter->state))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x &&
|
|
||||||
!qlcnic_use_msi) {
|
|
||||||
netdev_err(netdev, "No RSS support in INT-x mode\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
netif_device_detach(netdev);
|
netif_device_detach(netdev);
|
||||||
if (netif_running(netdev))
|
if (netif_running(netdev))
|
||||||
__qlcnic_down(adapter, netdev);
|
__qlcnic_down(adapter, netdev);
|
||||||
|
|
||||||
qlcnic_detach(adapter);
|
qlcnic_detach(adapter);
|
||||||
|
|
||||||
if (qlcnic_82xx_check(adapter)) {
|
|
||||||
if (txq != 0)
|
|
||||||
adapter->max_drv_tx_rings = txq;
|
|
||||||
|
|
||||||
if (qlcnic_check_multi_tx(adapter) &&
|
|
||||||
(txq > adapter->max_drv_tx_rings))
|
|
||||||
num_msix = adapter->max_drv_tx_rings;
|
|
||||||
else
|
|
||||||
num_msix = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qlcnic_83xx_check(adapter)) {
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
qlcnic_83xx_free_mbx_intr(adapter);
|
qlcnic_83xx_free_mbx_intr(adapter);
|
||||||
qlcnic_83xx_enable_mbx_poll(adapter);
|
qlcnic_83xx_enable_mbx_poll(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
netif_set_real_num_tx_queues(netdev, adapter->max_drv_tx_rings);
|
|
||||||
|
|
||||||
qlcnic_teardown_intr(adapter);
|
qlcnic_teardown_intr(adapter);
|
||||||
|
|
||||||
err = qlcnic_setup_intr(adapter, data, txq);
|
/* 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) {
|
if (err) {
|
||||||
kfree(adapter->msix_entries);
|
kfree(adapter->msix_entries);
|
||||||
netdev_err(netdev, "failed to setup interrupt\n");
|
netdev_err(netdev, "failed to setup interrupt\n");
|
||||||
|
|
|
@ -508,7 +508,11 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
|
||||||
dev_warn(&adapter->pdev->dev,
|
dev_warn(&adapter->pdev->dev,
|
||||||
"Device does not support MSI interrupts\n");
|
"Device does not support MSI interrupts\n");
|
||||||
|
|
||||||
err = qlcnic_setup_intr(adapter, 1, 0);
|
/* compute and set default and max tx/sds rings */
|
||||||
|
qlcnic_set_tx_ring_count(adapter, QLCNIC_SINGLE_RING);
|
||||||
|
qlcnic_set_sds_ring_count(adapter, QLCNIC_SINGLE_RING);
|
||||||
|
|
||||||
|
err = qlcnic_setup_intr(adapter);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
|
dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
|
||||||
goto err_out_disable_msi;
|
goto err_out_disable_msi;
|
||||||
|
|
|
@ -156,7 +156,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
|
||||||
const char *buf, size_t len)
|
const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
int err, max_sds_rings = adapter->max_sds_rings;
|
int err, drv_sds_rings = adapter->drv_sds_rings;
|
||||||
u16 beacon;
|
u16 beacon;
|
||||||
u8 h_beacon_state, b_state, b_rate;
|
u8 h_beacon_state, b_state, b_rate;
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
|
if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
|
||||||
qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
|
qlcnic_diag_free_res(adapter->netdev, drv_sds_rings);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (!ahw->beacon_state)
|
if (!ahw->beacon_state)
|
||||||
|
@ -1272,7 +1272,6 @@ void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
|
||||||
void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
|
void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct device *dev = &adapter->pdev->dev;
|
struct device *dev = &adapter->pdev->dev;
|
||||||
u32 state;
|
|
||||||
|
|
||||||
if (device_create_bin_file(dev, &bin_attr_port_stats))
|
if (device_create_bin_file(dev, &bin_attr_port_stats))
|
||||||
dev_info(dev, "failed to create port stats sysfs entry");
|
dev_info(dev, "failed to create port stats sysfs entry");
|
||||||
|
@ -1286,8 +1285,7 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
if (device_create_bin_file(dev, &bin_attr_mem))
|
if (device_create_bin_file(dev, &bin_attr_mem))
|
||||||
dev_info(dev, "failed to create mem sysfs entry\n");
|
dev_info(dev, "failed to create mem sysfs entry\n");
|
||||||
|
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
|
||||||
if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (device_create_bin_file(dev, &bin_attr_pci_config))
|
if (device_create_bin_file(dev, &bin_attr_pci_config))
|
||||||
|
@ -1313,7 +1311,6 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
|
void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct device *dev = &adapter->pdev->dev;
|
struct device *dev = &adapter->pdev->dev;
|
||||||
u32 state;
|
|
||||||
|
|
||||||
device_remove_bin_file(dev, &bin_attr_port_stats);
|
device_remove_bin_file(dev, &bin_attr_port_stats);
|
||||||
|
|
||||||
|
@ -1323,8 +1320,7 @@ void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
device_remove_bin_file(dev, &bin_attr_crb);
|
device_remove_bin_file(dev, &bin_attr_crb);
|
||||||
device_remove_bin_file(dev, &bin_attr_mem);
|
device_remove_bin_file(dev, &bin_attr_mem);
|
||||||
|
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
|
||||||
if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
device_remove_bin_file(dev, &bin_attr_pci_config);
|
device_remove_bin_file(dev, &bin_attr_pci_config);
|
||||||
|
|
Loading…
Reference in New Issue