bnx2x: Support loading cnic resources at run-time

This patch replaces the BCM_CNIC define with a flag which can change at run-time
and which does not use the CONFIG_CNIC kconfig option.
For the PF/hypervisor driver cnic is always supported, however allocation of
cnic resources and configuration of the HW for offload mode is done only when
the cnic module registers bnx2x.

Signed-off-by: Merav Sicron <meravs@broadcom.com>
Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Merav Sicron 2012-11-07 00:45:48 +00:00 committed by David S. Miller
parent babc6727d5
commit 55c11941e3
12 changed files with 1111 additions and 592 deletions

View file

@ -34,18 +34,10 @@
#include "bnx2x_hsi.h" #include "bnx2x_hsi.h"
#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
#define BCM_CNIC 1
#include "../cnic_if.h" #include "../cnic_if.h"
#endif
#ifdef BCM_CNIC
#define BNX2X_MIN_MSIX_VEC_CNT 3 #define BNX2X_MIN_MSIX_VEC_CNT(bp) ((bp)->min_msix_vec_cnt)
#define BNX2X_MSIX_VEC_FP_START 2
#else
#define BNX2X_MIN_MSIX_VEC_CNT 2
#define BNX2X_MSIX_VEC_FP_START 1
#endif
#include <linux/mdio.h> #include <linux/mdio.h>
@ -256,15 +248,10 @@ enum {
/* FCoE L2 */ /* FCoE L2 */
#define BNX2X_FCOE_ETH_CID(bp) (BNX2X_CNIC_START_ETH_CID(bp) + 1) #define BNX2X_FCOE_ETH_CID(bp) (BNX2X_CNIC_START_ETH_CID(bp) + 1)
/** Additional rings budgeting */ #define CNIC_SUPPORT(bp) ((bp)->cnic_support)
#ifdef BCM_CNIC #define CNIC_ENABLED(bp) ((bp)->cnic_enabled)
#define CNIC_PRESENT 1 #define CNIC_LOADED(bp) ((bp)->cnic_loaded)
#define FCOE_PRESENT 1 #define FCOE_INIT(bp) ((bp)->fcoe_init)
#else
#define CNIC_PRESENT 0
#define FCOE_PRESENT 0
#endif /* BCM_CNIC */
#define NON_ETH_CONTEXT_USE (FCOE_PRESENT)
#define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \ #define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
@ -297,9 +284,7 @@ enum {
OOO_TXQ_IDX_OFFSET, OOO_TXQ_IDX_OFFSET,
}; };
#define MAX_ETH_TXQ_IDX(bp) (BNX2X_NUM_NON_CNIC_QUEUES(bp) * (bp)->max_cos) #define MAX_ETH_TXQ_IDX(bp) (BNX2X_NUM_NON_CNIC_QUEUES(bp) * (bp)->max_cos)
#ifdef BCM_CNIC
#define FCOE_TXQ_IDX(bp) (MAX_ETH_TXQ_IDX(bp) + FCOE_TXQ_IDX_OFFSET) #define FCOE_TXQ_IDX(bp) (MAX_ETH_TXQ_IDX(bp) + FCOE_TXQ_IDX_OFFSET)
#endif
/* fast path */ /* fast path */
/* /*
@ -585,15 +570,9 @@ struct bnx2x_fastpath {
->var) ->var)
#define IS_ETH_FP(fp) (fp->index < \ #define IS_ETH_FP(fp) ((fp)->index < BNX2X_NUM_ETH_QUEUES((fp)->bp))
BNX2X_NUM_ETH_QUEUES(fp->bp)) #define IS_FCOE_FP(fp) ((fp)->index == FCOE_IDX((fp)->bp))
#ifdef BCM_CNIC #define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX(bp))
#define IS_FCOE_FP(fp) (fp->index == FCOE_IDX(fp->bp))
#define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX(bp))
#else
#define IS_FCOE_FP(fp) false
#define IS_FCOE_IDX(idx) false
#endif
/* MC hsi */ /* MC hsi */
@ -886,6 +865,18 @@ struct bnx2x_common {
(CHIP_REV(bp) == CHIP_REV_Bx)) (CHIP_REV(bp) == CHIP_REV_Bx))
#define CHIP_IS_E3A0(bp) (CHIP_IS_E3(bp) && \ #define CHIP_IS_E3A0(bp) (CHIP_IS_E3(bp) && \
(CHIP_REV(bp) == CHIP_REV_Ax)) (CHIP_REV(bp) == CHIP_REV_Ax))
/* This define is used in two main places:
* 1. In the early stages of nic_load, to know if to configrue Parser / Searcher
* to nic-only mode or to offload mode. Offload mode is configured if either the
* chip is E1x (where MIC_MODE register is not applicable), or if cnic already
* registered for this port (which means that the user wants storage services).
* 2. During cnic-related load, to know if offload mode is already configured in
* the HW or needs to be configrued.
* Since the transition from nic-mode to offload-mode in HW causes traffic
* coruption, nic-mode is configured only in ports on which storage services
* where never requested.
*/
#define CONFIGURE_NIC_MODE(bp) (!CHIP_IS_E1x(bp) && !CNIC_ENABLED(bp))
int flash_size; int flash_size;
#define BNX2X_NVRAM_1MB_SIZE 0x20000 /* 1M bit in bytes */ #define BNX2X_NVRAM_1MB_SIZE 0x20000 /* 1M bit in bytes */
@ -1003,18 +994,15 @@ union cdu_context {
#define CDU_ILT_PAGE_SZ (8192 << CDU_ILT_PAGE_SZ_HW) /* 32K */ #define CDU_ILT_PAGE_SZ (8192 << CDU_ILT_PAGE_SZ_HW) /* 32K */
#define ILT_PAGE_CIDS (CDU_ILT_PAGE_SZ / sizeof(union cdu_context)) #define ILT_PAGE_CIDS (CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
#ifdef BCM_CNIC
#define CNIC_ISCSI_CID_MAX 256 #define CNIC_ISCSI_CID_MAX 256
#define CNIC_FCOE_CID_MAX 2048 #define CNIC_FCOE_CID_MAX 2048
#define CNIC_CID_MAX (CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX) #define CNIC_CID_MAX (CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX)
#define CNIC_ILT_LINES DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS) #define CNIC_ILT_LINES DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
#endif
#define QM_ILT_PAGE_SZ_HW 0 #define QM_ILT_PAGE_SZ_HW 0
#define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 4K */ #define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 4K */
#define QM_CID_ROUND 1024 #define QM_CID_ROUND 1024
#ifdef BCM_CNIC
/* TM (timers) host DB constants */ /* TM (timers) host DB constants */
#define TM_ILT_PAGE_SZ_HW 0 #define TM_ILT_PAGE_SZ_HW 0
#define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */ #define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
@ -1032,8 +1020,6 @@ union cdu_context {
#define SRC_T2_SZ SRC_ILT_SZ #define SRC_T2_SZ SRC_ILT_SZ
#define SRC_ILT_LINES DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ) #define SRC_ILT_LINES DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
#endif
#define MAX_DMAE_C 8 #define MAX_DMAE_C 8
/* DMA memory not used in fastpath */ /* DMA memory not used in fastpath */
@ -1227,7 +1213,6 @@ struct bnx2x {
struct bnx2x_sp_objs *sp_objs; struct bnx2x_sp_objs *sp_objs;
struct bnx2x_fp_stats *fp_stats; struct bnx2x_fp_stats *fp_stats;
struct bnx2x_fp_txdata *bnx2x_txq; struct bnx2x_fp_txdata *bnx2x_txq;
int bnx2x_txq_size;
void __iomem *regview; void __iomem *regview;
void __iomem *doorbells; void __iomem *doorbells;
u16 db_size; u16 db_size;
@ -1350,6 +1335,15 @@ struct bnx2x {
#define NO_ISCSI_OOO(bp) ((bp)->flags & NO_ISCSI_OOO_FLAG) #define NO_ISCSI_OOO(bp) ((bp)->flags & NO_ISCSI_OOO_FLAG)
#define NO_FCOE(bp) ((bp)->flags & NO_FCOE_FLAG) #define NO_FCOE(bp) ((bp)->flags & NO_FCOE_FLAG)
u8 cnic_support;
bool cnic_enabled;
bool cnic_loaded;
/* Flag that indicates that we can start looking for FCoE L2 queue
* completions in the default status block.
*/
bool fcoe_init;
int pm_cap; int pm_cap;
int mrrs; int mrrs;
@ -1420,6 +1414,8 @@ struct bnx2x {
#define BNX2X_MAX_COS 3 #define BNX2X_MAX_COS 3
#define BNX2X_MAX_TX_COS 2 #define BNX2X_MAX_TX_COS 2
int num_queues; int num_queues;
uint num_ethernet_queues;
uint num_cnic_queues;
int num_napi_queues; int num_napi_queues;
int disable_tpa; int disable_tpa;
@ -1433,6 +1429,7 @@ struct bnx2x {
u8 igu_dsb_id; u8 igu_dsb_id;
u8 igu_base_sb; u8 igu_base_sb;
u8 igu_sb_cnt; u8 igu_sb_cnt;
u8 min_msix_vec_cnt;
dma_addr_t def_status_blk_mapping; dma_addr_t def_status_blk_mapping;
@ -1478,16 +1475,16 @@ struct bnx2x {
* Maximum supported number of RSS queues: number of IGU SBs minus one that goes * Maximum supported number of RSS queues: number of IGU SBs minus one that goes
* to CNIC. * to CNIC.
*/ */
#define BNX2X_MAX_RSS_COUNT(bp) ((bp)->igu_sb_cnt - CNIC_PRESENT) #define BNX2X_MAX_RSS_COUNT(bp) ((bp)->igu_sb_cnt - CNIC_SUPPORT(bp))
/* /*
* Maximum CID count that might be required by the bnx2x: * Maximum CID count that might be required by the bnx2x:
* Max RSS * Max_Tx_Multi_Cos + FCoE + iSCSI * Max RSS * Max_Tx_Multi_Cos + FCoE + iSCSI
*/ */
#define BNX2X_L2_CID_COUNT(bp) (BNX2X_NUM_ETH_QUEUES(bp) * BNX2X_MULTI_TX_COS \ #define BNX2X_L2_CID_COUNT(bp) (BNX2X_NUM_ETH_QUEUES(bp) * BNX2X_MULTI_TX_COS \
+ NON_ETH_CONTEXT_USE + CNIC_PRESENT) + 2 * CNIC_SUPPORT(bp))
#define BNX2X_L2_MAX_CID(bp) (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS \ #define BNX2X_L2_MAX_CID(bp) (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS \
+ NON_ETH_CONTEXT_USE + CNIC_PRESENT) + 2 * CNIC_SUPPORT(bp))
#define L2_ILT_LINES(bp) (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\ #define L2_ILT_LINES(bp) (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\
ILT_PAGE_CIDS)) ILT_PAGE_CIDS))
@ -1495,9 +1492,6 @@ struct bnx2x {
int dropless_fc; int dropless_fc;
#ifdef BCM_CNIC
u32 cnic_flags;
#define BNX2X_CNIC_FLAG_MAC_SET 1
void *t2; void *t2;
dma_addr_t t2_mapping; dma_addr_t t2_mapping;
struct cnic_ops __rcu *cnic_ops; struct cnic_ops __rcu *cnic_ops;
@ -1518,7 +1512,6 @@ struct bnx2x {
/* Start index of the "special" (CNIC related) L2 cleints */ /* Start index of the "special" (CNIC related) L2 cleints */
u8 cnic_base_cl_id; u8 cnic_base_cl_id;
#endif
int dmae_ready; int dmae_ready;
/* used to synchronize dmae accesses */ /* used to synchronize dmae accesses */
@ -1647,9 +1640,9 @@ struct bnx2x {
/* Tx queues may be less or equal to Rx queues */ /* Tx queues may be less or equal to Rx queues */
extern int num_queues; extern int num_queues;
#define BNX2X_NUM_QUEUES(bp) (bp->num_queues) #define BNX2X_NUM_QUEUES(bp) (bp->num_queues)
#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE) #define BNX2X_NUM_ETH_QUEUES(bp) ((bp)->num_ethernet_queues)
#define BNX2X_NUM_NON_CNIC_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - \ #define BNX2X_NUM_NON_CNIC_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - \
NON_ETH_CONTEXT_USE) (bp)->num_cnic_queues)
#define BNX2X_NUM_RX_QUEUES(bp) BNX2X_NUM_QUEUES(bp) #define BNX2X_NUM_RX_QUEUES(bp) BNX2X_NUM_QUEUES(bp)
#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1) #define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1)
@ -1689,6 +1682,13 @@ struct bnx2x_func_init_params {
u16 spq_prod; /* valid iff FUNC_FLG_SPQ */ u16 spq_prod; /* valid iff FUNC_FLG_SPQ */
}; };
#define for_each_cnic_queue(bp, var) \
for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
(var)++) \
if (skip_queue(bp, var)) \
continue; \
else
#define for_each_eth_queue(bp, var) \ #define for_each_eth_queue(bp, var) \
for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++) for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
@ -1702,6 +1702,22 @@ struct bnx2x_func_init_params {
else else
/* Skip forwarding FP */ /* Skip forwarding FP */
#define for_each_valid_rx_queue(bp, var) \
for ((var) = 0; \
(var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) : \
BNX2X_NUM_ETH_QUEUES(bp)); \
(var)++) \
if (skip_rx_queue(bp, var)) \
continue; \
else
#define for_each_rx_queue_cnic(bp, var) \
for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
(var)++) \
if (skip_rx_queue(bp, var)) \
continue; \
else
#define for_each_rx_queue(bp, var) \ #define for_each_rx_queue(bp, var) \
for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
if (skip_rx_queue(bp, var)) \ if (skip_rx_queue(bp, var)) \
@ -1709,6 +1725,22 @@ struct bnx2x_func_init_params {
else else
/* Skip OOO FP */ /* Skip OOO FP */
#define for_each_valid_tx_queue(bp, var) \
for ((var) = 0; \
(var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) : \
BNX2X_NUM_ETH_QUEUES(bp)); \
(var)++) \
if (skip_tx_queue(bp, var)) \
continue; \
else
#define for_each_tx_queue_cnic(bp, var) \
for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
(var)++) \
if (skip_tx_queue(bp, var)) \
continue; \
else
#define for_each_tx_queue(bp, var) \ #define for_each_tx_queue(bp, var) \
for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
if (skip_tx_queue(bp, var)) \ if (skip_tx_queue(bp, var)) \
@ -2179,7 +2211,6 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
#define BNX2X_MF_SD_PROTOCOL(bp) \ #define BNX2X_MF_SD_PROTOCOL(bp) \
((bp)->mf_config[BP_VN(bp)] & FUNC_MF_CFG_PROTOCOL_MASK) ((bp)->mf_config[BP_VN(bp)] & FUNC_MF_CFG_PROTOCOL_MASK)
#ifdef BCM_CNIC
#define BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) \ #define BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) \
(BNX2X_MF_SD_PROTOCOL(bp) == FUNC_MF_CFG_PROTOCOL_ISCSI) (BNX2X_MF_SD_PROTOCOL(bp) == FUNC_MF_CFG_PROTOCOL_ISCSI)
@ -2196,9 +2227,12 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
#define IS_MF_STORAGE_SD(bp) (IS_MF_SD(bp) && \ #define IS_MF_STORAGE_SD(bp) (IS_MF_SD(bp) && \
(BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) || \ (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) || \
BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp))) BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)))
#else
#define IS_MF_FCOE_AFEX(bp) false
#endif
enum {
SWITCH_UPDATE,
AFEX_UPDATE,
};
#define NUM_MACS 8
#endif /* bnx2x.h */ #endif /* bnx2x.h */

View file

@ -1152,6 +1152,25 @@ static void bnx2x_free_tpa_pool(struct bnx2x *bp,
} }
} }
void bnx2x_init_rx_rings_cnic(struct bnx2x *bp)
{
int j;
for_each_rx_queue_cnic(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
fp->rx_bd_cons = 0;
/* Activate BD ring */
/* Warning!
* this will generate an interrupt (to the TSTORM)
* must only be done after chip is initialized
*/
bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
fp->rx_sge_prod);
}
}
void bnx2x_init_rx_rings(struct bnx2x *bp) void bnx2x_init_rx_rings(struct bnx2x *bp)
{ {
int func = BP_FUNC(bp); int func = BP_FUNC(bp);
@ -1159,7 +1178,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
int i, j; int i, j;
/* Allocate TPA resources */ /* Allocate TPA resources */
for_each_rx_queue(bp, j) { for_each_eth_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j]; struct bnx2x_fastpath *fp = &bp->fp[j];
DP(NETIF_MSG_IFUP, DP(NETIF_MSG_IFUP,
@ -1217,7 +1236,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
} }
} }
for_each_rx_queue(bp, j) { for_each_eth_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j]; struct bnx2x_fastpath *fp = &bp->fp[j];
fp->rx_bd_cons = 0; fp->rx_bd_cons = 0;
@ -1244,29 +1263,45 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
} }
} }
static void bnx2x_free_tx_skbs_queue(struct bnx2x_fastpath *fp)
{
u8 cos;
struct bnx2x *bp = fp->bp;
for_each_cos_in_tx_queue(fp, cos) {
struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
unsigned pkts_compl = 0, bytes_compl = 0;
u16 sw_prod = txdata->tx_pkt_prod;
u16 sw_cons = txdata->tx_pkt_cons;
while (sw_cons != sw_prod) {
bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons),
&pkts_compl, &bytes_compl);
sw_cons++;
}
netdev_tx_reset_queue(
netdev_get_tx_queue(bp->dev,
txdata->txq_index));
}
}
static void bnx2x_free_tx_skbs_cnic(struct bnx2x *bp)
{
int i;
for_each_tx_queue_cnic(bp, i) {
bnx2x_free_tx_skbs_queue(&bp->fp[i]);
}
}
static void bnx2x_free_tx_skbs(struct bnx2x *bp) static void bnx2x_free_tx_skbs(struct bnx2x *bp)
{ {
int i; int i;
u8 cos;
for_each_tx_queue(bp, i) { for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i]; bnx2x_free_tx_skbs_queue(&bp->fp[i]);
for_each_cos_in_tx_queue(fp, cos) {
struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
unsigned pkts_compl = 0, bytes_compl = 0;
u16 sw_prod = txdata->tx_pkt_prod;
u16 sw_cons = txdata->tx_pkt_cons;
while (sw_cons != sw_prod) {
bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons),
&pkts_compl, &bytes_compl);
sw_cons++;
}
netdev_tx_reset_queue(
netdev_get_tx_queue(bp->dev,
txdata->txq_index));
}
} }
} }
@ -1294,11 +1329,20 @@ static void bnx2x_free_rx_bds(struct bnx2x_fastpath *fp)
} }
} }
static void bnx2x_free_rx_skbs_cnic(struct bnx2x *bp)
{
int j;
for_each_rx_queue_cnic(bp, j) {
bnx2x_free_rx_bds(&bp->fp[j]);
}
}
static void bnx2x_free_rx_skbs(struct bnx2x *bp) static void bnx2x_free_rx_skbs(struct bnx2x *bp)
{ {
int j; int j;
for_each_rx_queue(bp, j) { for_each_eth_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j]; struct bnx2x_fastpath *fp = &bp->fp[j];
bnx2x_free_rx_bds(fp); bnx2x_free_rx_bds(fp);
@ -1308,6 +1352,12 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
} }
} }
void bnx2x_free_skbs_cnic(struct bnx2x *bp)
{
bnx2x_free_tx_skbs_cnic(bp);
bnx2x_free_rx_skbs_cnic(bp);
}
void bnx2x_free_skbs(struct bnx2x *bp) void bnx2x_free_skbs(struct bnx2x *bp)
{ {
bnx2x_free_tx_skbs(bp); bnx2x_free_tx_skbs(bp);
@ -1347,11 +1397,12 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n", DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
bp->msix_table[offset].vector); bp->msix_table[offset].vector);
offset++; offset++;
#ifdef BCM_CNIC
if (nvecs == offset) if (CNIC_SUPPORT(bp)) {
return; if (nvecs == offset)
offset++; return;
#endif offset++;
}
for_each_eth_queue(bp, i) { for_each_eth_queue(bp, i) {
if (nvecs == offset) if (nvecs == offset)
@ -1368,7 +1419,7 @@ void bnx2x_free_irq(struct bnx2x *bp)
if (bp->flags & USING_MSIX_FLAG && if (bp->flags & USING_MSIX_FLAG &&
!(bp->flags & USING_SINGLE_MSIX_FLAG)) !(bp->flags & USING_SINGLE_MSIX_FLAG))
bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) + bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) +
CNIC_PRESENT + 1); CNIC_SUPPORT(bp) + 1);
else else
free_irq(bp->dev->irq, bp->dev); free_irq(bp->dev->irq, bp->dev);
} }
@ -1382,12 +1433,14 @@ int bnx2x_enable_msix(struct bnx2x *bp)
bp->msix_table[0].entry); bp->msix_table[0].entry);
msix_vec++; msix_vec++;
#ifdef BCM_CNIC /* Cnic requires an msix vector for itself */
bp->msix_table[msix_vec].entry = msix_vec; if (CNIC_SUPPORT(bp)) {
BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n", bp->msix_table[msix_vec].entry = msix_vec;
bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry); BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n",
msix_vec++; msix_vec, bp->msix_table[msix_vec].entry);
#endif msix_vec++;
}
/* We need separate vectors for ETH queues only (not FCoE) */ /* We need separate vectors for ETH queues only (not FCoE) */
for_each_eth_queue(bp, i) { for_each_eth_queue(bp, i) {
bp->msix_table[msix_vec].entry = msix_vec; bp->msix_table[msix_vec].entry = msix_vec;
@ -1396,7 +1449,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
msix_vec++; msix_vec++;
} }
req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_PRESENT + 1; req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_SUPPORT(bp) + 1;
rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt); rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
@ -1404,7 +1457,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
* reconfigure number of tx/rx queues according to available * reconfigure number of tx/rx queues according to available
* MSI-X vectors * MSI-X vectors
*/ */
if (rc >= BNX2X_MIN_MSIX_VEC_CNT) { if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) {
/* how less vectors we will have? */ /* how less vectors we will have? */
int diff = req_cnt - rc; int diff = req_cnt - rc;
@ -1419,7 +1472,8 @@ int bnx2x_enable_msix(struct bnx2x *bp)
/* /*
* decrease number of queues by number of unallocated entries * decrease number of queues by number of unallocated entries
*/ */
bp->num_queues -= diff; bp->num_ethernet_queues -= diff;
bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
BNX2X_DEV_INFO("New queue configuration set: %d\n", BNX2X_DEV_INFO("New queue configuration set: %d\n",
bp->num_queues); bp->num_queues);
@ -1435,6 +1489,9 @@ int bnx2x_enable_msix(struct bnx2x *bp)
BNX2X_DEV_INFO("Using single MSI-X vector\n"); BNX2X_DEV_INFO("Using single MSI-X vector\n");
bp->flags |= USING_SINGLE_MSIX_FLAG; bp->flags |= USING_SINGLE_MSIX_FLAG;
BNX2X_DEV_INFO("set number of queues to 1\n");
bp->num_ethernet_queues = 1;
bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
} else if (rc < 0) { } else if (rc < 0) {
BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc); BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc);
goto no_msix; goto no_msix;
@ -1464,9 +1521,9 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
return -EBUSY; return -EBUSY;
} }
#ifdef BCM_CNIC if (CNIC_SUPPORT(bp))
offset++; offset++;
#endif
for_each_eth_queue(bp, i) { for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i]; struct bnx2x_fastpath *fp = &bp->fp[i];
snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
@ -1485,7 +1542,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
} }
i = BNX2X_NUM_ETH_QUEUES(bp); i = BNX2X_NUM_ETH_QUEUES(bp);
offset = 1 + CNIC_PRESENT; offset = 1 + CNIC_SUPPORT(bp);
netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d ... fp[%d] %d\n", netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d ... fp[%d] %d\n",
bp->msix_table[0].vector, bp->msix_table[0].vector,
0, bp->msix_table[offset].vector, 0, bp->msix_table[offset].vector,
@ -1556,19 +1613,35 @@ static int bnx2x_setup_irqs(struct bnx2x *bp)
return 0; return 0;
} }
static void bnx2x_napi_enable_cnic(struct bnx2x *bp)
{
int i;
for_each_rx_queue_cnic(bp, i)
napi_enable(&bnx2x_fp(bp, i, napi));
}
static void bnx2x_napi_enable(struct bnx2x *bp) static void bnx2x_napi_enable(struct bnx2x *bp)
{ {
int i; int i;
for_each_rx_queue(bp, i) for_each_eth_queue(bp, i)
napi_enable(&bnx2x_fp(bp, i, napi)); napi_enable(&bnx2x_fp(bp, i, napi));
} }
static void bnx2x_napi_disable_cnic(struct bnx2x *bp)
{
int i;
for_each_rx_queue_cnic(bp, i)
napi_disable(&bnx2x_fp(bp, i, napi));
}
static void bnx2x_napi_disable(struct bnx2x *bp) static void bnx2x_napi_disable(struct bnx2x *bp)
{ {
int i; int i;
for_each_rx_queue(bp, i) for_each_eth_queue(bp, i)
napi_disable(&bnx2x_fp(bp, i, napi)); napi_disable(&bnx2x_fp(bp, i, napi));
} }
@ -1576,6 +1649,8 @@ void bnx2x_netif_start(struct bnx2x *bp)
{ {
if (netif_running(bp->dev)) { if (netif_running(bp->dev)) {
bnx2x_napi_enable(bp); bnx2x_napi_enable(bp);
if (CNIC_LOADED(bp))
bnx2x_napi_enable_cnic(bp);
bnx2x_int_enable(bp); bnx2x_int_enable(bp);
if (bp->state == BNX2X_STATE_OPEN) if (bp->state == BNX2X_STATE_OPEN)
netif_tx_wake_all_queues(bp->dev); netif_tx_wake_all_queues(bp->dev);
@ -1586,14 +1661,15 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
{ {
bnx2x_int_disable_sync(bp, disable_hw); bnx2x_int_disable_sync(bp, disable_hw);
bnx2x_napi_disable(bp); bnx2x_napi_disable(bp);
if (CNIC_LOADED(bp))
bnx2x_napi_disable_cnic(bp);
} }
u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb) u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
{ {
struct bnx2x *bp = netdev_priv(dev); struct bnx2x *bp = netdev_priv(dev);
#ifdef BCM_CNIC if (CNIC_LOADED(bp) && !NO_FCOE(bp)) {
if (!NO_FCOE(bp)) {
struct ethhdr *hdr = (struct ethhdr *)skb->data; struct ethhdr *hdr = (struct ethhdr *)skb->data;
u16 ether_type = ntohs(hdr->h_proto); u16 ether_type = ntohs(hdr->h_proto);
@ -1609,7 +1685,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP)) if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP))
return bnx2x_fcoe_tx(bp, txq_index); return bnx2x_fcoe_tx(bp, txq_index);
} }
#endif
/* select a non-FCoE queue */ /* select a non-FCoE queue */
return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp)); return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
} }
@ -1618,15 +1694,15 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
void bnx2x_set_num_queues(struct bnx2x *bp) void bnx2x_set_num_queues(struct bnx2x *bp)
{ {
/* RSS queues */ /* RSS queues */
bp->num_queues = bnx2x_calc_num_queues(bp); bp->num_ethernet_queues = bnx2x_calc_num_queues(bp);
#ifdef BCM_CNIC
/* override in STORAGE SD modes */ /* override in STORAGE SD modes */
if (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)) if (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))
bp->num_queues = 1; bp->num_ethernet_queues = 1;
#endif
/* Add special queues */ /* Add special queues */
bp->num_queues += NON_ETH_CONTEXT_USE; bp->num_cnic_queues = CNIC_SUPPORT(bp); /* For FCOE */
bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues); BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
} }
@ -1653,20 +1729,18 @@ void bnx2x_set_num_queues(struct bnx2x *bp)
* bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash() * bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash()
* will return a proper Tx index if TC is enabled (netdev->num_tc > 0). * will return a proper Tx index if TC is enabled (netdev->num_tc > 0).
*/ */
static int bnx2x_set_real_num_queues(struct bnx2x *bp) static int bnx2x_set_real_num_queues(struct bnx2x *bp, int include_cnic)
{ {
int rc, tx, rx; int rc, tx, rx;
tx = BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos; tx = BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos;
rx = BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE; rx = BNX2X_NUM_ETH_QUEUES(bp);
/* account for fcoe queue */ /* account for fcoe queue */
#ifdef BCM_CNIC if (include_cnic && !NO_FCOE(bp)) {
if (!NO_FCOE(bp)) { rx++;
rx += FCOE_PRESENT; tx++;
tx += FCOE_PRESENT;
} }
#endif
rc = netif_set_real_num_tx_queues(bp->dev, tx); rc = netif_set_real_num_tx_queues(bp->dev, tx);
if (rc) { if (rc) {
@ -1859,14 +1933,26 @@ static void bnx2x_squeeze_objects(struct bnx2x *bp)
(bp)->state = BNX2X_STATE_ERROR; \ (bp)->state = BNX2X_STATE_ERROR; \
goto label; \ goto label; \
} while (0) } while (0)
#else
#define LOAD_ERROR_EXIT_CNIC(bp, label) \
do { \
bp->cnic_loaded = false; \
goto label; \
} while (0)
#else /*BNX2X_STOP_ON_ERROR*/
#define LOAD_ERROR_EXIT(bp, label) \ #define LOAD_ERROR_EXIT(bp, label) \
do { \ do { \
(bp)->state = BNX2X_STATE_ERROR; \ (bp)->state = BNX2X_STATE_ERROR; \
(bp)->panic = 1; \ (bp)->panic = 1; \
return -EBUSY; \ return -EBUSY; \
} while (0) } while (0)
#endif #define LOAD_ERROR_EXIT_CNIC(bp, label) \
do { \
bp->cnic_loaded = false; \
(bp)->panic = 1; \
return -EBUSY; \
} while (0)
#endif /*BNX2X_STOP_ON_ERROR*/
bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err) bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err)
{ {
@ -1959,10 +2045,8 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
fp->max_cos = 1; fp->max_cos = 1;
/* Init txdata pointers */ /* Init txdata pointers */
#ifdef BCM_CNIC
if (IS_FCOE_FP(fp)) if (IS_FCOE_FP(fp))
fp->txdata_ptr[0] = &bp->bnx2x_txq[FCOE_TXQ_IDX(bp)]; fp->txdata_ptr[0] = &bp->bnx2x_txq[FCOE_TXQ_IDX(bp)];
#endif
if (IS_ETH_FP(fp)) if (IS_ETH_FP(fp))
for_each_cos_in_tx_queue(fp, cos) for_each_cos_in_tx_queue(fp, cos)
fp->txdata_ptr[cos] = &bp->bnx2x_txq[cos * fp->txdata_ptr[cos] = &bp->bnx2x_txq[cos *
@ -1980,11 +2064,95 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
else if (bp->flags & GRO_ENABLE_FLAG) else if (bp->flags & GRO_ENABLE_FLAG)
fp->mode = TPA_MODE_GRO; fp->mode = TPA_MODE_GRO;
#ifdef BCM_CNIC
/* We don't want TPA on an FCoE L2 ring */ /* We don't want TPA on an FCoE L2 ring */
if (IS_FCOE_FP(fp)) if (IS_FCOE_FP(fp))
fp->disable_tpa = 1; fp->disable_tpa = 1;
#endif }
int bnx2x_load_cnic(struct bnx2x *bp)
{
int i, rc, port = BP_PORT(bp);
DP(NETIF_MSG_IFUP, "Starting CNIC-related load\n");
mutex_init(&bp->cnic_mutex);
rc = bnx2x_alloc_mem_cnic(bp);
if (rc) {
BNX2X_ERR("Unable to allocate bp memory for cnic\n");
LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
}
rc = bnx2x_alloc_fp_mem_cnic(bp);
if (rc) {
BNX2X_ERR("Unable to allocate memory for cnic fps\n");
LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
}
/* Update the number of queues with the cnic queues */
rc = bnx2x_set_real_num_queues(bp, 1);
if (rc) {
BNX2X_ERR("Unable to set real_num_queues including cnic\n");
LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
}
/* Add all CNIC NAPI objects */
bnx2x_add_all_napi_cnic(bp);
DP(NETIF_MSG_IFUP, "cnic napi added\n");
bnx2x_napi_enable_cnic(bp);
rc = bnx2x_init_hw_func_cnic(bp);
if (rc)
LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic1);
bnx2x_nic_init_cnic(bp);
/* Enable Timer scan */
REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
for_each_cnic_queue(bp, i) {
rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
if (rc) {
BNX2X_ERR("Queue setup failed\n");
LOAD_ERROR_EXIT(bp, load_error_cnic2);
}
}
/* Initialize Rx filter. */
netif_addr_lock_bh(bp->dev);
bnx2x_set_rx_mode(bp->dev);
netif_addr_unlock_bh(bp->dev);
/* re-read iscsi info */
bnx2x_get_iscsi_info(bp);
bnx2x_setup_cnic_irq_info(bp);
bnx2x_setup_cnic_info(bp);
bp->cnic_loaded = true;
if (bp->state == BNX2X_STATE_OPEN)
bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
DP(NETIF_MSG_IFUP, "Ending successfully CNIC-related load\n");
return 0;
#ifndef BNX2X_STOP_ON_ERROR
load_error_cnic2:
/* Disable Timer scan */
REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
load_error_cnic1:
bnx2x_napi_disable_cnic(bp);
/* Update the number of queues without the cnic queues */
rc = bnx2x_set_real_num_queues(bp, 0);
if (rc)
BNX2X_ERR("Unable to set real_num_queues not including cnic\n");
load_error_cnic0:
BNX2X_ERR("CNIC-related load failed\n");
bnx2x_free_fp_mem_cnic(bp);
bnx2x_free_mem_cnic(bp);
return rc;
#endif /* ! BNX2X_STOP_ON_ERROR */
} }
@ -1995,6 +2163,10 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
u32 load_code; u32 load_code;
int i, rc; int i, rc;
DP(NETIF_MSG_IFUP, "Starting NIC load\n");
DP(NETIF_MSG_IFUP,
"CNIC is %s\n", CNIC_ENABLED(bp) ? "enabled" : "disabled");
#ifdef BNX2X_STOP_ON_ERROR #ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic)) { if (unlikely(bp->panic)) {
BNX2X_ERR("Can't load NIC when there is panic\n"); BNX2X_ERR("Can't load NIC when there is panic\n");
@ -2022,9 +2194,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
DP(NETIF_MSG_IFUP, "num queues: %d", bp->num_queues); DP(NETIF_MSG_IFUP, "num queues: %d", bp->num_queues);
for_each_queue(bp, i) for_each_queue(bp, i)
bnx2x_bz_fp(bp, i); bnx2x_bz_fp(bp, i);
memset(bp->bnx2x_txq, 0, bp->bnx2x_txq_size * memset(bp->bnx2x_txq, 0, (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS +
sizeof(struct bnx2x_fp_txdata)); bp->num_cnic_queues) *
sizeof(struct bnx2x_fp_txdata));
bp->fcoe_init = false;
/* Set the receive queues buffer size */ /* Set the receive queues buffer size */
bnx2x_set_rx_buf_size(bp); bnx2x_set_rx_buf_size(bp);
@ -2034,9 +2208,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* As long as bnx2x_alloc_mem() may possibly update /* As long as bnx2x_alloc_mem() may possibly update
* bp->num_queues, bnx2x_set_real_num_queues() should always * bp->num_queues, bnx2x_set_real_num_queues() should always
* come after it. * come after it. At this stage cnic queues are not counted.
*/ */
rc = bnx2x_set_real_num_queues(bp); rc = bnx2x_set_real_num_queues(bp, 0);
if (rc) { if (rc) {
BNX2X_ERR("Unable to set real_num_queues\n"); BNX2X_ERR("Unable to set real_num_queues\n");
LOAD_ERROR_EXIT(bp, load_error0); LOAD_ERROR_EXIT(bp, load_error0);
@ -2050,6 +2224,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Add all NAPI objects */ /* Add all NAPI objects */
bnx2x_add_all_napi(bp); bnx2x_add_all_napi(bp);
DP(NETIF_MSG_IFUP, "napi added\n");
bnx2x_napi_enable(bp); bnx2x_napi_enable(bp);
/* set pf load just before approaching the MCP */ /* set pf load just before approaching the MCP */
@ -2191,23 +2366,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
LOAD_ERROR_EXIT(bp, load_error3); LOAD_ERROR_EXIT(bp, load_error3);
} }
#ifdef BCM_CNIC for_each_nondefault_eth_queue(bp, i) {
/* Enable Timer scan */
REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
#endif
for_each_nondefault_queue(bp, i) {
rc = bnx2x_setup_queue(bp, &bp->fp[i], 0); rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
if (rc) { if (rc) {
BNX2X_ERR("Queue setup failed\n"); BNX2X_ERR("Queue setup failed\n");
LOAD_ERROR_EXIT(bp, load_error4); LOAD_ERROR_EXIT(bp, load_error3);
} }
} }
rc = bnx2x_init_rss_pf(bp); rc = bnx2x_init_rss_pf(bp);
if (rc) { if (rc) {
BNX2X_ERR("PF RSS init failed\n"); BNX2X_ERR("PF RSS init failed\n");
LOAD_ERROR_EXIT(bp, load_error4); LOAD_ERROR_EXIT(bp, load_error3);
} }
/* Now when Clients are configured we are ready to work */ /* Now when Clients are configured we are ready to work */
@ -2217,7 +2387,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = bnx2x_set_eth_mac(bp, true); rc = bnx2x_set_eth_mac(bp, true);
if (rc) { if (rc) {
BNX2X_ERR("Setting Ethernet MAC failed\n"); BNX2X_ERR("Setting Ethernet MAC failed\n");
LOAD_ERROR_EXIT(bp, load_error4); LOAD_ERROR_EXIT(bp, load_error3);
} }
if (bp->pending_max) { if (bp->pending_max) {
@ -2264,14 +2434,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* start the timer */ /* start the timer */
mod_timer(&bp->timer, jiffies + bp->current_interval); mod_timer(&bp->timer, jiffies + bp->current_interval);
#ifdef BCM_CNIC if (CNIC_ENABLED(bp))
/* re-read iscsi info */ bnx2x_load_cnic(bp);
bnx2x_get_iscsi_info(bp);
bnx2x_setup_cnic_irq_info(bp);
bnx2x_setup_cnic_info(bp);
if (bp->state == BNX2X_STATE_OPEN)
bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
#endif
/* mark driver is loaded in shmem2 */ /* mark driver is loaded in shmem2 */
if (SHMEM2_HAS(bp, drv_capabilities_flag)) { if (SHMEM2_HAS(bp, drv_capabilities_flag)) {
@ -2293,14 +2457,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (bp->port.pmf && (bp->state != BNX2X_STATE_DIAG)) if (bp->port.pmf && (bp->state != BNX2X_STATE_DIAG))
bnx2x_dcbx_init(bp, false); bnx2x_dcbx_init(bp, false);
DP(NETIF_MSG_IFUP, "Ending successfully NIC load\n");
return 0; return 0;
#ifndef BNX2X_STOP_ON_ERROR #ifndef BNX2X_STOP_ON_ERROR
load_error4:
#ifdef BCM_CNIC
/* Disable Timer scan */
REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
#endif
load_error3: load_error3:
bnx2x_int_disable_sync(bp, 1); bnx2x_int_disable_sync(bp, 1);
@ -2338,6 +2499,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
int i; int i;
bool global = false; bool global = false;
DP(NETIF_MSG_IFUP, "Starting NIC unload\n");
/* mark driver is unloaded in shmem2 */ /* mark driver is unloaded in shmem2 */
if (SHMEM2_HAS(bp, drv_capabilities_flag)) { if (SHMEM2_HAS(bp, drv_capabilities_flag)) {
u32 val; u32 val;
@ -2373,14 +2536,13 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
smp_mb(); smp_mb();
if (CNIC_LOADED(bp))
bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
/* Stop Tx */ /* Stop Tx */
bnx2x_tx_disable(bp); bnx2x_tx_disable(bp);
netdev_reset_tc(bp->dev); netdev_reset_tc(bp->dev);
#ifdef BCM_CNIC
bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
#endif
bp->rx_mode = BNX2X_RX_MODE_NONE; bp->rx_mode = BNX2X_RX_MODE_NONE;
del_timer_sync(&bp->timer); del_timer_sync(&bp->timer);
@ -2414,7 +2576,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
bnx2x_netif_stop(bp, 1); bnx2x_netif_stop(bp, 1);
/* Delete all NAPI objects */ /* Delete all NAPI objects */
bnx2x_del_all_napi(bp); bnx2x_del_all_napi(bp);
if (CNIC_LOADED(bp))
bnx2x_del_all_napi_cnic(bp);
/* Release IRQs */ /* Release IRQs */
bnx2x_free_irq(bp); bnx2x_free_irq(bp);
@ -2435,12 +2598,19 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
/* Free SKBs, SGEs, TPA pool and driver internals */ /* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp); bnx2x_free_skbs(bp);
if (CNIC_LOADED(bp))
bnx2x_free_skbs_cnic(bp);
for_each_rx_queue(bp, i) for_each_rx_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
if (CNIC_LOADED(bp)) {
bnx2x_free_fp_mem_cnic(bp);
bnx2x_free_mem_cnic(bp);
}
bnx2x_free_mem(bp); bnx2x_free_mem(bp);
bp->state = BNX2X_STATE_CLOSED; bp->state = BNX2X_STATE_CLOSED;
bp->cnic_loaded = false;
/* Check if there are pending parity attentions. If there are - set /* Check if there are pending parity attentions. If there are - set
* RECOVERY_IN_PROGRESS. * RECOVERY_IN_PROGRESS.
@ -2460,6 +2630,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp))) if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
bnx2x_disable_close_the_gate(bp); bnx2x_disable_close_the_gate(bp);
DP(NETIF_MSG_IFUP, "Ending NIC unload\n");
return 0; return 0;
} }
@ -2550,7 +2722,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
/* Fall out from the NAPI loop if needed */ /* Fall out from the NAPI loop if needed */
if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
#ifdef BCM_CNIC
/* No need to update SB for FCoE L2 ring as long as /* No need to update SB for FCoE L2 ring as long as
* it's connected to the default SB and the SB * it's connected to the default SB and the SB
* has been updated when NAPI was scheduled. * has been updated when NAPI was scheduled.
@ -2559,8 +2731,6 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
napi_complete(napi); napi_complete(napi);
break; break;
} }
#endif
bnx2x_update_fpsb_idx(fp); bnx2x_update_fpsb_idx(fp);
/* bnx2x_has_rx_work() reads the status block, /* bnx2x_has_rx_work() reads the status block,
* thus we need to ensure that status block indices * thus we need to ensure that status block indices
@ -2940,7 +3110,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
txq_index = skb_get_queue_mapping(skb); txq_index = skb_get_queue_mapping(skb);
txq = netdev_get_tx_queue(dev, txq_index); txq = netdev_get_tx_queue(dev, txq_index);
BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + FCOE_PRESENT); BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + (CNIC_LOADED(bp) ? 1 : 0));
txdata = &bp->bnx2x_txq[txq_index]; txdata = &bp->bnx2x_txq[txq_index];
@ -3339,13 +3509,11 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p)
return -EINVAL; return -EINVAL;
} }
#ifdef BCM_CNIC
if ((IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)) && if ((IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)) &&
!is_zero_ether_addr(addr->sa_data)) { !is_zero_ether_addr(addr->sa_data)) {
BNX2X_ERR("Can't configure non-zero address on iSCSI or FCoE functions in MF-SD mode\n"); BNX2X_ERR("Can't configure non-zero address on iSCSI or FCoE functions in MF-SD mode\n");
return -EINVAL; return -EINVAL;
} }
#endif
if (netif_running(dev)) { if (netif_running(dev)) {
rc = bnx2x_set_eth_mac(bp, false); rc = bnx2x_set_eth_mac(bp, false);
@ -3369,13 +3537,11 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
u8 cos; u8 cos;
/* Common */ /* Common */
#ifdef BCM_CNIC
if (IS_FCOE_IDX(fp_index)) { if (IS_FCOE_IDX(fp_index)) {
memset(sb, 0, sizeof(union host_hc_status_block)); memset(sb, 0, sizeof(union host_hc_status_block));
fp->status_blk_mapping = 0; fp->status_blk_mapping = 0;
} else { } else {
#endif
/* status blocks */ /* status blocks */
if (!CHIP_IS_E1x(bp)) if (!CHIP_IS_E1x(bp))
BNX2X_PCI_FREE(sb->e2_sb, BNX2X_PCI_FREE(sb->e2_sb,
@ -3387,9 +3553,8 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
bnx2x_fp(bp, fp_index, bnx2x_fp(bp, fp_index,
status_blk_mapping), status_blk_mapping),
sizeof(struct host_hc_status_block_e1x)); sizeof(struct host_hc_status_block_e1x));
#ifdef BCM_CNIC
} }
#endif
/* Rx */ /* Rx */
if (!skip_rx_queue(bp, fp_index)) { if (!skip_rx_queue(bp, fp_index)) {
bnx2x_free_rx_bds(fp); bnx2x_free_rx_bds(fp);
@ -3431,10 +3596,17 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
/* end of fastpath */ /* end of fastpath */
} }
void bnx2x_free_fp_mem_cnic(struct bnx2x *bp)
{
int i;
for_each_cnic_queue(bp, i)
bnx2x_free_fp_mem_at(bp, i);
}
void bnx2x_free_fp_mem(struct bnx2x *bp) void bnx2x_free_fp_mem(struct bnx2x *bp)
{ {
int i; int i;
for_each_queue(bp, i) for_each_eth_queue(bp, i)
bnx2x_free_fp_mem_at(bp, i); bnx2x_free_fp_mem_at(bp, i);
} }
@ -3519,14 +3691,11 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
u8 cos; u8 cos;
int rx_ring_size = 0; int rx_ring_size = 0;
#ifdef BCM_CNIC
if (!bp->rx_ring_size && if (!bp->rx_ring_size &&
(IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) { (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) {
rx_ring_size = MIN_RX_SIZE_NONTPA; rx_ring_size = MIN_RX_SIZE_NONTPA;
bp->rx_ring_size = rx_ring_size; bp->rx_ring_size = rx_ring_size;
} else } else if (!bp->rx_ring_size) {
#endif
if (!bp->rx_ring_size) {
rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp); rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp);
if (CHIP_IS_E3(bp)) { if (CHIP_IS_E3(bp)) {
@ -3550,9 +3719,8 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
/* Common */ /* Common */
sb = &bnx2x_fp(bp, index, status_blk); sb = &bnx2x_fp(bp, index, status_blk);
#ifdef BCM_CNIC
if (!IS_FCOE_IDX(index)) { if (!IS_FCOE_IDX(index)) {
#endif
/* status blocks */ /* status blocks */
if (!CHIP_IS_E1x(bp)) if (!CHIP_IS_E1x(bp))
BNX2X_PCI_ALLOC(sb->e2_sb, BNX2X_PCI_ALLOC(sb->e2_sb,
@ -3562,9 +3730,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
BNX2X_PCI_ALLOC(sb->e1x_sb, BNX2X_PCI_ALLOC(sb->e1x_sb,
&bnx2x_fp(bp, index, status_blk_mapping), &bnx2x_fp(bp, index, status_blk_mapping),
sizeof(struct host_hc_status_block_e1x)); sizeof(struct host_hc_status_block_e1x));
#ifdef BCM_CNIC
} }
#endif
/* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to /* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to
* set shortcuts for it. * set shortcuts for it.
@ -3641,22 +3807,8 @@ alloc_mem_err:
return 0; return 0;
} }
int bnx2x_alloc_fp_mem(struct bnx2x *bp) int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp)
{ {
int i;
/**
* 1. Allocate FP for leading - fatal if error
* 2. {CNIC} Allocate FCoE FP - fatal if error
* 3. {CNIC} Allocate OOO + FWD - disable OOO if error
* 4. Allocate RSS - fix number of queues if error
*/
/* leading */
if (bnx2x_alloc_fp_mem_at(bp, 0))
return -ENOMEM;
#ifdef BCM_CNIC
if (!NO_FCOE(bp)) if (!NO_FCOE(bp))
/* FCoE */ /* FCoE */
if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp))) if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp)))
@ -3664,7 +3816,21 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
* NO_FCOE_FLAG * NO_FCOE_FLAG
*/ */
return -ENOMEM; return -ENOMEM;
#endif
return 0;
}
int bnx2x_alloc_fp_mem(struct bnx2x *bp)
{
int i;
/* 1. Allocate FP for leading - fatal if error
* 2. Allocate RSS - fix number of queues if error
*/
/* leading */
if (bnx2x_alloc_fp_mem_at(bp, 0))
return -ENOMEM;
/* RSS */ /* RSS */
for_each_nondefault_eth_queue(bp, i) for_each_nondefault_eth_queue(bp, i)
@ -3676,17 +3842,17 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
int delta = BNX2X_NUM_ETH_QUEUES(bp) - i; int delta = BNX2X_NUM_ETH_QUEUES(bp) - i;
WARN_ON(delta < 0); WARN_ON(delta < 0);
#ifdef BCM_CNIC if (CNIC_SUPPORT(bp))
/** /* move non eth FPs next to last eth FP
* move non eth FPs next to last eth FP * must be done in that order
* must be done in that order * FCOE_IDX < FWD_IDX < OOO_IDX
* FCOE_IDX < FWD_IDX < OOO_IDX */
*/
/* move FCoE fp even NO_FCOE_FLAG is on */ /* move FCoE fp even NO_FCOE_FLAG is on */
bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta); bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta);
#endif bp->num_ethernet_queues -= delta;
bp->num_queues -= delta; bp->num_queues = bp->num_ethernet_queues +
bp->num_cnic_queues;
BNX2X_ERR("Adjusted num of queues from %d to %d\n", BNX2X_ERR("Adjusted num of queues from %d to %d\n",
bp->num_queues + delta, bp->num_queues); bp->num_queues + delta, bp->num_queues);
} }
@ -3711,7 +3877,7 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
struct msix_entry *tbl; struct msix_entry *tbl;
struct bnx2x_ilt *ilt; struct bnx2x_ilt *ilt;
int msix_table_size = 0; int msix_table_size = 0;
int fp_array_size; int fp_array_size, txq_array_size;
int i; int i;
/* /*
@ -3721,7 +3887,7 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
msix_table_size = bp->igu_sb_cnt + 1; msix_table_size = bp->igu_sb_cnt + 1;
/* fp array: RSS plus CNIC related L2 queues */ /* fp array: RSS plus CNIC related L2 queues */
fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + NON_ETH_CONTEXT_USE; fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + CNIC_SUPPORT(bp);
BNX2X_DEV_INFO("fp_array_size %d", fp_array_size); BNX2X_DEV_INFO("fp_array_size %d", fp_array_size);
fp = kcalloc(fp_array_size, sizeof(*fp), GFP_KERNEL); fp = kcalloc(fp_array_size, sizeof(*fp), GFP_KERNEL);
@ -3750,12 +3916,12 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
goto alloc_err; goto alloc_err;
/* Allocate memory for the transmission queues array */ /* Allocate memory for the transmission queues array */
bp->bnx2x_txq_size = BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS; txq_array_size =
#ifdef BCM_CNIC BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS + CNIC_SUPPORT(bp);
bp->bnx2x_txq_size++; BNX2X_DEV_INFO("txq_array_size %d", txq_array_size);
#endif
bp->bnx2x_txq = kcalloc(bp->bnx2x_txq_size, bp->bnx2x_txq = kcalloc(txq_array_size, sizeof(struct bnx2x_fp_txdata),
sizeof(struct bnx2x_fp_txdata), GFP_KERNEL); GFP_KERNEL);
if (!bp->bnx2x_txq) if (!bp->bnx2x_txq)
goto alloc_err; goto alloc_err;
@ -3838,7 +4004,7 @@ int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
return LINK_CONFIG_IDX(sel_phy_idx); return LINK_CONFIG_IDX(sel_phy_idx);
} }
#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC) #ifdef NETDEV_FCOE_WWNN
int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type) int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
{ {
struct bnx2x *bp = netdev_priv(dev); struct bnx2x *bp = netdev_priv(dev);

View file

@ -238,7 +238,6 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance);
* @dev_instance: private instance * @dev_instance: private instance
*/ */
irqreturn_t bnx2x_interrupt(int irq, void *dev_instance); irqreturn_t bnx2x_interrupt(int irq, void *dev_instance);
#ifdef BCM_CNIC
/** /**
* bnx2x_cnic_notify - send command to cnic driver * bnx2x_cnic_notify - send command to cnic driver
@ -262,8 +261,6 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp);
*/ */
void bnx2x_setup_cnic_info(struct bnx2x *bp); void bnx2x_setup_cnic_info(struct bnx2x *bp);
#endif
/** /**
* bnx2x_int_enable - enable HW interrupts. * bnx2x_int_enable - enable HW interrupts.
* *
@ -283,7 +280,7 @@ void bnx2x_int_enable(struct bnx2x *bp);
void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw); void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
/** /**
* bnx2x_nic_init - init driver internals. * bnx2x_nic_init_cnic - init driver internals for cnic.
* *
* @bp: driver handle * @bp: driver handle
* @load_code: COMMON, PORT or FUNCTION * @load_code: COMMON, PORT or FUNCTION
@ -293,8 +290,25 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
* - status blocks * - status blocks
* - etc. * - etc.
*/ */
void bnx2x_nic_init(struct bnx2x *bp, u32 load_code); void bnx2x_nic_init_cnic(struct bnx2x *bp);
/**
* bnx2x_nic_init - init driver internals.
*
* @bp: driver handle
*
* Initializes:
* - rings
* - status blocks
* - etc.
*/
void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
/**
* bnx2x_alloc_mem_cnic - allocate driver's memory for cnic.
*
* @bp: driver handle
*/
int bnx2x_alloc_mem_cnic(struct bnx2x *bp);
/** /**
* bnx2x_alloc_mem - allocate driver's memory. * bnx2x_alloc_mem - allocate driver's memory.
* *
@ -302,6 +316,12 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
*/ */
int bnx2x_alloc_mem(struct bnx2x *bp); int bnx2x_alloc_mem(struct bnx2x *bp);
/**
* bnx2x_free_mem_cnic - release driver's memory for cnic.
*
* @bp: driver handle
*/
void bnx2x_free_mem_cnic(struct bnx2x *bp);
/** /**
* bnx2x_free_mem - release driver's memory. * bnx2x_free_mem - release driver's memory.
* *
@ -407,6 +427,7 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
void bnx2x_set_reset_in_progress(struct bnx2x *bp); void bnx2x_set_reset_in_progress(struct bnx2x *bp);
void bnx2x_set_reset_global(struct bnx2x *bp); void bnx2x_set_reset_global(struct bnx2x *bp);
void bnx2x_disable_close_the_gate(struct bnx2x *bp); void bnx2x_disable_close_the_gate(struct bnx2x *bp);
int bnx2x_init_hw_func_cnic(struct bnx2x *bp);
/** /**
* bnx2x_sp_event - handle ramrods completion. * bnx2x_sp_event - handle ramrods completion.
@ -423,6 +444,14 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
*/ */
void bnx2x_ilt_set_info(struct bnx2x *bp); void bnx2x_ilt_set_info(struct bnx2x *bp);
/**
* bnx2x_ilt_set_cnic_info - prepare ILT configurations for SRC
* and TM.
*
* @bp: driver handle
*/
void bnx2x_ilt_set_info_cnic(struct bnx2x *bp);
/** /**
* bnx2x_dcbx_init - initialize dcbx protocol. * bnx2x_dcbx_init - initialize dcbx protocol.
* *
@ -491,12 +520,17 @@ int bnx2x_resume(struct pci_dev *pdev);
/* Release IRQ vectors */ /* Release IRQ vectors */
void bnx2x_free_irq(struct bnx2x *bp); void bnx2x_free_irq(struct bnx2x *bp);
void bnx2x_free_fp_mem_cnic(struct bnx2x *bp);
void bnx2x_free_fp_mem(struct bnx2x *bp); void bnx2x_free_fp_mem(struct bnx2x *bp);
int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp);
int bnx2x_alloc_fp_mem(struct bnx2x *bp); int bnx2x_alloc_fp_mem(struct bnx2x *bp);
void bnx2x_init_rx_rings(struct bnx2x *bp); void bnx2x_init_rx_rings(struct bnx2x *bp);
void bnx2x_init_rx_rings_cnic(struct bnx2x *bp);
void bnx2x_free_skbs_cnic(struct bnx2x *bp);
void bnx2x_free_skbs(struct bnx2x *bp); void bnx2x_free_skbs(struct bnx2x *bp);
void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw); void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
void bnx2x_netif_start(struct bnx2x *bp); void bnx2x_netif_start(struct bnx2x *bp);
int bnx2x_load_cnic(struct bnx2x *bp);
/** /**
* bnx2x_enable_msix - set msix configuration. * bnx2x_enable_msix - set msix configuration.
@ -547,7 +581,7 @@ void bnx2x_free_mem_bp(struct bnx2x *bp);
*/ */
int bnx2x_change_mtu(struct net_device *dev, int new_mtu); int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC) #ifdef NETDEV_FCOE_WWNN
/** /**
* bnx2x_fcoe_get_wwn - return the requested WWN value for this port * bnx2x_fcoe_get_wwn - return the requested WWN value for this port
* *
@ -793,23 +827,39 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
sge->addr_lo = 0; sge->addr_lo = 0;
} }
static inline void bnx2x_add_all_napi_cnic(struct bnx2x *bp)
{
int i;
/* Add NAPI objects */
for_each_rx_queue_cnic(bp, i)
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, BNX2X_NAPI_WEIGHT);
}
static inline void bnx2x_add_all_napi(struct bnx2x *bp) static inline void bnx2x_add_all_napi(struct bnx2x *bp)
{ {
int i; int i;
bp->num_napi_queues = bp->num_queues;
/* Add NAPI objects */ /* Add NAPI objects */
for_each_rx_queue(bp, i) for_each_eth_queue(bp, i)
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, BNX2X_NAPI_WEIGHT); bnx2x_poll, BNX2X_NAPI_WEIGHT);
} }
static inline void bnx2x_del_all_napi_cnic(struct bnx2x *bp)
{
int i;
for_each_rx_queue_cnic(bp, i)
netif_napi_del(&bnx2x_fp(bp, i, napi));
}
static inline void bnx2x_del_all_napi(struct bnx2x *bp) static inline void bnx2x_del_all_napi(struct bnx2x *bp)
{ {
int i; int i;
for_each_rx_queue(bp, i) for_each_eth_queue(bp, i)
netif_napi_del(&bnx2x_fp(bp, i, napi)); netif_napi_del(&bnx2x_fp(bp, i, napi));
} }
@ -979,11 +1029,9 @@ static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp)
{ {
struct bnx2x *bp = fp->bp; struct bnx2x *bp = fp->bp;
if (!CHIP_IS_E1x(bp)) { if (!CHIP_IS_E1x(bp)) {
#ifdef BCM_CNIC
/* there are special statistics counters for FCoE 136..140 */ /* there are special statistics counters for FCoE 136..140 */
if (IS_FCOE_FP(fp)) if (IS_FCOE_FP(fp))
return bp->cnic_base_cl_id + (bp->pf_num >> 1); return bp->cnic_base_cl_id + (bp->pf_num >> 1);
#endif
return fp->cl_id; return fp->cl_id;
} }
return fp->cl_id + BP_PORT(bp) * FP_SB_MAX_E1x; return fp->cl_id + BP_PORT(bp) * FP_SB_MAX_E1x;
@ -1102,7 +1150,6 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,
txdata->cid, txdata->txq_index); txdata->cid, txdata->txq_index);
} }
#ifdef BCM_CNIC
static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx) static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
{ {
return bp->cnic_base_cl_id + cl_idx + return bp->cnic_base_cl_id + cl_idx +
@ -1162,7 +1209,6 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id, fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
fp->igu_sb_id); fp->igu_sb_id);
} }
#endif
static inline int bnx2x_clean_tx_queue(struct bnx2x *bp, static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
struct bnx2x_fp_txdata *txdata) struct bnx2x_fp_txdata *txdata)
@ -1280,7 +1326,7 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
*/ */
return mtu <= SGE_PAGE_SIZE && (U_ETH_SGL_SIZE * fpp) <= MAX_SKB_FRAGS; return mtu <= SGE_PAGE_SIZE && (U_ETH_SGL_SIZE * fpp) <= MAX_SKB_FRAGS;
} }
#ifdef BCM_CNIC
/** /**
* bnx2x_get_iscsi_info - update iSCSI params according to licensing info. * bnx2x_get_iscsi_info - update iSCSI params according to licensing info.
* *
@ -1288,7 +1334,6 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
* *
*/ */
void bnx2x_get_iscsi_info(struct bnx2x *bp); void bnx2x_get_iscsi_info(struct bnx2x *bp);
#endif
/** /**
* bnx2x_link_sync_notify - send notification to other functions. * bnx2x_link_sync_notify - send notification to other functions.
@ -1340,13 +1385,11 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
static inline bool bnx2x_is_valid_ether_addr(struct bnx2x *bp, u8 *addr) static inline bool bnx2x_is_valid_ether_addr(struct bnx2x *bp, u8 *addr)
{ {
if (is_valid_ether_addr(addr)) if (is_valid_ether_addr(addr) ||
(is_zero_ether_addr(addr) &&
(IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))))
return true; return true;
#ifdef BCM_CNIC
if (is_zero_ether_addr(addr) &&
(IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)))
return true;
#endif
return false; return false;
} }

View file

@ -1908,10 +1908,10 @@ static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
/* first the HW mac address */ /* first the HW mac address */
memcpy(perm_addr, netdev->dev_addr, netdev->addr_len); memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
#ifdef BCM_CNIC if (CNIC_LOADED(bp))
/* second SAN address */ /* second SAN address */
memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len); memcpy(perm_addr+netdev->addr_len, bp->fip_mac,
#endif netdev->addr_len);
} }
static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio, static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,

View file

@ -2901,7 +2901,9 @@ static void bnx2x_get_channels(struct net_device *dev,
static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss) static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss)
{ {
bnx2x_disable_msi(bp); bnx2x_disable_msi(bp);
BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE; bp->num_ethernet_queues = num_rss;
bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
bnx2x_set_int_mode(bp); bnx2x_set_int_mode(bp);
} }

View file

@ -648,15 +648,25 @@ static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,
return rc; return rc;
} }
static int bnx2x_ilt_mem_op_cnic(struct bnx2x *bp, u8 memop)
{
int rc = 0;
if (CONFIGURE_NIC_MODE(bp))
rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
if (!rc)
rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
return rc;
}
static int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop) static int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop)
{ {
int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop); int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop);
if (!rc) if (!rc)
rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop); rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop);
if (!rc) if (!rc && CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))
rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop); rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
if (!rc)
rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
return rc; return rc;
} }
@ -781,12 +791,19 @@ static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp,
bnx2x_ilt_client_init_op(bp, ilt_cli, initop); bnx2x_ilt_client_init_op(bp, ilt_cli, initop);
} }
static void bnx2x_ilt_init_op_cnic(struct bnx2x *bp, u8 initop)
{
if (CONFIGURE_NIC_MODE(bp))
bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
}
static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop) static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)
{ {
bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop); bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop);
bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop); bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop);
bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop); if (CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))
bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop); bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
} }
static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num, static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
@ -890,7 +907,6 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
/**************************************************************************** /****************************************************************************
* SRC initializations * SRC initializations
****************************************************************************/ ****************************************************************************/
#ifdef BCM_CNIC
/* called during init func stage */ /* called during init func stage */
static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2, static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
dma_addr_t t2_mapping, int src_cid_count) dma_addr_t t2_mapping, int src_cid_count)
@ -915,5 +931,4 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
U64_HI((u64)t2_mapping + U64_HI((u64)t2_mapping +
(src_cid_count-1) * sizeof(struct src_ent))); (src_cid_count-1) * sizeof(struct src_ent)));
} }
#endif
#endif /* BNX2X_INIT_OPS_H */ #endif /* BNX2X_INIT_OPS_H */

View file

@ -11998,7 +11998,7 @@ void bnx2x_init_xgxs_loopback(struct link_params *params,
bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed); bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
} }
static void bnx2x_set_rx_filter(struct link_params *params, u8 en) void bnx2x_set_rx_filter(struct link_params *params, u8 en)
{ {
struct bnx2x *bp = params->bp; struct bnx2x *bp = params->bp;
u8 val = en * 0x1F; u8 val = en * 0x1F;

View file

@ -432,7 +432,8 @@ int bnx2x_phy_probe(struct link_params *params);
u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base, u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base, u8 port); u32 shmem2_base, u8 port);
/* Open / close the gate between the NIG and the BRB */
void bnx2x_set_rx_filter(struct link_params *params, u8 en);
/* DCBX structs */ /* DCBX structs */

File diff suppressed because it is too large Load diff

View file

@ -2107,6 +2107,7 @@
#define NIG_REG_LLH1_ERROR_MASK 0x10090 #define NIG_REG_LLH1_ERROR_MASK 0x10090
/* [RW 8] event id for llh1 */ /* [RW 8] event id for llh1 */
#define NIG_REG_LLH1_EVENT_ID 0x10088 #define NIG_REG_LLH1_EVENT_ID 0x10088
#define NIG_REG_LLH1_FUNC_EN 0x16104
#define NIG_REG_LLH1_FUNC_MEM 0x161c0 #define NIG_REG_LLH1_FUNC_MEM 0x161c0
#define NIG_REG_LLH1_FUNC_MEM_ENABLE 0x16160 #define NIG_REG_LLH1_FUNC_MEM_ENABLE 0x16160
#define NIG_REG_LLH1_FUNC_MEM_SIZE 16 #define NIG_REG_LLH1_FUNC_MEM_SIZE 16
@ -2302,6 +2303,15 @@
* set to 0x345678021. This is a new register (with 2_) added in E3 B0 to * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
* accommodate the 9 input clients to ETS arbiter. */ * accommodate the 9 input clients to ETS arbiter. */
#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB 0x18684 #define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB 0x18684
/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP
* packets to BRB LB interface to forward the packet to the host. All
* packets from MCP are forwarded to the network when this bit is cleared -
* regardless of the configured destination in tx_mng_destination register.
* When MCP-to-host paths for both ports 0 and 1 are disabled - the arbiter
* for BRB LB interface is bypassed and PBF LB traffic is always selected to
* send to BRB LB.
*/
#define NIG_REG_P0_TX_MNG_HOST_ENABLE 0x182f4
#define NIG_REG_P1_HWPFC_ENABLE 0x181d0 #define NIG_REG_P1_HWPFC_ENABLE 0x181d0
#define NIG_REG_P1_MAC_IN_EN 0x185c0 #define NIG_REG_P1_MAC_IN_EN 0x185c0
/* [RW 1] Output enable for TX MAC interface */ /* [RW 1] Output enable for TX MAC interface */
@ -2418,6 +2428,12 @@
#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB 0x186e4 #define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB 0x186e4
/* [R 1] TX FIFO for transmitting data to MAC is empty. */ /* [R 1] TX FIFO for transmitting data to MAC is empty. */
#define NIG_REG_P1_TX_MACFIFO_EMPTY 0x18594 #define NIG_REG_P1_TX_MACFIFO_EMPTY 0x18594
/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP
* packets to BRB LB interface to forward the packet to the host. All
* packets from MCP are forwarded to the network when this bit is cleared -
* regardless of the configured destination in tx_mng_destination register.
*/
#define NIG_REG_P1_TX_MNG_HOST_ENABLE 0x182f8
/* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets /* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets
forwarded to the host. */ forwarded to the host. */
#define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY 0x182b8 #define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY 0x182b8

View file

@ -5350,12 +5350,24 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) && else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) &&
(!test_bit(BNX2X_F_CMD_STOP, &o->pending))) (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
next_state = BNX2X_F_STATE_STARTED; next_state = BNX2X_F_STATE_STARTED;
/* Switch_update ramrod can be sent in either started or
* tx_stopped state, and it doesn't change the state.
*/
else if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
(!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
next_state = BNX2X_F_STATE_STARTED;
else if (cmd == BNX2X_F_CMD_TX_STOP) else if (cmd == BNX2X_F_CMD_TX_STOP)
next_state = BNX2X_F_STATE_TX_STOPPED; next_state = BNX2X_F_STATE_TX_STOPPED;
break; break;
case BNX2X_F_STATE_TX_STOPPED: case BNX2X_F_STATE_TX_STOPPED:
if (cmd == BNX2X_F_CMD_TX_START) if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
(!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
next_state = BNX2X_F_STATE_TX_STOPPED;
else if (cmd == BNX2X_F_CMD_TX_START)
next_state = BNX2X_F_STATE_STARTED; next_state = BNX2X_F_STATE_STARTED;
break; break;
@ -5637,6 +5649,28 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
U64_LO(data_mapping), NONE_CONNECTION_TYPE); U64_LO(data_mapping), NONE_CONNECTION_TYPE);
} }
static inline int bnx2x_func_send_switch_update(struct bnx2x *bp,
struct bnx2x_func_state_params *params)
{
struct bnx2x_func_sp_obj *o = params->f_obj;
struct function_update_data *rdata =
(struct function_update_data *)o->rdata;
dma_addr_t data_mapping = o->rdata_mapping;
struct bnx2x_func_switch_update_params *switch_update_params =
&params->params.switch_update;
memset(rdata, 0, sizeof(*rdata));
/* Fill the ramrod data with provided parameters */
rdata->tx_switch_suspend_change_flg = 1;
rdata->tx_switch_suspend = switch_update_params->suspend;
rdata->echo = SWITCH_UPDATE;
return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
U64_HI(data_mapping),
U64_LO(data_mapping), NONE_CONNECTION_TYPE);
}
static inline int bnx2x_func_send_afex_update(struct bnx2x *bp, static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
struct bnx2x_func_state_params *params) struct bnx2x_func_state_params *params)
{ {
@ -5657,6 +5691,7 @@ static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
cpu_to_le16(afex_update_params->afex_default_vlan); cpu_to_le16(afex_update_params->afex_default_vlan);
rdata->allowed_priorities_change_flg = 1; rdata->allowed_priorities_change_flg = 1;
rdata->allowed_priorities = afex_update_params->allowed_priorities; rdata->allowed_priorities = afex_update_params->allowed_priorities;
rdata->echo = AFEX_UPDATE;
/* No need for an explicit memory barrier here as long we would /* No need for an explicit memory barrier here as long we would
* need to ensure the ordering of writing to the SPQ element * need to ensure the ordering of writing to the SPQ element
@ -5773,6 +5808,8 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp,
return bnx2x_func_send_tx_stop(bp, params); return bnx2x_func_send_tx_stop(bp, params);
case BNX2X_F_CMD_TX_START: case BNX2X_F_CMD_TX_START:
return bnx2x_func_send_tx_start(bp, params); return bnx2x_func_send_tx_start(bp, params);
case BNX2X_F_CMD_SWITCH_UPDATE:
return bnx2x_func_send_switch_update(bp, params);
default: default:
BNX2X_ERR("Unknown command: %d\n", params->cmd); BNX2X_ERR("Unknown command: %d\n", params->cmd);
return -EINVAL; return -EINVAL;
@ -5818,16 +5855,30 @@ int bnx2x_func_state_change(struct bnx2x *bp,
struct bnx2x_func_state_params *params) struct bnx2x_func_state_params *params)
{ {
struct bnx2x_func_sp_obj *o = params->f_obj; struct bnx2x_func_sp_obj *o = params->f_obj;
int rc; int rc, cnt = 300;
enum bnx2x_func_cmd cmd = params->cmd; enum bnx2x_func_cmd cmd = params->cmd;
unsigned long *pending = &o->pending; unsigned long *pending = &o->pending;
mutex_lock(&o->one_pending_mutex); mutex_lock(&o->one_pending_mutex);
/* Check that the requested transition is legal */ /* Check that the requested transition is legal */
if (o->check_transition(bp, o, params)) { rc = o->check_transition(bp, o, params);
if ((rc == -EBUSY) &&
(test_bit(RAMROD_RETRY, &params->ramrod_flags))) {
while ((rc == -EBUSY) && (--cnt > 0)) {
mutex_unlock(&o->one_pending_mutex);
msleep(10);
mutex_lock(&o->one_pending_mutex);
rc = o->check_transition(bp, o, params);
}
if (rc == -EBUSY) {
mutex_unlock(&o->one_pending_mutex);
BNX2X_ERR("timeout waiting for previous ramrod completion\n");
return rc;
}
} else if (rc) {
mutex_unlock(&o->one_pending_mutex); mutex_unlock(&o->one_pending_mutex);
return -EINVAL; return rc;
} }
/* Set "pending" bit */ /* Set "pending" bit */

View file

@ -40,6 +40,12 @@ enum {
* pending commands list. * pending commands list.
*/ */
RAMROD_CONT, RAMROD_CONT,
/* If there is another pending ramrod, wait until it finishes and
* re-try to submit this one. This flag can be set only in sleepable
* context, and should not be set from the context that completes the
* ramrods as deadlock will occur.
*/
RAMROD_RETRY,
}; };
typedef enum { typedef enum {
@ -1061,6 +1067,7 @@ enum bnx2x_func_cmd {
BNX2X_F_CMD_AFEX_VIFLISTS, BNX2X_F_CMD_AFEX_VIFLISTS,
BNX2X_F_CMD_TX_STOP, BNX2X_F_CMD_TX_STOP,
BNX2X_F_CMD_TX_START, BNX2X_F_CMD_TX_START,
BNX2X_F_CMD_SWITCH_UPDATE,
BNX2X_F_CMD_MAX, BNX2X_F_CMD_MAX,
}; };
@ -1103,6 +1110,10 @@ struct bnx2x_func_start_params {
u8 network_cos_mode; u8 network_cos_mode;
}; };
struct bnx2x_func_switch_update_params {
u8 suspend;
};
struct bnx2x_func_afex_update_params { struct bnx2x_func_afex_update_params {
u16 vif_id; u16 vif_id;
u16 afex_default_vlan; u16 afex_default_vlan;
@ -1136,6 +1147,7 @@ struct bnx2x_func_state_params {
struct bnx2x_func_hw_init_params hw_init; struct bnx2x_func_hw_init_params hw_init;
struct bnx2x_func_hw_reset_params hw_reset; struct bnx2x_func_hw_reset_params hw_reset;
struct bnx2x_func_start_params start; struct bnx2x_func_start_params start;
struct bnx2x_func_switch_update_params switch_update;
struct bnx2x_func_afex_update_params afex_update; struct bnx2x_func_afex_update_params afex_update;
struct bnx2x_func_afex_viflists_params afex_viflists; struct bnx2x_func_afex_viflists_params afex_viflists;
struct bnx2x_func_tx_start_params tx_start; struct bnx2x_func_tx_start_params tx_start;