Commit 96635fbd authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 16514839 db62d7d9
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
#define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 3 #define _QLCNIC_LINUX_MINOR 3
#define _QLCNIC_LINUX_SUBVERSION 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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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); ...@@ -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) ...@@ -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 = tx_q; netdev->num_tx_queues = adapter->drv_tx_rings;
netdev->real_num_tx_queues = tx_q; netdev->real_num_tx_queues = adapter->drv_tx_rings;
err = netif_set_real_num_tx_queues(netdev, tx_q); err = netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);
if (err) if (err)
dev_err(&adapter->pdev->dev, "failed to set %d Tx queues\n", 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 { ...@@ -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, ...@@ -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) ...@@ -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 @@ ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, ...@@ -1290,7 +1295,7 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
} }
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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) ...@@ -2247,12 +2279,10 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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[] = { ...@@ -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_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
{"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
{"xmit_called", QLC_SIZEOF(stats.xmitcalled), {"xmit_called", QLC_SIZEOF(stats.xmitcalled),
QLC_OFF(stats.xmitcalled)}, QLC_OFF(stats.xmitcalled)},
{"xmit_finished", QLC_SIZEOF(stats.xmitfinished), {"xmit_finished", QLC_SIZEOF(stats.xmitfinished),
QLC_OFF(stats.xmitfinished)}, QLC_OFF(stats.xmitfinished)},
{"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)}, {"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)}, {"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
{"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)}, {"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_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)}, {"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
{"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, {"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)}, {"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
{"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)}, {"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_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
{"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] = { ...@@ -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] = { ...@@ -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[] = { ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 = rounddown_pow_of_two(min);
channel->max_tx = min_t(int, QLCNIC_MAX_TX_RINGS, num_online_cpus());
channel->rx_count = adapter->max_sds_rings; channel->max_rx = adapter->max_sds_rings;
channel->tx_count = adapter->max_drv_tx_rings; channel->max_tx = adapter->max_tx_rings;
channel->rx_count = adapter->drv_sds_rings;
channel->tx_count = adapter->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) ...@@ -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 @@ static int qlcnic_irq_test(struct net_device *netdev) ...@@ -931,10 +976,10 @@ static int qlcnic_irq_test(struct net_device *netdev)
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2412,8 +2460,16 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 (!qlcnic_use_msi_x && !qlcnic_use_msi) { if (queue_type == QLCNIC_RX_QUEUE) {
netdev_err(netdev, "No Multi TX-Q support in INT-x mode\n"); max_hw_rings = adapter->max_sds_rings;
return -EINVAL; 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_check_multi_tx(adapter)) { if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
netdev_err(netdev, "No Multi TX-Q support\n"); netdev_err(netdev, "No RSS/TSS support in INT-x mode\n");
return -EINVAL; return -EINVAL;
} }
if (txq > QLCNIC_MAX_TX_RINGS) { if (adapter->flags & QLCNIC_MSI_ENABLED) {
netdev_err(netdev, "Invalid ring count\n"); netdev_err(netdev, "No RSS/TSS support in MSI mode\n");
return -EINVAL; return -EINVAL;
} }
max_allowed = rounddown_pow_of_two(min_t(int, max_hw, if (ring_cnt < 2) {
num_online_cpus())); netdev_err(netdev,
if ((txq > max_allowed) || !is_power_of_2(txq)) { "%s rings value should not be lower than 2\n", buf);
if (!is_power_of_2(txq))
netdev_err(netdev,
"TX queue should be a power of 2\n");
if (txq > num_online_cpus())
netdev_err(netdev,
"Tx queue should not be higher than [%u], number of online CPUs in the system\n",
num_online_cpus());
netdev_err(netdev, "Unable to configure %u Tx rings\n", txq);
return -EINVAL; return -EINVAL;
} }
return 0; if (!is_power_of_2(ring_cnt)) {
} netdev_err(netdev, "%s rings value should be a power of 2\n",
buf);
int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter,
__u32 val)
{
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; return -EINVAL;
} }
if (val > QLCNIC_MAX_SDS_RINGS) { if (qlcnic_82xx_check(adapter) && (queue_type == QLCNIC_TX_QUEUE) &&
netdev_err(netdev, "RSS value should not be higher than %u\n", !qlcnic_check_multi_tx(adapter)) {
QLCNIC_MAX_SDS_RINGS); netdev_err(netdev, "No Multi Tx queue support\n");
return -EINVAL; return -EINVAL;
} }
max_allowed = rounddown_pow_of_two(min_t(int, max_hw, if (ring_cnt > num_online_cpus()) {
num_online_cpus())); netdev_err(netdev,
if ((val > max_allowed) || (val < 2) || !is_power_of_2(val)) { "%s value[%u] should not be higher than, number of online CPUs\n",
if (!is_power_of_2(val)) buf, num_online_cpus());
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 -EINVAL;
} }
return 0; return 0;
} }
int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, int txq) int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt)
{ {
int err;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
int num_msix; int err;
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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment