diff options
author | Vlad Zolotarov <vladz@broadcom.com> | 2011-06-14 14:33:44 +0300 |
---|---|---|
committer | David S. Miller <davem@conan.davemloft.net> | 2011-06-15 10:56:37 -0400 |
commit | 619c5cb6885b936c44ae1422ef805b69c6291485 (patch) | |
tree | 4604ae08f1eb12c6ad1f65106879c2e73946ae12 /drivers/net/bnx2x/bnx2x_main.c | |
parent | 042181f5aa8833a8918e1a91cfaf292146ffc62c (diff) |
New 7.0 FW: bnx2x, cnic, bnx2i, bnx2fc
New FW/HSI (7.0):
- Added support to 578xx chips
- Improved HSI - much less driver's direct access to the FW internal
memory needed.
New implementation of the HSI handling layer in the bnx2x (bnx2x_sp.c):
- Introduced chip dependent objects that have chip independent interfaces
for configuration of MACs, multicast addresses, Rx mode, indirection table,
fast path queues and function initialization/cleanup.
- Objects functionality is based on the private function pointers, which
allows not only a per-chip but also PF/VF differentiation while still
preserving the same interface towards the driver.
- Objects interface is not influenced by the HSI changes which do not require
providing new parameters keeping the code outside the bnx2x_sp.c invariant
with regard to such HSI chnages.
Changes in a CNIC, bnx2fc and bnx2i modules due to the new HSI.
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@conan.davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_main.c')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_main.c | 3725 |
1 files changed, 2403 insertions, 1322 deletions
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 84f419fcde2..63c92091586 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -39,6 +39,7 @@ #include <linux/mii.h> #include <linux/if_vlan.h> #include <net/ip.h> +#include <net/ipv6.h> #include <net/tcp.h> #include <net/checksum.h> #include <net/ip6_checksum.h> @@ -50,7 +51,6 @@ #include <linux/io.h> #include <linux/stringify.h> -#define BNX2X_MAIN #include "bnx2x.h" #include "bnx2x_init.h" #include "bnx2x_init_ops.h" @@ -74,12 +74,14 @@ #define TX_TIMEOUT (5*HZ) static char version[] __devinitdata = - "Broadcom NetXtreme II 5771x 10Gigabit Ethernet Driver " + "Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver " DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Eliezer Tamir"); MODULE_DESCRIPTION("Broadcom NetXtreme II " - "BCM57710/57711/57711E/57712/57712E Driver"); + "BCM57710/57711/57711E/" + "57712/57712_MF/57800/57800_MF/57810/57810_MF/" + "57840/57840_MF Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); MODULE_FIRMWARE(FW_FILE_NAME_E1); @@ -104,7 +106,7 @@ MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature"); #define INT_MODE_MSI 2 static int int_mode; module_param(int_mode, int, 0); -MODULE_PARM_DESC(int_mode, " Force interrupt mode other then MSI-X " +MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X " "(1 INT#x; 2 MSI)"); static int dropless_fc; @@ -123,37 +125,87 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, " Default debug msglevel"); -static struct workqueue_struct *bnx2x_wq; -#ifdef BCM_CNIC -static u8 ALL_ENODE_MACS[] = {0x01, 0x10, 0x18, 0x01, 0x00, 0x01}; -#endif + +struct workqueue_struct *bnx2x_wq; enum bnx2x_board_type { BCM57710 = 0, - BCM57711 = 1, - BCM57711E = 2, - BCM57712 = 3, - BCM57712E = 4 + BCM57711, + BCM57711E, + BCM57712, + BCM57712_MF, + BCM57800, + BCM57800_MF, + BCM57810, + BCM57810_MF, + BCM57840, + BCM57840_MF }; /* indexed by board_type, above */ static struct { char *name; } board_info[] __devinitdata = { - { "Broadcom NetXtreme II BCM57710 XGb" }, - { "Broadcom NetXtreme II BCM57711 XGb" }, - { "Broadcom NetXtreme II BCM57711E XGb" }, - { "Broadcom NetXtreme II BCM57712 XGb" }, - { "Broadcom NetXtreme II BCM57712E XGb" } + { "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" }, + { "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" }, + { "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" }, + { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet" }, + { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function" }, + { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet" }, + { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Multi Function" }, + { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet" }, + { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function" }, + { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet" }, + { "Broadcom NetXtreme II BCM57840 10/20 Gigabit " + "Ethernet Multi Function"} }; +#ifndef PCI_DEVICE_ID_NX2_57710 +#define PCI_DEVICE_ID_NX2_57710 CHIP_NUM_57710 +#endif +#ifndef PCI_DEVICE_ID_NX2_57711 +#define PCI_DEVICE_ID_NX2_57711 CHIP_NUM_57711 +#endif +#ifndef PCI_DEVICE_ID_NX2_57711E +#define PCI_DEVICE_ID_NX2_57711E CHIP_NUM_57711E +#endif +#ifndef PCI_DEVICE_ID_NX2_57712 +#define PCI_DEVICE_ID_NX2_57712 CHIP_NUM_57712 +#endif +#ifndef PCI_DEVICE_ID_NX2_57712_MF +#define PCI_DEVICE_ID_NX2_57712_MF CHIP_NUM_57712_MF +#endif +#ifndef PCI_DEVICE_ID_NX2_57800 +#define PCI_DEVICE_ID_NX2_57800 CHIP_NUM_57800 +#endif +#ifndef PCI_DEVICE_ID_NX2_57800_MF +#define PCI_DEVICE_ID_NX2_57800_MF CHIP_NUM_57800_MF +#endif +#ifndef PCI_DEVICE_ID_NX2_57810 +#define PCI_DEVICE_ID_NX2_57810 CHIP_NUM_57810 +#endif +#ifndef PCI_DEVICE_ID_NX2_57810_MF +#define PCI_DEVICE_ID_NX2_57810_MF CHIP_NUM_57810_MF +#endif +#ifndef PCI_DEVICE_ID_NX2_57840 +#define PCI_DEVICE_ID_NX2_57840 CHIP_NUM_57840 +#endif +#ifndef PCI_DEVICE_ID_NX2_57840_MF +#define PCI_DEVICE_ID_NX2_57840_MF CHIP_NUM_57840_MF +#endif static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = { { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 }, { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 }, { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E }, { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712), BCM57712 }, - { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712E), BCM57712E }, + { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712_MF), BCM57712_MF }, + { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800), BCM57800 }, + { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800_MF), BCM57800_MF }, + { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810), BCM57810 }, + { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810_MF), BCM57810_MF }, + { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840), BCM57840 }, + { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_MF), BCM57840_MF }, { 0 } }; @@ -163,11 +215,47 @@ MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl); * General service functions ****************************************************************************/ -static inline void storm_memset_ov(struct bnx2x *bp, u16 ov, u16 abs_fid) +static inline void __storm_memset_dma_mapping(struct bnx2x *bp, + u32 addr, dma_addr_t mapping) +{ + REG_WR(bp, addr, U64_LO(mapping)); + REG_WR(bp, addr + 4, U64_HI(mapping)); +} + +static inline void storm_memset_spq_addr(struct bnx2x *bp, + dma_addr_t mapping, u16 abs_fid) +{ + u32 addr = XSEM_REG_FAST_MEMORY + + XSTORM_SPQ_PAGE_BASE_OFFSET(abs_fid); + + __storm_memset_dma_mapping(bp, addr, mapping); +} + +static inline void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid, + u16 pf_id) { - REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_E1HOV_OFFSET(abs_fid), ov); + REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_VF_TO_PF_OFFSET(abs_fid), + pf_id); + REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_VF_TO_PF_OFFSET(abs_fid), + pf_id); + REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_VF_TO_PF_OFFSET(abs_fid), + pf_id); + REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_VF_TO_PF_OFFSET(abs_fid), + pf_id); } +static inline void storm_memset_func_en(struct bnx2x *bp, u16 abs_fid, + u8 enable) +{ + REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(abs_fid), + enable); + REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNC_EN_OFFSET(abs_fid), + enable); + REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNC_EN_OFFSET(abs_fid), + enable); + REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(abs_fid), + enable); +} static inline void storm_memset_eq_data(struct bnx2x *bp, struct event_ring_data *eq_data, @@ -187,45 +275,6 @@ static inline void storm_memset_eq_prod(struct bnx2x *bp, u16 eq_prod, REG_WR16(bp, addr, eq_prod); } -static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port, - u16 fw_sb_id, u8 sb_index, - u8 ticks) -{ - - int index_offset = CHIP_IS_E2(bp) ? - offsetof(struct hc_status_block_data_e2, index_data) : - offsetof(struct hc_status_block_data_e1x, index_data); - u32 addr = BAR_CSTRORM_INTMEM + - CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) + - index_offset + - sizeof(struct hc_index_data)*sb_index + - offsetof(struct hc_index_data, timeout); - REG_WR8(bp, addr, ticks); - DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n", - port, fw_sb_id, sb_index, ticks); -} -static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port, - u16 fw_sb_id, u8 sb_index, - u8 disable) -{ - u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT); - int index_offset = CHIP_IS_E2(bp) ? - offsetof(struct hc_status_block_data_e2, index_data) : - offsetof(struct hc_status_block_data_e1x, index_data); - u32 addr = BAR_CSTRORM_INTMEM + - CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) + - index_offset + - sizeof(struct hc_index_data)*sb_index + - offsetof(struct hc_index_data, flags); - u16 flags = REG_RD16(bp, addr); - /* clear and set */ - flags &= ~HC_INDEX_DATA_HC_ENABLED; - flags |= enable_flag; - REG_WR16(bp, addr, flags); - DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n", - port, fw_sb_id, sb_index, disable); -} - /* used only at init * locking is done by mcp */ @@ -319,13 +368,6 @@ static void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, } -const u32 dmae_reg_go_c[] = { - DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3, - DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7, - DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11, - DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15 -}; - /* copy command into DMAE command memory and set DMAE command go */ void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx) { @@ -406,7 +448,11 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, bp->slowpath->wb_data[0], bp->slowpath->wb_data[1], bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]); - /* lock the dmae channel */ + /* + * Lock the dmae channel. Disable BHs to prevent a dead-lock + * as long as this code is called both from syscall context and + * from ndo_set_rx_mode() flow that may be called from BH. + */ spin_lock_bh(&bp->dmae_lock); /* reset completion */ @@ -730,9 +776,9 @@ void bnx2x_panic_dump(struct bnx2x *bp) /* Indices */ /* Common */ BNX2X_ERR("def_idx(0x%x) def_att_idx(0x%x) attn_state(0x%x)" - " spq_prod_idx(0x%x)\n", - bp->def_idx, bp->def_att_idx, - bp->attn_state, bp->spq_prod_idx); + " spq_prod_idx(0x%x) next_stats_cnt(0x%x)\n", + bp->def_idx, bp->def_att_idx, bp->attn_state, + bp->spq_prod_idx, bp->stats_counter); BNX2X_ERR("DSB: attn bits(0x%x) ack(0x%x) id(0x%x) idx(0x%x)\n", bp->def_status_blk->atten_status_block.attn_bits, bp->def_status_blk->atten_status_block.attn_bits_ack, @@ -749,15 +795,17 @@ void bnx2x_panic_dump(struct bnx2x *bp) CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) + i*sizeof(u32)); - pr_cont("igu_sb_id(0x%x) igu_seg_id (0x%x) " + pr_cont("igu_sb_id(0x%x) igu_seg_id(0x%x) " "pf_id(0x%x) vnic_id(0x%x) " - "vf_id(0x%x) vf_valid (0x%x)\n", + "vf_id(0x%x) vf_valid (0x%x) " + "state(0x%x)\n", sp_sb_data.igu_sb_id, sp_sb_data.igu_seg_id, sp_sb_data.p_func.pf_id, sp_sb_data.p_func.vnic_id, sp_sb_data.p_func.vf_id, - sp_sb_data.p_func.vf_valid); + sp_sb_data.p_func.vf_valid, + sp_sb_data.state); for_each_eth_queue(bp, i) { @@ -766,13 +814,13 @@ void bnx2x_panic_dump(struct bnx2x *bp) struct hc_status_block_data_e2 sb_data_e2; struct hc_status_block_data_e1x sb_data_e1x; struct hc_status_block_sm *hc_sm_p = - CHIP_IS_E2(bp) ? - sb_data_e2.common.state_machine : - sb_data_e1x.common.state_machine; + CHIP_IS_E1x(bp) ? + sb_data_e1x.common.state_machine : + sb_data_e2.common.state_machine; struct hc_index_data *hc_index_p = - CHIP_IS_E2(bp) ? - sb_data_e2.index_data : - sb_data_e1x.index_data; + CHIP_IS_E1x(bp) ? + sb_data_e1x.index_data : + sb_data_e2.index_data; int data_size; u32 *sb_data_p; @@ -795,8 +843,8 @@ void bnx2x_panic_dump(struct bnx2x *bp) i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod, fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb)); - loop = CHIP_IS_E2(bp) ? - HC_SB_MAX_INDICES_E2 : HC_SB_MAX_INDICES_E1X; + loop = CHIP_IS_E1x(bp) ? + HC_SB_MAX_INDICES_E1X : HC_SB_MAX_INDICES_E2; /* host sb data */ @@ -816,35 +864,39 @@ void bnx2x_panic_dump(struct bnx2x *bp) fp->sb_index_values[j], (j == loop - 1) ? ")" : " "); /* fw sb data */ - data_size = CHIP_IS_E2(bp) ? - sizeof(struct hc_status_block_data_e2) : - sizeof(struct hc_status_block_data_e1x); + data_size = CHIP_IS_E1x(bp) ? + sizeof(struct hc_status_block_data_e1x) : + sizeof(struct hc_status_block_data_e2); data_size /= sizeof(u32); - sb_data_p = CHIP_IS_E2(bp) ? - (u32 *)&sb_data_e2 : - (u32 *)&sb_data_e1x; + sb_data_p = CHIP_IS_E1x(bp) ? + (u32 *)&sb_data_e1x : + (u32 *)&sb_data_e2; /* copy sb data in here */ for (j = 0; j < data_size; j++) *(sb_data_p + j) = REG_RD(bp, BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id) + j * sizeof(u32)); - if (CHIP_IS_E2(bp)) { - pr_cont("pf_id(0x%x) vf_id (0x%x) vf_valid(0x%x) " - "vnic_id(0x%x) same_igu_sb_1b(0x%x)\n", + if (!CHIP_IS_E1x(bp)) { + pr_cont("pf_id(0x%x) vf_id(0x%x) vf_valid(0x%x) " + "vnic_id(0x%x) same_igu_sb_1b(0x%x) " + "state(0x%x)\n", sb_data_e2.common.p_func.pf_id, sb_data_e2.common.p_func.vf_id, sb_data_e2.common.p_func.vf_valid, sb_data_e2.common.p_func.vnic_id, - sb_data_e2.common.same_igu_sb_1b); + sb_data_e2.common.same_igu_sb_1b, + sb_data_e2.common.state); } else { - pr_cont("pf_id(0x%x) vf_id (0x%x) vf_valid(0x%x) " - "vnic_id(0x%x) same_igu_sb_1b(0x%x)\n", + pr_cont("pf_id(0x%x) vf_id(0x%x) vf_valid(0x%x) " + "vnic_id(0x%x) same_igu_sb_1b(0x%x) " + "state(0x%x)\n", sb_data_e1x.common.p_func.pf_id, sb_data_e1x.common.p_func.vf_id, sb_data_e1x.common.p_func.vf_valid, sb_data_e1x.common.p_func.vnic_id, - sb_data_e1x.common.same_igu_sb_1b); + sb_data_e1x.common.same_igu_sb_1b, + sb_data_e1x.common.state); } /* SB_SMs data */ @@ -933,6 +985,373 @@ void bnx2x_panic_dump(struct bnx2x *bp) BNX2X_ERR("end crash dump -----------------\n"); } +/* + * FLR Support for E2 + * + * bnx2x_pf_flr_clnup() is called during nic_load in the per function HW + * initialization. + */ +#define FLR_WAIT_USEC 10000 /* 10 miliseconds */ +#define FLR_WAIT_INTERAVAL 50 /* usec */ +#define FLR_POLL_CNT (FLR_WAIT_USEC/FLR_WAIT_INTERAVAL) /* 200 */ + +struct pbf_pN_buf_regs { + int pN; + u32 init_crd; + u32 crd; + u32 crd_freed; +}; + +struct pbf_pN_cmd_regs { + int pN; + u32 lines_occup; + u32 lines_freed; +}; + +static void bnx2x_pbf_pN_buf_flushed(struct bnx2x *bp, + struct pbf_pN_buf_regs *regs, + u32 poll_count) +{ + u32 init_crd, crd, crd_start, crd_freed, crd_freed_start; + u32 cur_cnt = poll_count; + + crd_freed = crd_freed_start = REG_RD(bp, regs->crd_freed); + crd = crd_start = REG_RD(bp, regs->crd); + init_crd = REG_RD(bp, regs->init_crd); + + DP(BNX2X_MSG_SP, "INIT CREDIT[%d] : %x\n", regs->pN, init_crd); + DP(BNX2X_MSG_SP, "CREDIT[%d] : s:%x\n", regs->pN, crd); + DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: s:%x\n", regs->pN, crd_freed); + + while ((crd != init_crd) && ((u32)SUB_S32(crd_freed, crd_freed_start) < + (init_crd - crd_start))) { + if (cur_cnt--) { + udelay(FLR_WAIT_INTERAVAL); + crd = REG_RD(bp, regs->crd); + crd_freed = REG_RD(bp, regs->crd_freed); + } else { + DP(BNX2X_MSG_SP, "PBF tx buffer[%d] timed out\n", + regs->pN); + DP(BNX2X_MSG_SP, "CREDIT[%d] : c:%x\n", + regs->pN, crd); + DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: c:%x\n", + regs->pN, crd_freed); + break; + } + } + DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF tx buffer[%d]\n", + poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN); +} + +static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp, + struct pbf_pN_cmd_regs *regs, + u32 poll_count) +{ + u32 occup, to_free, freed, freed_start; + u32 cur_cnt = poll_count; + + occup = to_free = REG_RD(bp, regs->lines_occup); + freed = freed_start = REG_RD(bp, regs->lines_freed); + + DP(BNX2X_MSG_SP, "OCCUPANCY[%d] : s:%x\n", regs->pN, occup); + DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n", regs->pN, freed); + + while (occup && ((u32)SUB_S32(freed, freed_start) < to_free)) { + if (cur_cnt--) { + udelay(FLR_WAIT_INTERAVAL); + occup = REG_RD(bp, regs->lines_occup); + freed = REG_RD(bp, regs->lines_freed); + } else { + DP(BNX2X_MSG_SP, "PBF cmd queue[%d] timed out\n", + regs->pN); + DP(BNX2X_MSG_SP, "OCCUPANCY[%d] : s:%x\n", + regs->pN, occup); + DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n", + regs->pN, freed); + break; + } + } + DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF cmd queue[%d]\n", + poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN); +} + +static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg, + u32 expected, u32 poll_count) +{ + u32 cur_cnt = poll_count; + u32 val; + + while ((val = REG_RD(bp, reg)) != expected && cur_cnt--) + udelay(FLR_WAIT_INTERAVAL); + + return val; +} + +static inline int bnx2x_flr_clnup_poll_hw_counter(struct bnx2x *bp, u32 reg, + char *msg, u32 poll_cnt) +{ + u32 val = bnx2x_flr_clnup_reg_poll(bp, reg, 0, poll_cnt); + if (val != 0) { + BNX2X_ERR("%s usage count=%d\n", msg, val); + return 1; + } + return 0; +} + +static u32 bnx2x_flr_clnup_poll_count(struct bnx2x *bp) +{ + /* adjust polling timeout */ + if (CHIP_REV_IS_EMUL(bp)) + return FLR_POLL_CNT * 2000; + + if (CHIP_REV_IS_FPGA(bp)) + return FLR_POLL_CNT * 120; + + return FLR_POLL_CNT; +} + +static void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count) +{ + struct pbf_pN_cmd_regs cmd_regs[] = { + {0, (CHIP_IS_E3B0(bp)) ? + PBF_REG_TQ_OCCUPANCY_Q0 : + PBF_REG_P0_TQ_OCCUPANCY, + (CHIP_IS_E3B0(bp)) ? + PBF_REG_TQ_LINES_FREED_CNT_Q0 : + PBF_REG_P0_TQ_LINES_FREED_CNT}, + {1, (CHIP_IS_E3B0(bp)) ? + PBF_REG_TQ_OCCUPANCY_Q1 : + PBF_REG_P1_TQ_OCCUPANCY, + (CHIP_IS_E3B0(bp)) ? + PBF_REG_TQ_LINES_FREED_CNT_Q1 : + PBF_REG_P1_TQ_LINES_FREED_CNT}, + {4, (CHIP_IS_E3B0(bp)) ? + PBF_REG_TQ_OCCUPANCY_LB_Q : + PBF_REG_P4_TQ_OCCUPANCY, + (CHIP_IS_E3B0(bp)) ? + PBF_REG_TQ_LINES_FREED_CNT_LB_Q : + PBF_REG_P4_TQ_LINES_FREED_CNT} + }; + + struct pbf_pN_buf_regs buf_regs[] = { + {0, (CHIP_IS_E3B0(bp)) ? + PBF_REG_INIT_CRD_Q0 : + PBF_REG_P0_INIT_CRD , + (CHIP_IS_E3B0(bp)) ? + PBF_REG_CREDIT_Q0 : + PBF_REG_P0_CREDIT, + (CHIP_IS_E3B0(bp)) ? + PBF_REG_INTERNAL_CRD_FREED_CNT_Q0 : + PBF_REG_P0_INTERNAL_CRD_FREED_CNT}, + {1, (CHIP_IS_E3B0(bp)) ? + PBF_REG_INIT_CRD_Q1 : + PBF_REG_P1_INIT_CRD, + (CHIP_IS_E3B0(bp)) ? + PBF_REG_CREDIT_Q1 : + PBF_REG_P1_CREDIT, + (CHIP_IS_E3B0(bp)) ? + PBF_REG_INTERNAL_CRD_FREED_CNT_Q1 : + PBF_REG_P1_INTERNAL_CRD_FREED_CNT}, + {4, (CHIP_IS_E3B0(bp)) ? + PBF_REG_INIT_CRD_LB_Q : + PBF_REG_P4_INIT_CRD, + (CHIP_IS_E3B0(bp)) ? + PBF_REG_CREDIT_LB_Q : + PBF_REG_P4_CREDIT, + (CHIP_IS_E3B0(bp)) ? + PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q : + PBF_REG_P4_INTERNAL_CRD_FREED_CNT}, + }; + + int i; + + /* Verify the command queues are flushed P0, P1, P4 */ + for (i = 0; i < ARRAY_SIZE(cmd_regs); i++) + bnx2x_pbf_pN_cmd_flushed(bp, &cmd_regs[i], poll_count); + + + /* Verify the transmission buffers are flushed P0, P1, P4 */ + for (i = 0; i < ARRAY_SIZE(buf_regs); i++) + bnx2x_pbf_pN_buf_flushed(bp, &buf_regs[i], poll_count); +} + +#define OP_GEN_PARAM(param) \ + (((param) << SDM_OP_GEN_COMP_PARAM_SHIFT) & SDM_OP_GEN_COMP_PARAM) + +#define OP_GEN_TYPE(type) \ + (((type) << SDM_OP_GEN_COMP_TYPE_SHIFT) & SDM_OP_GEN_COMP_TYPE) + +#define OP_GEN_AGG_VECT(index) \ + (((index) << SDM_OP_GEN_AGG_VECT_IDX_SHIFT) & SDM_OP_GEN_AGG_VECT_IDX) + + +static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func, + u32 poll_cnt) +{ + struct sdm_op_gen op_gen = {0}; + + u32 comp_addr = BAR_CSTRORM_INTMEM + + CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(clnup_func); + int ret = 0; + + if (REG_RD(bp, comp_addr)) { + BNX2X_ERR("Cleanup complete is not 0\n"); + return 1; + } + + op_gen.command |= OP_GEN_PARAM(XSTORM_AGG_INT_FINAL_CLEANUP_INDEX); + op_gen.command |= OP_GEN_TYPE(XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE); + op_gen.command |= OP_GEN_AGG_VECT(clnup_func); + op_gen.command |= 1 << SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT; + + DP(BNX2X_MSG_SP, "FW Final cleanup\n"); + REG_WR(bp, XSDM_REG_OPERATION_GEN, op_gen.command); + + if (bnx2x_flr_clnup_reg_poll(bp, comp_addr, 1, poll_cnt) != 1) { + BNX2X_ERR("FW final cleanup did not succeed\n"); + ret = 1; + } + /* Zero completion for nxt FLR */ + REG_WR(bp, comp_addr, 0); + + return ret; +} + +static inline u8 bnx2x_is_pcie_pending(struct pci_dev *dev) +{ + int pos; + u16 status; + + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!pos) + return false; + + pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status); + return status & PCI_EXP_DEVSTA_TRPND; +} + +/* PF FLR specific routines +*/ +static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt) +{ + + /* wait for CFC PF usage-counter to zero (includes all the VFs) */ + if (bnx2x_flr_clnup_poll_hw_counter(bp, + CFC_REG_NUM_LCIDS_INSIDE_PF, + "CFC PF usage counter timed out", + poll_cnt)) + return 1; + + + /* Wait for DQ PF usage-counter to zero (until DQ cleanup) */ + if (bnx2x_flr_clnup_poll_hw_counter(bp, + DORQ_REG_PF_USAGE_CNT, + "DQ PF usage counter timed out", + poll_cnt)) + return 1; + + /* Wait for QM PF usage-counter to zero (until DQ cleanup) */ + if (bnx2x_flr_clnup_poll_hw_counter(bp, + QM_REG_PF_USG_CNT_0 + 4*BP_FUNC(bp), + "QM PF usage counter timed out", + poll_cnt)) + return 1; + + /* Wait for Timer PF usage-counters to zero (until DQ cleanup) */ + if (bnx2x_flr_clnup_poll_hw_counter(bp, + TM_REG_LIN0_VNIC_UC + 4*BP_PORT(bp), + "Timers VNIC usage counter timed out", + poll_cnt)) + return 1; + if (bnx2x_flr_clnup_poll_hw_counter(bp, + TM_REG_LIN0_NUM_SCANS + 4*BP_PORT(bp), + "Timers NUM_SCANS usage counter timed out", + poll_cnt)) + return 1; + + /* Wait DMAE PF usage counter to zero */ + if (bnx2x_flr_clnup_poll_hw_counter(bp, + dmae_reg_go_c[INIT_DMAE_C(bp)], + "DMAE dommand register timed out", + poll_cnt)) + return 1; + + return 0; +} + +static void bnx2x_hw_enable_status(struct bnx2x *bp) +{ + u32 val; + + val = REG_RD(bp, CFC_REG_WEAK_ENABLE_PF); + DP(BNX2X_MSG_SP, "CFC_REG_WEAK_ENABLE_PF is 0x%x\n", val); + + val = REG_RD(bp, PBF_REG_DISABLE_PF); + DP(BNX2X_MSG_SP, "PBF_REG_DISABLE_PF is 0x%x\n", val); + + val = REG_RD(bp, IGU_REG_PCI_PF_MSI_EN); + DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSI_EN is 0x%x\n", val); + + val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_EN); + DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_EN is 0x%x\n", val); + + val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_FUNC_MASK); + DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_FUNC_MASK is 0x%x\n", val); + + val = REG_RD(bp, PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR); + DP(BNX2X_MSG_SP, "PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR is 0x%x\n", val); + + val = REG_RD(bp, PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR); + DP(BNX2X_MSG_SP, "PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR is 0x%x\n", val); + + val = REG_RD(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER); + DP(BNX2X_MSG_SP, "PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER is 0x%x\n", + val); +} + +static int bnx2x_pf_flr_clnup(struct bnx2x *bp) +{ + u32 poll_cnt = bnx2x_flr_clnup_poll_count(bp); + + DP(BNX2X_MSG_SP, "Cleanup after FLR PF[%d]\n", BP_ABS_FUNC(bp)); + + /* Re-enable PF target read access */ + REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); + + /* Poll HW usage counters */ + if (bnx2x_poll_hw_usage_counters(bp, poll_cnt)) + return -EBUSY; + + /* Zero the igu 'trailing edge' and 'leading edge' */ + + /* Send the FW cleanup command */ + if (bnx2x_send_final_clnup(bp, (u8)BP_FUNC(bp), poll_cnt)) + return -EBUSY; + + /* ATC cleanup */ + + /* Verify TX hw is flushed */ + bnx2x_tx_hw_flushed(bp, poll_cnt); + + /* Wait 100ms (not adjusted according to platform) */ + msleep(100); + + /* Verify no pending pci transactions */ + if (bnx2x_is_pcie_pending(bp->pdev)) + BNX2X_ERR("PCIE Transactions still pending\n"); + + /* Debug */ + bnx2x_hw_enable_status(bp); + + /* + * Master enable - Due to WB DMAE writes performed before this + * register is re-initialized as part of the regular function init + */ + REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1); + + return 0; +} + static void bnx2x_hc_int_enable(struct bnx2x *bp) { int port = BP_PORT(bp); @@ -1188,52 +1607,85 @@ static bool bnx2x_trylock_hw_lock(struct bnx2x *bp, u32 resource) } #ifdef BCM_CNIC -static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid); +static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err); #endif -void bnx2x_sp_event(struct bnx2x_fastpath *fp, - union eth_rx_cqe *rr_cqe) +void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) { struct bnx2x *bp = fp->bp; int cid = SW_CID(rr_cqe->ramrod_cqe.conn_and_cmd_data); int command = CQE_CMD(rr_cqe->ramrod_cqe.conn_and_cmd_data); + enum bnx2x_queue_cmd drv_cmd = BNX2X_Q_CMD_MAX; + struct bnx2x_queue_sp_obj *q_obj = &fp->q_obj; DP(BNX2X_MSG_SP, "fp %d cid %d got ramrod #%d state is %x type is %d\n", fp->index, cid, command, bp->state, rr_cqe->ramrod_cqe.ramrod_type); - switch (command | fp->state) { - case (RAMROD_CMD_ID_ETH_CLIENT_SETUP | BNX2X_FP_STATE_OPENING): + switch (command) { + case (RAMROD_CMD_ID_ETH_CLIENT_UPDATE): + DP(NETIF_MSG_IFUP, "got UPDATE ramrod. CID %d\n", cid); + drv_cmd = BNX2X_Q_CMD_UPDATE; + break; + case (RAMROD_CMD_ID_ETH_CLIENT_SETUP): DP(NETIF_MSG_IFUP, "got MULTI[%d] setup ramrod\n", cid); - fp->state = BNX2X_FP_STATE_OPEN; + drv_cmd = BNX2X_Q_CMD_SETUP; break; - case (RAMROD_CMD_ID_ETH_HALT | BNX2X_FP_STATE_HALTING): + case (RAMROD_CMD_ID_ETH_HALT): DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n", cid); - fp->state = BNX2X_FP_STATE_HALTED; + drv_cmd = BNX2X_Q_CMD_HALT; break; - case (RAMROD_CMD_ID_ETH_TERMINATE | BNX2X_FP_STATE_TERMINATING): + case (RAMROD_CMD_ID_ETH_TERMINATE): DP(NETIF_MSG_IFDOWN, "got MULTI[%d] teminate ramrod\n", cid); - fp->state = BNX2X_FP_STATE_TERMINATED; + drv_cmd = BNX2X_Q_CMD_TERMINATE; break; - default: - BNX2X_ERR("unexpected MC reply (%d) " - "fp[%d] state is %x\n", - command, fp->index, fp->state); + case (RAMROD_CMD_ID_ETH_EMPTY): + DP(NETIF_MSG_IFDOWN, "got MULTI[%d] empty ramrod\n", cid); + drv_cmd = BNX2X_Q_CMD_EMPTY; break; + + default: + BNX2X_ERR("unexpected MC reply (%d) on fp[%d]\n", + command, fp->index); + return; } + if ((drv_cmd != BNX2X_Q_CMD_MAX) && + q_obj->complete_cmd(bp, q_obj, drv_cmd)) + /* q_obj->complete_cmd() failure means that this was + * an unexpected completion. + * + * In this case we don't want to increase the bp->spq_left + * because apparently we haven't sent this command the first + * place. + */ +#ifdef BNX2X_STOP_ON_ERROR + bnx2x_panic(); +#else + return; +#endif + smp_mb__before_atomic_inc(); atomic_inc(&bp->cq_spq_left); - /* push the change in fp->state and towards the memory */ - smp_wmb(); + /* push the change in bp->spq_left and towards the memory */ + smp_mb__after_atomic_inc(); return; } +void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp, + u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod) +{ + u32 start = BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset; + + bnx2x_update_rx_prod_gen(bp, fp, bd_prod, rx_comp_prod, rx_sge_prod, + start); +} + irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) { struct bnx2x *bp = netdev_priv(dev_instance); @@ -1258,7 +1710,7 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) mask = 0x2 << (fp->index + CNIC_CONTEXT_USE); if (status & mask) { - /* Handle Rx and Tx according to SB id */ + /* Handle Rx or Tx according to SB id */ prefetch(fp->rx_cons_sb); prefetch(fp->tx_cons_sb); prefetch(&fp->sb_running_index[SM_RX_ID]); @@ -1272,11 +1724,13 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) if (status & (mask | 0x1)) { struct cnic_ops *c_ops = NULL; - rcu_read_lock(); - c_ops = rcu_dereference(bp->cnic_ops); - if (c_ops) - c_ops->cnic_handler(bp->cnic_data, NULL); - rcu_read_unlock(); + if (likely(bp->state == BNX2X_STATE_OPEN)) { + rcu_read_lock(); + c_ops = rcu_dereference(bp->cnic_ops); + if (c_ops) + c_ops->cnic_handler(bp->cnic_data, NULL); + rcu_read_unlock(); + } status &= ~mask; } @@ -1297,9 +1751,6 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) return IRQ_HANDLED; } -/* end of fast path */ - - /* Link */ /* @@ -1939,11 +2390,11 @@ static void bnx2x_link_attn(struct bnx2x *bp) pause_enabled); } - if (bp->link_vars.mac_type == MAC_TYPE_BMAC) { + if (bp->link_vars.mac_type != MAC_TYPE_EMAC) { struct host_port_stats *pstats; pstats = bnx2x_sp(bp, port_stats); - /* reset old bmac stats */ + /* reset old mac stats */ memset(&(pstats->mac_stx[0]), 0, sizeof(struct mac_stx)); } @@ -1998,7 +2449,7 @@ static void bnx2x_pmf_update(struct bnx2x *bp) if (bp->common.int_block == INT_BLOCK_HC) { REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val); REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val); - } else if (CHIP_IS_E2(bp)) { + } else if (!CHIP_IS_E1x(bp)) { REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val); REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val); } @@ -2059,45 +2510,89 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param) static u8 stat_counter_valid(struct bnx2x *bp, struct bnx2x_fastpath *fp) { #ifdef BCM_CNIC - if (IS_FCOE_FP(fp) && IS_MF(bp)) + /* Statistics are not supported for CNIC Clients at the moment */ + if (IS_FCOE_FP(fp)) return false; #endif return true; } -static inline u16 bnx2x_get_cl_flags(struct bnx2x *bp, - struct bnx2x_fastpath *fp) +void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p) +{ + if (CHIP_IS_E1x(bp)) { + struct tstorm_eth_function_common_config tcfg = {0}; + + storm_memset_func_cfg(bp, &tcfg, p->func_id); + } + + /* Enable the function in the FW */ + storm_memset_vf_to_pf(bp, p->func_id, p->pf_id); + storm_memset_func_en(bp, p->func_id, 1); + + /* spq */ + if (p->func_flgs & FUNC_FLG_SPQ) { + storm_memset_spq_addr(bp, p->spq_map, p->func_id); + REG_WR(bp, XSEM_REG_FAST_MEMORY + + XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod); + } +} + +static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp, + struct bnx2x_fastpath *fp, + bool leading) { - u16 flags = 0; + unsigned long flags = 0; - /* calculate queue flags */ - flags |= QUEUE_FLG_CACHE_ALIGN; - flags |= QUEUE_FLG_HC; - flags |= IS_MF_SD(bp) ? QUEUE_FLG_OV : 0; + /* PF driver will always initialize the Queue to an ACTIVE state */ + __set_bit(BNX2X_Q_FLG_ACTIVE, &flags); - flags |= QUEUE_FLG_VLAN; - DP(NETIF_MSG_IFUP, "vlan removal enabled\n"); + /* calculate other queue flags */ + if (IS_MF_SD(bp)) + __set_bit(BNX2X_Q_FLG_OV, &flags); + + if (IS_FCOE_FP(fp)) + __set_bit(BNX2X_Q_FLG_FCOE, &flags); if (!fp->disable_tpa) - flags |= QUEUE_FLG_TPA; + __set_bit(BNX2X_Q_FLG_TPA, &flags); + + if (stat_counter_valid(bp, fp)) { + __set_bit(BNX2X_Q_FLG_STATS, &flags); + __set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags); + } + + if (leading) { + __set_bit(BNX2X_Q_FLG_LEADING_RSS, &flags); + __set_bit(BNX2X_Q_FLG_MCAST, &flags); + } - flags = stat_counter_valid(bp, fp) ? - (flags | QUEUE_FLG_STATS) : (flags & ~QUEUE_FLG_STATS); + /* Always set HW VLAN stripping */ + __set_bit(BNX2X_Q_FLG_VLAN, &flags); return flags; } -static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp, +static void bnx2x_pf_q_prep_general(struct bnx2x *bp, + struct bnx2x_fastpath *fp, struct bnx2x_general_setup_params *gen_init) +{ + gen_init->stat_id = bnx2x_stats_id(fp); + gen_init->spcl_id = fp->cl_id; + + /* Always use mini-jumbo MTU for FCoE L2 ring */ + if (IS_FCOE_FP(fp)) + gen_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU; + else + gen_init->mtu = bp->dev->mtu; +} + +static void bnx2x_pf_rx_q_prep(struct bnx2x *bp, struct bnx2x_fastpath *fp, struct rxq_pause_params *pause, - struct bnx2x_rxq_init_params *rxq_init) + struct bnx2x_rxq_setup_params *rxq_init) { - u16 max_sge = 0; + u8 max_sge = 0; u16 sge_sz = 0; u16 tpa_agg_size = 0; - /* calculate queue flags */ - u16 flags = bnx2x_get_cl_flags(bp, fp); - if (!fp->disable_tpa) { pause->sge_th_hi = 250; pause->sge_th_lo = 150; @@ -2118,33 +2613,37 @@ static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp, pause->bd_th_lo = 250; pause->rcq_th_hi = 350; pause->rcq_th_lo = 250; - pause->sge_th_hi = 0; - pause->sge_th_lo = 0; + pause->pri_map = 1; } /* rxq setup */ - rxq_init->flags = flags; - rxq_init->cxt = &bp->context.vcxt[fp->cid].eth; rxq_init->dscr_map = fp->rx_desc_mapping; rxq_init->sge_map = fp->rx_sge_mapping; rxq_init->rcq_map = fp->rx_comp_mapping; rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE; - /* Always use mini-jumbo MTU for FCoE L2 ring */ - if (IS_FCOE_FP(fp)) - rxq_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU; - else - rxq_init->mtu = bp->dev->mtu; + /* This should be a maximum number of data bytes that may be + * placed on the BD (not including paddings). + */ + rxq_init->buf_sz = fp->rx_buf_size - BNX2X_FW_RX_ALIGN - + IP_HEADER_ALIGNMENT_PADDING; - rxq_init->buf_sz = fp->rx_buf_size; rxq_init->cl_qzone_id = fp->cl_qzone_id; - rxq_init->cl_id = fp->cl_id; - rxq_init->spcl_id = fp->cl_id; - rxq_init->stat_id = fp->cl_id; rxq_init->tpa_agg_sz = tpa_agg_size; rxq_init->sge_buf_sz = sge_sz; rxq_init->max_sges_pkt = max_sge; + rxq_init->rss_engine_id = BP_FUNC(bp); + + /* Maximum number or simultaneous TPA aggregation for this Queue. + * + * For PF Clients it should be the maximum avaliable number. + * VF driver(s) may want to define it to a smaller value. + */ + rxq_init->max_tpa_queues = + (CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 : + ETH_MAX_AGGREGATION_QUEUES_E1H_E2); + rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT; rxq_init->fw_sb_id = fp->fw_sb_id; @@ -2152,46 +2651,35 @@ static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp, rxq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS; else rxq_init->sb_cq_index = U_SB_ETH_RX_CQ_INDEX; - - rxq_init->cid = HW_CID(bp, fp->cid); - - rxq_init->hc_rate = bp->rx_ticks ? (1000000 / bp->rx_ticks) : 0; } -static void bnx2x_pf_tx_cl_prep(struct bnx2x *bp, - struct bnx2x_fastpath *fp, struct bnx2x_txq_init_params *txq_init) +static void bnx2x_pf_tx_q_prep(struct bnx2x *bp, + struct bnx2x_fastpath *fp, struct bnx2x_txq_setup_params *txq_init) { - u16 flags = bnx2x_get_cl_flags(bp, fp); - - txq_init->flags = flags; - txq_init->cxt = &bp->context.vcxt[fp->cid].eth; txq_init->dscr_map = fp->tx_desc_mapping; - txq_init->stat_id = fp->cl_id; - txq_init->cid = HW_CID(bp, fp->cid); txq_init->sb_cq_index = C_SB_ETH_TX_CQ_INDEX; txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW; txq_init->fw_sb_id = fp->fw_sb_id; + /* + * set the tss leading client id for TX classfication == + * leading RSS client id + */ + txq_init->tss_leading_cl_id = bnx2x_fp(bp, 0, cl_id); + if (IS_FCOE_FP(fp)) { txq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS; txq_init->traffic_type = LLFC_TRAFFIC_TYPE_FCOE; } - - txq_init->hc_rate = bp->tx_ticks ? (1000000 / bp->tx_ticks) : 0; } static void bnx2x_pf_init(struct bnx2x *bp) { struct bnx2x_func_init_params func_init = {0}; - struct bnx2x_rss_params rss = {0}; struct event_ring_data eq_data = { {0} }; u16 flags; - /* pf specific setups */ - if (!CHIP_IS_E1(bp)) - storm_memset_ov(bp, bp->mf_ov, BP_FUNC(bp)); - - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { /* reset IGU PF statistics: MSIX + ATTN */ /* PF */ REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT + @@ -2209,27 +2697,14 @@ static void bnx2x_pf_init(struct bnx2x *bp) /* function setup flags */ flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ); - if (CHIP_IS_E1x(bp)) - flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0; - else - flags |= FUNC_FLG_TPA; - - /* function setup */ - - /** - * Although RSS is meaningless when there is a single HW queue we - * still need it enabled in order to have HW Rx hash generated. + /* This flag is relevant for E1x only. + * E2 doesn't have a TPA configuration in a function level. */ - rss.cap = (RSS_IPV4_CAP | RSS_IPV4_TCP_CAP | - RSS_IPV6_CAP | RSS_IPV6_TCP_CAP); - rss.mode = bp->multi_mode; - rss.result_mask = MULTI_MASK; - func_init.rss = &rss; + flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0; func_init.func_flgs = flags; func_init.pf_id = BP_FUNC(bp); func_init.func_id = BP_FUNC(bp); - func_init.fw_stat_map = bnx2x_sp_mapping(bp, fw_stats); func_init.spq_map = bp->spq_mapping; func_init.spq_prod = bp->spq_prod_idx; @@ -2238,11 +2713,11 @@ static void bnx2x_pf_init(struct bnx2x *bp) memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port)); /* - Congestion management values depend on the link rate - There is no active link so initial link rate is set to 10 Gbps. - When the link comes up The congestion management values are - re-calculated according to the actual link rate. - */ + * Congestion management values depend on the link rate + * There is no active link so initial link rate is set to 10 Gbps. + * When the link comes up The congestion management values are + * re-calculated according to the actual link rate. + */ bp->link_vars.line_speed = SPEED_10000; bnx2x_cmng_fns_init(bp, true, bnx2x_get_cmng_fns_mode(bp)); @@ -2250,10 +2725,6 @@ static void bnx2x_pf_init(struct bnx2x *bp) if (bp->port.pmf) storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp)); - /* no rx until link is up */ - bp->rx_mode = BNX2X_RX_MODE_NONE; - bnx2x_set_storm_rx_mode(bp); - /* init Event Queue */ eq_data.base_addr.hi = U64_HI(bp->eq_mapping); eq_data.base_addr.lo = U64_LO(bp->eq_mapping); @@ -2268,11 +2739,9 @@ static void bnx2x_e1h_disable(struct bnx2x *bp) { int port = BP_PORT(bp); - netif_tx_disable(bp->dev); + bnx2x_tx_disable(bp); REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); - - netif_carrier_off(bp->dev); } static void bnx2x_e1h_enable(struct bnx2x *bp) @@ -2375,12 +2844,47 @@ static inline void bnx2x_sp_prod_update(struct bnx2x *bp) mmiowb(); } -/* the slow path queue is odd since completions arrive on the fastpath ring */ +/** + * bnx2x_is_contextless_ramrod - check if the current command ends on EQ + * + * @cmd: command to check + * @cmd_type: command type + */ +static inline bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type) +{ + if ((cmd_type == NONE_CONNECTION_TYPE) || + (cmd == RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES) || + (cmd == RAMROD_CMD_ID_ETH_FILTER_RULES) || + (cmd == RAMROD_CMD_ID_ETH_MULTICAST_RULES) || + (cmd == RAMROD_CMD_ID_ETH_SET_MAC) || + (cmd == RAMROD_CMD_ID_ETH_RSS_UPDATE)) + return true; + else + return false; + +} + + +/** + * bnx2x_sp_post - place a single command on an SP ring + * + * @bp: driver handle + * @command: command to place (e.g. SETUP, FILTER_RULES, etc.) + * @cid: SW CID the command is related to + * @data_hi: command private data address (high 32 bits) + * @data_lo: command private data address (low 32 bits) + * @cmd_type: command type (e.g. NONE, ETH) + * + * SP data is handled as if it's always an address pair, thus data fields are + * not swapped to little endian in upper functions. Instead this function swaps + * data as if it's two u32 fields. + */ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, - u32 data_hi, u32 data_lo, int common) + u32 data_hi, u32 data_lo, int cmd_type) { struct eth_spe *spe; u16 type; + bool common = bnx2x_is_contextless_ramrod(command, cmd_type); #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) @@ -2410,17 +2914,7 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, cpu_to_le32((command << SPE_HDR_CMD_ID_SHIFT) | HW_CID(bp, cid)); - if (common) - /* Common ramrods: - * FUNC_START, FUNC_STOP, CFC_DEL, STATS, SET_MAC - * TRAFFIC_STOP, TRAFFIC_START - */ - type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT) - & SPE_HDR_CONN_TYPE; - else - /* ETH ramrods: SETUP, HALT */ - type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT) - & SPE_HDR_CONN_TYPE; + type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE; type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) & SPE_HDR_FUNCTION_ID); @@ -2432,7 +2926,8 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, /* stats ramrod has it's own slot on the spq */ if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY) { - /* It's ok if the actual decrement is issued towards the memory + /* + * It's ok if the actual decrement is issued towards the memory * somewhere between the spin_lock and spin_unlock. Thus no * more explict memory barrier is needed. */ @@ -2728,13 +3223,13 @@ static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn) } if (attn & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) { - val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0); - BNX2X_ERR("PXP hw attention 0x%x\n", val); + BNX2X_ERR("PXP hw attention-0 0x%x\n", val); /* RQ_USDMDP_FIFO_OVERFLOW */ if (val & 0x18000) BNX2X_ERR("FATAL error from PXP\n"); - if (CHIP_IS_E2(bp)) { + + if (!CHIP_IS_E1x(bp)) { val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_1); BNX2X_ERR("PXP hw attention-1 0x%x\n", val); } @@ -3224,7 +3719,7 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) attn.sig[1] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port*4); attn.sig[2] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port*4); attn.sig[3] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port*4); - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) attn.sig[4] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 + port*4); else @@ -3320,6 +3815,15 @@ static void bnx2x_attn_int(struct bnx2x *bp) bnx2x_attn_int_deasserted(bp, deasserted); } +void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment, + u16 index, u8 op, u8 update) +{ + u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8; + + bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update, + igu_addr); +} + static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod) { /* No memory barriers */ @@ -3331,6 +3835,8 @@ static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod) static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid, union event_ring_elem *elem) { + u8 err = elem->message.error; + if (!bp->cnic_eth_dev.starting_cid || (cid < bp->cnic_eth_dev.starting_cid && cid != bp->cnic_eth_dev.iscsi_l2_cid)) @@ -3338,16 +3844,122 @@ static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid, DP(BNX2X_MSG_SP, "got delete ramrod for CNIC CID %d\n", cid); - if (unlikely(elem->message.data.cfc_del_event.error)) { + if (unlikely(err)) { + BNX2X_ERR("got delete ramrod for CNIC CID %d with error!\n", cid); bnx2x_panic_dump(bp); } - bnx2x_cnic_cfc_comp(bp, cid); + bnx2x_cnic_cfc_comp(bp, cid, err); return 0; } #endif +static inline void bnx2x_handle_mcast_eqe(struct bnx2x *bp) +{ + struct bnx2x_mcast_ramrod_params rparam; + int rc; + + memset(&rparam, 0, sizeof(rparam)); + + rparam.mcast_obj = &bp->mcast_obj; + + netif_addr_lock_bh(bp->dev); + + /* Clear pending state for the last command */ + bp->mcast_obj.raw.clear_pending(&bp->mcast_obj.raw); + + /* If there are pending mcast commands - send them */ + if (bp->mcast_obj.check_pending(&bp->mcast_obj)) { + rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT); + if (rc < 0) + BNX2X_ERR("Failed to send pending mcast commands: %d\n", + rc); + } + + netif_addr_unlock_bh(bp->dev); +} + +static inline void bnx2x_handle_classification_eqe(struct bnx2x *bp, + union event_ring_elem *elem) +{ + unsigned long ramrod_flags = 0; + int rc = 0; + u32 cid = elem->message.data.eth_event.echo & BNX2X_SWCID_MASK; + struct bnx2x_vlan_mac_obj *vlan_mac_obj; + + /* Always push next commands out, don't wait here */ + __set_bit(RAMROD_CONT, &ramrod_flags); + + switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) { + case BNX2X_FILTER_MAC_PENDING: +#ifdef BCM_CNIC + if (cid == BNX2X_ISCSI_ETH_CID) + vlan_mac_obj = &bp->iscsi_l2_mac_obj; + else +#endif + vlan_mac_obj = &bp->fp[cid].mac_obj; + + break; + vlan_mac_obj = &bp->fp[cid].mac_obj; + + case BNX2X_FILTER_MCAST_PENDING: + /* This is only relevant for 57710 where multicast MACs are + * configured as unicast MACs using the same ramrod. + */ + bnx2x_handle_mcast_eqe(bp); + return; + default: + BNX2X_ERR("Unsupported classification command: %d\n", + elem->message.data.eth_event.echo); + return; + } + + rc = vlan_mac_obj->complete(bp, vlan_mac_obj, elem, &ramrod_flags); + + if (rc < 0) + BNX2X_ERR("Failed to schedule new commands: %d\n", rc); + else if (rc > 0) + DP(BNX2X_MSG_SP, "Scheduled next pending commands...\n"); + +} + +#ifdef BCM_CNIC +static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start); +#endif + +static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp) +{ + netif_addr_lock_bh(bp->dev); + + clear_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state); + + /* Send rx_mode command again if was requested */ + if (test_and_clear_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state)) + bnx2x_set_storm_rx_mode(bp); +#ifdef BCM_CNIC + else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, + &bp->sp_state)) + bnx2x_set_iscsi_eth_rx_mode(bp, true); + else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, + &bp->sp_state)) + bnx2x_set_iscsi_eth_rx_mode(bp, false); +#endif + + netif_addr_unlock_bh(bp->dev); +} + +static inline struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj( + struct bnx2x *bp, u32 cid) +{ +#ifdef BCM_CNIC + if (cid == BNX2X_FCOE_ETH_CID) + return &bnx2x_fcoe(bp, q_obj); + else +#endif + return &bnx2x_fp(bp, cid, q_obj); +} + static void bnx2x_eq_int(struct bnx2x *bp) { u16 hw_cons, sw_cons, sw_prod; @@ -3355,6 +3967,9 @@ static void bnx2x_eq_int(struct bnx2x *bp) u32 cid; u8 opcode; int spqe_cnt = 0; + struct bnx2x_queue_sp_obj *q_obj; + struct bnx2x_func_sp_obj *f_obj = &bp->func_obj; + struct bnx2x_raw_obj *rss_raw = &bp->rss_conf_obj.raw; hw_cons = le16_to_cpu(*bp->eq_cons_sb); @@ -3389,7 +4004,8 @@ static void bnx2x_eq_int(struct bnx2x *bp) /* handle eq element */ switch (opcode) { case EVENT_RING_OPCODE_STAT_QUERY: - DP(NETIF_MSG_TIMER, "got statistics comp event\n"); + DP(NETIF_MSG_TIMER, "got statistics comp event %d\n", + bp->stats_comp++); /* nothing to do with stats comp */ continue; @@ -3404,12 +4020,13 @@ static void bnx2x_eq_int(struct bnx2x *bp) #ifdef BCM_CNIC if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem)) goto next_spqe; - if (cid == BNX2X_FCOE_ETH_CID) - bnx2x_fcoe(bp, state) = BNX2X_FP_STATE_CLOSED; - else #endif - bnx2x_fp(bp, cid, state) = - BNX2X_FP_STATE_CLOSED; + q_obj = bnx2x_cid_to_q_obj(bp, cid); + + if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL)) + break; + + goto next_spqe; @@ -3417,42 +4034,75 @@ static void bnx2x_eq_int(struct bnx2x *bp) DP(NETIF_MSG_IFUP, "got STOP TRAFFIC\n"); bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED); goto next_spqe; + case EVENT_RING_OPCODE_START_TRAFFIC: DP(NETIF_MSG_IFUP, "got START TRAFFIC\n"); bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED); goto next_spqe; + case EVENT_RING_OPCODE_FUNCTION_START: + DP(NETIF_MSG_IFUP, "got FUNC_START ramrod\n"); + if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_START)) + break; + + goto next_spqe; + + case EVENT_RING_OPCODE_FUNCTION_STOP: + DP(NETIF_MSG_IFDOWN, "got FUNC_STOP ramrod\n"); + if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_STOP)) + break; + + goto next_spqe; } switch (opcode | bp->state) { - case (EVENT_RING_OPCODE_FUNCTION_START | + case (EVENT_RING_OPCODE_RSS_UPDATE_RULES | + BNX2X_STATE_OPEN): + case (EVENT_RING_OPCODE_RSS_UPDATE_RULES | BNX2X_STATE_OPENING_WAIT4_PORT): - DP(NETIF_MSG_IFUP, "got setup ramrod\n"); - bp->state = BNX2X_STATE_FUNC_STARTED; + cid = elem->message.data.eth_event.echo & + BNX2X_SWCID_MASK; + DP(NETIF_MSG_IFUP, "got RSS_UPDATE ramrod. CID %d\n", + cid); + rss_raw->clear_pending(rss_raw); break; - case (EVENT_RING_OPCODE_FUNCTION_STOP | + case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN): + case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG): + case (EVENT_RING_OPCODE_SET_MAC | + BNX2X_STATE_CLOSING_WAIT4_HALT): + case (EVENT_RING_OPCODE_CLASSIFICATION_RULES | + BNX2X_STATE_OPEN): + case (EVENT_RING_OPCODE_CLASSIFICATION_RULES | + BNX2X_STATE_DIAG): + case (EVENT_RING_OPCODE_CLASSIFICATION_RULES | BNX2X_STATE_CLOSING_WAIT4_HALT): - DP(NETIF_MSG_IFDOWN, "got halt ramrod\n"); - bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD; + DP(NETIF_MSG_IFUP, "got (un)set mac ramrod\n"); + bnx2x_handle_classification_eqe(bp, elem); break; - case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN): - case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG): - DP(NETIF_MSG_IFUP, "got set mac ramrod\n"); - if (elem->message.data.set_mac_event.echo) - bp->set_mac_pending = 0; + case (EVENT_RING_OPCODE_MULTICAST_RULES | + BNX2X_STATE_OPEN): + case (EVENT_RING_OPCODE_MULTICAST_RULES | + BNX2X_STATE_DIAG): + case (EVENT_RING_OPCODE_MULTICAST_RULES | + BNX2X_STATE_CLOSING_WAIT4_HALT): + DP(NETIF_MSG_IFUP, "got mcast ramrod\n"); + bnx2x_handle_mcast_eqe(bp); break; - case (EVENT_RING_OPCODE_SET_MAC | + case (EVENT_RING_OPCODE_FILTERS_RULES | + BNX2X_STATE_OPEN): + case (EVENT_RING_OPCODE_FILTERS_RULES | + BNX2X_STATE_DIAG): + case (EVENT_RING_OPCODE_FILTERS_RULES | BNX2X_STATE_CLOSING_WAIT4_HALT): - DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n"); - if (elem->message.data.set_mac_event.echo) - bp->set_mac_pending = 0; + DP(NETIF_MSG_IFUP, "got rx_mode ramrod\n"); + bnx2x_handle_rx_mode_eqe(bp); break; default: /* unknown event log error and continue */ - BNX2X_ERR("Unknown EQ event %d\n", - elem->message.opcode); + BNX2X_ERR("Unknown EQ event %d, bp->state 0x%x\n", + elem->message.opcode, bp->state); } next_spqe: spqe_cnt++; @@ -3544,6 +4194,14 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) /* end of slow path */ + +void bnx2x_drv_pulse(struct bnx2x *bp) +{ + SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb, + bp->fw_drv_pulse_wr_seq); +} + + static void bnx2x_timer(unsigned long data) { struct bnx2x *bp = (struct bnx2x *) data; @@ -3567,7 +4225,7 @@ static void bnx2x_timer(unsigned long data) bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK; /* TBD - add SYSTEM_TIME */ drv_pulse = bp->fw_drv_pulse_wr_seq; - SHMEM_WR(bp, func_mb[mb_idx].drv_pulse_mb, drv_pulse); + bnx2x_drv_pulse(bp); mcp_pulse = (SHMEM_RD(bp, func_mb[mb_idx].mcp_pulse_mb) & MCP_PULSE_SEQ_MASK); @@ -3630,18 +4288,16 @@ static inline void bnx2x_zero_fp_sb(struct bnx2x *bp, int fw_sb_id) struct hc_status_block_data_e1x sb_data_e1x; /* disable the function first */ - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2)); - sb_data_e2.common.p_func.pf_id = HC_FUNCTION_DISABLED; - sb_data_e2.common.p_func.vf_id = HC_FUNCTION_DISABLED; + sb_data_e2.common.state = SB_DISABLED; sb_data_e2.common.p_func.vf_valid = false; sb_data_p = (u32 *)&sb_data_e2; data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32); } else { memset(&sb_data_e1x, 0, sizeof(struct hc_status_block_data_e1x)); - sb_data_e1x.common.p_func.pf_id = HC_FUNCTION_DISABLED; - sb_data_e1x.common.p_func.vf_id = HC_FUNCTION_DISABLED; + sb_data_e1x.common.state = SB_DISABLED; sb_data_e1x.common.p_func.vf_valid = false; sb_data_p = (u32 *)&sb_data_e1x; data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32); @@ -3675,8 +4331,7 @@ static inline void bnx2x_zero_sp_sb(struct bnx2x *bp) struct hc_sp_status_block_data sp_sb_data; memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data)); - sp_sb_data.p_func.pf_id = HC_FUNCTION_DISABLED; - sp_sb_data.p_func.vf_id = HC_FUNCTION_DISABLED; + sp_sb_data.state = SB_DISABLED; sp_sb_data.p_func.vf_valid = false; bnx2x_wr_sp_sb_data(bp, &sp_sb_data); @@ -3719,8 +4374,9 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, bnx2x_zero_fp_sb(bp, fw_sb_id); - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2)); + sb_data_e2.common.state = SB_ENABLED; sb_data_e2.common.p_func.pf_id = BP_FUNC(bp); sb_data_e2.common.p_func.vf_id = vfid; sb_data_e2.common.p_func.vf_valid = vf_valid; @@ -3734,6 +4390,7 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, } else { memset(&sb_data_e1x, 0, sizeof(struct hc_status_block_data_e1x)); + sb_data_e1x.common.state = SB_ENABLED; sb_data_e1x.common.p_func.pf_id = BP_FUNC(bp); sb_data_e1x.common.p_func.vf_id = 0xff; sb_data_e1x.common.p_func.vf_valid = false; @@ -3757,19 +4414,7 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size); } -void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u16 fw_sb_id, - u8 sb_index, u8 disable, u16 usec) -{ - int port = BP_PORT(bp); - u8 ticks = usec / BNX2X_BTR; - - storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks); - - disable = disable ? 1 : (usec ? 0 : 1); - storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable); -} - -static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u16 fw_sb_id, +static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u8 fw_sb_id, u16 tx_usec, u16 rx_usec) { bnx2x_update_coalesce_sb_index(bp, fw_sb_id, U_SB_ETH_RX_CQ_INDEX, @@ -3816,7 +4461,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp) bp->attn_group[index].sig[sindex] = REG_RD(bp, reg_offset + sindex*0x4 + 0x10*index); - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) /* * enable5 is separate from the rest of the registers, * and therefore the address skip is 4 @@ -3834,7 +4479,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp) REG_WR(bp, reg_offset, U64_LO(section)); REG_WR(bp, reg_offset + 4, U64_HI(section)); - } else if (CHIP_IS_E2(bp)) { + } else if (!CHIP_IS_E1x(bp)) { REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_L, U64_LO(section)); REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_H, U64_HI(section)); } @@ -3844,6 +4489,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp) bnx2x_zero_sp_sb(bp); + sp_sb_data.state = SB_ENABLED; sp_sb_data.host_sb_addr.lo = U64_LO(section); sp_sb_data.host_sb_addr.hi = U64_HI(section); sp_sb_data.igu_sb_id = igu_sp_sb_index; @@ -3854,9 +4500,6 @@ static void bnx2x_init_def_sb(struct bnx2x *bp) bnx2x_wr_sp_sb_data(bp, &sp_sb_data); - bp->stats_pending = 0; - bp->set_mac_pending = 0; - bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0); } @@ -3902,34 +4545,129 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp) min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1); } -static void bnx2x_init_ind_table(struct bnx2x *bp) + +/* called with netif_addr_lock_bh() */ +void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id, + unsigned long rx_mode_flags, + unsigned long rx_accept_flags, + unsigned long tx_accept_flags, + unsigned long ramrod_flags) { - int i; + struct bnx2x_rx_mode_ramrod_params ramrod_param; + int rc; + + memset(&ramrod_param, 0, sizeof(ramrod_param)); - for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++) - bp->rx_indir_table[i] = i % BNX2X_NUM_ETH_QUEUES(bp); + /* Prepare ramrod parameters */ + ramrod_param.cid = 0; + ramrod_param.cl_id = cl_id; + ramrod_param.rx_mode_obj = &bp->rx_mode_obj; + ramrod_param.func_id = BP_FUNC(bp); - bnx2x_push_indir_table(bp); + ramrod_param.pstate = &bp->sp_state; + ramrod_param.state = BNX2X_FILTER_RX_MODE_PENDING; + + ramrod_param.rdata = bnx2x_sp(bp, rx_mode_rdata); + ramrod_param.rdata_mapping = bnx2x_sp_mapping(bp, rx_mode_rdata); + + set_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state); + + ramrod_param.ramrod_flags = ramrod_flags; + ramrod_param.rx_mode_flags = rx_mode_flags; + + ramrod_param.rx_accept_flags = rx_accept_flags; + ramrod_param.tx_accept_flags = tx_accept_flags; + + rc = bnx2x_config_rx_mode(bp, &ramrod_param); + if (rc < 0) { + BNX2X_ERR("Set rx_mode %d failed\n", bp->rx_mode); + return; + } } -static void bnx2x_init_internal_common(struct bnx2x *bp) +/* called with netif_addr_lock_bh() */ +void bnx2x_set_storm_rx_mode(struct bnx2x *bp) { - int i; + unsigned long rx_mode_flags = 0, ramrod_flags = 0; + unsigned long rx_accept_flags = 0, tx_accept_flags = 0; - if (!CHIP_IS_E1(bp)) { +#ifdef BCM_CNIC + if (!NO_FCOE(bp)) + + /* Configure rx_mode of FCoE Queue */ + __set_bit(BNX2X_RX_MODE_FCOE_ETH, &rx_mode_flags); +#endif + + switch (bp->rx_mode) { + case BNX2X_RX_MODE_NONE: + /* + * 'drop all' supersedes any accept flags that may have been + * passed to the function. + */ + break; + case BNX2X_RX_MODE_NORMAL: + __set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags); + __set_bit(BNX2X_ACCEPT_MULTICAST, &rx_accept_flags); + __set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags); + + /* internal switching mode */ + __set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags); + __set_bit(BNX2X_ACCEPT_MULTICAST, &tx_accept_flags); + __set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags); + + break; + case BNX2X_RX_MODE_ALLMULTI: + __set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags); + __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags); + __set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags); + + /* internal switching mode */ + __set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags); + __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags); + __set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags); + + break; + case BNX2X_RX_MODE_PROMISC: + /* According to deffinition of SI mode, iface in promisc mode + * should receive matched and unmatched (in resolution of port) + * unicast packets. + */ + __set_bit(BNX2X_ACCEPT_UNMATCHED, &rx_accept_flags); + __set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags); + __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags); + __set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags); + + /* internal switching mode */ + __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags); + __set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags); - /* xstorm needs to know whether to add ovlan to packets or not, - * in switch-independent we'll write 0 to here... */ - REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET, - bp->mf_mode); - REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_MODE_OFFSET, - bp->mf_mode); - REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNCTION_MODE_OFFSET, - bp->mf_mode); - REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNCTION_MODE_OFFSET, - bp->mf_mode); + if (IS_MF_SI(bp)) + __set_bit(BNX2X_ACCEPT_ALL_UNICAST, &tx_accept_flags); + else + __set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags); + + break; + default: + BNX2X_ERR("Unknown rx_mode: %d\n", bp->rx_mode); + return; + } + + if (bp->rx_mode != BNX2X_RX_MODE_NONE) { + __set_bit(BNX2X_ACCEPT_ANY_VLAN, &rx_accept_flags); + __set_bit(BNX2X_ACCEPT_ANY_VLAN, &tx_accept_flags); } + __set_bit(RAMROD_RX, &ramrod_flags); + __set_bit(RAMROD_TX, &ramrod_flags); + + bnx2x_set_q_rx_mode(bp, bp->fp->cl_id, rx_mode_flags, rx_accept_flags, + tx_accept_flags, ramrod_flags); +} + +static void bnx2x_init_internal_common(struct bnx2x *bp) +{ + int i; + if (IS_MF_SI(bp)) /* * In switch independent mode, the TSTORM needs to accept @@ -3938,25 +4676,22 @@ static void bnx2x_init_internal_common(struct bnx2x *bp) */ REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 2); + else if (!CHIP_IS_E1(bp)) /* 57710 doesn't support MF */ + REG_WR8(bp, BAR_TSTRORM_INTMEM + + TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 0); /* Zero this manually as its initialization is currently missing in the initTool */ for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++) REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_AGG_DATA_OFFSET + i * 4, 0); - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_IGU_MODE_OFFSET, CHIP_INT_MODE_IS_BC(bp) ? HC_IGU_BC_MODE : HC_IGU_NBC_MODE); } } -static void bnx2x_init_internal_port(struct bnx2x *bp) -{ - /* port */ - bnx2x_dcb_init_intmem_pfc(bp); -} - static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code) { switch (load_code) { @@ -3966,7 +4701,7 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code) /* no break */ case FW_MSG_CODE_DRV_LOAD_PORT: - bnx2x_init_internal_port(bp); + /* nothing to do */ /* no break */ case FW_MSG_CODE_DRV_LOAD_FUNCTION: @@ -3980,31 +4715,57 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code) } } -static void bnx2x_init_fp_sb(struct bnx2x *bp, int fp_idx) +static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp) { - struct bnx2x_fastpath *fp = &bp->fp[fp_idx]; + return fp->bp->igu_base_sb + fp->index + CNIC_CONTEXT_USE; +} + +static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp) +{ + return fp->bp->base_fw_ndsb + fp->index + CNIC_CONTEXT_USE; +} + +static inline u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp) +{ + if (CHIP_IS_E1x(fp->bp)) + return BP_L_ID(fp->bp) + fp->index; + else /* We want Client ID to be the same as IGU SB ID for 57712 */ + return bnx2x_fp_igu_sb_id(fp); +} - fp->state = BNX2X_FP_STATE_CLOSED; +static void bnx2x_init_fp(struct bnx2x *bp, int fp_idx) +{ + struct bnx2x_fastpath *fp = &bp->fp[fp_idx]; + unsigned long q_type = 0; fp->cid = fp_idx; - fp->cl_id = BP_L_ID(bp) + fp_idx; - fp->fw_sb_id = bp->base_fw_ndsb + fp->cl_id + CNIC_CONTEXT_USE; - fp->igu_sb_id = bp->igu_base_sb + fp_idx + CNIC_CONTEXT_USE; + fp->cl_id = bnx2x_fp_cl_id(fp); + fp->fw_sb_id = bnx2x_fp_fw_sb_id(fp); + fp->igu_sb_id = bnx2x_fp_igu_sb_id(fp); /* qZone id equals to FW (per path) client id */ - fp->cl_qzone_id = fp->cl_id + - BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 : - ETH_MAX_RX_CLIENTS_E1H); + fp->cl_qzone_id = bnx2x_fp_qzone_id(fp); + /* init shortcut */ - fp->ustorm_rx_prods_offset = CHIP_IS_E2(bp) ? - USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id) : - USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id); + fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp); /* Setup SB indicies */ fp->rx_cons_sb = BNX2X_RX_SB_INDEX; fp->tx_cons_sb = BNX2X_TX_SB_INDEX; + /* Configure Queue State object */ + __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type); + __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type); + bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, fp->cid, BP_FUNC(bp), + bnx2x_sp(bp, q_rdata), bnx2x_sp_mapping(bp, q_rdata), + q_type); + + /** + * Configure classification DBs: Always enable Tx switching + */ + bnx2x_init_vlan_mac_fp_objs(fp, BNX2X_OBJ_TYPE_RX_TX); + DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) " "cl_id %d fw_sb %d igu_sb %d\n", - fp_idx, bp, fp->status_blk.e1x_sb, fp->cl_id, fp->fw_sb_id, + fp_idx, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id, fp->igu_sb_id); bnx2x_init_sb(bp, fp->status_blk_mapping, BNX2X_VF_ID_INVALID, false, fp->fw_sb_id, fp->igu_sb_id); @@ -4017,14 +4778,14 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) int i; for_each_eth_queue(bp, i) - bnx2x_init_fp_sb(bp, i); + bnx2x_init_fp(bp, i); #ifdef BCM_CNIC if (!NO_FCOE(bp)) bnx2x_init_fcoe_fp(bp); bnx2x_init_sb(bp, bp->cnic_sb_mapping, BNX2X_VF_ID_INVALID, false, - CNIC_SB_ID(bp), CNIC_IGU_SB_ID(bp)); + bnx2x_cnic_fw_sb_id(bp), bnx2x_cnic_igu_sb_id(bp)); #endif @@ -4043,7 +4804,6 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) bnx2x_init_eq_ring(bp); bnx2x_init_internal(bp, load_code); bnx2x_pf_init(bp); - bnx2x_init_ind_table(bp); bnx2x_stats_init(bp); /* flush all before enabling interrupts */ @@ -4249,8 +5009,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) msleep(50); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03); msleep(50); - bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON); DP(NETIF_MSG_HW, "part2\n"); @@ -4314,8 +5074,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) msleep(50); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03); msleep(50); - bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON); #ifndef BCM_CNIC /* set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); @@ -4335,7 +5095,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) static void bnx2x_enable_blocks_attention(struct bnx2x *bp) { REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0); - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40); else REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0); @@ -4369,7 +5129,7 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp) if (CHIP_REV_IS_FPGA(bp)) REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000); - else if (CHIP_IS_E2(bp)) + else if (!CHIP_IS_E1x(bp)) REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, (PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF | PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT @@ -4382,7 +5142,11 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp) REG_WR(bp, TSDM_REG_TSDM_INT_MASK_1, 0); REG_WR(bp, TCM_REG_TCM_INT_MASK, 0); /* REG_WR(bp, TSEM_REG_TSEM_INT_MASK_0, 0); */ -/* REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0); */ + + if (!CHIP_IS_E1x(bp)) + /* enable VFC attentions: bits 11 and 12, bits 31:13 reserved */ + REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0x07ff); + REG_WR(bp, CDU_REG_CDU_INT_MASK, 0); REG_WR(bp, DMAE_REG_DMAE_INT_MASK, 0); /* REG_WR(bp, MISC_REG_MISC_INT_MASK, 0); */ @@ -4391,10 +5155,24 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp) static void bnx2x_reset_common(struct bnx2x *bp) { + u32 val = 0x1400; + /* reset_common */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, 0xd3ffff7f); - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403); + + if (CHIP_IS_E3(bp)) { + val |= MISC_REGISTERS_RESET_REG_2_MSTAT0; + val |= MISC_REGISTERS_RESET_REG_2_MSTAT1; + } + + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, val); +} + +static void bnx2x_setup_dmae(struct bnx2x *bp) +{ + bp->dmae_ready = 0; + spin_lock_init(&bp->dmae_lock); } static void bnx2x_init_pxp(struct bnx2x *bp) @@ -4521,22 +5299,48 @@ static void bnx2x_pf_disable(struct bnx2x *bp) REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 0); } -static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) +static inline void bnx2x__common_init_phy(struct bnx2x *bp) +{ + u32 shmem_base[2], shmem2_base[2]; + shmem_base[0] = bp->common.shmem_base; + shmem2_base[0] = bp->common.shmem2_base; + if (!CHIP_IS_E1x(bp)) { + shmem_base[1] = + SHMEM2_RD(bp, other_shmem_base_addr); + shmem2_base[1] = + SHMEM2_RD(bp, other_shmem2_base_addr); + } + bnx2x_acquire_phy_lock(bp); + bnx2x_common_init_phy(bp, shmem_base, shmem2_base, + bp->common.chip_id); + bnx2x_release_phy_lock(bp); +} + +/** + * bnx2x_init_hw_common - initialize the HW at the COMMON phase. + * + * @bp: driver handle + */ +static int bnx2x_init_hw_common(struct bnx2x *bp) { - u32 val, i; + u32 val; DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_ABS_FUNC(bp)); bnx2x_reset_common(bp); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff); - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc); - bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE); - if (!CHIP_IS_E1(bp)) - REG_WR(bp, MISC_REG_E1HMF_MODE, IS_MF(bp)); + val = 0xfffc; + if (CHIP_IS_E3(bp)) { + val |= MISC_REGISTERS_RESET_REG_2_MSTAT0; + val |= MISC_REGISTERS_RESET_REG_2_MSTAT1; + } + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, val); - if (CHIP_IS_E2(bp)) { - u8 fid; + bnx2x_init_block(bp, BLOCK_MISC, PHASE_COMMON); + + if (!CHIP_IS_E1x(bp)) { + u8 abs_func_id; /** * 4-port mode or 2-port mode we need to turn of master-enable @@ -4545,29 +5349,30 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) * for all functions on the given path, this means 0,2,4,6 for * path 0 and 1,3,5,7 for path 1 */ - for (fid = BP_PATH(bp); fid < E2_FUNC_MAX*2; fid += 2) { - if (fid == BP_ABS_FUNC(bp)) { + for (abs_func_id = BP_PATH(bp); + abs_func_id < E2_FUNC_MAX*2; abs_func_id += 2) { + if (abs_func_id == BP_ABS_FUNC(bp)) { REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1); continue; } - bnx2x_pretend_func(bp, fid); + bnx2x_pretend_func(bp, abs_func_id); /* clear pf enable */ bnx2x_pf_disable(bp); bnx2x_pretend_func(bp, BP_ABS_FUNC(bp)); } } - bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_PXP, PHASE_COMMON); if (CHIP_IS_E1(bp)) { /* enable HW interrupt from PXP on USDM overflow bit 16 on INT_MASK_0 */ REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0); } - bnx2x_init_block(bp, PXP2_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_PXP2, PHASE_COMMON); bnx2x_init_pxp(bp); #ifdef __BIG_ENDIAN @@ -4610,7 +5415,69 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) * This needs to be done by the first PF that is loaded in a path * (i.e. common phase) */ - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { +/* In E2 there is a bug in the timers block that can cause function 6 / 7 + * (i.e. vnic3) to start even if it is marked as "scan-off". + * This occurs when a different function (func2,3) is being marked + * as "scan-off". Real-life scenario for example: if a driver is being + * load-unloaded while func6,7 are down. This will cause the timer to access + * the ilt, translate to a logical address and send a request to read/write. + * Since the ilt for the function that is down is not valid, this will cause + * a translation error which is unrecoverable. + * The Workaround is intended to make sure that when this happens nothing fatal + * will occur. The workaround: + * 1. First PF driver which loads on a path will: + * a. After taking the chip out of reset, by using pretend, + * it will write "0" to the following registers of + * the other vnics. + * REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0); + * REG_WR(pdev, CFC_REG_WEAK_ENABLE_PF,0); + * REG_WR(pdev, CFC_REG_STRONG_ENABLE_PF,0); + * And for itself it will write '1' to + * PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER to enable + * dmae-operations (writing to pram for example.) + * note: can be done for only function 6,7 but cleaner this + * way. + * b. Write zero+valid to the entire ILT. + * c. Init the first_timers_ilt_entry, last_timers_ilt_entry of + * VNIC3 (of that port). The range allocated will be the + * entire ILT. This is needed to prevent ILT range error. + * 2. Any PF driver load flow: + * a. ILT update with the physical addresses of the allocated + * logical pages. + * b. Wait 20msec. - note that this timeout is needed to make + * sure there are no requests in one of the PXP internal + * queues with "old" ILT addresses. + * c. PF enable in the PGLC. + * d. Clear the was_error of the PF in the PGLC. (could have + * occured while driver was down) + * e. PF enable in the CFC (WEAK + STRONG) + * f. Timers scan enable + * 3. PF driver unload flow: + * a. Clear the Timers scan_en. + * b. Polling for scan_on=0 for that PF. + * c. Clear the PF enable bit in the PXP. + * d. Clear the PF enable in the CFC (WEAK + STRONG) + * e. Write zero+valid to all ILT entries (The valid bit must + * stay set) + * f. If this is VNIC 3 of a port then also init + * first_timers_ilt_entry to zero and last_timers_ilt_entry + * to the last enrty in the ILT. + * + * Notes: + * Currently the PF error in the PGLC is non recoverable. + * In the future the there will be a recovery routine for this error. + * Currently attention is masked. + * Having an MCP lock on the load/unload process does not guarantee that + * there is no Timer disable during Func6/7 enable. This is because the + * Timers scan is currently being cleared by the MCP on FLR. + * Step 2.d can be done only for PF6/7 and the driver can also check if + * there is error before clearing it. But the flow above is simpler and + * more general. + * All ILT entries are written by zero+valid and not just PF6/7 + * ILT entries since in the future the ILT entries allocation for + * PF-s might be dynamic. + */ struct ilt_client_info ilt_cli; struct bnx2x_ilt ilt; memset(&ilt_cli, 0, sizeof(struct ilt_client_info)); @@ -4624,7 +5491,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) /* Step 1: set zeroes to all ilt page entries with valid bit on * Step 2: set the timers first/last ilt entry to point * to the entire range to prevent ILT range error for 3rd/4th - * vnic (this code assumes existence of the vnic) + * vnic (this code assumes existance of the vnic) * * both steps performed by call to bnx2x_ilt_client_init_op() * with dummy TM client @@ -4645,12 +5512,12 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0); REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0); - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { int factor = CHIP_REV_IS_EMUL(bp) ? 1000 : (CHIP_REV_IS_FPGA(bp) ? 400 : 0); - bnx2x_init_block(bp, PGLUE_B_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_PGLUE_B, PHASE_COMMON); - bnx2x_init_block(bp, ATC_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_ATC, PHASE_COMMON); /* let the HW do it's magic ... */ do { @@ -4664,26 +5531,27 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) } } - bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_DMAE, PHASE_COMMON); /* clean the DMAE memory */ bp->dmae_ready = 1; - bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8); + bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8, 1); + + bnx2x_init_block(bp, BLOCK_TCM, PHASE_COMMON); - bnx2x_init_block(bp, TCM_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, UCM_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, CCM_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, XCM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_UCM, PHASE_COMMON); + + bnx2x_init_block(bp, BLOCK_CCM, PHASE_COMMON); + + bnx2x_init_block(bp, BLOCK_XCM, PHASE_COMMON); bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3); - bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_QM, PHASE_COMMON); - if (CHIP_MODE_IS_4_PORT(bp)) - bnx2x_init_block(bp, QM_4PORT_BLOCK, COMMON_STAGE); /* QM queues pointers table */ bnx2x_qm_init_ptr_table(bp, bp->qm_cid_count, INITOP_SET); @@ -4693,57 +5561,51 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) REG_WR(bp, QM_REG_SOFT_RESET, 0); #ifdef BCM_CNIC - bnx2x_init_block(bp, TIMERS_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON); #endif - bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON); REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT); - - if (!CHIP_REV_IS_SLOW(bp)) { + if (!CHIP_REV_IS_SLOW(bp)) /* enable hw interrupt from doorbell Q */ REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0); - } - bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); - if (CHIP_MODE_IS_4_PORT(bp)) { - REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD, 248); - REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD, 328); - } + bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON); - bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON); REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); -#ifndef BCM_CNIC - /* set NIC mode */ - REG_WR(bp, PRS_REG_NIC_MODE, 1); -#endif + if (!CHIP_IS_E1(bp)) - REG_WR(bp, PRS_REG_E1HOV_MODE, IS_MF_SD(bp)); + REG_WR(bp, PRS_REG_E1HOV_MODE, bp->path_has_ovlan); - if (CHIP_IS_E2(bp)) { - /* Bit-map indicating which L2 hdrs may appear after the - basic Ethernet header */ - int has_ovlan = IS_MF_SD(bp); - REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6)); - REG_WR(bp, PRS_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0)); - } + if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3B0(bp)) + /* Bit-map indicating which L2 hdrs may appear + * after the basic Ethernet header + */ + REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC, + bp->path_has_ovlan ? 7 : 6); - bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, USDM_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, XSDM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_TSDM, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_CSDM, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_USDM, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_XSDM, PHASE_COMMON); - bnx2x_init_fill(bp, TSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp)); - bnx2x_init_fill(bp, USEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp)); - bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp)); - bnx2x_init_fill(bp, XSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp)); + if (!CHIP_IS_E1x(bp)) { + /* reset VFC memories */ + REG_WR(bp, TSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST, + VFC_MEMORIES_RST_REG_CAM_RST | + VFC_MEMORIES_RST_REG_RAM_RST); + REG_WR(bp, XSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST, + VFC_MEMORIES_RST_REG_CAM_RST | + VFC_MEMORIES_RST_REG_RAM_RST); - bnx2x_init_block(bp, TSEM_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, USEM_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE); + msleep(20); + } - if (CHIP_MODE_IS_4_PORT(bp)) - bnx2x_init_block(bp, XSEM_4PORT_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_TSEM, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_USEM, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_CSEM, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_XSEM, PHASE_COMMON); /* sync semi rtc */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, @@ -4751,21 +5613,18 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x80000000); - bnx2x_init_block(bp, UPB_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_UPB, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_XPB, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_PBF, PHASE_COMMON); - if (CHIP_IS_E2(bp)) { - int has_ovlan = IS_MF_SD(bp); - REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6)); - REG_WR(bp, PBF_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0)); - } + if (!CHIP_IS_E1x(bp)) + REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC, + bp->path_has_ovlan ? 7 : 6); REG_WR(bp, SRC_REG_SOFT_RST, 1); - for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4) - REG_WR(bp, i, random32()); - bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_SRC, PHASE_COMMON); + #ifdef BCM_CNIC REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672); REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc); @@ -4786,11 +5645,11 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) "of cdu_context(%ld)\n", (long)sizeof(union cdu_context)); - bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_CDU, PHASE_COMMON); val = (4 << 24) + (0 << 12) + 1024; REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val); - bnx2x_init_block(bp, CFC_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_CFC, PHASE_COMMON); REG_WR(bp, CFC_REG_INIT_REG, 0x7FF); /* enable context validation interrupt from CFC */ REG_WR(bp, CFC_REG_CFC_INT_MASK, 0); @@ -4798,20 +5657,19 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) /* set the thresholds to prevent CFC/CDU race */ REG_WR(bp, CFC_REG_DEBUG0, 0x20020000); - bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_HC, PHASE_COMMON); - if (CHIP_IS_E2(bp) && BP_NOMCP(bp)) + if (!CHIP_IS_E1x(bp) && BP_NOMCP(bp)) REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x36); - bnx2x_init_block(bp, IGU_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_IGU, PHASE_COMMON); + bnx2x_init_block(bp, BLOCK_MISC_AEU, PHASE_COMMON); - bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE); /* Reset PCIE errors for debug */ REG_WR(bp, 0x2814, 0xffffffff); REG_WR(bp, 0x3820, 0xffffffff); - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_CONTROL_5, (PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 | PXPCS_TL_CONTROL_5_ERR_UNSPPORT)); @@ -4825,21 +5683,15 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5)); } - bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE); - - bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, BLOCK_NIG, PHASE_COMMON); if (!CHIP_IS_E1(bp)) { - REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp)); - REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(bp)); - } - if (CHIP_IS_E2(bp)) { - /* Bit-map indicating which L2 hdrs may appear after the - basic Ethernet header */ - REG_WR(bp, NIG_REG_P0_HDRS_AFTER_BASIC, (IS_MF_SD(bp) ? 7 : 6)); + /* in E3 this done in per-port section */ + if (!CHIP_IS_E3(bp)) + REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp)); } + if (CHIP_IS_E1H(bp)) + /* not applicable for E2 (and above ...) */ + REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(bp)); if (CHIP_REV_IS_SLOW(bp)) msleep(200); @@ -4885,123 +5737,133 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) bnx2x_enable_blocks_parity(bp); if (!BP_NOMCP(bp)) { - /* In E2 2-PORT mode, same ext phy is used for the two paths */ - if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) || - CHIP_IS_E1x(bp)) { - u32 shmem_base[2], shmem2_base[2]; - shmem_base[0] = bp->common.shmem_base; - shmem2_base[0] = bp->common.shmem2_base; - if (CHIP_IS_E2(bp)) { - shmem_base[1] = - SHMEM2_RD(bp, other_shmem_base_addr); - shmem2_base[1] = - SHMEM2_RD(bp, other_shmem2_base_addr); - } - bnx2x_acquire_phy_lock(bp); - bnx2x_common_init_phy(bp, shmem_base, shmem2_base, - bp->common.chip_id); - bnx2x_release_phy_lock(bp); - } + if (CHIP_IS_E1x(bp)) + bnx2x__common_init_phy(bp); } else BNX2X_ERR("Bootcode is missing - can not initialize link\n"); return 0; } +/** + * bnx2x_init_hw_common_chip - init HW at the COMMON_CHIP phase. + * + * @bp: driver handle + */ +static int bnx2x_init_hw_common_chip(struct bnx2x *bp) +{ + int rc = bnx2x_init_hw_common(bp); + + if (rc) + return rc; + + /* In E2 2-PORT mode, same ext phy is used for the two paths */ + if (!BP_NOMCP(bp)) + bnx2x__common_init_phy(bp); + + return 0; +} + static int bnx2x_init_hw_port(struct bnx2x *bp) { int port = BP_PORT(bp); - int init_stage = port ? PORT1_STAGE : PORT0_STAGE; + int init_phase = port ? PHASE_PORT1 : PHASE_PORT0; u32 low, high; u32 val; + bnx2x__link_reset(bp); + DP(BNX2X_MSG_MCP, "starting port init port %d\n", port); REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0); - bnx2x_init_block(bp, PXP_BLOCK, init_stage); - bnx2x_init_block(bp, PXP2_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_MISC, init_phase); + bnx2x_init_block(bp, BLOCK_PXP, init_phase); + bnx2x_init_block(bp, BLOCK_PXP2, init_phase); /* Timers bug workaround: disables the pf_master bit in pglue at * common phase, we need to enable it here before any dmae access are * attempted. Therefore we manually added the enable-master to the * port phase (it also happens in the function phase) */ - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1); - bnx2x_init_block(bp, TCM_BLOCK, init_stage); - bnx2x_init_block(bp, UCM_BLOCK, init_stage); - bnx2x_init_block(bp, CCM_BLOCK, init_stage); - bnx2x_init_block(bp, XCM_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_ATC, init_phase); + bnx2x_init_block(bp, BLOCK_DMAE, init_phase); + bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase); + bnx2x_init_block(bp, BLOCK_QM, init_phase); + + bnx2x_init_block(bp, BLOCK_TCM, init_phase); + bnx2x_init_block(bp, BLOCK_UCM, init_phase); + bnx2x_init_block(bp, BLOCK_CCM, init_phase); + bnx2x_init_block(bp, BLOCK_XCM, init_phase); /* QM cid (connection) count */ bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET); #ifdef BCM_CNIC - bnx2x_init_block(bp, TIMERS_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_TM, init_phase); REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20); REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31); #endif - bnx2x_init_block(bp, DQ_BLOCK, init_stage); - - if (CHIP_MODE_IS_4_PORT(bp)) - bnx2x_init_block(bp, QM_4PORT_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_DORQ, init_phase); if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) { - bnx2x_init_block(bp, BRB1_BLOCK, init_stage); - if (CHIP_REV_IS_SLOW(bp) && CHIP_IS_E1(bp)) { - /* no pause for emulation and FPGA */ - low = 0; - high = 513; - } else { - if (IS_MF(bp)) - low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246); - else if (bp->dev->mtu > 4096) { - if (bp->flags & ONE_PORT_FLAG) - low = 160; - else { - val = bp->dev->mtu; - /* (24*1024 + val*4)/256 */ - low = 96 + (val/64) + - ((val % 64) ? 1 : 0); - } - } else - low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160); - high = low + 56; /* 14*1024/256 */ - } + bnx2x_init_block(bp, BLOCK_BRB1, init_phase); + + if (IS_MF(bp)) + low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246); + else if (bp->dev->mtu > 4096) { + if (bp->flags & ONE_PORT_FLAG) + low = 160; + else { + val = bp->dev->mtu; + /* (24*1024 + val*4)/256 */ + low = 96 + (val/64) + + ((val % 64) ? 1 : 0); + } + } else + low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160); + high = low + 56; /* 14*1024/256 */ REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low); REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high); } - if (CHIP_MODE_IS_4_PORT(bp)) { - REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 + port*8, 248); - REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 + port*8, 328); - REG_WR(bp, (BP_PORT(bp) ? BRB1_REG_MAC_GUARANTIED_1 : - BRB1_REG_MAC_GUARANTIED_0), 40); - } + if (CHIP_MODE_IS_4_PORT(bp)) + REG_WR(bp, (BP_PORT(bp) ? + BRB1_REG_MAC_GUARANTIED_1 : + BRB1_REG_MAC_GUARANTIED_0), 40); - bnx2x_init_block(bp, PRS_BLOCK, init_stage); - bnx2x_init_block(bp, TSDM_BLOCK, init_stage); - bnx2x_init_block(bp, CSDM_BLOCK, init_stage); - bnx2x_init_block(bp, USDM_BLOCK, init_stage); - bnx2x_init_block(bp, XSDM_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_PRS, init_phase); + if (CHIP_IS_E3B0(bp)) + /* Ovlan exists only if we are in multi-function + + * switch-dependent mode, in switch-independent there + * is no ovlan headers + */ + REG_WR(bp, BP_PORT(bp) ? + PRS_REG_HDRS_AFTER_BASIC_PORT_1 : + PRS_REG_HDRS_AFTER_BASIC_PORT_0, + (bp->path_has_ovlan ? 7 : 6)); - bnx2x_init_block(bp, TSEM_BLOCK, init_stage); - bnx2x_init_block(bp, USEM_BLOCK, init_stage); - bnx2x_init_block(bp, CSEM_BLOCK, init_stage); - bnx2x_init_block(bp, XSEM_BLOCK, init_stage); - if (CHIP_MODE_IS_4_PORT(bp)) - bnx2x_init_block(bp, XSEM_4PORT_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_TSDM, init_phase); + bnx2x_init_block(bp, BLOCK_CSDM, init_phase); + bnx2x_init_block(bp, BLOCK_USDM, init_phase); + bnx2x_init_block(bp, BLOCK_XSDM, init_phase); + + bnx2x_init_block(bp, BLOCK_TSEM, init_phase); + bnx2x_init_block(bp, BLOCK_USEM, init_phase); + bnx2x_init_block(bp, BLOCK_CSEM, init_phase); + bnx2x_init_block(bp, BLOCK_XSEM, init_phase); - bnx2x_init_block(bp, UPB_BLOCK, init_stage); - bnx2x_init_block(bp, XPB_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_UPB, init_phase); + bnx2x_init_block(bp, BLOCK_XPB, init_phase); - bnx2x_init_block(bp, PBF_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_PBF, init_phase); - if (!CHIP_IS_E2(bp)) { + if (CHIP_IS_E1x(bp)) { /* configure PBF to work without PAUSE mtu 9000 */ REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0); @@ -5017,20 +5879,20 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) } #ifdef BCM_CNIC - bnx2x_init_block(bp, SRCH_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_SRC, init_phase); #endif - bnx2x_init_block(bp, CDU_BLOCK, init_stage); - bnx2x_init_block(bp, CFC_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_CDU, init_phase); + bnx2x_init_block(bp, BLOCK_CFC, init_phase); if (CHIP_IS_E1(bp)) { REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0); REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0); } - bnx2x_init_block(bp, HC_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_HC, init_phase); - bnx2x_init_block(bp, IGU_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_IGU, init_phase); - bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase); /* init aeu_mask_attn_func_0/1: * - SF mode: bits 3-7 are masked. only bits 0-2 are in use * - MF mode: bit 3 is masked. bits 0-2 are in use as in SF @@ -5040,22 +5902,31 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) val |= CHIP_IS_E1(bp) ? 0 : 0x10; REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, val); - bnx2x_init_block(bp, PXPCS_BLOCK, init_stage); - bnx2x_init_block(bp, EMAC0_BLOCK, init_stage); - bnx2x_init_block(bp, EMAC1_BLOCK, init_stage); - bnx2x_init_block(bp, DBU_BLOCK, init_stage); - bnx2x_init_block(bp, DBG_BLOCK, init_stage); + bnx2x_init_block(bp, BLOCK_NIG, init_phase); - bnx2x_init_block(bp, NIG_BLOCK, init_stage); + if (!CHIP_IS_E1x(bp)) { + /* Bit-map indicating which L2 hdrs may appear after the + * basic Ethernet header + */ + REG_WR(bp, BP_PORT(bp) ? + NIG_REG_P1_HDRS_AFTER_BASIC : + NIG_REG_P0_HDRS_AFTER_BASIC, + IS_MF_SD(bp) ? 7 : 6); - REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1); + if (CHIP_IS_E3(bp)) + REG_WR(bp, BP_PORT(bp) ? + NIG_REG_LLH1_MF_MODE : + NIG_REG_LLH_MF_MODE, IS_MF(bp)); + } + if (!CHIP_IS_E3(bp)) + REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1); if (!CHIP_IS_E1(bp)) { /* 0x2 disable mf_ov, 0x1 enable */ REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4, (IS_MF_SD(bp) ? 0x1 : 0x2)); - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { val = 0; switch (bp->mf_mode) { case MULTI_FUNCTION_SD: @@ -5076,17 +5947,16 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) } } - bnx2x_init_block(bp, MCP_BLOCK, init_stage); - bnx2x_init_block(bp, DMAE_BLOCK, init_stage); - if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base, - bp->common.shmem2_base, port)) { + + /* If SPIO5 is set to generate interrupts, enable it for this port */ + val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN); + if (val & (1 << MISC_REGISTERS_SPIO_5)) { u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); val = REG_RD(bp, reg_addr); val |= AEU_INPUTS_ATTN_BITS_SPIO5; REG_WR(bp, reg_addr, val); } - bnx2x__link_reset(bp); return 0; } @@ -5105,7 +5975,7 @@ static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr) static inline void bnx2x_igu_clear_sb(struct bnx2x *bp, u8 idu_sb_id) { - bnx2x_igu_clear_sb_gen(bp, idu_sb_id, true /*PF*/); + bnx2x_igu_clear_sb_gen(bp, BP_FUNC(bp), idu_sb_id, true /*PF*/); } static inline void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func) @@ -5119,6 +5989,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) { int port = BP_PORT(bp); int func = BP_FUNC(bp); + int init_phase = PHASE_PF0 + func; struct bnx2x_ilt *ilt = BP_ILT(bp); u16 cdu_ilt_start; u32 addr, val; @@ -5127,6 +5998,10 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) DP(BNX2X_MSG_MCP, "starting func init func %d\n", func); + /* FLR cleanup - hmmm */ + if (!CHIP_IS_E1x(bp)) + bnx2x_pf_flr_clnup(bp); + /* set MSI reconfigure capability */ if (bp->common.int_block == INT_BLOCK_HC) { addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0); @@ -5135,6 +6010,9 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) REG_WR(bp, addr, val); } + bnx2x_init_block(bp, BLOCK_PXP, init_phase); + bnx2x_init_block(bp, BLOCK_PXP2, init_phase); + ilt = BP_ILT(bp); cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start; @@ -5160,7 +6038,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) REG_WR(bp, PRS_REG_NIC_MODE, 1); #endif /* BCM_CNIC */ - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { u32 pf_conf = IGU_PF_CONF_FUNC_EN; /* Turn on a single ISR mode in IGU if driver is going to use @@ -5187,58 +6065,55 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) bp->dmae_ready = 1; - bnx2x_init_block(bp, PGLUE_B_BLOCK, FUNC0_STAGE + func); + bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase); - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, func); - bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, TCM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, UCM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, CCM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, XCM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, TSEM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, USEM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, CSEM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, XSEM_BLOCK, FUNC0_STAGE + func); - - if (CHIP_IS_E2(bp)) { - REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_PATH_ID_OFFSET, - BP_PATH(bp)); - REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_PATH_ID_OFFSET, - BP_PATH(bp)); - } - - if (CHIP_MODE_IS_4_PORT(bp)) - bnx2x_init_block(bp, XSEM_4PORT_BLOCK, FUNC0_STAGE + func); - - if (CHIP_IS_E2(bp)) + bnx2x_init_block(bp, BLOCK_ATC, init_phase); + bnx2x_init_block(bp, BLOCK_DMAE, init_phase); + bnx2x_init_block(bp, BLOCK_NIG, init_phase); + bnx2x_init_block(bp, BLOCK_SRC, init_phase); + bnx2x_init_block(bp, BLOCK_MISC, init_phase); + bnx2x_init_block(bp, BLOCK_TCM, init_phase); + bnx2x_init_block(bp, BLOCK_UCM, init_phase); + bnx2x_init_block(bp, BLOCK_CCM, init_phase); + bnx2x_init_block(bp, BLOCK_XCM, init_phase); + bnx2x_init_block(bp, BLOCK_TSEM, init_phase); + bnx2x_init_block(bp, BLOCK_USEM, init_phase); + bnx2x_init_block(bp, BLOCK_CSEM, init_phase); + bnx2x_init_block(bp, BLOCK_XSEM, init_phase); + + if (!CHIP_IS_E1x(bp)) REG_WR(bp, QM_REG_PF_EN, 1); - bnx2x_init_block(bp, QM_BLOCK, FUNC0_STAGE + func); - - if (CHIP_MODE_IS_4_PORT(bp)) - bnx2x_init_block(bp, QM_4PORT_BLOCK, FUNC0_STAGE + func); - - bnx2x_init_block(bp, TIMERS_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, DQ_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, BRB1_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, PRS_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, TSDM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, CSDM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, USDM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, XSDM_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, UPB_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, XPB_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, PBF_BLOCK, FUNC0_STAGE + func); - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) { + REG_WR(bp, TSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func); + REG_WR(bp, USEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func); + REG_WR(bp, CSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func); + REG_WR(bp, XSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func); + } + bnx2x_init_block(bp, BLOCK_QM, init_phase); + + bnx2x_init_block(bp, BLOCK_TM, init_phase); + bnx2x_init_block(bp, BLOCK_DORQ, init_phase); + bnx2x_init_block(bp, BLOCK_BRB1, init_phase); + bnx2x_init_block(bp, BLOCK_PRS, init_phase); + bnx2x_init_block(bp, BLOCK_TSDM, init_phase); + bnx2x_init_block(bp, BLOCK_CSDM, init_phase); + bnx2x_init_block(bp, BLOCK_USDM, init_phase); + bnx2x_init_block(bp, BLOCK_XSDM, init_phase); + bnx2x_init_block(bp, BLOCK_UPB, init_phase); + bnx2x_init_block(bp, BLOCK_XPB, init_phase); + bnx2x_init_block(bp, BLOCK_PBF, init_phase); + if (!CHIP_IS_E1x(bp)) REG_WR(bp, PBF_REG_DISABLE_PF, 0); - bnx2x_init_block(bp, CDU_BLOCK, FUNC0_STAGE + func); + bnx2x_init_block(bp, BLOCK_CDU, init_phase); - bnx2x_init_block(bp, CFC_BLOCK, FUNC0_STAGE + func); + bnx2x_init_block(bp, BLOCK_CFC, init_phase); - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 1); if (IS_MF(bp)) { @@ -5246,7 +6121,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->mf_ov); } - bnx2x_init_block(bp, MISC_AEU_BLOCK, FUNC0_STAGE + func); + bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase); /* HC init per function */ if (bp->common.int_block == INT_BLOCK_HC) { @@ -5256,21 +6131,21 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0); REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0); } - bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func); + bnx2x_init_block(bp, BLOCK_HC, init_phase); } else { int num_segs, sb_idx, prod_offset; REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0); - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0); REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0); } - bnx2x_init_block(bp, IGU_BLOCK, FUNC0_STAGE + func); + bnx2x_init_block(bp, BLOCK_IGU, init_phase); - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { int dsb_idx = 0; /** * Producer memory: @@ -5365,13 +6240,6 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) REG_WR(bp, 0x2114, 0xffffffff); REG_WR(bp, 0x2120, 0xffffffff); - bnx2x_init_block(bp, EMAC0_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, EMAC1_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, DBU_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, DBG_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, MCP_BLOCK, FUNC0_STAGE + func); - bnx2x_init_block(bp, DMAE_BLOCK, FUNC0_STAGE + func); - if (CHIP_IS_E1x(bp)) { main_mem_size = HC_REG_MAIN_MEMORY_SIZE / 2; /*dwords*/ main_mem_base = HC_REG_MAIN_MEMORY + @@ -5397,65 +6265,26 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) REG_RD(bp, main_mem_prty_clr); } +#ifdef BNX2X_STOP_ON_ERROR + /* Enable STORMs SP logging */ + REG_WR8(bp, BAR_USTRORM_INTMEM + + USTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1); + REG_WR8(bp, BAR_TSTRORM_INTMEM + + TSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1); + REG_WR8(bp, BAR_CSTRORM_INTMEM + + CSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1); + REG_WR8(bp, BAR_XSTRORM_INTMEM + + XSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1); +#endif + bnx2x_phy_probe(&bp->link_params); return 0; } -int bnx2x_init_hw(struct bnx2x *bp, u32 load_code) -{ - int rc = 0; - - DP(BNX2X_MSG_MCP, "function %d load_code %x\n", - BP_ABS_FUNC(bp), load_code); - - bp->dmae_ready = 0; - spin_lock_init(&bp->dmae_lock); - - switch (load_code) { - case FW_MSG_CODE_DRV_LOAD_COMMON: - case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: - rc = bnx2x_init_hw_common(bp, load_code); - if (rc) - goto init_hw_err; - /* no break */ - - case FW_MSG_CODE_DRV_LOAD_PORT: - rc = bnx2x_init_hw_port(bp); - if (rc) - goto init_hw_err; - /* no break */ - - case FW_MSG_CODE_DRV_LOAD_FUNCTION: - rc = bnx2x_init_hw_func(bp); - if (rc) - goto init_hw_err; - break; - - default: - BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code); - break; - } - - if (!BP_NOMCP(bp)) { - int mb_idx = BP_FW_MB_IDX(bp); - - bp->fw_drv_pulse_wr_seq = - (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) & - DRV_PULSE_SEQ_MASK); - DP(BNX2X_MSG_MCP, "drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq); - } - -init_hw_err: - bnx2x_gunzip_end(bp); - - return rc; -} void bnx2x_free_mem(struct bnx2x *bp) { - bnx2x_gunzip_end(bp); - /* fastpath */ bnx2x_free_fp_mem(bp); /* end of fastpath */ @@ -5463,6 +6292,9 @@ void bnx2x_free_mem(struct bnx2x *bp) BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping, sizeof(struct host_sp_status_block)); + BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping, + bp->fw_stats_data_sz + bp->fw_stats_req_sz); + BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping, sizeof(struct bnx2x_slowpath)); @@ -5474,7 +6306,7 @@ void bnx2x_free_mem(struct bnx2x *bp) BNX2X_FREE(bp->ilt->lines); #ifdef BCM_CNIC - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping, sizeof(struct host_hc_status_block_e2)); else @@ -5488,18 +6320,67 @@ void bnx2x_free_mem(struct bnx2x *bp) BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping, BCM_PAGE_SIZE * NUM_EQ_PAGES); +} + +static inline int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp) +{ + int num_groups; + + /* number of eth_queues */ + u8 num_queue_stats = BNX2X_NUM_ETH_QUEUES(bp); + + /* Total number of FW statistics requests = + * 1 for port stats + 1 for PF stats + num_eth_queues */ + bp->fw_stats_num = 2 + num_queue_stats; + + + /* Request is built from stats_query_header and an array of + * stats_query_cmd_group each of which contains + * STATS_QUERY_CMD_COUNT rules. The real number or requests is + * configured in the stats_query_header. + */ + num_groups = (2 + num_queue_stats) / STATS_QUERY_CMD_COUNT + + (((2 + num_queue_stats) % STATS_QUERY_CMD_COUNT) ? 1 : 0); + + bp->fw_stats_req_sz = sizeof(struct stats_query_header) + + num_groups * sizeof(struct stats_query_cmd_group); - BNX2X_FREE(bp->rx_indir_table); + /* Data for statistics requests + stats_conter + * + * stats_counter holds per-STORM counters that are incremented + * when STORM has finished with the current request. + */ + bp->fw_stats_data_sz = sizeof(struct per_port_stats) + + sizeof(struct per_pf_stats) + + sizeof(struct per_queue_stats) * num_queue_stats + + sizeof(struct stats_counter); + + BNX2X_PCI_ALLOC(bp->fw_stats, &bp->fw_stats_mapping, + bp->fw_stats_data_sz + bp->fw_stats_req_sz); + + /* Set shortcuts */ + bp->fw_stats_req = (struct bnx2x_fw_stats_req *)bp->fw_stats; + bp->fw_stats_req_mapping = bp->fw_stats_mapping; + + bp->fw_stats_data = (struct bnx2x_fw_stats_data *) + ((u8 *)bp->fw_stats + bp->fw_stats_req_sz); + + bp->fw_stats_data_mapping = bp->fw_stats_mapping + + bp->fw_stats_req_sz; + return 0; + +alloc_mem_err: + BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping, + bp->fw_stats_data_sz + bp->fw_stats_req_sz); + return -ENOMEM; } int bnx2x_alloc_mem(struct bnx2x *bp) { - if (bnx2x_gunzip_init(bp)) - return -ENOMEM; - #ifdef BCM_CNIC - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) + /* size = the status block + ramrod buffers */ BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping, sizeof(struct host_hc_status_block_e2)); else @@ -5517,6 +6398,10 @@ int bnx2x_alloc_mem(struct bnx2x *bp) BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping, sizeof(struct bnx2x_slowpath)); + /* Allocated memory for FW statistics */ + if (bnx2x_alloc_fw_stats_mem(bp)) + goto alloc_mem_err; + bp->context.size = sizeof(union cdu_context) * bp->l2_cid_count; BNX2X_PCI_ALLOC(bp->context.vcxt, &bp->context.cxt_mapping, @@ -5534,8 +6419,6 @@ int bnx2x_alloc_mem(struct bnx2x *bp) BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping, BCM_PAGE_SIZE * NUM_EQ_PAGES); - BNX2X_ALLOC(bp->rx_indir_table, sizeof(bp->rx_indir_table[0]) * - TSTORM_INDIRECTION_TABLE_SIZE); /* fastpath */ /* need to be done at the end, since it's self adjusting to amount @@ -5553,235 +6436,76 @@ alloc_mem_err: /* * Init service functions */ -int bnx2x_func_start(struct bnx2x *bp) -{ - bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, 0, 0, 1); - - /* Wait for completion */ - return bnx2x_wait_ramrod(bp, BNX2X_STATE_FUNC_STARTED, 0, &(bp->state), - WAIT_RAMROD_COMMON); -} -static int bnx2x_func_stop(struct bnx2x *bp) +int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac, + struct bnx2x_vlan_mac_obj *obj, bool set, + int mac_type, unsigned long *ramrod_flags) { - bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0, 1); - - /* Wait for completion */ - return bnx2x_wait_ramrod(bp, BNX2X_STATE_CLOSING_WAIT4_UNLOAD, - 0, &(bp->state), WAIT_RAMROD_COMMON); -} - -int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, - int *state_p, int flags) -{ - /* can take a while if any port is running */ - int cnt = 5000; - u8 poll = flags & WAIT_RAMROD_POLL; - u8 common = flags & WAIT_RAMROD_COMMON; + int rc; + struct bnx2x_vlan_mac_ramrod_params ramrod_param; - DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n", - poll ? "polling" : "waiting", state, idx); + memset(&ramrod_param, 0, sizeof(ramrod_param)); - might_sleep(); - while (cnt--) { - if (poll) { - if (common) - bnx2x_eq_int(bp); - else { - bnx2x_rx_int(bp->fp, 10); - /* if index is different from 0 - * the reply for some commands will - * be on the non default queue - */ - if (idx) - bnx2x_rx_int(&bp->fp[idx], 10); - } - } + /* Fill general parameters */ + ramrod_param.vlan_mac_obj = obj; + ramrod_param.ramrod_flags = *ramrod_flags; - mb(); /* state is changed by bnx2x_sp_event() */ - if (*state_p == state) { -#ifdef BNX2X_STOP_ON_ERROR - DP(NETIF_MSG_IFUP, "exit (cnt %d)\n", 5000 - cnt); -#endif - return 0; - } + /* Fill a user request section if needed */ + if (!test_bit(RAMROD_CONT, ramrod_flags)) { + memcpy(ramrod_param.user_req.u.mac.mac, mac, ETH_ALEN); - msleep(1); + __set_bit(mac_type, &ramrod_param.user_req.vlan_mac_flags); - if (bp->panic) - return -EIO; + /* Set the command: ADD or DEL */ + if (set) + ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD; + else + ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_DEL; } - /* timeout! */ - BNX2X_ERR("timeout %s for state %x on IDX [%d]\n", - poll ? "polling" : "waiting", state, idx); -#ifdef BNX2X_STOP_ON_ERROR - bnx2x_panic(); -#endif - - return -EBUSY; -} - -static u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset) -{ - if (CHIP_IS_E1H(bp)) - return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp); - else if (CHIP_MODE_IS_4_PORT(bp)) - return E2_FUNC_MAX * rel_offset + BP_FUNC(bp); - else - return E2_FUNC_MAX * rel_offset + BP_VN(bp); + rc = bnx2x_config_vlan_mac(bp, &ramrod_param); + if (rc < 0) + BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del")); + return rc; } -/** - * LLH CAM line allocations: currently only iSCSI and ETH macs are - * relevant. In addition, current implementation is tuned for a - * single ETH MAC. - */ -enum { - LLH_CAM_ISCSI_ETH_LINE = 0, - LLH_CAM_ETH_LINE, - LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE -}; - -static void bnx2x_set_mac_in_nig(struct bnx2x *bp, - int set, - unsigned char *dev_addr, - int index) +int bnx2x_del_all_macs(struct bnx2x *bp, + struct bnx2x_vlan_mac_obj *mac_obj, + int mac_type, bool wait_for_comp) { - u32 wb_data[2]; - u32 mem_offset, ena_offset, mem_index; - /** - * indexes mapping: - * 0..7 - goes to MEM - * 8..15 - goes to MEM2 - */ - - if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE) - return; - - /* calculate memory start offset according to the mapping - * and index in the memory */ - if (index < NIG_LLH_FUNC_MEM_MAX_OFFSET) { - mem_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM : - NIG_REG_LLH0_FUNC_MEM; - ena_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE : - NIG_REG_LLH0_FUNC_MEM_ENABLE; - mem_index = index; - } else { - mem_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2 : - NIG_REG_P0_LLH_FUNC_MEM2; - ena_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2_ENABLE : - NIG_REG_P0_LLH_FUNC_MEM2_ENABLE; - mem_index = index - NIG_LLH_FUNC_MEM_MAX_OFFSET; - } - - if (set) { - /* LLH_FUNC_MEM is a u64 WB register */ - mem_offset += 8*mem_index; - - wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) | - (dev_addr[4] << 8) | dev_addr[5]); - wb_data[1] = ((dev_addr[0] << 8) | dev_addr[1]); - - REG_WR_DMAE(bp, mem_offset, wb_data, 2); - } - - /* enable/disable the entry */ - REG_WR(bp, ena_offset + 4*mem_index, set); - -} + int rc; + unsigned long ramrod_flags = 0, vlan_mac_flags = 0; -void bnx2x_set_eth_mac(struct bnx2x *bp, int set) -{ - u8 cam_offset = (CHIP_IS_E1(bp) ? (BP_PORT(bp) ? 32 : 0) : - bnx2x_e1h_cam_offset(bp, CAM_ETH_LINE)); + /* Wait for completion of requested */ + if (wait_for_comp) + __set_bit(RAMROD_COMP_WAIT, &ramrod_flags); - /* networking MAC */ - bnx2x_set_mac_addr_gen(bp, set, bp->dev->dev_addr, - (1 << bp->fp->cl_id), cam_offset , 0); + /* Set the mac type of addresses we want to clear */ + __set_bit(mac_type, &vlan_mac_flags); - bnx2x_set_mac_in_nig(bp, set, bp->dev->dev_addr, LLH_CAM_ETH_LINE); + rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags, &ramrod_flags); + if (rc < 0) + BNX2X_ERR("Failed to delete MACs: %d\n", rc); - if (CHIP_IS_E1(bp)) { - /* broadcast MAC */ - static const u8 bcast[ETH_ALEN] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1); - } + return rc; } -#ifdef BCM_CNIC -/** - * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s). - * - * @bp: driver handle - * @set: set or clear the CAM entry - * - * This function will wait until the ramdord completion returns. - * Return 0 if success, -ENODEV if ramrod doesn't return. - */ -static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) +int bnx2x_set_eth_mac(struct bnx2x *bp, bool set) { - u8 cam_offset = (CHIP_IS_E1(bp) ? ((BP_PORT(bp) ? 32 : 0) + 2) : - bnx2x_e1h_cam_offset(bp, CAM_ISCSI_ETH_LINE)); - u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID + - BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE; - u32 cl_bit_vec = (1 << iscsi_l2_cl_id); - u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac; - - /* Send a SET_MAC ramrod */ - bnx2x_set_mac_addr_gen(bp, set, iscsi_mac, cl_bit_vec, - cam_offset, 0); - - bnx2x_set_mac_in_nig(bp, set, iscsi_mac, LLH_CAM_ISCSI_ETH_LINE); - - return 0; -} + unsigned long ramrod_flags = 0; -/** - * bnx2x_set_fip_eth_mac_addr - set FCoE L2 MAC(s) - * - * @bp: driver handle - * @set: set or clear the CAM entry - * - * This function will wait until the ramrod completion returns. - * Returns 0 if success, -ENODEV if ramrod doesn't return. - */ -int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set) -{ - u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id)); - /** - * CAM allocation for E1H - * eth unicasts: by func number - * iscsi: by func number - * fip unicast: by func number - * fip multicast: by func number - */ - bnx2x_set_mac_addr_gen(bp, set, bp->fip_mac, - cl_bit_vec, bnx2x_e1h_cam_offset(bp, CAM_FIP_ETH_LINE), 0); + DP(NETIF_MSG_IFUP, "Adding Eth MAC\n"); - return 0; + __set_bit(RAMROD_COMP_WAIT, &ramrod_flags); + /* Eth MAC is set on RSS leading client (fp[0]) */ + return bnx2x_set_mac_one(bp, bp->dev->dev_addr, &bp->fp->mac_obj, set, + BNX2X_ETH_MAC, &ramrod_flags); } -int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set) +int bnx2x_setup_leading(struct bnx2x *bp) { - u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id)); - - /** - * CAM allocation for E1H - * eth unicasts: by func number - * iscsi: by func number - * fip unicast: by func number - * fip multicast: by func number - */ - bnx2x_set_mac_addr_gen(bp, set, ALL_ENODE_MACS, cl_bit_vec, - bnx2x_e1h_cam_offset(bp, CAM_FIP_MCAST_LINE), 0); - - return 0; + return bnx2x_setup_queue(bp, &bp->fp[0], 1); } -#endif - /** * bnx2x_set_int_mode - configure interrupt mode @@ -5792,7 +6516,6 @@ int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set) */ static void __devinit bnx2x_set_int_mode(struct bnx2x *bp) { - switch (int_mode) { case INT_MODE_MSI: bnx2x_enable_msi(bp); @@ -5852,7 +6575,7 @@ void bnx2x_ilt_set_info(struct bnx2x *bp) ilt_client->page_size = CDU_ILT_PAGE_SZ; ilt_client->flags = ILT_CLIENT_SKIP_MEM; ilt_client->start = line; - line += L2_ILT_LINES(bp); + line += bnx2x_cid_ilt_lines(bp); #ifdef BCM_CNIC line += CNIC_ILT_LINES; #endif @@ -5932,12 +6655,72 @@ void bnx2x_ilt_set_info(struct bnx2x *bp) #else ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM); #endif + BUG_ON(line > ILT_MAX_LINES); +} + +/** + * bnx2x_pf_q_prep_init - prepare INIT transition parameters + * + * @bp: driver handle + * @fp: pointer to fastpath + * @init_params: pointer to parameters structure + * + * parameters configured: + * - HC configuration + * - Queue's CDU context + */ +static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp, + struct bnx2x_fastpath *fp, struct bnx2x_queue_init_params *init_params) +{ + /* FCoE Queue uses Default SB, thus has no HC capabilities */ + if (!IS_FCOE_FP(fp)) { + __set_bit(BNX2X_Q_FLG_HC, &init_params->rx.flags); + __set_bit(BNX2X_Q_FLG_HC, &init_params->tx.flags); + + /* If HC is supporterd, enable host coalescing in the transition + * to INIT state. + */ + __set_bit(BNX2X_Q_FLG_HC_EN, &init_params->rx.flags); + __set_bit(BNX2X_Q_FLG_HC_EN, &init_params->tx.flags); + + /* HC rate */ + init_params->rx.hc_rate = bp->rx_ticks ? + (1000000 / bp->rx_ticks) : 0; + init_params->tx.hc_rate = bp->tx_ticks ? + (1000000 / bp->tx_ticks) : 0; + + /* FW SB ID */ + init_params->rx.fw_sb_id = init_params->tx.fw_sb_id = + fp->fw_sb_id; + + /* + * CQ index among the SB indices: FCoE clients uses the default + * SB, therefore it's different. + */ + init_params->rx.sb_cq_index = U_SB_ETH_RX_CQ_INDEX; + init_params->tx.sb_cq_index = C_SB_ETH_TX_CQ_INDEX; + } + + init_params->cxt = &bp->context.vcxt[fp->cid].eth; } -int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp, - int is_leading) +/** + * bnx2x_setup_queue - setup queue + * + * @bp: driver handle + * @fp: pointer to fastpath + * @leading: is leading + * + * This function performs 2 steps in a Queue state machine + * actually: 1) RESET->INIT 2) INIT->SETUP + */ + +int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp, + bool leading) { - struct bnx2x_client_init_params params = { {0} }; + struct bnx2x_queue_state_params q_params = {0}; + struct bnx2x_queue_setup_params *setup_params = + &q_params.params.setup; int rc; /* reset IGU state skip FCoE L2 queue */ @@ -5945,79 +6728,73 @@ int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp, bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0); - params.ramrod_params.pstate = &fp->state; - params.ramrod_params.state = BNX2X_FP_STATE_OPEN; - params.ramrod_params.index = fp->index; - params.ramrod_params.cid = fp->cid; + q_params.q_obj = &fp->q_obj; + /* We want to wait for completion in this context */ + __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags); -#ifdef BCM_CNIC - if (IS_FCOE_FP(fp)) - params.ramrod_params.flags |= CLIENT_IS_FCOE; + /* Prepare the INIT parameters */ + bnx2x_pf_q_prep_init(bp, fp, &q_params.params.init); -#endif + /* Set the command */ + q_params.cmd = BNX2X_Q_CMD_INIT; - if (is_leading) - params.ramrod_params.flags |= CLIENT_IS_LEADING_RSS; + /* Change the state to INIT */ + rc = bnx2x_queue_state_change(bp, &q_params); + if (rc) { + BNX2X_ERR("Queue INIT failed\n"); + return rc; + } + + /* Now move the Queue to the SETUP state... */ + memset(setup_params, 0, sizeof(*setup_params)); + + /* Set QUEUE flags */ + setup_params->flags = bnx2x_get_q_flags(bp, fp, leading); - bnx2x_pf_rx_cl_prep(bp, fp, ¶ms.pause, ¶ms.rxq_params); + /* Set general SETUP parameters */ + bnx2x_pf_q_prep_general(bp, fp, &setup_params->gen_params); - bnx2x_pf_tx_cl_prep(bp, fp, ¶ms.txq_params); + bnx2x_pf_rx_q_prep(bp, fp, &setup_params->pause, + &setup_params->rxq_params); + + bnx2x_pf_tx_q_prep(bp, fp, &setup_params->txq_params); + + /* Set the command */ + q_params.cmd = BNX2X_Q_CMD_SETUP; + + /* Change the state to SETUP */ + rc = bnx2x_queue_state_change(bp, &q_params); + if (rc) + BNX2X_ERR("Queue SETUP failed\n"); - rc = bnx2x_setup_fw_client(bp, ¶ms, 1, - bnx2x_sp(bp, client_init_data), - bnx2x_sp_mapping(bp, client_init_data)); return rc; } -static int bnx2x_stop_fw_client(struct bnx2x *bp, - struct bnx2x_client_ramrod_params *p) +static int bnx2x_stop_queue(struct bnx2x *bp, int index) { + struct bnx2x_fastpath *fp = &bp->fp[index]; + struct bnx2x_queue_state_params q_params = {0}; int rc; - int poll_flag = p->poll ? WAIT_RAMROD_POLL : 0; + q_params.q_obj = &fp->q_obj; + /* We want to wait for completion in this context */ + __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags); /* halt the connection */ - *p->pstate = BNX2X_FP_STATE_HALTING; - bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, p->cid, 0, - p->cl_id, 0); - - /* Wait for completion */ - rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, p->index, - p->pstate, poll_flag); - if (rc) /* timeout */ + q_params.cmd = BNX2X_Q_CMD_HALT; + rc = bnx2x_queue_state_change(bp, &q_params); + if (rc) return rc; - *p->pstate = BNX2X_FP_STATE_TERMINATING; - bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, p->cid, 0, - p->cl_id, 0); - /* Wait for completion */ - rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_TERMINATED, p->index, - p->pstate, poll_flag); - if (rc) /* timeout */ + /* terminate the connection */ + q_params.cmd = BNX2X_Q_CMD_TERMINATE; + rc = bnx2x_queue_state_change(bp, &q_params); + if (rc) return rc; - /* delete cfc entry */ - bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, p->cid, 0, 0, 1); - - /* Wait for completion */ - rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, p->index, - p->pstate, WAIT_RAMROD_COMMON); - return rc; -} - -static int bnx2x_stop_client(struct bnx2x *bp, int index) -{ - struct bnx2x_client_ramrod_params client_stop = {0}; - struct bnx2x_fastpath *fp = &bp->fp[index]; - - client_stop.index = index; - client_stop.cid = fp->cid; - client_stop.cl_id = fp->cl_id; - client_stop.pstate = &(fp->state); - client_stop.poll = 0; - - return bnx2x_stop_fw_client(bp, &client_stop); + q_params.cmd = BNX2X_Q_CMD_CFC_DEL; + return bnx2x_queue_state_change(bp, &q_params); } @@ -6026,12 +6803,6 @@ static void bnx2x_reset_func(struct bnx2x *bp) int port = BP_PORT(bp); int func = BP_FUNC(bp); int i; - int pfunc_offset_fp = offsetof(struct hc_sb_data, p_func) + - (CHIP_IS_E2(bp) ? - offsetof(struct hc_status_block_data_e2, common) : - offsetof(struct hc_status_block_data_e1x, common)); - int pfunc_offset_sp = offsetof(struct hc_sp_status_block_data, p_func); - int pfid_offset = offsetof(struct pci_entity, pf_id); /* Disable the function in the FW */ REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(func), 0); @@ -6042,20 +6813,21 @@ static void bnx2x_reset_func(struct bnx2x *bp) /* FP SBs */ for_each_eth_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; - REG_WR8(bp, - BAR_CSTRORM_INTMEM + - CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id) - + pfunc_offset_fp + pfid_offset, - HC_FUNCTION_DISABLED); + REG_WR8(bp, BAR_CSTRORM_INTMEM + + CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(fp->fw_sb_id), + SB_DISABLED); } +#ifdef BCM_CNIC + /* CNIC SB */ + REG_WR8(bp, BAR_CSTRORM_INTMEM + + CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(bnx2x_cnic_fw_sb_id(bp)), + SB_DISABLED); +#endif /* SP SB */ - REG_WR8(bp, - BAR_CSTRORM_INTMEM + - CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) + - pfunc_offset_sp + pfid_offset, - HC_FUNCTION_DISABLED); - + REG_WR8(bp, BAR_CSTRORM_INTMEM + + CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func), + SB_DISABLED); for (i = 0; i < XSTORM_SPQ_DATA_SIZE / 4; i++) REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_DATA_OFFSET(func), @@ -6089,7 +6861,7 @@ static void bnx2x_reset_func(struct bnx2x *bp) /* Timers workaround bug for E2: if this is vnic-3, * we need to set the entire ilt range for this timers. */ - if (CHIP_IS_E2(bp) && BP_VN(bp) == 3) { + if (!CHIP_IS_E1x(bp) && BP_VN(bp) == 3) { struct ilt_client_info ilt_cli; /* use dummy TM client */ memset(&ilt_cli, 0, sizeof(struct ilt_client_info)); @@ -6101,7 +6873,7 @@ static void bnx2x_reset_func(struct bnx2x *bp) } /* this assumes that reset_port() called before reset_func()*/ - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) bnx2x_pf_disable(bp); bp->dmae_ready = 0; @@ -6112,6 +6884,9 @@ static void bnx2x_reset_port(struct bnx2x *bp) int port = BP_PORT(bp); u32 val; + /* Reset physical Link */ + bnx2x__link_reset(bp); + REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0); /* Do not rcv packets to BRB */ @@ -6133,92 +6908,66 @@ static void bnx2x_reset_port(struct bnx2x *bp) /* TODO: Close Doorbell port? */ } -static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code) +static inline int bnx2x_reset_hw(struct bnx2x *bp, u32 load_code) { - DP(BNX2X_MSG_MCP, "function %d reset_code %x\n", - BP_ABS_FUNC(bp), reset_code); + struct bnx2x_func_state_params func_params = {0}; - switch (reset_code) { - case FW_MSG_CODE_DRV_UNLOAD_COMMON: - bnx2x_reset_port(bp); - bnx2x_reset_func(bp); - bnx2x_reset_common(bp); - break; - - case FW_MSG_CODE_DRV_UNLOAD_PORT: - bnx2x_reset_port(bp); - bnx2x_reset_func(bp); - break; - - case FW_MSG_CODE_DRV_UNLOAD_FUNCTION: - bnx2x_reset_func(bp); - break; - - default: - BNX2X_ERR("Unknown reset_code (0x%x) from MCP\n", reset_code); - break; - } -} + /* Prepare parameters for function state transitions */ + __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); -#ifdef BCM_CNIC -static inline void bnx2x_del_fcoe_eth_macs(struct bnx2x *bp) -{ - if (bp->flags & FCOE_MACS_SET) { - if (!IS_MF_SD(bp)) - bnx2x_set_fip_eth_mac_addr(bp, 0); + func_params.f_obj = &bp->func_obj; + func_params.cmd = BNX2X_F_CMD_HW_RESET; - bnx2x_set_all_enode_macs(bp, 0); + func_params.params.hw_init.load_phase = load_code; - bp->flags &= ~FCOE_MACS_SET; - } + return bnx2x_func_state_change(bp, &func_params); } -#endif -void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) +static inline int bnx2x_func_stop(struct bnx2x *bp) { - int port = BP_PORT(bp); - u32 reset_code = 0; - int i, cnt, rc; - - /* Wait until tx fastpath tasks complete */ - for_each_tx_queue(bp, i) { - struct bnx2x_fastpath *fp = &bp->fp[i]; + struct bnx2x_func_state_params func_params = {0}; + int rc; - cnt = 1000; - while (bnx2x_has_tx_work_unload(fp)) { + /* Prepare parameters for function state transitions */ + __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); + func_params.f_obj = &bp->func_obj; + func_params.cmd = BNX2X_F_CMD_STOP; - if (!cnt) { - BNX2X_ERR("timeout waiting for queue[%d]\n", - i); + /* + * Try to stop the function the 'good way'. If fails (in case + * of a parity error during bnx2x_chip_cleanup()) and we are + * not in a debug mode, perform a state transaction in order to + * enable further HW_RESET transaction. + */ + rc = bnx2x_func_state_change(bp, &func_params); + if (rc) { #ifdef BNX2X_STOP_ON_ERROR - bnx2x_panic(); - return -EBUSY; + return rc; #else - break; + BNX2X_ERR("FUNC_STOP ramrod failed. Running a dry " + "transaction\n"); + __set_bit(RAMROD_DRV_CLR_ONLY, &func_params.ramrod_flags); + return bnx2x_func_state_change(bp, &func_params); #endif - } - cnt--; - msleep(1); - } } - /* Give HW time to discard old tx messages */ - msleep(1); - - bnx2x_set_eth_mac(bp, 0); - bnx2x_invalidate_uc_list(bp); - - if (CHIP_IS_E1(bp)) - bnx2x_invalidate_e1_mc_list(bp); - else { - bnx2x_invalidate_e1h_mc_list(bp); - REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); - } + return 0; +} -#ifdef BCM_CNIC - bnx2x_del_fcoe_eth_macs(bp); -#endif +/** + * bnx2x_send_unload_req - request unload mode from the MCP. + * + * @bp: driver handle + * @unload_mode: requested function's unload mode + * + * Return unload mode returned by the MCP: COMMON, PORT or FUNC. + */ +u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode) +{ + u32 reset_code = 0; + int port = BP_PORT(bp); + /* Select the UNLOAD request mode */ if (unload_mode == UNLOAD_NORMAL) reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; @@ -6245,54 +6994,135 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) } else reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; + /* Send the request to the MCP */ + if (!BP_NOMCP(bp)) + reset_code = bnx2x_fw_command(bp, reset_code, 0); + else { + int path = BP_PATH(bp); + + DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d] " + "%d, %d, %d\n", + path, load_count[path][0], load_count[path][1], + load_count[path][2]); + load_count[path][0]--; + load_count[path][1 + port]--; + DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d] " + "%d, %d, %d\n", + path, load_count[path][0], load_count[path][1], + load_count[path][2]); + if (load_count[path][0] == 0) + reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON; + else if (load_count[path][1 + port] == 0) + reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT; + else + reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION; + } + + return reset_code; +} + +/** + * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP. + * + * @bp: driver handle + */ +void bnx2x_send_unload_done(struct bnx2x *bp) +{ + /* Report UNLOAD_DONE to MCP */ + if (!BP_NOMCP(bp)) + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); +} + +void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) +{ + int port = BP_PORT(bp); + int i, rc; + struct bnx2x_mcast_ramrod_params rparam = {0}; + u32 reset_code; + + /* Wait until tx fastpath tasks complete */ + for_each_tx_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + + rc = bnx2x_clean_tx_queue(bp, fp); +#ifdef BNX2X_STOP_ON_ERROR + if (rc) + return; +#endif + } + + /* Give HW time to discard old tx messages */ + usleep_range(1000, 1000); + + /* Clean all ETH MACs */ + rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_ETH_MAC, false); + if (rc < 0) + BNX2X_ERR("Failed to delete all ETH macs: %d\n", rc); + + /* Clean up UC list */ + rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_UC_LIST_MAC, + true); + if (rc < 0) + BNX2X_ERR("Failed to schedule DEL commands for UC MACs list: " + "%d\n", rc); + + /* Disable LLH */ + if (!CHIP_IS_E1(bp)) + REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); + + /* Set "drop all" (stop Rx). + * We need to take a netif_addr_lock() here in order to prevent + * a race between the completion code and this code. + */ + netif_addr_lock_bh(bp->dev); + /* Schedule the rx_mode command */ + if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) + set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state); + else + bnx2x_set_storm_rx_mode(bp); + + /* Cleanup multicast configuration */ + rparam.mcast_obj = &bp->mcast_obj; + rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL); + if (rc < 0) + BNX2X_ERR("Failed to send DEL multicast command: %d\n", rc); + + netif_addr_unlock_bh(bp->dev); + + /* Close multi and leading connections - Completions for ramrods are collected in a synchronous way */ + * Completions for ramrods are collected in a synchronous way + */ for_each_queue(bp, i) - - if (bnx2x_stop_client(bp, i)) + if (bnx2x_stop_queue(bp, i)) #ifdef BNX2X_STOP_ON_ERROR return; #else goto unload_error; #endif + /* If SP settings didn't get completed so far - something + * very wrong has happen. + */ + if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) + BNX2X_ERR("Hmmm... Common slow path ramrods got stuck!\n"); +#ifndef BNX2X_STOP_ON_ERROR +unload_error: +#endif rc = bnx2x_func_stop(bp); if (rc) { BNX2X_ERR("Function stop failed!\n"); #ifdef BNX2X_STOP_ON_ERROR return; -#else - goto unload_error; -#endif - } -#ifndef BNX2X_STOP_ON_ERROR -unload_error: #endif - if (!BP_NOMCP(bp)) - reset_code = bnx2x_fw_command(bp, reset_code, 0); - else { - DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d] " - "%d, %d, %d\n", BP_PATH(bp), - load_count[BP_PATH(bp)][0], - load_count[BP_PATH(bp)][1], - load_count[BP_PATH(bp)][2]); - load_count[BP_PATH(bp)][0]--; - load_count[BP_PATH(bp)][1 + port]--; - DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d] " - "%d, %d, %d\n", BP_PATH(bp), - load_count[BP_PATH(bp)][0], load_count[BP_PATH(bp)][1], - load_count[BP_PATH(bp)][2]); - if (load_count[BP_PATH(bp)][0] == 0) - reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON; - else if (load_count[BP_PATH(bp)][1 + port] == 0) - reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT; - else - reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION; } - if ((reset_code == FW_MSG_CODE_DRV_UNLOAD_COMMON) || - (reset_code == FW_MSG_CODE_DRV_UNLOAD_PORT)) - bnx2x__link_reset(bp); + /* + * Send the UNLOAD_REQUEST to the MCP. This will return if + * this function should perform FUNC, PORT or COMMON HW + * reset. + */ + reset_code = bnx2x_send_unload_req(bp, unload_mode); /* Disable HW interrupts, NAPI */ bnx2x_netif_stop(bp, 1); @@ -6301,12 +7131,13 @@ unload_error: bnx2x_free_irq(bp); /* Reset the chip */ - bnx2x_reset_chip(bp, reset_code); + rc = bnx2x_reset_hw(bp, reset_code); + if (rc) + BNX2X_ERR("HW_RESET failed\n"); - /* Report UNLOAD_DONE to MCP */ - if (!BP_NOMCP(bp)) - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); + /* Report UNLOAD_DONE to MCP */ + bnx2x_send_unload_done(bp); } void bnx2x_disable_close_the_gate(struct bnx2x *bp) @@ -6323,7 +7154,7 @@ void bnx2x_disable_close_the_gate(struct bnx2x *bp) val = REG_RD(bp, addr); val &= ~(0x300); REG_WR(bp, addr, val); - } else if (CHIP_IS_E1H(bp)) { + } else { val = REG_RD(bp, MISC_REG_AEU_GENERAL_MASK); val &= ~(MISC_AEU_GENERAL_MASK_REG_AEU_PXP_CLOSE_MASK | MISC_AEU_GENERAL_MASK_REG_AEU_NIG_CLOSE_MASK); @@ -6820,8 +7651,8 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; /* save our pf_num */ int orig_pf_num = bp->pf_num; - u32 swap_en; - u32 swap_val; + int port; + u32 swap_en, swap_val, value; /* clear the UNDI indication */ REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); @@ -6856,21 +7687,19 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); bnx2x_undi_int_disable(bp); + port = BP_PORT(bp); /* close input traffic and wait for it */ /* Do not rcv packets to BRB */ - REG_WR(bp, - (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_DRV_MASK : - NIG_REG_LLH0_BRB1_DRV_MASK), 0x0); + REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_DRV_MASK : + NIG_REG_LLH0_BRB1_DRV_MASK), 0x0); /* Do not direct rcv packets that are not for MCP to * the BRB */ - REG_WR(bp, - (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_NOT_MCP : - NIG_REG_LLH0_BRB1_NOT_MCP), 0x0); + REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP : + NIG_REG_LLH0_BRB1_NOT_MCP), 0x0); /* clear AEU */ - REG_WR(bp, - (BP_PORT(bp) ? MISC_REG_AEU_MASK_ATTN_FUNC_1 : - MISC_REG_AEU_MASK_ATTN_FUNC_0), 0); + REG_WR(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 : + MISC_REG_AEU_MASK_ATTN_FUNC_0), 0); msleep(10); /* save NIG port swap info */ @@ -6880,9 +7709,17 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, 0xd3ffffff); + + value = 0x1400; + if (CHIP_IS_E3(bp)) { + value |= MISC_REGISTERS_RESET_REG_2_MSTAT0; + value |= MISC_REGISTERS_RESET_REG_2_MSTAT1; + } + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, - 0x1403); + value); + /* take the NIG out of reset and restore swap values */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, @@ -6923,7 +7760,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) /* Set doorbell size */ bp->db_size = (1 << BNX2X_DB_SHIFT); - if (CHIP_IS_E2(bp)) { + if (!CHIP_IS_E1x(bp)) { val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR); if ((val & 1) == 0) val = REG_RD(bp, MISC_REG_PORT4MODE_EN); @@ -6943,16 +7780,6 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) bp->pfid = bp->pf_num; /* 0..7 */ } - /* - * set base FW non-default (fast path) status block id, this value is - * used to initialize the fw_sb_id saved on the fp/queue structure to - * determine the id used by the FW. - */ - if (CHIP_IS_E1x(bp)) - bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x; - else /* E2 */ - bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E2; - bp->link_params.chip_id = bp->common.chip_id; BNX2X_DEV_INFO("chip ID is 0x%x\n", id); @@ -6971,6 +7798,8 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) bnx2x_init_shmem(bp); + + bp->common.shmem2_base = REG_RD(bp, (BP_PATH(bp) ? MISC_REG_GENERIC_CR_1 : MISC_REG_GENERIC_CR_0)); @@ -7080,8 +7909,14 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp) } } } - bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, - NUM_IGU_SB_REQUIRED(bp->l2_cid_count)); + + /* It's expected that number of CAM entries for this + * functions is equal to the MSI-X table size (which was a + * used during bp->l2_cid_count value calculation. + * We want a harsh warning if these values are different! + */ + WARN_ON(bp->igu_sb_cnt != NUM_IGU_SB_REQUIRED(bp->l2_cid_count)); + if (bp->igu_sb_cnt == 0) BNX2X_ERR("CAM configuration error\n"); } @@ -7130,24 +7965,25 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp, return; } - switch (switch_cfg) { - case SWITCH_CFG_1G: - bp->port.phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR + - port*0x10); - BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr); - break; - - case SWITCH_CFG_10G: - bp->port.phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR + - port*0x18); - BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr); - break; - - default: - BNX2X_ERR("BAD switch_cfg link_config 0x%x\n", - bp->port.link_config[0]); - return; + if (CHIP_IS_E3(bp)) + bp->port.phy_addr = REG_RD(bp, MISC_REG_WC0_CTRL_PHY_ADDR); + else { + switch (switch_cfg) { + case SWITCH_CFG_1G: + bp->port.phy_addr = REG_RD( + bp, NIG_REG_SERDES0_CTRL_PHY_ADDR + port*0x10); + break; + case SWITCH_CFG_10G: + bp->port.phy_addr = REG_RD( + bp, NIG_REG_XGXS0_CTRL_PHY_ADDR + port*0x18); + break; + default: + BNX2X_ERR("BAD switch_cfg link_config 0x%x\n", + bp->port.link_config[0]); + return; + } } + BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr); /* mask what we support according to speed_cap_mask per configuration */ for (idx = 0; idx < cfg_size; idx++) { if (!(bp->link_params.speed_cap_mask[idx] & @@ -7331,8 +8167,6 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) break; case PORT_FEATURE_LINK_SPEED_10G_CX4: - case PORT_FEATURE_LINK_SPEED_10G_KX4: - case PORT_FEATURE_LINK_SPEED_10G_KR: if (bp->port.supported[idx] & SUPPORTED_10000baseT_Full) { bp->link_params.req_line_speed[idx] = @@ -7503,6 +8337,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) u8 *fip_mac = bp->fip_mac; #endif + /* Zero primary MAC configuration */ + memset(bp->dev->dev_addr, 0, ETH_ALEN); + if (BP_NOMCP(bp)) { BNX2X_ERROR("warning: random MAC workaround active\n"); random_ether_addr(bp->dev->dev_addr); @@ -7524,9 +8361,10 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) iscsi_mac_addr_upper); val = MF_CFG_RD(bp, func_ext_config[func]. iscsi_mac_addr_lower); - BNX2X_DEV_INFO("Read iSCSI MAC: " - "0x%x:0x%04x\n", val2, val); bnx2x_set_mac_buf(iscsi_mac, val, val2); + BNX2X_DEV_INFO("Read iSCSI MAC: " + BNX2X_MAC_FMT"\n", + BNX2X_MAC_PRN_LIST(iscsi_mac)); } else bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG; @@ -7535,9 +8373,10 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) fcoe_mac_addr_upper); val = MF_CFG_RD(bp, func_ext_config[func]. fcoe_mac_addr_lower); - BNX2X_DEV_INFO("Read FCoE MAC to " - "0x%x:0x%04x\n", val2, val); bnx2x_set_mac_buf(fip_mac, val, val2); + BNX2X_DEV_INFO("Read FCoE L2 MAC to " + BNX2X_MAC_FMT"\n", + BNX2X_MAC_PRN_LIST(fip_mac)); } else bp->flags |= NO_FCOE_FLAG; @@ -7586,6 +8425,13 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) memset(bp->fip_mac, 0, ETH_ALEN); } #endif + + if (!is_valid_ether_addr(bp->dev->dev_addr)) + dev_err(&bp->pdev->dev, + "bad Ethernet MAC address configuration: " + BNX2X_MAC_FMT", change it manually before bringing up " + "the appropriate network interface\n", + BNX2X_MAC_PRN_LIST(bp->dev->dev_addr)); } static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) @@ -7607,17 +8453,55 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) } else { bp->common.int_block = INT_BLOCK_IGU; val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION); + + if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) { + int tout = 5000; + + BNX2X_DEV_INFO("FORCING Normal Mode\n"); + + val &= ~(IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN); + REG_WR(bp, IGU_REG_BLOCK_CONFIGURATION, val); + REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x7f); + + while (tout && REG_RD(bp, IGU_REG_RESET_MEMORIES)) { + tout--; + usleep_range(1000, 1000); + } + + if (REG_RD(bp, IGU_REG_RESET_MEMORIES)) { + dev_err(&bp->pdev->dev, + "FORCING Normal Mode failed!!!\n"); + return -EPERM; + } + } + if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) { - DP(NETIF_MSG_PROBE, "IGU Backward Compatible Mode\n"); + BNX2X_DEV_INFO("IGU Backward Compatible Mode\n"); bp->common.int_block |= INT_BLOCK_MODE_BW_COMP; } else - DP(NETIF_MSG_PROBE, "IGU Normal Mode\n"); + BNX2X_DEV_INFO("IGU Normal Mode\n"); bnx2x_get_igu_cam_info(bp); } - DP(NETIF_MSG_PROBE, "igu_dsb_id %d igu_base_sb %d igu_sb_cnt %d\n", - bp->igu_dsb_id, bp->igu_base_sb, bp->igu_sb_cnt); + + /* + * set base FW non-default (fast path) status block id, this value is + * used to initialize the fw_sb_id saved on the fp/queue structure to + * determine the id used by the FW. + */ + if (CHIP_IS_E1x(bp)) + bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x + BP_L_ID(bp); + else /* + * 57712 - we currently use one FW SB per IGU SB (Rx and Tx of + * the same queue are indicated on the same IGU SB). So we prefer + * FW and IGU SBs to be the same value. + */ + bp->base_fw_ndsb = bp->igu_base_sb; + + BNX2X_DEV_INFO("igu_dsb_id %d igu_base_sb %d igu_sb_cnt %d\n" + "base_fw_ndsb %d\n", bp->igu_dsb_id, bp->igu_base_sb, + bp->igu_sb_cnt, bp->base_fw_ndsb); /* * Initialize MF configuration @@ -7628,10 +8512,10 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) vn = BP_E1HVN(bp); if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) { - DP(NETIF_MSG_PROBE, - "shmem2base 0x%x, size %d, mfcfg offset %d\n", - bp->common.shmem2_base, SHMEM2_RD(bp, size), - (u32)offsetof(struct shmem2_region, mf_cfg_addr)); + BNX2X_DEV_INFO("shmem2base 0x%x, size %d, mfcfg offset %d\n", + bp->common.shmem2_base, SHMEM2_RD(bp, size), + (u32)offsetof(struct shmem2_region, mf_cfg_addr)); + if (SHMEM2_HAS(bp, mf_cfg_addr)) bp->common.mf_cfg_base = SHMEM2_RD(bp, mf_cfg_addr); else @@ -7662,8 +8546,8 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) bp->mf_config[vn] = MF_CFG_RD(bp, func_mf_config[func].config); } else - DP(NETIF_MSG_PROBE, "illegal MAC " - "address for SI\n"); + BNX2X_DEV_INFO("illegal MAC address " + "for SI\n"); break; case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED: /* get OV configuration */ @@ -7696,13 +8580,16 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) FUNC_MF_CFG_E1HOV_TAG_MASK; if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) { bp->mf_ov = val; - BNX2X_DEV_INFO("MF OV for func %d is %d" - " (0x%04x)\n", func, - bp->mf_ov, bp->mf_ov); + bp->path_has_ovlan = true; + + BNX2X_DEV_INFO("MF OV for func %d is %d " + "(0x%04x)\n", func, bp->mf_ov, + bp->mf_ov); } else { - BNX2X_ERR("No valid MF OV for func %d," - " aborting\n", func); - rc = -EPERM; + dev_err(&bp->pdev->dev, + "No valid MF OV for func %d, " + "aborting\n", func); + return -EPERM; } break; case MULTI_FUNCTION_SI: @@ -7711,31 +8598,40 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) break; default: if (vn) { - BNX2X_ERR("VN %d in single function mode," - " aborting\n", vn); - rc = -EPERM; + dev_err(&bp->pdev->dev, + "VN %d is in a single function mode, " + "aborting\n", vn); + return -EPERM; } break; } + /* check if other port on the path needs ovlan: + * Since MF configuration is shared between ports + * Possible mixed modes are only + * {SF, SI} {SF, SD} {SD, SF} {SI, SF} + */ + if (CHIP_MODE_IS_4_PORT(bp) && + !bp->path_has_ovlan && + !IS_MF(bp) && + bp->common.mf_cfg_base != SHMEM_MF_CFG_ADDR_NONE) { + u8 other_port = !BP_PORT(bp); + u8 other_func = BP_PATH(bp) + 2*other_port; + val = MF_CFG_RD(bp, + func_mf_config[other_func].e1hov_tag); + if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) + bp->path_has_ovlan = true; + } } /* adjust igu_sb_cnt to MF for E1x */ if (CHIP_IS_E1x(bp) && IS_MF(bp)) bp->igu_sb_cnt /= E1HVN_MAX; - /* - * adjust E2 sb count: to be removed when FW will support - * more then 16 L2 clients - */ -#define MAX_L2_CLIENTS 16 - if (CHIP_IS_E2(bp)) - bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, - MAX_L2_CLIENTS / (IS_MF(bp) ? 4 : 1)); + /* port info */ + bnx2x_get_port_hwinfo(bp); if (!BP_NOMCP(bp)) { - bnx2x_get_port_hwinfo(bp); - bp->fw_seq = (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK); @@ -7749,6 +8645,16 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) bnx2x_get_cnic_info(bp); #endif + /* Get current FW pulse sequence */ + if (!BP_NOMCP(bp)) { + int mb_idx = BP_FW_MB_IDX(bp); + + bp->fw_drv_pulse_wr_seq = + (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) & + DRV_PULSE_SEQ_MASK); + BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq); + } + return rc; } @@ -7816,6 +8722,55 @@ out_not_found: return; } +static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp) +{ + u32 flags = 0; + + if (CHIP_REV_IS_FPGA(bp)) + SET_FLAGS(flags, MODE_FPGA); + else if (CHIP_REV_IS_EMUL(bp)) + SET_FLAGS(flags, MODE_EMUL); + else + SET_FLAGS(flags, MODE_ASIC); + + if (CHIP_MODE_IS_4_PORT(bp)) + SET_FLAGS(flags, MODE_PORT4); + else + SET_FLAGS(flags, MODE_PORT2); + + if (CHIP_IS_E2(bp)) + SET_FLAGS(flags, MODE_E2); + else if (CHIP_IS_E3(bp)) { + SET_FLAGS(flags, MODE_E3); + if (CHIP_REV(bp) == CHIP_REV_Ax) + SET_FLAGS(flags, MODE_E3_A0); + else {/*if (CHIP_REV(bp) == CHIP_REV_Bx)*/ + SET_FLAGS(flags, MODE_E3_B0); + SET_FLAGS(flags, MODE_COS_BC); + } + } + + if (IS_MF(bp)) { + SET_FLAGS(flags, MODE_MF); + switch (bp->mf_mode) { + case MULTI_FUNCTION_SD: + SET_FLAGS(flags, MODE_MF_SD); + break; + case MULTI_FUNCTION_SI: + SET_FLAGS(flags, MODE_MF_SI); + break; + } + } else + SET_FLAGS(flags, MODE_SF); + +#if defined(__LITTLE_ENDIAN) + SET_FLAGS(flags, MODE_LITTLE_ENDIAN); +#else /*(__BIG_ENDIAN)*/ + SET_FLAGS(flags, MODE_BIG_ENDIAN); +#endif + INIT_MODE_FLAGS(bp) = flags; +} + static int __devinit bnx2x_init_bp(struct bnx2x *bp) { int func; @@ -7833,9 +8788,14 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task); rc = bnx2x_get_hwinfo(bp); + if (rc) + return rc; - if (!rc) - rc = bnx2x_alloc_mem_bp(bp); + bnx2x_set_modes_bitmap(bp); + + rc = bnx2x_alloc_mem_bp(bp); + if (rc) + return rc; bnx2x_read_fwinfo(bp); @@ -7888,6 +8848,13 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON); bnx2x_dcbx_init_params(bp); +#ifdef BCM_CNIC + if (CHIP_IS_E1x(bp)) + bp->cnic_base_cl_id = FP_SB_MAX_E1x; + else + bp->cnic_base_cl_id = FP_SB_MAX_E2; +#endif + return rc; } @@ -7896,6 +8863,10 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) * General service functions ****************************************************************************/ +/* + * net_device service functions + */ + /* called with rtnl_lock */ static int bnx2x_open(struct net_device *dev) { @@ -7954,193 +8925,119 @@ static int bnx2x_close(struct net_device *dev) return 0; } -#define E1_MAX_UC_LIST 29 -#define E1H_MAX_UC_LIST 30 -#define E2_MAX_UC_LIST 14 -static inline u8 bnx2x_max_uc_list(struct bnx2x *bp) +static inline int bnx2x_init_mcast_macs_list(struct bnx2x *bp, + struct bnx2x_mcast_ramrod_params *p) { - if (CHIP_IS_E1(bp)) - return E1_MAX_UC_LIST; - else if (CHIP_IS_E1H(bp)) - return E1H_MAX_UC_LIST; - else - return E2_MAX_UC_LIST; -} + int mc_count = netdev_mc_count(bp->dev); + struct bnx2x_mcast_list_elem *mc_mac = + kzalloc(sizeof(*mc_mac) * mc_count, GFP_ATOMIC); + struct netdev_hw_addr *ha; + if (!mc_mac) + return -ENOMEM; -static inline u8 bnx2x_uc_list_cam_offset(struct bnx2x *bp) -{ - if (CHIP_IS_E1(bp)) - /* CAM Entries for Port0: - * 0 - prim ETH MAC - * 1 - BCAST MAC - * 2 - iSCSI L2 ring ETH MAC - * 3-31 - UC MACs - * - * Port1 entries are allocated the same way starting from - * entry 32. - */ - return 3 + 32 * BP_PORT(bp); - else if (CHIP_IS_E1H(bp)) { - /* CAM Entries: - * 0-7 - prim ETH MAC for each function - * 8-15 - iSCSI L2 ring ETH MAC for each function - * 16 till 255 UC MAC lists for each function - * - * Remark: There is no FCoE support for E1H, thus FCoE related - * MACs are not considered. - */ - return E1H_FUNC_MAX * (CAM_ISCSI_ETH_LINE + 1) + - bnx2x_max_uc_list(bp) * BP_FUNC(bp); - } else { - /* CAM Entries (there is a separate CAM per engine): - * 0-4 - prim ETH MAC for each function - * 4-7 - iSCSI L2 ring ETH MAC for each function - * 8-11 - FIP ucast L2 MAC for each function - * 12-15 - ALL_ENODE_MACS mcast MAC for each function - * 16 till 71 UC MAC lists for each function - */ - u8 func_idx = - (CHIP_MODE_IS_4_PORT(bp) ? BP_FUNC(bp) : BP_VN(bp)); + INIT_LIST_HEAD(&p->mcast_list); - return E2_FUNC_MAX * (CAM_MAX_PF_LINE + 1) + - bnx2x_max_uc_list(bp) * func_idx; + netdev_for_each_mc_addr(ha, bp->dev) { + mc_mac->mac = bnx2x_mc_addr(ha); + list_add_tail(&mc_mac->link, &p->mcast_list); + mc_mac++; } + + p->mcast_list_len = mc_count; + + return 0; +} + +static inline void bnx2x_free_mcast_macs_list( + struct bnx2x_mcast_ramrod_params *p) +{ + struct bnx2x_mcast_list_elem *mc_mac = + list_first_entry(&p->mcast_list, struct bnx2x_mcast_list_elem, + link); + + WARN_ON(!mc_mac); + kfree(mc_mac); } -/* set uc list, do not wait as wait implies sleep and - * set_rx_mode can be invoked from non-sleepable context. +/** + * bnx2x_set_uc_list - configure a new unicast MACs list. + * + * @bp: driver handle * - * Instead we use the same ramrod data buffer each time we need - * to configure a list of addresses, and use the fact that the - * list of MACs is changed in an incremental way and that the - * function is called under the netif_addr_lock. A temporary - * inconsistent CAM configuration (possible in case of very fast - * sequence of add/del/add on the host side) will shortly be - * restored by the handler of the last ramrod. + * We will use zero (0) as a MAC type for these MACs. */ -static int bnx2x_set_uc_list(struct bnx2x *bp) +static inline int bnx2x_set_uc_list(struct bnx2x *bp) { - int i = 0, old; + int rc; struct net_device *dev = bp->dev; - u8 offset = bnx2x_uc_list_cam_offset(bp); struct netdev_hw_addr *ha; - struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config); - dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config); + struct bnx2x_vlan_mac_obj *mac_obj = &bp->fp->mac_obj; + unsigned long ramrod_flags = 0; - if (netdev_uc_count(dev) > bnx2x_max_uc_list(bp)) - return -EINVAL; + /* First schedule a cleanup up of old configuration */ + rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_UC_LIST_MAC, false); + if (rc < 0) { + BNX2X_ERR("Failed to schedule DELETE operations: %d\n", rc); + return rc; + } netdev_for_each_uc_addr(ha, dev) { - /* copy mac */ - config_cmd->config_table[i].msb_mac_addr = - swab16(*(u16 *)&bnx2x_uc_addr(ha)[0]); - config_cmd->config_table[i].middle_mac_addr = - swab16(*(u16 *)&bnx2x_uc_addr(ha)[2]); - config_cmd->config_table[i].lsb_mac_addr = - swab16(*(u16 *)&bnx2x_uc_addr(ha)[4]); - - config_cmd->config_table[i].vlan_id = 0; - config_cmd->config_table[i].pf_id = BP_FUNC(bp); - config_cmd->config_table[i].clients_bit_vector = - cpu_to_le32(1 << BP_L_ID(bp)); - - SET_FLAG(config_cmd->config_table[i].flags, - MAC_CONFIGURATION_ENTRY_ACTION_TYPE, - T_ETH_MAC_COMMAND_SET); - - DP(NETIF_MSG_IFUP, - "setting UCAST[%d] (%04x:%04x:%04x)\n", i, - config_cmd->config_table[i].msb_mac_addr, - config_cmd->config_table[i].middle_mac_addr, - config_cmd->config_table[i].lsb_mac_addr); - - i++; - - /* Set uc MAC in NIG */ - bnx2x_set_mac_in_nig(bp, 1, bnx2x_uc_addr(ha), - LLH_CAM_ETH_LINE + i); - } - old = config_cmd->hdr.length; - if (old > i) { - for (; i < old; i++) { - if (CAM_IS_INVALID(config_cmd-> - config_table[i])) { - /* already invalidated */ - break; - } - /* invalidate */ - SET_FLAG(config_cmd->config_table[i].flags, - MAC_CONFIGURATION_ENTRY_ACTION_TYPE, - T_ETH_MAC_COMMAND_INVALIDATE); + rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true, + BNX2X_UC_LIST_MAC, &ramrod_flags); + if (rc < 0) { + BNX2X_ERR("Failed to schedule ADD operations: %d\n", + rc); + return rc; } } - wmb(); - - config_cmd->hdr.length = i; - config_cmd->hdr.offset = offset; - config_cmd->hdr.client_id = 0xff; - /* Mark that this ramrod doesn't use bp->set_mac_pending for - * synchronization. - */ - config_cmd->hdr.echo = 0; - - mb(); - - return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0, - U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1); - + /* Execute the pending commands */ + __set_bit(RAMROD_CONT, &ramrod_flags); + return bnx2x_set_mac_one(bp, NULL, mac_obj, false /* don't care */, + BNX2X_UC_LIST_MAC, &ramrod_flags); } -void bnx2x_invalidate_uc_list(struct bnx2x *bp) +static inline int bnx2x_set_mc_list(struct bnx2x *bp) { - int i; - struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config); - dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config); - int ramrod_flags = WAIT_RAMROD_COMMON; - u8 offset = bnx2x_uc_list_cam_offset(bp); - u8 max_list_size = bnx2x_max_uc_list(bp); - - for (i = 0; i < max_list_size; i++) { - SET_FLAG(config_cmd->config_table[i].flags, - MAC_CONFIGURATION_ENTRY_ACTION_TYPE, - T_ETH_MAC_COMMAND_INVALIDATE); - bnx2x_set_mac_in_nig(bp, 0, NULL, LLH_CAM_ETH_LINE + 1 + i); - } - - wmb(); + struct net_device *dev = bp->dev; + struct bnx2x_mcast_ramrod_params rparam = {0}; + int rc = 0; - config_cmd->hdr.length = max_list_size; - config_cmd->hdr.offset = offset; - config_cmd->hdr.client_id = 0xff; - /* We'll wait for a completion this time... */ - config_cmd->hdr.echo = 1; + rparam.mcast_obj = &bp->mcast_obj; - bp->set_mac_pending = 1; + /* first, clear all configured multicast MACs */ + rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL); + if (rc < 0) { + BNX2X_ERR("Failed to clear multicast " + "configuration: %d\n", rc); + return rc; + } - mb(); + /* then, configure a new MACs list */ + if (netdev_mc_count(dev)) { + rc = bnx2x_init_mcast_macs_list(bp, &rparam); + if (rc) { + BNX2X_ERR("Failed to create multicast MACs " + "list: %d\n", rc); + return rc; + } - bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0, - U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1); + /* Now add the new MACs */ + rc = bnx2x_config_mcast(bp, &rparam, + BNX2X_MCAST_CMD_ADD); + if (rc < 0) + BNX2X_ERR("Failed to set a new multicast " + "configuration: %d\n", rc); - /* Wait for a completion */ - bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, - ramrod_flags); + bnx2x_free_mcast_macs_list(&rparam); + } + return rc; } -static inline int bnx2x_set_mc_list(struct bnx2x *bp) -{ - /* some multicasts */ - if (CHIP_IS_E1(bp)) { - return bnx2x_set_e1_mc_list(bp); - } else { /* E1H and newer */ - return bnx2x_set_e1h_mc_list(bp); - } -} -/* called with netif_tx_lock from dev_mcast.c */ +/* If bp->state is OPEN, should be called with netif_addr_lock_bh() */ void bnx2x_set_rx_mode(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); @@ -8151,23 +9048,31 @@ void bnx2x_set_rx_mode(struct net_device *dev) return; } - DP(NETIF_MSG_IFUP, "dev->flags = %x\n", dev->flags); + DP(NETIF_MSG_IFUP, "dev->flags = %x\n", bp->dev->flags); if (dev->flags & IFF_PROMISC) rx_mode = BNX2X_RX_MODE_PROMISC; - else if (dev->flags & IFF_ALLMULTI) + else if ((dev->flags & IFF_ALLMULTI) || + ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) && + CHIP_IS_E1(bp))) rx_mode = BNX2X_RX_MODE_ALLMULTI; else { /* some multicasts */ - if (bnx2x_set_mc_list(bp)) + if (bnx2x_set_mc_list(bp) < 0) rx_mode = BNX2X_RX_MODE_ALLMULTI; - /* some unicasts */ - if (bnx2x_set_uc_list(bp)) + if (bnx2x_set_uc_list(bp) < 0) rx_mode = BNX2X_RX_MODE_PROMISC; } bp->rx_mode = rx_mode; + + /* Schedule the rx_mode command */ + if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) { + set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state); + return; + } + bnx2x_set_storm_rx_mode(bp); } @@ -8258,8 +9163,28 @@ static const struct net_device_ops bnx2x_netdev_ops = { #endif }; +static inline int bnx2x_set_coherency_mask(struct bnx2x *bp) +{ + struct device *dev = &bp->pdev->dev; + + if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) { + bp->flags |= USING_DAC_FLAG; + if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) { + dev_err(dev, "dma_set_coherent_mask failed, " + "aborting\n"); + return -EIO; + } + } else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) { + dev_err(dev, "System does not support DMA, aborting\n"); + return -EIO; + } + + return 0; +} + static int __devinit bnx2x_init_dev(struct pci_dev *pdev, - struct net_device *dev) + struct net_device *dev, + unsigned long board_type) { struct bnx2x *bp; int rc; @@ -8321,21 +9246,9 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, goto err_out_release; } - if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) == 0) { - bp->flags |= USING_DAC_FLAG; - if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)) != 0) { - dev_err(&bp->pdev->dev, "dma_set_coherent_mask" - " failed, aborting\n"); - rc = -EIO; - goto err_out_release; - } - - } else if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)) != 0) { - dev_err(&bp->pdev->dev, - "System does not support DMA, aborting\n"); - rc = -EIO; + rc = bnx2x_set_coherency_mask(bp); + if (rc) goto err_out_release; - } dev->mem_start = pci_resource_start(pdev, 0); dev->base_addr = dev->mem_start; @@ -8371,6 +9284,12 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(bp)*16, 0); REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(bp)*16, 0); + /** + * Enable internal target-read (in case we are probed after PF FLR). + * Must be done prior to any BAR read access + */ + REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); + /* Reset the load counter */ bnx2x_clear_load_cnt(bp); @@ -8585,7 +9504,7 @@ int bnx2x_init_firmware(struct bnx2x *bp) fw_file_name = FW_FILE_NAME_E1; else if (CHIP_IS_E1H(bp)) fw_file_name = FW_FILE_NAME_E1H; - else if (CHIP_IS_E2(bp)) + else if (!CHIP_IS_E1x(bp)) fw_file_name = FW_FILE_NAME_E2; else { BNX2X_ERR("Unsupported chip revision\n"); @@ -8653,6 +9572,44 @@ request_firmware_exit: return rc; } +static void bnx2x_release_firmware(struct bnx2x *bp) +{ + kfree(bp->init_ops_offsets); + kfree(bp->init_ops); + kfree(bp->init_data); + release_firmware(bp->firmware); +} + + +static struct bnx2x_func_sp_drv_ops bnx2x_func_sp_drv = { + .init_hw_cmn_chip = bnx2x_init_hw_common_chip, + .init_hw_cmn = bnx2x_init_hw_common, + .init_hw_port = bnx2x_init_hw_port, + .init_hw_func = bnx2x_init_hw_func, + + .reset_hw_cmn = bnx2x_reset_common, + .reset_hw_port = bnx2x_reset_port, + .reset_hw_func = bnx2x_reset_func, + + .gunzip_init = bnx2x_gunzip_init, + .gunzip_end = bnx2x_gunzip_end, + + .init_fw = bnx2x_init_firmware, + .release_fw = bnx2x_release_firmware, +}; + +void bnx2x__init_func_obj(struct bnx2x *bp) +{ + /* Prepare DMAE related driver resources */ + bnx2x_setup_dmae(bp); + + bnx2x_init_func_obj(bp, &bp->func_obj, + bnx2x_sp(bp, func_rdata), + bnx2x_sp_mapping(bp, func_rdata), + &bnx2x_func_sp_drv); +} + +/* must be called after sriov-enable */ static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count) { int cid_count = L2_FP_COUNT(l2_cid_count); @@ -8663,6 +9620,25 @@ static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count) return roundup(cid_count, QM_CID_ROUND); } +/** + * bnx2x_pci_msix_table_size - get the size of the MSI-X table. + * + * @dev: pci device + * + */ +static inline int bnx2x_pci_msix_table_size(struct pci_dev *pdev) +{ + int pos; + u16 control; + + pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); + if (!pos) + return 0; + + pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &control); + return (control & PCI_MSIX_FLAGS_QSIZE) + 1; +} + static int __devinit bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -8675,12 +9651,28 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, case BCM57710: case BCM57711: case BCM57711E: - cid_count = FP_SB_MAX_E1x; - break; - case BCM57712: - case BCM57712E: - cid_count = FP_SB_MAX_E2; + case BCM57712_MF: + case BCM57800: + case BCM57800_MF: + case BCM57810: + case BCM57810_MF: + case BCM57840: + case BCM57840_MF: + /* The size requested for the MSI-X table corresponds to the + * actual amount of avaliable IGU/HC status blocks. It includes + * the default SB vector but we want cid_count to contain the + * amount of only non-default SBs, that's what '-1' stands for. + */ + cid_count = bnx2x_pci_msix_table_size(pdev) - 1; + + /* do not allow initial cid_count grow above 16 + * since Special CIDs starts from this number + * use old FP_SB_MAX_E1x define for this matter + */ + cid_count = min_t(int, FP_SB_MAX_E1x, cid_count); + + WARN_ON(!cid_count); break; default: @@ -8689,7 +9681,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, return -ENODEV; } - cid_count += NONE_ETH_CONTEXT_USE + CNIC_CONTEXT_USE; + cid_count += FCOE_CONTEXT_USE; /* dev zeroed in init_etherdev */ dev = alloc_etherdev_mq(sizeof(*bp), cid_count); @@ -8698,6 +9690,11 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, return -ENOMEM; } + /* We don't need a Tx queue for a CNIC and an OOO Rx-only ring, + * so update a cid_count after a netdev allocation. + */ + cid_count += CNIC_CONTEXT_USE; + bp = netdev_priv(dev); bp->msg_enable = debug; @@ -8705,12 +9702,14 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, bp->l2_cid_count = cid_count; - rc = bnx2x_init_dev(pdev, dev); + rc = bnx2x_init_dev(pdev, dev, ent->driver_data); if (rc < 0) { free_netdev(dev); return rc; } + BNX2X_DEV_INFO("cid_count=%d\n", cid_count); + rc = bnx2x_init_bp(bp); if (rc) goto init_one_exit; @@ -8847,12 +9846,17 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bp->rx_mode = BNX2X_RX_MODE_NONE; +#ifdef BCM_CNIC + bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); +#endif + /* Stop Tx */ + bnx2x_tx_disable(bp); + bnx2x_netif_stop(bp, 0); - netif_carrier_off(bp->dev); del_timer_sync(&bp->timer); - bp->stats_state = STATS_STATE_DISABLED; - DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n"); + + bnx2x_stats_handle(bp, STATS_EVENT_STOP); /* Release IRQs */ bnx2x_free_irq(bp); @@ -8867,6 +9871,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bp->state = BNX2X_STATE_CLOSED; + netif_carrier_off(bp->dev); + return 0; } @@ -9043,6 +10049,24 @@ module_init(bnx2x_init); module_exit(bnx2x_cleanup); #ifdef BCM_CNIC +/** + * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s). + * + * @bp: driver handle + * @set: set or clear the CAM entry + * + * This function will wait until the ramdord completion returns. + * Return 0 if success, -ENODEV if ramrod doesn't return. + */ +static inline int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp) +{ + unsigned long ramrod_flags = 0; + + __set_bit(RAMROD_COMP_WAIT, &ramrod_flags); + return bnx2x_set_mac_one(bp, bp->cnic_eth_dev.iscsi_mac, + &bp->iscsi_l2_mac_obj, true, + BNX2X_ISCSI_ETH_MAC, &ramrod_flags); +} /* count denotes the number of new completions we have seen */ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count) @@ -9063,23 +10087,22 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count) u16 type = (le16_to_cpu(bp->cnic_kwq_cons->hdr.type) & SPE_HDR_CONN_TYPE) >> SPE_HDR_CONN_TYPE_SHIFT; + u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->hdr.conn_and_cmd_data) + >> SPE_HDR_CMD_ID_SHIFT) & 0xff; /* Set validation for iSCSI L2 client before sending SETUP * ramrod */ if (type == ETH_CONNECTION_TYPE) { - u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons-> - hdr.conn_and_cmd_data) >> - SPE_HDR_CMD_ID_SHIFT) & 0xff; - if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP) - bnx2x_set_ctx_validation(&bp->context. - vcxt[BNX2X_ISCSI_ETH_CID].eth, - HW_CID(bp, BNX2X_ISCSI_ETH_CID)); + bnx2x_set_ctx_validation(bp, &bp->context. + vcxt[BNX2X_ISCSI_ETH_CID].eth, + BNX2X_ISCSI_ETH_CID); } - /* There may be not more than 8 L2 and not more than 8 L5 SPEs - * We also check that the number of outstanding + /* + * There may be not more than 8 L2, not more than 8 L5 SPEs + * and in the air. We also check that number of outstanding * COMMON ramrods is not more than the EQ and SPQ can * accommodate. */ @@ -9205,18 +10228,61 @@ int bnx2x_cnic_notify(struct bnx2x *bp, int cmd) return bnx2x_cnic_ctl_send(bp, &ctl); } -static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid) +static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err) { - struct cnic_ctl_info ctl; + struct cnic_ctl_info ctl = {0}; /* first we tell CNIC and only then we count this as a completion */ ctl.cmd = CNIC_CTL_COMPLETION_CMD; ctl.data.comp.cid = cid; + ctl.data.comp.error = err; bnx2x_cnic_ctl_send_bh(bp, &ctl); bnx2x_cnic_sp_post(bp, 0); } + +/* Called with netif_addr_lock_bh() taken. + * Sets an rx_mode config for an iSCSI ETH client. + * Doesn't block. + * Completion should be checked outside. + */ +static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start) +{ + unsigned long accept_flags = 0, ramrod_flags = 0; + u8 cl_id = bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX); + int sched_state = BNX2X_FILTER_ISCSI_ETH_STOP_SCHED; + + if (start) { + /* Start accepting on iSCSI L2 ring. Accept all multicasts + * because it's the only way for UIO Queue to accept + * multicasts (in non-promiscuous mode only one Queue per + * function will receive multicast packets (leading in our + * case). + */ + __set_bit(BNX2X_ACCEPT_UNICAST, &accept_flags); + __set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags); + __set_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags); + __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags); + + /* Clear STOP_PENDING bit if START is requested */ + clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &bp->sp_state); + + sched_state = BNX2X_FILTER_ISCSI_ETH_START_SCHED; + } else + /* Clear START_PENDING bit if STOP is requested */ + clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &bp->sp_state); + + if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) + set_bit(sched_state, &bp->sp_state); + else { + __set_bit(RAMROD_RX, &ramrod_flags); + bnx2x_set_q_rx_mode(bp, cl_id, 0, accept_flags, 0, + ramrod_flags); + } +} + + static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) { struct bnx2x *bp = netdev_priv(dev); @@ -9240,45 +10306,65 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) /* rtnl_lock is held. */ case DRV_CTL_START_L2_CMD: { - u32 cli = ctl->data.ring.client_id; - - /* Clear FCoE FIP and ALL ENODE MACs addresses first */ - bnx2x_del_fcoe_eth_macs(bp); + struct cnic_eth_dev *cp = &bp->cnic_eth_dev; + unsigned long sp_bits = 0; + + /* Configure the iSCSI classification object */ + bnx2x_init_mac_obj(bp, &bp->iscsi_l2_mac_obj, + cp->iscsi_l2_client_id, + cp->iscsi_l2_cid, BP_FUNC(bp), + bnx2x_sp(bp, mac_rdata), + bnx2x_sp_mapping(bp, mac_rdata), + BNX2X_FILTER_MAC_PENDING, + &bp->sp_state, BNX2X_OBJ_TYPE_RX, + &bp->macs_pool); /* Set iSCSI MAC address */ - bnx2x_set_iscsi_eth_mac_addr(bp, 1); + rc = bnx2x_set_iscsi_eth_mac_addr(bp); + if (rc) + break; mmiowb(); barrier(); - /* Start accepting on iSCSI L2 ring. Accept all multicasts - * because it's the only way for UIO Client to accept - * multicasts (in non-promiscuous mode only one Client per - * function will receive multicast packets (leading in our - * case). - */ - bnx2x_rxq_set_mac_filters(bp, cli, - BNX2X_ACCEPT_UNICAST | - BNX2X_ACCEPT_BROADCAST | - BNX2X_ACCEPT_ALL_MULTICAST); - storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp)); + /* Start accepting on iSCSI L2 ring */ + + netif_addr_lock_bh(dev); + bnx2x_set_iscsi_eth_rx_mode(bp, true); + netif_addr_unlock_bh(dev); + + /* bits to wait on */ + __set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits); + __set_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &sp_bits); + + if (!bnx2x_wait_sp_comp(bp, sp_bits)) + BNX2X_ERR("rx_mode completion timed out!\n"); break; } /* rtnl_lock is held. */ case DRV_CTL_STOP_L2_CMD: { - u32 cli = ctl->data.ring.client_id; + unsigned long sp_bits = 0; /* Stop accepting on iSCSI L2 ring */ - bnx2x_rxq_set_mac_filters(bp, cli, BNX2X_ACCEPT_NONE); - storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp)); + netif_addr_lock_bh(dev); + bnx2x_set_iscsi_eth_rx_mode(bp, false); + netif_addr_unlock_bh(dev); + + /* bits to wait on */ + __set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits); + __set_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &sp_bits); + + if (!bnx2x_wait_sp_comp(bp, sp_bits)) + BNX2X_ERR("rx_mode completion timed out!\n"); mmiowb(); barrier(); /* Unset iSCSI L2 MAC */ - bnx2x_set_iscsi_eth_mac_addr(bp, 0); + rc = bnx2x_del_all_macs(bp, &bp->iscsi_l2_mac_obj, + BNX2X_ISCSI_ETH_MAC, true); break; } case DRV_CTL_RET_L2_SPQ_CREDIT_CMD: { @@ -9290,11 +10376,6 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) break; } - case DRV_CTL_ISCSI_STOPPED_CMD: { - bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_ISCSI_STOPPED); - break; - } - default: BNX2X_ERR("unknown command %x\n", ctl->cmd); rc = -EINVAL; @@ -9315,13 +10396,13 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp) cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX; cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX; } - if (CHIP_IS_E2(bp)) + if (!CHIP_IS_E1x(bp)) cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e2_sb; else cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e1x_sb; - cp->irq_arr[0].status_blk_num = CNIC_SB_ID(bp); - cp->irq_arr[0].status_blk_num2 = CNIC_IGU_SB_ID(bp); + cp->irq_arr[0].status_blk_num = bnx2x_cnic_fw_sb_id(bp); + cp->irq_arr[0].status_blk_num2 = bnx2x_cnic_igu_sb_id(bp); cp->irq_arr[1].status_blk = bp->def_status_blk; cp->irq_arr[1].status_blk_num = DEF_SB_ID; cp->irq_arr[1].status_blk_num2 = DEF_SB_IGU_ID; @@ -9352,7 +10433,7 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops, bp->cnic_data = data; cp->num_irq = 0; - cp->drv_state = CNIC_DRV_STATE_REGD; + cp->drv_state |= CNIC_DRV_STATE_REGD; cp->iro_arr = bp->iro_arr; bnx2x_setup_cnic_irq_info(bp); @@ -9406,8 +10487,8 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev) cp->drv_register_cnic = bnx2x_register_cnic; cp->drv_unregister_cnic = bnx2x_unregister_cnic; cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID; - cp->iscsi_l2_client_id = BNX2X_ISCSI_ETH_CL_ID + - BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE; + cp->iscsi_l2_client_id = + bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX); cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID; if (NO_ISCSI_OOO(bp)) |