-/* bnx2x.c: Broadcom Everest network driver.
+/* bnx2x_main.c: Broadcom Everest network driver.
*
* Copyright (c) 2007-2008 Broadcom Corporation
*
*
*/
-/* define this to make the driver freeze on error
- * to allow getting debug info
- * (you will need to reboot afterwards)
- */
-/*#define BNX2X_STOP_ON_ERROR*/
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/mii.h>
#ifdef NETIF_F_HW_VLAN_TX
#include <linux/if_vlan.h>
- #define BCM_VLAN 1
#endif
#include <net/ip.h>
#include <net/tcp.h>
#include <net/checksum.h>
+#include <linux/version.h>
+#include <net/ip6_checksum.h>
#include <linux/workqueue.h>
#include <linux/crc32.h>
+#include <linux/crc32c.h>
#include <linux/prefetch.h>
#include <linux/zlib.h>
-#include <linux/version.h>
#include <linux/io.h>
#include "bnx2x_reg.h"
#define DRV_MODULE_VERSION "1.42.4"
#define DRV_MODULE_RELDATE "2008/4/9"
-#define BNX2X_BC_VER 0x040200
+#define BNX2X_BC_VER 0x040200
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (5*HZ)
+/* Time in jiffies before concluding the transmitter is hung */
+#define TX_TIMEOUT (5*HZ)
static char version[] __devinitdata =
- "Broadcom NetXtreme II 5771X 10Gigabit Ethernet Driver "
+ "Broadcom NetXtreme II 5771x 10Gigabit Ethernet Driver "
DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Eliezer Tamir");
static int use_inta;
static int poll;
-static int onefunc;
-static int nomcp;
static int debug;
+static int nomcp;
+static int load_count[3]; /* 0-common, 1-port0, 2-port1 */
static int use_multi;
module_param(use_inta, int, 0);
module_param(poll, int, 0);
-module_param(onefunc, int, 0);
module_param(debug, int, 0);
+module_param(nomcp, int, 0);
MODULE_PARM_DESC(use_inta, "use INT#A instead of MSI-X");
MODULE_PARM_DESC(poll, "use polling (for debug)");
-MODULE_PARM_DESC(onefunc, "enable only first function");
-MODULE_PARM_DESC(nomcp, "ignore management CPU (Implies onefunc)");
MODULE_PARM_DESC(debug, "default debug msglevel");
+MODULE_PARM_DESC(nomcp, "ignore management CPU");
#ifdef BNX2X_MULTI
module_param(use_multi, int, 0);
enum bnx2x_board_type {
BCM57710 = 0,
+ BCM57711 = 1,
+ BCM57711E = 2,
};
-/* indexed by board_t, above */
+/* indexed by board_type, above */
static struct {
char *name;
} board_info[] __devinitdata = {
- { "Broadcom NetXtreme II BCM57710 XGb" }
+ { "Broadcom NetXtreme II BCM57710 XGb" },
+ { "Broadcom NetXtreme II BCM57711 XGb" },
+ { "Broadcom NetXtreme II BCM57711E XGb" }
};
+
static const struct pci_device_id bnx2x_pci_tbl[] = {
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57710,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM57710 },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57711,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM57711 },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57711E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM57711E },
{ 0 }
};
#else
DMAE_CMD_ENDIANITY_DW_SWAP |
#endif
- (bp->port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0));
+ (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
+ (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
dmae->src_addr_lo = U64_LO(dma_addr);
dmae->src_addr_hi = U64_HI(dma_addr);
dmae->dst_addr_lo = dst_addr >> 2;
*wb_comp = 0;
- bnx2x_post_dmae(bp, dmae, (bp->port)*MAX_DMAE_C_PER_PORT);
+ bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
udelay(5);
#else
DMAE_CMD_ENDIANITY_DW_SWAP |
#endif
- (bp->port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0));
+ (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
+ (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
dmae->src_addr_lo = src_addr >> 2;
dmae->src_addr_hi = 0;
dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_data));
*wb_comp = 0;
- bnx2x_post_dmae(bp, dmae, (bp->port)*MAX_DMAE_C_PER_PORT);
+ bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
udelay(5);
static int bnx2x_mc_assert(struct bnx2x *bp)
{
- int i, j, rc = 0;
char last_idx;
- const char storm[] = {"XTCU"};
- const u32 intmem_base[] = {
- BAR_XSTRORM_INTMEM,
- BAR_TSTRORM_INTMEM,
- BAR_CSTRORM_INTMEM,
- BAR_USTRORM_INTMEM
- };
-
- /* Go through all instances of all SEMIs */
- for (i = 0; i < 4; i++) {
- last_idx = REG_RD8(bp, XSTORM_ASSERT_LIST_INDEX_OFFSET +
- intmem_base[i]);
- if (last_idx)
- BNX2X_LOG("DATA %cSTORM_ASSERT_LIST_INDEX 0x%x\n",
- storm[i], last_idx);
-
- /* print the asserts */
- for (j = 0; j < STROM_ASSERT_ARRAY_SIZE; j++) {
- u32 row0, row1, row2, row3;
-
- row0 = REG_RD(bp, XSTORM_ASSERT_LIST_OFFSET(j) +
- intmem_base[i]);
- row1 = REG_RD(bp, XSTORM_ASSERT_LIST_OFFSET(j) + 4 +
- intmem_base[i]);
- row2 = REG_RD(bp, XSTORM_ASSERT_LIST_OFFSET(j) + 8 +
- intmem_base[i]);
- row3 = REG_RD(bp, XSTORM_ASSERT_LIST_OFFSET(j) + 12 +
- intmem_base[i]);
-
- if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
- BNX2X_LOG("DATA %cSTORM_ASSERT_INDEX 0x%x ="
- " 0x%08x 0x%08x 0x%08x 0x%08x\n",
- storm[i], j, row3, row2, row1, row0);
- rc++;
- } else {
- break;
- }
+ int i, rc = 0;
+ u32 row0, row1, row2, row3;
+
+ /* XSTORM */
+ last_idx = REG_RD8(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_ASSERT_LIST_INDEX_OFFSET);
+ if (last_idx)
+ BNX2X_ERR("XSTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
+
+ /* print the asserts */
+ for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
+
+ row0 = REG_RD(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_ASSERT_LIST_OFFSET(i));
+ row1 = REG_RD(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_ASSERT_LIST_OFFSET(i) + 4);
+ row2 = REG_RD(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_ASSERT_LIST_OFFSET(i) + 8);
+ row3 = REG_RD(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_ASSERT_LIST_OFFSET(i) + 12);
+
+ if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
+ BNX2X_ERR("XSTORM_ASSERT_INDEX 0x%x = 0x%08x"
+ " 0x%08x 0x%08x 0x%08x\n",
+ i, row3, row2, row1, row0);
+ rc++;
+ } else {
+ break;
+ }
+ }
+
+ /* TSTORM */
+ last_idx = REG_RD8(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_ASSERT_LIST_INDEX_OFFSET);
+ if (last_idx)
+ BNX2X_ERR("TSTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
+
+ /* print the asserts */
+ for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
+
+ row0 = REG_RD(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_ASSERT_LIST_OFFSET(i));
+ row1 = REG_RD(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_ASSERT_LIST_OFFSET(i) + 4);
+ row2 = REG_RD(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_ASSERT_LIST_OFFSET(i) + 8);
+ row3 = REG_RD(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_ASSERT_LIST_OFFSET(i) + 12);
+
+ if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
+ BNX2X_ERR("TSTORM_ASSERT_INDEX 0x%x = 0x%08x"
+ " 0x%08x 0x%08x 0x%08x\n",
+ i, row3, row2, row1, row0);
+ rc++;
+ } else {
+ break;
+ }
+ }
+
+ /* CSTORM */
+ last_idx = REG_RD8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_ASSERT_LIST_INDEX_OFFSET);
+ if (last_idx)
+ BNX2X_ERR("CSTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
+
+ /* print the asserts */
+ for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
+
+ row0 = REG_RD(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_ASSERT_LIST_OFFSET(i));
+ row1 = REG_RD(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_ASSERT_LIST_OFFSET(i) + 4);
+ row2 = REG_RD(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_ASSERT_LIST_OFFSET(i) + 8);
+ row3 = REG_RD(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_ASSERT_LIST_OFFSET(i) + 12);
+
+ if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
+ BNX2X_ERR("CSTORM_ASSERT_INDEX 0x%x = 0x%08x"
+ " 0x%08x 0x%08x 0x%08x\n",
+ i, row3, row2, row1, row0);
+ rc++;
+ } else {
+ break;
+ }
+ }
+
+ /* USTORM */
+ last_idx = REG_RD8(bp, BAR_USTRORM_INTMEM +
+ USTORM_ASSERT_LIST_INDEX_OFFSET);
+ if (last_idx)
+ BNX2X_ERR("USTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
+
+ /* print the asserts */
+ for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
+
+ row0 = REG_RD(bp, BAR_USTRORM_INTMEM +
+ USTORM_ASSERT_LIST_OFFSET(i));
+ row1 = REG_RD(bp, BAR_USTRORM_INTMEM +
+ USTORM_ASSERT_LIST_OFFSET(i) + 4);
+ row2 = REG_RD(bp, BAR_USTRORM_INTMEM +
+ USTORM_ASSERT_LIST_OFFSET(i) + 8);
+ row3 = REG_RD(bp, BAR_USTRORM_INTMEM +
+ USTORM_ASSERT_LIST_OFFSET(i) + 12);
+
+ if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
+ BNX2X_ERR("USTORM_ASSERT_INDEX 0x%x = 0x%08x"
+ " 0x%08x 0x%08x 0x%08x\n",
+ i, row3, row2, row1, row0);
+ rc++;
+ } else {
+ break;
}
}
+
return rc;
}
struct eth_tx_db_data *hw_prods = fp->hw_tx_prods;
BNX2X_ERR("queue[%d]: tx_pkt_prod(%x) tx_pkt_cons(%x)"
- " tx_bd_prod(%x) tx_bd_cons(%x) *tx_cons_sb(%x)"
- " *rx_cons_sb(%x) rx_comp_prod(%x)"
- " rx_comp_cons(%x) fp_c_idx(%x) fp_u_idx(%x)"
- " bd data(%x,%x)\n",
+ " tx_bd_prod(%x) tx_bd_cons(%x) *tx_cons_sb(%x)\n",
i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod,
- fp->tx_bd_cons, *fp->tx_cons_sb, *fp->rx_cons_sb,
- fp->rx_comp_prod, fp->rx_comp_cons, fp->fp_c_idx,
- fp->fp_u_idx, hw_prods->packets_prod,
+ fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb));
+ BNX2X_ERR(" rx_comp_prod(%x) rx_comp_cons(%x)"
+ " *rx_cons_sb(%x)\n",
+ fp->rx_comp_prod, fp->rx_comp_cons,
+ le16_to_cpu(*fp->rx_cons_sb));
+ BNX2X_ERR(" fp_c_idx(%x) fp_u_idx(%x)"
+ " bd data(%x,%x)\n",
+ fp->fp_c_idx, fp->fp_u_idx, hw_prods->packets_prod,
hw_prods->bds_prod);
start = TX_BD(le16_to_cpu(*fp->tx_cons_sb) - 10);
struct sw_rx_bd *sw_bd = &fp->rx_buf_ring[j];
BNX2X_ERR("rx_bd[%x]=[%x:%x] sw_bd=[%p]\n",
- j, rx_bd[0], rx_bd[1], sw_bd->skb);
+ j, rx_bd[1], rx_bd[0], sw_bd->skb);
}
start = RCQ_BD(fp->rx_comp_cons - 10);
bp->def_c_idx, bp->def_u_idx, bp->def_x_idx, bp->def_t_idx,
bp->def_att_idx, bp->attn_state, bp->spq_prod_idx);
-
+ bnx2x_fw_dump(bp);
bnx2x_mc_assert(bp);
BNX2X_ERR("end crash dump -----------------\n");
static void bnx2x_int_enable(struct bnx2x *bp)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
u32 val = REG_RD(bp, addr);
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
HC_CONFIG_0_REG_INT_LINE_EN_0 |
HC_CONFIG_0_REG_ATTN_BIT_EN_0);
- /* Errata A0.158 workaround */
DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x) MSI-X %d\n",
val, port, addr, msix);
val, port, addr, msix);
REG_WR(bp, addr, val);
+
+ if (CHIP_IS_E1H(bp)) {
+ /* init leading/trailing edge */
+ if (IS_E1HMF(bp)) {
+ val = (0xfe0f | (1 << (BP_E1HVN(bp) + 4)));
+ if (bp->port.pmf)
+ /* enable nig attention */
+ val |= 0x0100;
+ } else
+ val = 0xffff;
+
+ REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
+ REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
+ }
}
static void bnx2x_int_disable(struct bnx2x *bp)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
u32 val = REG_RD(bp, addr);
static void bnx2x_int_disable_sync(struct bnx2x *bp)
{
-
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
int i;
+ /* disable interrupt handling */
atomic_inc(&bp->intr_sem);
/* prevent the HW from sending interrupts */
bnx2x_int_disable(bp);
/* make sure sp_task is not running */
cancel_work_sync(&bp->sp_task);
-
}
-/* fast path code */
+/* fast path */
/*
- * general service functions
+ * General service functions
*/
-static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 id,
+static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
u8 storm, u16 index, u8 op, u8 update)
{
- u32 igu_addr = (IGU_ADDR_INT_ACK + IGU_PORT_BASE * bp->port) * 8;
+ u32 igu_addr = (IGU_ADDR_INT_ACK + IGU_FUNC_BASE * BP_FUNC(bp)) * 8;
struct igu_ack_register igu_ack;
igu_ack.status_block_index = index;
igu_ack.sb_id_and_flags =
- ((id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) |
+ ((sb_id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) |
(storm << IGU_ACK_REGISTER_STORM_ID_SHIFT) |
(update << IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT) |
(op << IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT));
-/* DP(NETIF_MSG_INTR, "write 0x%08x to IGU addr 0x%x\n",
- (*(u32 *)&igu_ack), BAR_IGU_INTMEM + igu_addr); */
+ DP(BNX2X_MSG_OFF, "write 0x%08x to IGU addr 0x%x\n",
+ (*(u32 *)&igu_ack), BAR_IGU_INTMEM + igu_addr);
REG_WR(bp, BAR_IGU_INTMEM + igu_addr, (*(u32 *)&igu_ack));
}
if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
rx_cons_sb++;
- if ((rx_cons_sb != fp->rx_comp_cons) ||
- (le16_to_cpu(*fp->tx_cons_sb) != fp->tx_pkt_cons))
+ if ((fp->rx_comp_cons != rx_cons_sb) ||
+ (fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) ||
+ (fp->tx_pkt_prod != fp->tx_pkt_cons))
return 1;
return 0;
static u16 bnx2x_ack_int(struct bnx2x *bp)
{
- u32 igu_addr = (IGU_ADDR_SIMD_MASK + IGU_PORT_BASE * bp->port) * 8;
+ u32 igu_addr = (IGU_ADDR_SIMD_MASK + IGU_FUNC_BASE * BP_FUNC(bp)) * 8;
u32 result = REG_RD(bp, BAR_IGU_INTMEM + igu_addr);
-/* DP(NETIF_MSG_INTR, "read 0x%08x from IGU addr 0x%x\n",
- result, BAR_IGU_INTMEM + igu_addr); */
+ DP(BNX2X_MSG_OFF, "read 0x%08x from IGU addr 0x%x\n",
+ result, BAR_IGU_INTMEM + igu_addr);
#ifdef IGU_DEBUG
#warning IGU_DEBUG active
struct sw_tx_bd *tx_buf = &fp->tx_buf_ring[idx];
struct eth_tx_bd *tx_bd;
struct sk_buff *skb = tx_buf->skb;
- u16 bd_idx = tx_buf->first_bd;
+ u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
int nbd;
DP(BNX2X_MSG_OFF, "pkt_idx %d buff @(%p)->skb %p\n",
BD_UNMAP_LEN(tx_bd), PCI_DMA_TODEVICE);
nbd = le16_to_cpu(tx_bd->nbd) - 1;
+ new_cons = nbd + tx_buf->first_bd;
#ifdef BNX2X_STOP_ON_ERROR
if (nbd > (MAX_SKB_FRAGS + 2)) {
- BNX2X_ERR("bad nbd!\n");
+ BNX2X_ERR("BAD nbd!\n");
bnx2x_panic();
}
#endif
tx_buf->first_bd = 0;
tx_buf->skb = NULL;
- return bd_idx;
+ return new_cons;
}
-static inline u32 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
+static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
{
- u16 used;
- u32 prod;
- u32 cons;
+ s16 used;
+ u16 prod;
+ u16 cons;
- /* Tell compiler that prod and cons can change */
- barrier();
+ barrier(); /* Tell compiler that prod and cons can change */
prod = fp->tx_bd_prod;
cons = fp->tx_bd_cons;
- used = (NUM_TX_BD - NUM_TX_RINGS + prod - cons +
- (cons / TX_DESC_CNT) - (prod / TX_DESC_CNT));
-
- if (prod >= cons) {
- /* used = prod - cons - prod/size + cons/size */
- used -= NUM_TX_BD - NUM_TX_RINGS;
- }
+ /* NUM_TX_RINGS = number of "next-page" entries
+ It will be used as a threshold */
+ used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS;
+#ifdef BNX2X_STOP_ON_ERROR
+ BUG_TRAP(used >= 0);
BUG_TRAP(used <= fp->bp->tx_ring_size);
BUG_TRAP((fp->bp->tx_ring_size - used) <= MAX_TX_AVAIL);
+#endif
- return (fp->bp->tx_ring_size - used);
+ return (s16)(fp->bp->tx_ring_size) - used;
}
static void bnx2x_tx_int(struct bnx2x_fastpath *fp, int work)
/* prefetch(bp->tx_buf_ring[pkt_cons].skb); */
- DP(NETIF_MSG_TX_DONE, "hw_cons %u sw_cons %u pkt_cons %d\n",
+ DP(NETIF_MSG_TX_DONE, "hw_cons %u sw_cons %u pkt_cons %u\n",
hw_cons, sw_cons, pkt_cons);
-/* if (NEXT_TX_IDX(sw_cons) != hw_cons) {
+/* if (NEXT_TX_IDX(sw_cons) != hw_cons) {
rmb();
prefetch(fp->tx_buf_ring[NEXT_TX_IDX(sw_cons)].skb);
}
netif_wake_queue(bp->dev);
netif_tx_unlock(bp->dev);
-
}
}
int cid = SW_CID(rr_cqe->ramrod_cqe.conn_and_cmd_data);
int command = CQE_CMD(rr_cqe->ramrod_cqe.conn_and_cmd_data);
- DP(NETIF_MSG_RX_STATUS,
+ 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.type);
+ FP_IDX(fp), cid, command, bp->state,
+ rr_cqe->ramrod_cqe.ramrod_type);
bp->spq_left++;
- if (fp->index) {
+ if (FP_IDX(fp)) {
switch (command | fp->state) {
case (RAMROD_CMD_ID_ETH_CLIENT_SETUP |
BNX2X_FP_STATE_OPENING):
break;
default:
- BNX2X_ERR("unexpected MC reply(%d) state is %x\n",
- command, fp->state);
+ BNX2X_ERR("unexpected MC reply (%d) "
+ "fp->state is %x\n", command, fp->state);
+ break;
}
- mb(); /* force bnx2x_wait_ramrod to see the change */
+ mb(); /* force bnx2x_wait_ramrod() to see the change */
return;
}
break;
case (RAMROD_CMD_ID_ETH_CFC_DEL | BNX2X_STATE_CLOSING_WAIT4_HALT):
- DP(NETIF_MSG_IFDOWN, "got delete ramrod for MULTI[%d]\n",
- cid);
+ DP(NETIF_MSG_IFDOWN, "got delete ramrod for MULTI[%d]\n", cid);
bnx2x_fp(bp, cid, state) = BNX2X_FP_STATE_CLOSED;
break;
case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_OPEN):
+ case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DIAG):
DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
break;
case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_CLOSING_WAIT4_HALT):
- DP(NETIF_MSG_IFUP, "got (un)set mac ramrod\n");
+ DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
break;
default:
- BNX2X_ERR("unexpected ramrod (%d) state is %x\n",
+ BNX2X_ERR("unexpected MC reply (%d) bp->state is %x\n",
command, bp->state);
+ break;
}
-
- mb(); /* force bnx2x_wait_ramrod to see the change */
+ mb(); /* force bnx2x_wait_ramrod() to see the change */
}
static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
PCI_DMA_FROMDEVICE);
if (unlikely(dma_mapping_error(mapping))) {
-
dev_kfree_skb(skb);
return -ENOMEM;
}
static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
{
struct bnx2x *bp = fp->bp;
- u16 bd_cons, bd_prod, comp_ring_cons;
+ u16 bd_cons, bd_prod, bd_prod_fw, comp_ring_cons;
u16 hw_comp_cons, sw_comp_cons, sw_comp_prod;
int rx_pkt = 0;
return 0;
#endif
+ /* CQ "next element" is of the size of the regular element,
+ that's why it's ok here */
hw_comp_cons = le16_to_cpu(*fp->rx_cons_sb);
if ((hw_comp_cons & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
hw_comp_cons++;
bd_cons = fp->rx_bd_cons;
bd_prod = fp->rx_bd_prod;
+ bd_prod_fw = bd_prod;
sw_comp_cons = fp->rx_comp_cons;
sw_comp_prod = fp->rx_comp_prod;
DP(NETIF_MSG_RX_STATUS,
"queue[%d]: hw_comp_cons %u sw_comp_cons %u\n",
- fp->index, hw_comp_cons, sw_comp_cons);
+ FP_IDX(fp), hw_comp_cons, sw_comp_cons);
while (sw_comp_cons != hw_comp_cons) {
- unsigned int len, pad;
- struct sw_rx_bd *rx_buf;
+ struct sw_rx_bd *rx_buf = NULL;
struct sk_buff *skb;
union eth_rx_cqe *cqe;
+ u8 cqe_fp_flags;
+ u16 len, pad;
comp_ring_cons = RCQ_BD(sw_comp_cons);
bd_prod = RX_BD(bd_prod);
bd_cons = RX_BD(bd_cons);
cqe = &fp->rx_comp_ring[comp_ring_cons];
+ cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
- DP(NETIF_MSG_RX_STATUS, "hw_comp_cons %u sw_comp_cons %u"
- " comp_ring (%u) bd_ring (%u,%u)\n",
- hw_comp_cons, sw_comp_cons,
- comp_ring_cons, bd_prod, bd_cons);
DP(NETIF_MSG_RX_STATUS, "CQE type %x err %x status %x"
- " queue %x vlan %x len %x\n",
- cqe->fast_path_cqe.type,
- cqe->fast_path_cqe.error_type_flags,
- cqe->fast_path_cqe.status_flags,
+ " queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags),
+ cqe_fp_flags, cqe->fast_path_cqe.status_flags,
cqe->fast_path_cqe.rss_hash_result,
- cqe->fast_path_cqe.vlan_tag, cqe->fast_path_cqe.pkt_len);
+ le16_to_cpu(cqe->fast_path_cqe.vlan_tag),
+ le16_to_cpu(cqe->fast_path_cqe.pkt_len));
/* is this a slowpath msg? */
- if (unlikely(cqe->fast_path_cqe.type)) {
+ if (unlikely(CQE_TYPE(cqe_fp_flags))) {
bnx2x_sp_event(fp, cqe);
goto next_cqe;
} else {
rx_buf = &fp->rx_buf_ring[bd_cons];
skb = rx_buf->skb;
-
len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
pad = cqe->fast_path_cqe.placement_offset;
prefetch(((char *)(skb)) + 128);
/* is this an error packet? */
- if (unlikely(cqe->fast_path_cqe.error_type_flags &
- ETH_RX_ERROR_FALGS)) {
+ if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) {
/* do we sometimes forward error packets anyway? */
DP(NETIF_MSG_RX_ERR,
- "ERROR flags(%u) Rx packet(%u)\n",
- cqe->fast_path_cqe.error_type_flags,
- sw_comp_cons);
+ "ERROR flags %x rx packet %u\n",
+ cqe_fp_flags, sw_comp_cons);
/* TBD make sure MC counts this as a drop */
goto reuse_rx;
}
len + pad);
if (new_skb == NULL) {
DP(NETIF_MSG_RX_ERR,
- "ERROR packet dropped "
+ "ERROR packet dropped "
"because of alloc failure\n");
/* TBD count this as a drop? */
goto reuse_rx;
} else {
DP(NETIF_MSG_RX_ERR,
- "ERROR packet dropped because "
+ "ERROR packet dropped because "
"of alloc failure\n");
reuse_rx:
bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod);
}
#ifdef BCM_VLAN
- if ((le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags)
- & PARSING_FLAGS_NUMBER_OF_NESTED_VLANS)
- && (bp->vlgrp != NULL))
+ if ((bp->vlgrp != NULL) &&
+ (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
+ PARSING_FLAGS_VLAN))
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
le16_to_cpu(cqe->fast_path_cqe.vlan_tag));
else
#endif
- netif_receive_skb(skb);
+ netif_receive_skb(skb);
bp->dev->last_rx = jiffies;
bd_cons = NEXT_RX_IDX(bd_cons);
bd_prod = NEXT_RX_IDX(bd_prod);
+ bd_prod_fw = NEXT_RX_IDX(bd_prod_fw);
+ rx_pkt++;
next_cqe:
sw_comp_prod = NEXT_RCQ_IDX(sw_comp_prod);
sw_comp_cons = NEXT_RCQ_IDX(sw_comp_cons);
- rx_pkt++;
- if ((rx_pkt == budget))
+ if (rx_pkt == budget)
break;
} /* while */
fp->rx_bd_cons = bd_cons;
- fp->rx_bd_prod = bd_prod;
+ fp->rx_bd_prod = bd_prod_fw;
fp->rx_comp_cons = sw_comp_cons;
fp->rx_comp_prod = sw_comp_prod;
REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_RCQ_PROD_OFFSET(bp->port, fp->index), sw_comp_prod);
+ TSTORM_RX_PRODS_OFFSET(BP_PORT(bp), FP_CL_ID(fp)),
+ sw_comp_prod);
+
mmiowb(); /* keep prod updates ordered */
struct bnx2x_fastpath *fp = fp_cookie;
struct bnx2x *bp = fp->bp;
struct net_device *dev = bp->dev;
- int index = fp->index;
+ int index = FP_IDX(fp);
- DP(NETIF_MSG_INTR, "got an msix interrupt on [%d]\n", index);
- bnx2x_ack_sb(bp, index, USTORM_ID, 0, IGU_INT_DISABLE, 0);
+ DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB [%d:%d]\n",
+ index, FP_SB_ID(fp));
+ bnx2x_ack_sb(bp, FP_SB_ID(fp), USTORM_ID, 0, IGU_INT_DISABLE, 0);
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
prefetch(&fp->status_blk->u_status_block.status_block_index);
netif_rx_schedule(dev, &bnx2x_fp(bp, index, napi));
+
return IRQ_HANDLED;
}
struct net_device *dev = dev_instance;
struct bnx2x *bp = netdev_priv(dev);
u16 status = bnx2x_ack_int(bp);
+ u16 mask;
+ /* Return here if interrupt is shared and it's not for us */
if (unlikely(status == 0)) {
DP(NETIF_MSG_INTR, "not our interrupt!\n");
return IRQ_NONE;
}
-
- DP(NETIF_MSG_INTR, "got an interrupt status is %u\n", status);
+ DP(NETIF_MSG_INTR, "got an interrupt status %u\n", status);
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
return IRQ_HANDLED;
#endif
- /* Return here if interrupt is shared and is disabled */
+ /* Return here if interrupt is disabled */
if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
return IRQ_HANDLED;
}
- if (status & 0x2) {
+ mask = 0x2 << bp->fp[0].sb_id;
+ if (status & mask) {
struct bnx2x_fastpath *fp = &bp->fp[0];
prefetch(fp->rx_cons_sb);
netif_rx_schedule(dev, &bnx2x_fp(bp, 0, napi));
- status &= ~0x2;
- if (!status)
- return IRQ_HANDLED;
+ status &= ~mask;
}
- if (unlikely(status & 0x1)) {
+ if (unlikely(status & 0x1)) {
schedule_work(&bp->sp_task);
status &= ~0x1;
return IRQ_HANDLED;
}
- DP(NETIF_MSG_INTR, "got an unknown interrupt! (status is %u)\n",
- status);
+ if (status)
+ DP(NETIF_MSG_INTR, "got an unknown interrupt! (status %u)\n",
+ status);
return IRQ_HANDLED;
}
{
u32 lock_status;
u32 resource_bit = (1 << resource);
- u8 port = bp->port;
+ u8 port = BP_PORT(bp);
int cnt;
/* Validating that the resource is within range */
{
u32 lock_status;
u32 resource_bit = (1 << resource);
- u8 port = bp->port;
+ u8 port = BP_PORT(bp);
/* Validating that the resource is within range */
if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
{
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
- mutex_lock(&bp->phy_mutex);
+ mutex_lock(&bp->port.phy_mutex);
if ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) ||
(ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073))
(ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073))
bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO);
- mutex_unlock(&bp->phy_mutex);
+ mutex_unlock(&bp->port.phy_mutex);
}
int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode)
{
/* The GPIO should be swapped if swap register is set and active */
int gpio_port = (REG_RD(bp, NIG_REG_PORT_SWAP) &&
- REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ bp->port;
+ REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ BP_PORT(bp);
int gpio_shift = gpio_num +
(gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
u32 gpio_mask = (1 << gpio_shift);
{
switch (bp->link_vars.ieee_fc) {
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE:
- bp->advertising &= ~(ADVERTISED_Asym_Pause |
+ bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
ADVERTISED_Pause);
break;
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH:
- bp->advertising |= (ADVERTISED_Asym_Pause |
+ bp->port.advertising |= (ADVERTISED_Asym_Pause |
ADVERTISED_Pause);
break;
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC:
- bp->advertising |= ADVERTISED_Asym_Pause;
+ bp->port.advertising |= ADVERTISED_Asym_Pause;
break;
default:
- bp->advertising &= ~(ADVERTISED_Asym_Pause |
+ bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
ADVERTISED_Pause);
break;
}
bnx2x_link_report(bp);
bnx2x_calc_fc_adv(bp);
+
return rc;
}
return rc;
}
+/* Calculates the sum of vn_min_rates.
+ It's needed for further normalizing of the min_rates.
+
+ Returns:
+ sum of vn_min_rates
+ or
+ 0 - if all the min_rates are 0.
+ In the later case fainess algorithm should be deactivated.
+ If not all min_rates are zero then those that are zeroes will
+ be set to 1.
+ */
+static u32 bnx2x_calc_vn_wsum(struct bnx2x *bp)
+{
+ int i, port = BP_PORT(bp);
+ u32 wsum = 0;
+ int all_zero = 1;
+
+ for (i = 0; i < E1HVN_MAX; i++) {
+ u32 vn_cfg =
+ SHMEM_RD(bp, mf_cfg.func_mf_config[2*i + port].config);
+ u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
+ FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
+ if (!(vn_cfg & FUNC_MF_CFG_FUNC_HIDE)) {
+ /* If min rate is zero - set it to 1 */
+ if (!vn_min_rate)
+ vn_min_rate = DEF_MIN_RATE;
+ else
+ all_zero = 0;
+
+ wsum += vn_min_rate;
+ }
+ }
+
+ /* ... only if all min rates are zeros - disable FAIRNESS */
+ if (all_zero)
+ return 0;
+
+ return wsum;
+}
+
+static void bnx2x_init_port_minmax(struct bnx2x *bp,
+ int en_fness,
+ u16 port_rate,
+ struct cmng_struct_per_port *m_cmng_port)
+{
+ u32 r_param = port_rate / 8;
+ int port = BP_PORT(bp);
+ int i;
+
+ memset(m_cmng_port, 0, sizeof(struct cmng_struct_per_port));
+
+ /* Enable minmax only if we are in e1hmf mode */
+ if (IS_E1HMF(bp)) {
+ u32 fair_periodic_timeout_usec;
+ u32 t_fair;
+
+ /* Enable rate shaping and fairness */
+ m_cmng_port->flags.cmng_vn_enable = 1;
+ m_cmng_port->flags.fairness_enable = en_fness ? 1 : 0;
+ m_cmng_port->flags.rate_shaping_enable = 1;
+
+ if (!en_fness)
+ DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
+ " fairness will be disabled\n");
+
+ /* 100 usec in SDM ticks = 25 since each tick is 4 usec */
+ m_cmng_port->rs_vars.rs_periodic_timeout =
+ RS_PERIODIC_TIMEOUT_USEC / 4;
+
+ /* this is the threshold below which no timer arming will occur
+ 1.25 coefficient is for the threshold to be a little bigger
+ than the real time, to compensate for timer in-accuracy */
+ m_cmng_port->rs_vars.rs_threshold =
+ (RS_PERIODIC_TIMEOUT_USEC * r_param * 5) / 4;
+
+ /* resolution of fairness timer */
+ fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
+ /* for 10G it is 1000usec. for 1G it is 10000usec. */
+ t_fair = T_FAIR_COEF / port_rate;
+
+ /* this is the threshold below which we won't arm
+ the timer anymore */
+ m_cmng_port->fair_vars.fair_threshold = QM_ARB_BYTES;
+
+ /* we multiply by 1e3/8 to get bytes/msec.
+ We don't want the credits to pass a credit
+ of the T_FAIR*FAIR_MEM (algorithm resolution) */
+ m_cmng_port->fair_vars.upper_bound =
+ r_param * t_fair * FAIR_MEM;
+ /* since each tick is 4 usec */
+ m_cmng_port->fair_vars.fairness_timeout =
+ fair_periodic_timeout_usec / 4;
+
+ } else {
+ /* Disable rate shaping and fairness */
+ m_cmng_port->flags.cmng_vn_enable = 0;
+ m_cmng_port->flags.fairness_enable = 0;
+ m_cmng_port->flags.rate_shaping_enable = 0;
+
+ DP(NETIF_MSG_IFUP,
+ "Single function mode minmax will be disabled\n");
+ }
+
+ /* Store it to internal memory */
+ for (i = 0; i < sizeof(struct cmng_struct_per_port) / 4; i++)
+ REG_WR(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i * 4,
+ ((u32 *)(m_cmng_port))[i]);
+}
+
+static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func,
+ u32 wsum, u16 port_rate,
+ struct cmng_struct_per_port *m_cmng_port)
+{
+ struct rate_shaping_vars_per_vn m_rs_vn;
+ struct fairness_vars_per_vn m_fair_vn;
+ u32 vn_cfg = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+ u16 vn_min_rate, vn_max_rate;
+ int i;
+
+ /* If function is hidden - set min and max to zeroes */
+ if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) {
+ vn_min_rate = 0;
+ vn_max_rate = 0;
+
+ } else {
+ vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
+ FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
+ /* If FAIRNESS is enabled (not all min rates are zeroes) and
+ if current min rate is zero - set it to 1.
+ This is a requirment of the algorithm. */
+ if ((vn_min_rate == 0) && wsum)
+ vn_min_rate = DEF_MIN_RATE;
+ vn_max_rate = ((vn_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
+ FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
+ }
+
+ DP(NETIF_MSG_IFUP, "func %d: vn_min_rate=%d vn_max_rate=%d "
+ "wsum=%d\n", func, vn_min_rate, vn_max_rate, wsum);
+
+ memset(&m_rs_vn, 0, sizeof(struct rate_shaping_vars_per_vn));
+ memset(&m_fair_vn, 0, sizeof(struct fairness_vars_per_vn));
+
+ /* global vn counter - maximal Mbps for this vn */
+ m_rs_vn.vn_counter.rate = vn_max_rate;
+
+ /* quota - number of bytes transmitted in this period */
+ m_rs_vn.vn_counter.quota =
+ (vn_max_rate * RS_PERIODIC_TIMEOUT_USEC) / 8;
+
+#ifdef BNX2X_PER_PROT_QOS
+ /* per protocol counter */
+ for (protocol = 0; protocol < NUM_OF_PROTOCOLS; protocol++) {
+ /* maximal Mbps for this protocol */
+ m_rs_vn.protocol_counters[protocol].rate =
+ protocol_max_rate[protocol];
+ /* the quota in each timer period -
+ number of bytes transmitted in this period */
+ m_rs_vn.protocol_counters[protocol].quota =
+ (u32)(rs_periodic_timeout_usec *
+ ((double)m_rs_vn.
+ protocol_counters[protocol].rate/8));
+ }
+#endif
+
+ if (wsum) {
+ /* credit for each period of the fairness algorithm:
+ number of bytes in T_FAIR (the vn share the port rate).
+ wsum should not be larger than 10000, thus
+ T_FAIR_COEF / (8 * wsum) will always be grater than zero */
+ m_fair_vn.vn_credit_delta =
+ max((u64)(vn_min_rate * (T_FAIR_COEF / (8 * wsum))),
+ (u64)(m_cmng_port->fair_vars.fair_threshold * 2));
+ DP(NETIF_MSG_IFUP, "m_fair_vn.vn_credit_delta=%d\n",
+ m_fair_vn.vn_credit_delta);
+ }
+
+#ifdef BNX2X_PER_PROT_QOS
+ do {
+ u32 protocolWeightSum = 0;
+
+ for (protocol = 0; protocol < NUM_OF_PROTOCOLS; protocol++)
+ protocolWeightSum +=
+ drvInit.protocol_min_rate[protocol];
+ /* per protocol counter -
+ NOT NEEDED IF NO PER-PROTOCOL CONGESTION MANAGEMENT */
+ if (protocolWeightSum > 0) {
+ for (protocol = 0;
+ protocol < NUM_OF_PROTOCOLS; protocol++)
+ /* credit for each period of the
+ fairness algorithm - number of bytes in
+ T_FAIR (the protocol share the vn rate) */
+ m_fair_vn.protocol_credit_delta[protocol] =
+ (u32)((vn_min_rate / 8) * t_fair *
+ protocol_min_rate / protocolWeightSum);
+ }
+ } while (0);
+#endif
+
+ /* Store it to internal memory */
+ for (i = 0; i < sizeof(struct rate_shaping_vars_per_vn)/4; i++)
+ REG_WR(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(func) + i * 4,
+ ((u32 *)(&m_rs_vn))[i]);
+
+ for (i = 0; i < sizeof(struct fairness_vars_per_vn)/4; i++)
+ REG_WR(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(func) + i * 4,
+ ((u32 *)(&m_fair_vn))[i]);
+}
+
/* This function is called upon link interrupt */
static void bnx2x_link_attn(struct bnx2x *bp)
{
+ int vn;
+
bnx2x_phy_hw_lock(bp);
bnx2x_link_update(&bp->link_params, &bp->link_vars);
bnx2x_phy_hw_unlock(bp);
/* indicate link status */
bnx2x_link_report(bp);
+
+ if (IS_E1HMF(bp)) {
+ int func;
+
+ for (vn = VN_0; vn < E1HVN_MAX; vn++) {
+ if (vn == BP_E1HVN(bp))
+ continue;
+
+ func = ((vn << 1) | BP_PORT(bp));
+
+ /* Set the attention towards other drivers
+ on the same port */
+ REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
+ (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
+ }
+ }
+
+ if (CHIP_IS_E1H(bp) && (bp->link_vars.line_speed > 0)) {
+ struct cmng_struct_per_port m_cmng_port;
+ u32 wsum;
+ int port = BP_PORT(bp);
+
+ /* Init RATE SHAPING and FAIRNESS contexts */
+ wsum = bnx2x_calc_vn_wsum(bp);
+ bnx2x_init_port_minmax(bp, (int)wsum,
+ bp->link_vars.line_speed,
+ &m_cmng_port);
+ if (IS_E1HMF(bp))
+ for (vn = VN_0; vn < E1HVN_MAX; vn++)
+ bnx2x_init_vn_minmax(bp, 2*vn + port,
+ wsum, bp->link_vars.line_speed,
+ &m_cmng_port);
+ }
}
static void bnx2x__link_status_update(struct bnx2x *bp)
bnx2x_link_report(bp);
}
+static void bnx2x_pmf_update(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ u32 val;
+
+ bp->port.pmf = 1;
+ DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
+
+ /* enable nig attention */
+ val = (0xff0f | (1 << (BP_E1HVN(bp) + 4)));
+ REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
+ REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
+}
+
/* end of Link */
/* slow path */
static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
u32 data_hi, u32 data_lo, int common)
{
- int port = bp->port;
+ int func = BP_FUNC(bp);
- DP(NETIF_MSG_TIMER,
- "spe (%x:%x) command %d hw_cid %x data (%x:%x) left %x\n",
+ DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
+ "SPQE (%x:%x) command %d hw_cid %x data (%x:%x) left %x\n",
(u32)U64_HI(bp->spq_mapping), (u32)(U64_LO(bp->spq_mapping) +
(void *)bp->spq_prod_bd - (void *)bp->spq), command,
HW_CID(bp, cid), data_hi, data_lo, bp->spq_left);
return -EIO;
#endif
- spin_lock(&bp->spq_lock);
+ spin_lock_bh(&bp->spq_lock);
if (!bp->spq_left) {
BNX2X_ERR("BUG! SPQ ring full!\n");
- spin_unlock(&bp->spq_lock);
+ spin_unlock_bh(&bp->spq_lock);
bnx2x_panic();
return -EBUSY;
}
bp->spq_prod_idx++;
}
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(port),
+ REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
bp->spq_prod_idx);
- spin_unlock(&bp->spq_lock);
+ spin_unlock_bh(&bp->spq_lock);
return 0;
}
/* acquire split MCP access lock register */
static int bnx2x_lock_alr(struct bnx2x *bp)
{
- int rc = 0;
u32 i, j, val;
+ int rc = 0;
might_sleep();
i = 100;
msleep(5);
}
-
if (!(val & (1L << 31))) {
BNX2X_ERR("Cannot acquire nvram interface\n");
-
rc = -EBUSY;
}
static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
{
- int port = bp->port;
- u32 igu_addr = (IGU_ADDR_ATTN_BITS_SET + IGU_PORT_BASE * port) * 8;
+ int port = BP_PORT(bp);
+ int func = BP_FUNC(bp);
+ u32 igu_addr = (IGU_ADDR_ATTN_BITS_SET + IGU_FUNC_BASE * func) * 8;
u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
MISC_REG_AEU_MASK_ATTN_FUNC_0;
u32 nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 :
static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
int reg_offset;
u32 val;
- if (attn & AEU_INPUTS_ATTN_BITS_SPIO5) {
+ reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
+ MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
- reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
- MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
+ if (attn & AEU_INPUTS_ATTN_BITS_SPIO5) {
val = REG_RD(bp, reg_offset);
val &= ~AEU_INPUTS_ATTN_BITS_SPIO5;
BNX2X_ERR("SPIO5 hw attention\n");
- switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+ switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
/* Fan failure attention */
break;
}
}
+
+ if (attn & HW_INTERRUT_ASSERT_SET_0) {
+
+ val = REG_RD(bp, reg_offset);
+ val &= ~(attn & HW_INTERRUT_ASSERT_SET_0);
+ REG_WR(bp, reg_offset, val);
+
+ BNX2X_ERR("FATAL HW block attention set0 0x%x\n",
+ (attn & HW_INTERRUT_ASSERT_SET_0));
+ bnx2x_panic();
+ }
}
static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
if (val & 0x2)
BNX2X_ERR("FATAL error from DORQ\n");
}
+
+ if (attn & HW_INTERRUT_ASSERT_SET_1) {
+
+ int port = BP_PORT(bp);
+ int reg_offset;
+
+ reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_1 :
+ MISC_REG_AEU_ENABLE1_FUNC_0_OUT_1);
+
+ val = REG_RD(bp, reg_offset);
+ val &= ~(attn & HW_INTERRUT_ASSERT_SET_1);
+ REG_WR(bp, reg_offset, val);
+
+ BNX2X_ERR("FATAL HW block attention set1 0x%x\n",
+ (attn & HW_INTERRUT_ASSERT_SET_1));
+ bnx2x_panic();
+ }
}
static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
if (val & 0x18000)
BNX2X_ERR("FATAL error from PXP\n");
}
+
+ if (attn & HW_INTERRUT_ASSERT_SET_2) {
+
+ int port = BP_PORT(bp);
+ int reg_offset;
+
+ reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_2 :
+ MISC_REG_AEU_ENABLE1_FUNC_0_OUT_2);
+
+ val = REG_RD(bp, reg_offset);
+ val &= ~(attn & HW_INTERRUT_ASSERT_SET_2);
+ REG_WR(bp, reg_offset, val);
+
+ BNX2X_ERR("FATAL HW block attention set2 0x%x\n",
+ (attn & HW_INTERRUT_ASSERT_SET_2));
+ bnx2x_panic();
+ }
}
static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
{
+ u32 val;
+
if (attn & EVEREST_GEN_ATTN_IN_USE_MASK) {
- if (attn & BNX2X_MC_ASSERT_BITS) {
+ if (attn & BNX2X_PMF_LINK_ASSERT) {
+ int func = BP_FUNC(bp);
+
+ REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
+ bnx2x__link_status_update(bp);
+ if (SHMEM_RD(bp, func_mb[func].drv_status) &
+ DRV_STATUS_PMF)
+ bnx2x_pmf_update(bp);
+
+ } else if (attn & BNX2X_MC_ASSERT_BITS) {
BNX2X_ERR("MC assert!\n");
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_10, 0);
BNX2X_ERR("MCP assert!\n");
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_11, 0);
- bnx2x_mc_assert(bp);
+ bnx2x_fw_dump(bp);
} else
BNX2X_ERR("Unknown HW assert! (attn 0x%x)\n", attn);
}
if (attn & EVEREST_LATCHED_ATTN_IN_USE_MASK) {
-
+ BNX2X_ERR("LATCHED attention 0x%08x (masked)\n", attn);
+ if (attn & BNX2X_GRC_TIMEOUT) {
+ val = CHIP_IS_E1H(bp) ?
+ REG_RD(bp, MISC_REG_GRC_TIMEOUT_ATTN) : 0;
+ BNX2X_ERR("GRC time-out 0x%08x\n", val);
+ }
+ if (attn & BNX2X_GRC_RSV) {
+ val = CHIP_IS_E1H(bp) ?
+ REG_RD(bp, MISC_REG_GRC_RSV_ATTN) : 0;
+ BNX2X_ERR("GRC reserved 0x%08x\n", val);
+ }
REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x7ff);
- BNX2X_ERR("LATCHED attention 0x%x (masked)\n", attn);
}
}
{
struct attn_route attn;
struct attn_route group_mask;
- int port = bp->port;
+ int port = BP_PORT(bp);
int index;
u32 reg_addr;
u32 val;
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);
- DP(NETIF_MSG_HW, "attn %llx\n", (unsigned long long)attn.sig[0]);
+ DP(NETIF_MSG_HW, "attn: %08x %08x %08x %08x\n",
+ attn.sig[0], attn.sig[1], attn.sig[2], attn.sig[3]);
for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
if (deasserted & (1 << index)) {
group_mask = bp->attn_group[index];
- DP(NETIF_MSG_HW, "group[%d]: %llx\n", index,
- (unsigned long long)group_mask.sig[0]);
+ DP(NETIF_MSG_HW, "group[%d]: %08x %08x %08x %08x\n",
+ index, group_mask.sig[0], group_mask.sig[1],
+ group_mask.sig[2], group_mask.sig[3]);
bnx2x_attn_int_deasserted3(bp,
attn.sig[3] & group_mask.sig[3]);
bnx2x_attn_int_deasserted0(bp,
attn.sig[0] & group_mask.sig[0]);
- if ((attn.sig[0] & group_mask.sig[0] &
- HW_INTERRUT_ASSERT_SET_0) ||
- (attn.sig[1] & group_mask.sig[1] &
- HW_INTERRUT_ASSERT_SET_1) ||
- (attn.sig[2] & group_mask.sig[2] &
- HW_INTERRUT_ASSERT_SET_2))
- BNX2X_ERR("FATAL HW block attention"
- " set0 0x%x set1 0x%x"
- " set2 0x%x\n",
- (attn.sig[0] & group_mask.sig[0] &
- HW_INTERRUT_ASSERT_SET_0),
- (attn.sig[1] & group_mask.sig[1] &
- HW_INTERRUT_ASSERT_SET_1),
- (attn.sig[2] & group_mask.sig[2] &
- HW_INTERRUT_ASSERT_SET_2));
-
if ((attn.sig[0] & group_mask.sig[0] &
HW_PRTY_ASSERT_SET_0) ||
(attn.sig[1] & group_mask.sig[1] &
bnx2x_unlock_alr(bp);
- reg_addr = (IGU_ADDR_ATTN_BITS_CLR + IGU_PORT_BASE * port) * 8;
+ reg_addr = (IGU_ADDR_ATTN_BITS_CLR + IGU_FUNC_BASE * BP_FUNC(bp)) * 8;
val = ~deasserted;
-/* DP(NETIF_MSG_INTR, "write 0x%08x to IGU addr 0x%x\n",
+/* DP(NETIF_MSG_INTR, "write 0x%08x to IGU addr 0x%x\n",
val, BAR_IGU_INTMEM + reg_addr); */
REG_WR(bp, BAR_IGU_INTMEM + reg_addr, val);
if (bp->aeu_mask & (deasserted & 0xff))
- BNX2X_ERR("IGU BUG\n");
+ BNX2X_ERR("IGU BUG!\n");
if (~bp->attn_state & deasserted)
- BNX2X_ERR("IGU BUG\n");
+ BNX2X_ERR("IGU BUG!\n");
reg_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
MISC_REG_AEU_MASK_ATTN_FUNC_0;
attn_bits, attn_ack, asserted, deasserted);
if (~(attn_bits ^ attn_ack) & (attn_bits ^ attn_state))
- BNX2X_ERR("bad attention state\n");
+ BNX2X_ERR("BAD attention state\n");
/* handle bits that were raised */
if (asserted)
struct bnx2x *bp = container_of(work, struct bnx2x, sp_task);
u16 status;
+
/* Return here if interrupt is disabled */
if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n");
}
status = bnx2x_update_dsb_idx(bp);
- if (status == 0)
- BNX2X_ERR("spurious slowpath interrupt!\n");
+/* if (status == 0) */
+/* BNX2X_ERR("spurious slowpath interrupt!\n"); */
- DP(NETIF_MSG_INTR, "got a slowpath interrupt (updated %x)\n", status);
+ DP(BNX2X_MSG_SP, "got a slowpath interrupt (updated %x)\n", status);
/* HW attentions */
if (status & 0x1)
bnx2x_attn_int(bp);
- /* CStorm events: query_stats, port delete ramrod */
- if (status & 0x2)
- bp->stat_pending = 0;
-
bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, bp->def_att_idx,
IGU_INT_NOP, 1);
bnx2x_ack_sb(bp, DEF_SB_ID, USTORM_ID, le16_to_cpu(bp->def_u_idx),
static void bnx2x_init_mac_stats(struct bnx2x *bp)
{
struct dmae_command *dmae;
- int port = bp->port;
+ int port = BP_PORT(bp);
int loader_idx = port * 8;
u32 opcode;
u32 mac_addr;
bp->executer_idx = 0;
- if (bp->fw_mb) {
+ if (bp->func_stx) {
/* MCP */
opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
sizeof(u32));
dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, eth_stats) +
sizeof(u32));
- dmae->dst_addr_lo = bp->fw_mb >> 2;
+ dmae->dst_addr_lo = bp->func_stx >> 2;
dmae->dst_addr_hi = 0;
dmae->len = (offsetof(struct bnx2x_eth_stats, mac_stx_end) -
sizeof(u32)) >> 2;
static void bnx2x_init_stats(struct bnx2x *bp)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
bp->stats_state = STATS_STATE_DISABLE;
bp->executer_idx = 0;
static void bnx2x_update_stats(struct bnx2x *bp)
{
- int i;
-
if (!bnx2x_update_storm_stats(bp)) {
if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
if (bp->msglevel & NETIF_MSG_TIMER) {
struct bnx2x_eth_stats *estats = bnx2x_sp(bp, eth_stats);
struct net_device_stats *nstats = &bp->dev->stats;
+ int i;
printk(KERN_DEBUG "%s:\n", bp->dev->name);
printk(KERN_DEBUG " tx avail (%4x) tx hc idx (%x)"
/* loader */
if (bp->executer_idx) {
struct dmae_command *dmae = &bp->dmae;
- int port = bp->port;
+ int port = BP_PORT(bp);
int loader_idx = port * 8;
memset(dmae, 0, sizeof(struct dmae_command));
rc = bnx2x_rx_int(fp, 1000);
}
- if (!nomcp) {
- int port = bp->port;
+ if (!BP_NOMCP(bp)) {
+ int func = BP_FUNC(bp);
u32 drv_pulse;
u32 mcp_pulse;
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[port].drv_pulse_mb, drv_pulse);
+ SHMEM_WR(bp, func_mb[func].drv_pulse_mb, drv_pulse);
- mcp_pulse = (SHMEM_RD(bp, func_mb[port].mcp_pulse_mb) &
+ mcp_pulse = (SHMEM_RD(bp, func_mb[func].mcp_pulse_mb) &
MCP_PULSE_SEQ_MASK);
/* The delta between driver pulse and mcp response
* should be 1 (before mcp response) or 0 (after mcp response)
* nic init service functions
*/
-static void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
- dma_addr_t mapping, int id)
+static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id)
{
- int port = bp->port;
- u64 section;
+ int port = BP_PORT(bp);
+
+ bnx2x_init_fill(bp, BAR_USTRORM_INTMEM +
+ USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0,
+ sizeof(struct ustorm_def_status_block)/4);
+ bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0,
+ sizeof(struct cstorm_def_status_block)/4);
+}
+
+static void bnx2x_init_sb(struct bnx2x *bp, int sb_id,
+ struct host_status_block *sb, dma_addr_t mapping)
+{
+ int port = BP_PORT(bp);
int index;
+ u64 section;
/* USTORM */
section = ((u64)mapping) + offsetof(struct host_status_block,
u_status_block);
- sb->u_status_block.status_block_id = id;
+ sb->u_status_block.status_block_id = sb_id;
REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_SB_HOST_SB_ADDR_OFFSET(port, id), U64_LO(section));
+ USTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id), U64_LO(section));
REG_WR(bp, BAR_USTRORM_INTMEM +
- ((USTORM_SB_HOST_SB_ADDR_OFFSET(port, id)) + 4),
+ ((USTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id)) + 4),
U64_HI(section));
for (index = 0; index < HC_USTORM_SB_NUM_INDICES; index++)
REG_WR16(bp, BAR_USTRORM_INTMEM +
- USTORM_SB_HC_DISABLE_OFFSET(port, id, index), 0x1);
+ USTORM_SB_HC_DISABLE_OFFSET(port, sb_id, index), 1);
/* CSTORM */
section = ((u64)mapping) + offsetof(struct host_status_block,
c_status_block);
- sb->c_status_block.status_block_id = id;
+ sb->c_status_block.status_block_id = sb_id;
REG_WR(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HOST_SB_ADDR_OFFSET(port, id), U64_LO(section));
+ CSTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id), U64_LO(section));
REG_WR(bp, BAR_CSTRORM_INTMEM +
- ((CSTORM_SB_HOST_SB_ADDR_OFFSET(port, id)) + 4),
+ ((CSTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id)) + 4),
U64_HI(section));
for (index = 0; index < HC_CSTORM_SB_NUM_INDICES; index++)
REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_DISABLE_OFFSET(port, id, index), 0x1);
+ CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id, index), 1);
+
+ bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+}
+
+static void bnx2x_zero_def_sb(struct bnx2x *bp)
+{
+ int func = BP_FUNC(bp);
- bnx2x_ack_sb(bp, id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+ bnx2x_init_fill(bp, BAR_USTRORM_INTMEM +
+ USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
+ sizeof(struct ustorm_def_status_block)/4);
+ bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
+ sizeof(struct cstorm_def_status_block)/4);
+ bnx2x_init_fill(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
+ sizeof(struct xstorm_def_status_block)/4);
+ bnx2x_init_fill(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
+ sizeof(struct tstorm_def_status_block)/4);
}
static void bnx2x_init_def_sb(struct bnx2x *bp,
struct host_def_status_block *def_sb,
- dma_addr_t mapping, int id)
+ dma_addr_t mapping, int sb_id)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
+ int func = BP_FUNC(bp);
int index, val, reg_offset;
u64 section;
/* ATTN */
section = ((u64)mapping) + offsetof(struct host_def_status_block,
atten_status_block);
- def_sb->atten_status_block.status_block_id = id;
+ def_sb->atten_status_block.status_block_id = sb_id;
bp->def_att_idx = 0;
bp->attn_state = 0;
reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
- for (index = 0; index < 3; index++) {
+ for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
bp->attn_group[index].sig[0] = REG_RD(bp,
reg_offset + 0x10*index);
bp->attn_group[index].sig[1] = REG_RD(bp,
reg_offset = (port ? HC_REG_ATTN_NUM_P1 : HC_REG_ATTN_NUM_P0);
val = REG_RD(bp, reg_offset);
- val |= id;
+ val |= sb_id;
REG_WR(bp, reg_offset, val);
/* USTORM */
section = ((u64)mapping) + offsetof(struct host_def_status_block,
u_def_status_block);
- def_sb->u_def_status_block.status_block_id = id;
+ def_sb->u_def_status_block.status_block_id = sb_id;
bp->def_u_idx = 0;
REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
+ USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
REG_WR(bp, BAR_USTRORM_INTMEM +
- ((USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)) + 4),
+ ((USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
U64_HI(section));
- REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_HC_BTR_OFFSET(port),
+ REG_WR8(bp, BAR_USTRORM_INTMEM + DEF_USB_FUNC_OFF +
+ USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+ REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_HC_BTR_OFFSET(func),
BNX2X_BTR);
for (index = 0; index < HC_USTORM_DEF_SB_NUM_INDICES; index++)
REG_WR16(bp, BAR_USTRORM_INTMEM +
- USTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1);
+ USTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
/* CSTORM */
section = ((u64)mapping) + offsetof(struct host_def_status_block,
c_def_status_block);
- def_sb->c_def_status_block.status_block_id = id;
+ def_sb->c_def_status_block.status_block_id = sb_id;
bp->def_c_idx = 0;
REG_WR(bp, BAR_CSTRORM_INTMEM +
- CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
+ CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
REG_WR(bp, BAR_CSTRORM_INTMEM +
- ((CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)) + 4),
+ ((CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
U64_HI(section));
- REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_OFFSET(port),
+ REG_WR8(bp, BAR_CSTRORM_INTMEM + DEF_CSB_FUNC_OFF +
+ CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+ REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_OFFSET(func),
BNX2X_BTR);
for (index = 0; index < HC_CSTORM_DEF_SB_NUM_INDICES; index++)
REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1);
+ CSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
/* TSTORM */
section = ((u64)mapping) + offsetof(struct host_def_status_block,
t_def_status_block);
- def_sb->t_def_status_block.status_block_id = id;
+ def_sb->t_def_status_block.status_block_id = sb_id;
bp->def_t_idx = 0;
REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
+ TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
REG_WR(bp, BAR_TSTRORM_INTMEM +
- ((TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)) + 4),
+ ((TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
U64_HI(section));
- REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_HC_BTR_OFFSET(port),
+ REG_WR8(bp, BAR_TSTRORM_INTMEM + DEF_TSB_FUNC_OFF +
+ TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+ REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_HC_BTR_OFFSET(func),
BNX2X_BTR);
for (index = 0; index < HC_TSTORM_DEF_SB_NUM_INDICES; index++)
REG_WR16(bp, BAR_TSTRORM_INTMEM +
- TSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1);
+ TSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
/* XSTORM */
section = ((u64)mapping) + offsetof(struct host_def_status_block,
x_def_status_block);
- def_sb->x_def_status_block.status_block_id = id;
+ def_sb->x_def_status_block.status_block_id = sb_id;
bp->def_x_idx = 0;
REG_WR(bp, BAR_XSTRORM_INTMEM +
- XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section));
+ XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
REG_WR(bp, BAR_XSTRORM_INTMEM +
- ((XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)) + 4),
+ ((XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
U64_HI(section));
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(port),
+ REG_WR8(bp, BAR_XSTRORM_INTMEM + DEF_XSB_FUNC_OFF +
+ XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+ REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(func),
BNX2X_BTR);
for (index = 0; index < HC_XSTORM_DEF_SB_NUM_INDICES; index++)
REG_WR16(bp, BAR_XSTRORM_INTMEM +
- XSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1);
-
- bp->stat_pending = 0;
+ XSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
- bnx2x_ack_sb(bp, id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+ bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
}
static void bnx2x_update_coalesce(struct bnx2x *bp)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
int i;
for_each_queue(bp, i) {
+ int sb_id = bp->fp[i].sb_id;
/* HC_INDEX_U_ETH_RX_CQ_CONS */
REG_WR8(bp, BAR_USTRORM_INTMEM +
- USTORM_SB_HC_TIMEOUT_OFFSET(port, i,
+ USTORM_SB_HC_TIMEOUT_OFFSET(port, sb_id,
HC_INDEX_U_ETH_RX_CQ_CONS),
- bp->rx_ticks_int/12);
+ bp->rx_ticks/12);
REG_WR16(bp, BAR_USTRORM_INTMEM +
- USTORM_SB_HC_DISABLE_OFFSET(port, i,
+ USTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
HC_INDEX_U_ETH_RX_CQ_CONS),
- bp->rx_ticks_int ? 0 : 1);
+ bp->rx_ticks ? 0 : 1);
/* HC_INDEX_C_ETH_TX_CQ_CONS */
REG_WR8(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_TIMEOUT_OFFSET(port, i,
+ CSTORM_SB_HC_TIMEOUT_OFFSET(port, sb_id,
HC_INDEX_C_ETH_TX_CQ_CONS),
- bp->tx_ticks_int/12);
+ bp->tx_ticks/12);
REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_DISABLE_OFFSET(port, i,
+ CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
HC_INDEX_C_ETH_TX_CQ_CONS),
- bp->tx_ticks_int ? 0 : 1);
+ bp->tx_ticks ? 0 : 1);
}
}
{
u16 ring_prod;
int i, j;
- int port = bp->port;
bp->rx_buf_use_size = bp->dev->mtu;
rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2];
rx_bd->addr_hi =
cpu_to_le32(U64_HI(fp->rx_desc_mapping +
- BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
+ BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
rx_bd->addr_lo =
cpu_to_le32(U64_LO(fp->rx_desc_mapping +
- BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
-
+ BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
}
+ /* CQ ring */
for (i = 1; i <= NUM_RCQ_RINGS; i++) {
struct eth_rx_cqe_next_page *nextpg;
&fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
nextpg->addr_hi =
cpu_to_le32(U64_HI(fp->rx_comp_mapping +
- BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+ BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
nextpg->addr_lo =
cpu_to_le32(U64_LO(fp->rx_comp_mapping +
- BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+ BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
}
/* rx completion queue */
/* Warning! this will generate an interrupt (to the TSTORM) */
/* must only be done when chip is initialized */
REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_RCQ_PROD_OFFSET(port, j), ring_prod);
+ TSTORM_RX_PRODS_OFFSET(BP_PORT(bp), FP_CL_ID(fp)),
+ ring_prod);
if (j != 0)
continue;
REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(port),
+ USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(BP_PORT(bp)),
U64_LO(fp->rx_comp_mapping));
REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(port) + 4,
+ USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(BP_PORT(bp)) + 4,
U64_HI(fp->rx_comp_mapping));
}
}
tx_bd->addr_hi =
cpu_to_le32(U64_HI(fp->tx_desc_mapping +
- BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
+ BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
tx_bd->addr_lo =
cpu_to_le32(U64_LO(fp->tx_desc_mapping +
- BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
+ BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
}
fp->tx_pkt_prod = 0;
static void bnx2x_init_sp_ring(struct bnx2x *bp)
{
- int port = bp->port;
+ int func = BP_FUNC(bp);
spin_lock_init(&bp->spq_lock);
bp->spq_prod_bd = bp->spq;
bp->spq_last_bd = bp->spq_prod_bd + MAX_SP_DESC_CNT;
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PAGE_BASE_OFFSET(port),
+ REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PAGE_BASE_OFFSET(func),
U64_LO(bp->spq_mapping));
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PAGE_BASE_OFFSET(port) + 4,
+ REG_WR(bp,
+ XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PAGE_BASE_OFFSET(func) + 4,
U64_HI(bp->spq_mapping));
- REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PROD_OFFSET(port),
+ REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PROD_OFFSET(func),
bp->spq_prod_idx);
}
for_each_queue(bp, i) {
struct eth_context *context = bnx2x_sp(bp, context[i].eth);
struct bnx2x_fastpath *fp = &bp->fp[i];
+ u8 sb_id = FP_SB_ID(fp);
context->xstorm_st_context.tx_bd_page_base_hi =
U64_HI(fp->tx_desc_mapping);
U64_HI(fp->tx_prods_mapping);
context->xstorm_st_context.db_data_addr_lo =
U64_LO(fp->tx_prods_mapping);
-
- context->ustorm_st_context.rx_bd_page_base_hi =
+ context->xstorm_st_context.statistics_data = (BP_CL_ID(bp) |
+ XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
+
+ context->ustorm_st_context.common.sb_index_numbers =
+ BNX2X_RX_SB_INDEX_NUM;
+ context->ustorm_st_context.common.clientId = FP_CL_ID(fp);
+ context->ustorm_st_context.common.status_block_id = sb_id;
+ context->ustorm_st_context.common.flags =
+ USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT;
+ context->ustorm_st_context.common.mc_alignment_size = 64;
+ context->ustorm_st_context.common.bd_buff_size =
+ bp->rx_buf_use_size;
+ context->ustorm_st_context.common.bd_page_base_hi =
U64_HI(fp->rx_desc_mapping);
- context->ustorm_st_context.rx_bd_page_base_lo =
+ context->ustorm_st_context.common.bd_page_base_lo =
U64_LO(fp->rx_desc_mapping);
- context->ustorm_st_context.status_block_id = i;
- context->ustorm_st_context.sb_index_number =
- HC_INDEX_U_ETH_RX_CQ_CONS;
- context->ustorm_st_context.rcq_base_address_hi =
- U64_HI(fp->rx_comp_mapping);
- context->ustorm_st_context.rcq_base_address_lo =
- U64_LO(fp->rx_comp_mapping);
- context->ustorm_st_context.flags =
- USTORM_ETH_ST_CONTEXT_ENABLE_MC_ALIGNMENT;
- context->ustorm_st_context.mc_alignment_size = 64;
- context->ustorm_st_context.num_rss = bp->num_queues;
-
context->cstorm_st_context.sb_index_number =
HC_INDEX_C_ETH_TX_CQ_CONS;
- context->cstorm_st_context.status_block_id = i;
+ context->cstorm_st_context.status_block_id = sb_id;
context->xstorm_ag_context.cdu_reserved =
CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, i),
static void bnx2x_init_ind_table(struct bnx2x *bp)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
int i;
if (!is_multi(bp))
return;
+ DP(NETIF_MSG_IFUP, "Initializing indirection table\n");
for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
- REG_WR8(bp, TSTORM_INDIRECTION_TABLE_OFFSET(port) + i,
+ REG_WR8(bp, BAR_TSTRORM_INTMEM +
+ TSTORM_INDIRECTION_TABLE_OFFSET(port) + i,
i % bp->num_queues);
REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
static void bnx2x_set_client_config(struct bnx2x *bp)
{
-#ifdef BCM_VLAN
- int mode = bp->rx_mode;
-#endif
- int i, port = bp->port;
struct tstorm_eth_client_config tstorm_client = {0};
+ int port = BP_PORT(bp);
+ int i;
- tstorm_client.mtu = bp->dev->mtu;
+ tstorm_client.mtu = bp->dev->mtu + ETH_OVREHEAD;
tstorm_client.statistics_counter_id = 0;
tstorm_client.config_flags =
TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
#ifdef BCM_VLAN
- if (mode && bp->vlgrp) {
+ if (bp->rx_mode && bp->vlgrp) {
tstorm_client.config_flags |=
TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE;
DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
}
#endif
- if (mode != BNX2X_RX_MODE_PROMISC)
- tstorm_client.drop_flags =
- TSTORM_ETH_CLIENT_CONFIG_DROP_MAC_ERR;
for_each_queue(bp, i) {
REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_CLIENT_CONFIG_OFFSET(port, i),
+ TSTORM_CLIENT_CONFIG_OFFSET(port, bp->fp[i].cl_id),
((u32 *)&tstorm_client)[0]);
REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_CLIENT_CONFIG_OFFSET(port, i) + 4,
+ TSTORM_CLIENT_CONFIG_OFFSET(port, bp->fp[i].cl_id) + 4,
((u32 *)&tstorm_client)[1]);
}
-/* DP(NETIF_MSG_IFUP, "tstorm_client: 0x%08x 0x%08x\n",
- ((u32 *)&tstorm_client)[0], ((u32 *)&tstorm_client)[1]); */
+ DP(BNX2X_MSG_OFF, "tstorm_client: 0x%08x 0x%08x\n",
+ ((u32 *)&tstorm_client)[0], ((u32 *)&tstorm_client)[1]);
}
static void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
{
- int mode = bp->rx_mode;
- int port = bp->port;
struct tstorm_eth_mac_filter_config tstorm_mac_filter = {0};
+ int mode = bp->rx_mode;
+ int mask = (1 << BP_L_ID(bp));
+ int func = BP_FUNC(bp);
int i;
DP(NETIF_MSG_RX_STATUS, "rx mode is %d\n", mode);
switch (mode) {
case BNX2X_RX_MODE_NONE: /* no Rx */
- tstorm_mac_filter.ucast_drop_all = 1;
- tstorm_mac_filter.mcast_drop_all = 1;
- tstorm_mac_filter.bcast_drop_all = 1;
+ tstorm_mac_filter.ucast_drop_all = mask;
+ tstorm_mac_filter.mcast_drop_all = mask;
+ tstorm_mac_filter.bcast_drop_all = mask;
break;
case BNX2X_RX_MODE_NORMAL:
- tstorm_mac_filter.bcast_accept_all = 1;
+ tstorm_mac_filter.bcast_accept_all = mask;
break;
case BNX2X_RX_MODE_ALLMULTI:
- tstorm_mac_filter.mcast_accept_all = 1;
- tstorm_mac_filter.bcast_accept_all = 1;
+ tstorm_mac_filter.mcast_accept_all = mask;
+ tstorm_mac_filter.bcast_accept_all = mask;
break;
case BNX2X_RX_MODE_PROMISC:
- tstorm_mac_filter.ucast_accept_all = 1;
- tstorm_mac_filter.mcast_accept_all = 1;
- tstorm_mac_filter.bcast_accept_all = 1;
+ tstorm_mac_filter.ucast_accept_all = mask;
+ tstorm_mac_filter.mcast_accept_all = mask;
+ tstorm_mac_filter.bcast_accept_all = mask;
break;
default:
- BNX2X_ERR("bad rx mode (%d)\n", mode);
+ BNX2X_ERR("BAD rx mode (%d)\n", mode);
+ break;
}
for (i = 0; i < sizeof(struct tstorm_eth_mac_filter_config)/4; i++) {
REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_MAC_FILTER_CONFIG_OFFSET(port) + i * 4,
+ TSTORM_MAC_FILTER_CONFIG_OFFSET(func) + i * 4,
((u32 *)&tstorm_mac_filter)[i]);
-/* DP(NETIF_MSG_IFUP, "tstorm_mac_filter[%d]: 0x%08x\n", i,
+/* DP(NETIF_MSG_IFUP, "tstorm_mac_filter[%d]: 0x%08x\n", i,
((u32 *)&tstorm_mac_filter)[i]); */
}
static void bnx2x_init_internal(struct bnx2x *bp)
{
- int port = bp->port;
struct tstorm_eth_function_common_config tstorm_config = {0};
struct stats_indication_flags stats_flags = {0};
+ int port = BP_PORT(bp);
+ int func = BP_FUNC(bp);
+ int i;
if (is_multi(bp)) {
tstorm_config.config_flags = MULTI_FLAGS;
tstorm_config.rss_result_mask = MULTI_MASK;
}
+ tstorm_config.leading_client_id = BP_L_ID(bp);
+
REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(port),
+ TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(func),
(*(u32 *)&tstorm_config));
-/* DP(NETIF_MSG_IFUP, "tstorm_config: 0x%08x\n",
+/* DP(NETIF_MSG_IFUP, "tstorm_config: 0x%08x\n",
(*(u32 *)&tstorm_config)); */
bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx until link is up */
bnx2x_set_storm_rx_mode(bp);
- stats_flags.collect_eth = cpu_to_le32(1);
+ stats_flags.collect_eth = 1;
REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(port),
((u32 *)&stats_flags)[0]);
REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(port) + 4,
((u32 *)&stats_flags)[1]);
-/* DP(NETIF_MSG_IFUP, "stats_flags: 0x%08x 0x%08x\n",
+/* DP(NETIF_MSG_IFUP, "stats_flags: 0x%08x 0x%08x\n",
((u32 *)&stats_flags)[0], ((u32 *)&stats_flags)[1]); */
+
+ if (CHIP_IS_E1H(bp)) {
+ REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET,
+ IS_E1HMF(bp));
+ REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_MODE_OFFSET,
+ IS_E1HMF(bp));
+ REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNCTION_MODE_OFFSET,
+ IS_E1HMF(bp));
+ REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNCTION_MODE_OFFSET,
+ IS_E1HMF(bp));
+
+ REG_WR16(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_E1HOV_OFFSET(func), bp->e1hov);
+ }
+
+ /* Zero this manualy 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 + 4*i, 0);
}
static void bnx2x_nic_init(struct bnx2x *bp)
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
+ fp->bp = bp;
fp->state = BNX2X_FP_STATE_CLOSED;
- DP(NETIF_MSG_IFUP, "bnx2x_init_sb(%p,%p,%d);\n",
- bp, fp->status_blk, i);
fp->index = i;
- bnx2x_init_sb(bp, fp->status_blk, fp->status_blk_mapping, i);
+ fp->cl_id = BP_L_ID(bp) + i;
+ fp->sb_id = fp->cl_id;
+ DP(NETIF_MSG_IFUP,
+ "bnx2x_init_sb(%p,%p) index %d cl_id %d sb %d\n",
+ bp, fp->status_blk, i, FP_CL_ID(fp), FP_SB_ID(fp));
+ bnx2x_init_sb(bp, FP_SB_ID(fp), fp->status_blk,
+ fp->status_blk_mapping);
}
bnx2x_init_def_sb(bp, bp->def_status_blk,
- bp->def_status_blk_mapping, 0x10);
+ bp->def_status_blk_mapping, DEF_SB_ID);
bnx2x_update_coalesce(bp);
bnx2x_init_rx_rings(bp);
bnx2x_init_tx_ring(bp);
bnx2x_init_stats(bp);
bnx2x_init_ind_table(bp);
bnx2x_int_enable(bp);
-
}
/* end of nic init */
gunzip_nomem1:
printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for"
- " uncompression\n", bp->dev->name);
+ " un-compression\n", bp->dev->name);
return -ENOMEM;
}
n = 10;
-#define FNAME 0x8
+#define FNAME 0x8
if (zbuf[3] & FNAME)
while ((zbuf[n++] != 0) && (n < len));
/* nic load/unload */
/*
- * general service functions
+ * General service functions
*/
/* send a NIG loopback debug packet */
static void bnx2x_lb_pckt(struct bnx2x *bp)
{
-#ifdef USE_DMAE
u32 wb_write[3];
-#endif
/* Ethernet source and destination addresses */
-#ifdef USE_DMAE
wb_write[0] = 0x55555555;
wb_write[1] = 0x55555555;
- wb_write[2] = 0x20; /* SOP */
+ wb_write[2] = 0x20; /* SOP */
REG_WR_DMAE(bp, NIG_REG_DEBUG_PACKET_LB, wb_write, 3);
-#else
- REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB, 0x55555555);
- REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB + 4, 0x55555555);
- /* SOP */
- REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB + 8, 0x20);
-#endif
/* NON-IP protocol */
-#ifdef USE_DMAE
wb_write[0] = 0x09000000;
wb_write[1] = 0x55555555;
- wb_write[2] = 0x10; /* EOP, eop_bvalid = 0 */
+ wb_write[2] = 0x10; /* EOP, eop_bvalid = 0 */
REG_WR_DMAE(bp, NIG_REG_DEBUG_PACKET_LB, wb_write, 3);
-#else
- REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB, 0x09000000);
- REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB + 4, 0x55555555);
- /* EOP, eop_bvalid = 0 */
- REG_WR_IND(bp, NIG_REG_DEBUG_PACKET_LB + 8, 0x10);
-#endif
}
/* some of the internal memories
/* Wait until NIG register shows 1 packet of size 0x10 */
count = 1000 * factor;
while (count) {
-#ifdef BNX2X_DMAE_RD
+
bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
val = *bnx2x_sp(bp, wb_data[0]);
-#else
- val = REG_RD(bp, NIG_REG_STAT2_BRB_OCTET);
- REG_RD(bp, NIG_REG_STAT2_BRB_OCTET + 4);
-#endif
if (val == 0x10)
break;
count = 1000 * factor;
while (count) {
val = REG_RD(bp, PRS_REG_NUM_OF_PACKETS);
-
if (val == 1)
break;
}
/* Reset and init BRB, PRS */
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, 0x3);
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, 0x03);
msleep(50);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x3);
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
msleep(50);
bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
packets of size 11*0x10 = 0xb0 */
count = 1000 * factor;
while (count) {
-#ifdef BNX2X_DMAE_RD
+
bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
val = *bnx2x_sp(bp, wb_data[0]);
-#else
- val = REG_RD(bp, NIG_REG_STAT2_BRB_OCTET);
- REG_RD(bp, NIG_REG_STAT2_BRB_OCTET + 4);
-#endif
if (val == 0xb0)
break;
REG_WR(bp, XSDM_REG_XSDM_INT_MASK_0, 0);
REG_WR(bp, XSDM_REG_XSDM_INT_MASK_1, 0);
REG_WR(bp, XCM_REG_XCM_INT_MASK, 0);
-/* REG_WR(bp, XSEM_REG_XSEM_INT_MASK_0, 0); */
-/* REG_WR(bp, XSEM_REG_XSEM_INT_MASK_1, 0); */
+/* REG_WR(bp, XSEM_REG_XSEM_INT_MASK_0, 0); */
+/* REG_WR(bp, XSEM_REG_XSEM_INT_MASK_1, 0); */
REG_WR(bp, USDM_REG_USDM_INT_MASK_0, 0);
REG_WR(bp, USDM_REG_USDM_INT_MASK_1, 0);
REG_WR(bp, UCM_REG_UCM_INT_MASK, 0);
-/* REG_WR(bp, USEM_REG_USEM_INT_MASK_0, 0); */
-/* REG_WR(bp, USEM_REG_USEM_INT_MASK_1, 0); */
+/* REG_WR(bp, USEM_REG_USEM_INT_MASK_0, 0); */
+/* REG_WR(bp, USEM_REG_USEM_INT_MASK_1, 0); */
REG_WR(bp, GRCBASE_UPB + PB_REG_PB_INT_MASK, 0);
REG_WR(bp, CSDM_REG_CSDM_INT_MASK_0, 0);
REG_WR(bp, CSDM_REG_CSDM_INT_MASK_1, 0);
REG_WR(bp, CCM_REG_CCM_INT_MASK, 0);
-/* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */
-/* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */
- REG_WR(bp, PXP2_REG_PXP2_INT_MASK, 0x480000);
+/* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */
+/* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */
+ if (CHIP_REV_IS_FPGA(bp))
+ REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
+ else
+ REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x480000);
REG_WR(bp, TSDM_REG_TSDM_INT_MASK_0, 0);
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); */
+/* REG_WR(bp, TSEM_REG_TSEM_INT_MASK_0, 0); */
+/* REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0); */
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); */
- REG_WR(bp, PBF_REG_PBF_INT_MASK, 0X18); /* bit 3,4 masked */
+/* REG_WR(bp, MISC_REG_MISC_INT_MASK, 0); */
+ REG_WR(bp, PBF_REG_PBF_INT_MASK, 0X18); /* bit 3,4 masked */
}
-static int bnx2x_function_init(struct bnx2x *bp, int mode)
+
+static int bnx2x_init_common(struct bnx2x *bp)
{
- int func = bp->port;
- int port = func ? PORT1 : PORT0;
u32 val, i;
-#ifdef USE_DMAE
- u32 wb_write[2];
-#endif
-
- DP(BNX2X_MSG_MCP, "function is %d mode is %x\n", func, mode);
- if ((func != 0) && (func != 1)) {
- BNX2X_ERR("BAD function number (%d)\n", func);
- return -ENODEV;
- }
- bnx2x_gunzip_init(bp);
+ DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_FUNC(bp));
- if (mode & 0x1) { /* init common */
- DP(BNX2X_MSG_MCP, "starting common init func %d mode %x\n",
- func, mode);
- 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_COMMON_START, MISC_COMMON_END);
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
- REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100);
- msleep(30);
- REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0);
+ bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END);
+ if (CHIP_IS_E1H(bp))
+ REG_WR(bp, MISC_REG_E1HMF_MODE, IS_E1HMF(bp));
- bnx2x_init_block(bp, PXP_COMMON_START, PXP_COMMON_END);
- bnx2x_init_block(bp, PXP2_COMMON_START, PXP2_COMMON_END);
+ REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100);
+ msleep(30);
+ REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0);
- bnx2x_init_pxp(bp);
+ bnx2x_init_block(bp, PXP_COMMON_START, PXP_COMMON_END);
+ 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);
+ }
- if (CHIP_REV(bp) == CHIP_REV_Ax) {
- /* 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_COMMON_START, PXP2_COMMON_END);
+ bnx2x_init_pxp(bp);
#ifdef __BIG_ENDIAN
- REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, 1);
- REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, 1);
- REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
- REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
- REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
- REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 1);
-
-/* REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
- REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
- REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, 1);
- REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, 1);
- REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
+ REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, 1);
+ REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, 1);
+ REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
+ REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
+ REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
+ REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 1);
+
+/* REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
+ REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
+ REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, 1);
+ REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, 1);
+ REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
#endif
#ifndef BCM_ISCSI
REG_WR(bp, PRS_REG_NIC_MODE, 1);
#endif
- REG_WR(bp, PXP2_REG_RQ_CDU_P_SIZE, 5);
+ REG_WR(bp, PXP2_REG_RQ_CDU_P_SIZE, 2);
#ifdef BCM_ISCSI
- REG_WR(bp, PXP2_REG_RQ_TM_P_SIZE, 5);
- REG_WR(bp, PXP2_REG_RQ_QM_P_SIZE, 5);
- REG_WR(bp, PXP2_REG_RQ_SRC_P_SIZE, 5);
+ REG_WR(bp, PXP2_REG_RQ_TM_P_SIZE, 5);
+ REG_WR(bp, PXP2_REG_RQ_QM_P_SIZE, 5);
+ REG_WR(bp, PXP2_REG_RQ_SRC_P_SIZE, 5);
#endif
- bnx2x_init_block(bp, DMAE_COMMON_START, DMAE_COMMON_END);
+ if (CHIP_REV_IS_FPGA(bp) && CHIP_IS_E1H(bp))
+ REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x1);
- /* let the HW do it's magic ... */
- msleep(100);
- /* finish PXP init
- (can be moved up if we want to use the DMAE) */
- val = REG_RD(bp, PXP2_REG_RQ_CFG_DONE);
- if (val != 1) {
- BNX2X_ERR("PXP2 CFG failed\n");
- return -EBUSY;
- }
+ /* let the HW do it's magic ... */
+ msleep(100);
+ /* finish PXP init */
+ val = REG_RD(bp, PXP2_REG_RQ_CFG_DONE);
+ if (val != 1) {
+ BNX2X_ERR("PXP2 CFG failed\n");
+ return -EBUSY;
+ }
+ val = REG_RD(bp, PXP2_REG_RD_INIT_DONE);
+ if (val != 1) {
+ BNX2X_ERR("PXP2 RD_INIT failed\n");
+ return -EBUSY;
+ }
- val = REG_RD(bp, PXP2_REG_RD_INIT_DONE);
- if (val != 1) {
- BNX2X_ERR("PXP2 RD_INIT failed\n");
- return -EBUSY;
- }
+ REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
+ REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
- REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
- REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
+ bnx2x_init_block(bp, DMAE_COMMON_START, DMAE_COMMON_END);
- bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8);
+ /* clean the DMAE memory */
+ bp->dmae_ready = 1;
+ bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8);
- bnx2x_init_block(bp, TCM_COMMON_START, TCM_COMMON_END);
- bnx2x_init_block(bp, UCM_COMMON_START, UCM_COMMON_END);
- bnx2x_init_block(bp, CCM_COMMON_START, CCM_COMMON_END);
- bnx2x_init_block(bp, XCM_COMMON_START, XCM_COMMON_END);
+ bnx2x_init_block(bp, TCM_COMMON_START, TCM_COMMON_END);
+ bnx2x_init_block(bp, UCM_COMMON_START, UCM_COMMON_END);
+ bnx2x_init_block(bp, CCM_COMMON_START, CCM_COMMON_END);
+ bnx2x_init_block(bp, XCM_COMMON_START, XCM_COMMON_END);
-#ifdef BNX2X_DMAE_RD
- 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);
-#else
- REG_RD(bp, XSEM_REG_PASSIVE_BUFFER);
- REG_RD(bp, XSEM_REG_PASSIVE_BUFFER + 4);
- REG_RD(bp, XSEM_REG_PASSIVE_BUFFER + 8);
- REG_RD(bp, CSEM_REG_PASSIVE_BUFFER);
- REG_RD(bp, CSEM_REG_PASSIVE_BUFFER + 4);
- REG_RD(bp, CSEM_REG_PASSIVE_BUFFER + 8);
- REG_RD(bp, TSEM_REG_PASSIVE_BUFFER);
- REG_RD(bp, TSEM_REG_PASSIVE_BUFFER + 4);
- REG_RD(bp, TSEM_REG_PASSIVE_BUFFER + 8);
- REG_RD(bp, USEM_REG_PASSIVE_BUFFER);
- REG_RD(bp, USEM_REG_PASSIVE_BUFFER + 4);
- REG_RD(bp, USEM_REG_PASSIVE_BUFFER + 8);
-#endif
- bnx2x_init_block(bp, QM_COMMON_START, QM_COMMON_END);
- /* soft reset pulse */
- REG_WR(bp, QM_REG_SOFT_RESET, 1);
- REG_WR(bp, QM_REG_SOFT_RESET, 0);
+ 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_COMMON_START, QM_COMMON_END);
+ /* soft reset pulse */
+ REG_WR(bp, QM_REG_SOFT_RESET, 1);
+ REG_WR(bp, QM_REG_SOFT_RESET, 0);
#ifdef BCM_ISCSI
- bnx2x_init_block(bp, TIMERS_COMMON_START, TIMERS_COMMON_END);
+ bnx2x_init_block(bp, TIMERS_COMMON_START, TIMERS_COMMON_END);
#endif
- bnx2x_init_block(bp, DQ_COMMON_START, DQ_COMMON_END);
- REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_BITS);
- if (CHIP_REV(bp) == CHIP_REV_Ax) {
- /* enable hw interrupt from doorbell Q */
- REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
- }
- bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
+ bnx2x_init_block(bp, DQ_COMMON_START, DQ_COMMON_END);
+ REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_SHIFT);
+ if (!CHIP_REV_IS_SLOW(bp)) {
+ /* enable hw interrupt from doorbell Q */
+ REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
+ }
- if (CHIP_REV_IS_SLOW(bp)) {
- /* fix for emulation and FPGA for no pause */
- REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0, 513);
- REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_1, 513);
- REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0, 0);
- REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_1, 0);
- }
+ bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
+ if (CHIP_REV_IS_SLOW(bp)) {
+ /* fix for emulation and FPGA for no pause */
+ REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0, 513);
+ REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_1, 513);
+ REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0, 0);
+ REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_1, 0);
+ }
- bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+ bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+ if (CHIP_IS_E1H(bp))
+ REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp));
- bnx2x_init_block(bp, TSDM_COMMON_START, TSDM_COMMON_END);
- bnx2x_init_block(bp, CSDM_COMMON_START, CSDM_COMMON_END);
- bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END);
- bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END);
+ bnx2x_init_block(bp, TSDM_COMMON_START, TSDM_COMMON_END);
+ bnx2x_init_block(bp, CSDM_COMMON_START, CSDM_COMMON_END);
+ bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END);
+ bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END);
+ if (CHIP_IS_E1H(bp)) {
+ bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0,
+ STORM_INTMEM_SIZE_E1H/2);
+ bnx2x_init_fill(bp,
+ TSTORM_INTMEM_ADDR + STORM_INTMEM_SIZE_E1H/2,
+ 0, STORM_INTMEM_SIZE_E1H/2);
+ bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0,
+ STORM_INTMEM_SIZE_E1H/2);
+ bnx2x_init_fill(bp,
+ CSTORM_INTMEM_ADDR + STORM_INTMEM_SIZE_E1H/2,
+ 0, STORM_INTMEM_SIZE_E1H/2);
+ bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR, 0,
+ STORM_INTMEM_SIZE_E1H/2);
+ bnx2x_init_fill(bp,
+ XSTORM_INTMEM_ADDR + STORM_INTMEM_SIZE_E1H/2,
+ 0, STORM_INTMEM_SIZE_E1H/2);
+ bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0,
+ STORM_INTMEM_SIZE_E1H/2);
+ bnx2x_init_fill(bp,
+ USTORM_INTMEM_ADDR + STORM_INTMEM_SIZE_E1H/2,
+ 0, STORM_INTMEM_SIZE_E1H/2);
+ } else { /* E1 */
bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0,
STORM_INTMEM_SIZE_E1);
bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0,
STORM_INTMEM_SIZE_E1);
bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0,
STORM_INTMEM_SIZE_E1);
+ }
- bnx2x_init_block(bp, TSEM_COMMON_START, TSEM_COMMON_END);
- bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END);
- bnx2x_init_block(bp, CSEM_COMMON_START, CSEM_COMMON_END);
- bnx2x_init_block(bp, XSEM_COMMON_START, XSEM_COMMON_END);
-
- /* sync semi rtc */
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
- 0x80000000);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
- 0x80000000);
-
- bnx2x_init_block(bp, UPB_COMMON_START, UPB_COMMON_END);
- bnx2x_init_block(bp, XPB_COMMON_START, XPB_COMMON_END);
- bnx2x_init_block(bp, PBF_COMMON_START, PBF_COMMON_END);
-
- 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, 0xc0cac01a);
- /* TODO: replace with something meaningful */
- }
- /* SRCH COMMON comes here */
- REG_WR(bp, SRC_REG_SOFT_RST, 0);
-
- if (sizeof(union cdu_context) != 1024) {
- /* we currently assume that a context is 1024 bytes */
- printk(KERN_ALERT PFX "please adjust the size of"
- " cdu_context(%ld)\n",
- (long)sizeof(union cdu_context));
- }
- val = (4 << 24) + (0 << 12) + 1024;
- REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
- bnx2x_init_block(bp, CDU_COMMON_START, CDU_COMMON_END);
-
- bnx2x_init_block(bp, CFC_COMMON_START, CFC_COMMON_END);
- REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
-
- bnx2x_init_block(bp, HC_COMMON_START, HC_COMMON_END);
- bnx2x_init_block(bp, MISC_AEU_COMMON_START,
- MISC_AEU_COMMON_END);
- /* RXPCS COMMON comes here */
- /* EMAC0 COMMON comes here */
- /* EMAC1 COMMON comes here */
- /* DBU COMMON comes here */
- /* DBG COMMON comes here */
- bnx2x_init_block(bp, NIG_COMMON_START, NIG_COMMON_END);
+ bnx2x_init_block(bp, TSEM_COMMON_START, TSEM_COMMON_END);
+ bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END);
+ bnx2x_init_block(bp, CSEM_COMMON_START, CSEM_COMMON_END);
+ bnx2x_init_block(bp, XSEM_COMMON_START, XSEM_COMMON_END);
- if (CHIP_REV_IS_SLOW(bp))
- msleep(200);
+ /* sync semi rtc */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+ 0x80000000);
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
+ 0x80000000);
- /* finish CFC init */
- val = REG_RD(bp, CFC_REG_LL_INIT_DONE);
- if (val != 1) {
- BNX2X_ERR("CFC LL_INIT failed\n");
- return -EBUSY;
- }
+ bnx2x_init_block(bp, UPB_COMMON_START, UPB_COMMON_END);
+ bnx2x_init_block(bp, XPB_COMMON_START, XPB_COMMON_END);
+ bnx2x_init_block(bp, PBF_COMMON_START, PBF_COMMON_END);
- val = REG_RD(bp, CFC_REG_AC_INIT_DONE);
- if (val != 1) {
- BNX2X_ERR("CFC AC_INIT failed\n");
- return -EBUSY;
- }
+ 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, 0xc0cac01a);
+ /* TODO: replace with something meaningful */
+ }
+ if (CHIP_IS_E1H(bp))
+ bnx2x_init_block(bp, SRCH_COMMON_START, SRCH_COMMON_END);
+ REG_WR(bp, SRC_REG_SOFT_RST, 0);
- val = REG_RD(bp, CFC_REG_CAM_INIT_DONE);
- if (val != 1) {
- BNX2X_ERR("CFC CAM_INIT failed\n");
- return -EBUSY;
- }
+ if (sizeof(union cdu_context) != 1024)
+ /* we currently assume that a context is 1024 bytes */
+ printk(KERN_ALERT PFX "please adjust the size of"
+ " cdu_context(%ld)\n", (long)sizeof(union cdu_context));
- REG_WR(bp, CFC_REG_DEBUG0, 0);
+ bnx2x_init_block(bp, CDU_COMMON_START, CDU_COMMON_END);
+ val = (4 << 24) + (0 << 12) + 1024;
+ REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
+ if (CHIP_IS_E1(bp)) {
+ /* !!! fix pxp client crdit until excel update */
+ REG_WR(bp, CDU_REG_CDU_DEBUG, 0x264);
+ REG_WR(bp, CDU_REG_CDU_DEBUG, 0);
+ }
- /* read NIG statistic
- to see if this is our first up since powerup */
-#ifdef BNX2X_DMAE_RD
- bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
- val = *bnx2x_sp(bp, wb_data[0]);
-#else
- val = REG_RD(bp, NIG_REG_STAT2_BRB_OCTET);
- REG_RD(bp, NIG_REG_STAT2_BRB_OCTET + 4);
-#endif
- /* do internal memory self test */
- if ((val == 0) && bnx2x_int_mem_test(bp)) {
- BNX2X_ERR("internal mem selftest failed\n");
- return -EBUSY;
- }
+ bnx2x_init_block(bp, CFC_COMMON_START, CFC_COMMON_END);
+ REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
- /* clear PXP2 attentions */
- REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR);
+ bnx2x_init_block(bp, HC_COMMON_START, HC_COMMON_END);
+ bnx2x_init_block(bp, MISC_AEU_COMMON_START, MISC_AEU_COMMON_END);
- enable_blocks_attention(bp);
- /* enable_blocks_parity(bp); */
+ /* PXPCS COMMON comes here */
+ /* Reset PCIE errors for debug */
+ REG_WR(bp, 0x2814, 0xffffffff);
+ REG_WR(bp, 0x3820, 0xffffffff);
- switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
- case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
- /* Fan failure is indicated by SPIO 5 */
- bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
- MISC_REGISTERS_SPIO_INPUT_HI_Z);
+ /* EMAC0 COMMON comes here */
+ /* EMAC1 COMMON comes here */
+ /* DBU COMMON comes here */
+ /* DBG COMMON comes here */
+
+ bnx2x_init_block(bp, NIG_COMMON_START, NIG_COMMON_END);
+ if (CHIP_IS_E1H(bp)) {
+ REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_E1HMF(bp));
+ REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_E1HMF(bp));
+ }
+
+ if (CHIP_REV_IS_SLOW(bp))
+ msleep(200);
+
+ /* finish CFC init */
+ val = reg_poll(bp, CFC_REG_LL_INIT_DONE, 1, 100, 10);
+ if (val != 1) {
+ BNX2X_ERR("CFC LL_INIT failed\n");
+ return -EBUSY;
+ }
+ val = reg_poll(bp, CFC_REG_AC_INIT_DONE, 1, 100, 10);
+ if (val != 1) {
+ BNX2X_ERR("CFC AC_INIT failed\n");
+ return -EBUSY;
+ }
+ val = reg_poll(bp, CFC_REG_CAM_INIT_DONE, 1, 100, 10);
+ if (val != 1) {
+ BNX2X_ERR("CFC CAM_INIT failed\n");
+ return -EBUSY;
+ }
+ REG_WR(bp, CFC_REG_DEBUG0, 0);
- /* set to active low mode */
- val = REG_RD(bp, MISC_REG_SPIO_INT);
- val |= ((1 << MISC_REGISTERS_SPIO_5) <<
+ /* read NIG statistic
+ to see if this is our first up since powerup */
+ bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
+ val = *bnx2x_sp(bp, wb_data[0]);
+
+ /* do internal memory self test */
+ if ((CHIP_IS_E1(bp)) && (val == 0) && bnx2x_int_mem_test(bp)) {
+ BNX2X_ERR("internal mem self test failed\n");
+ return -EBUSY;
+ }
+
+ switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+ case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
+ /* Fan failure is indicated by SPIO 5 */
+ bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
+ MISC_REGISTERS_SPIO_INPUT_HI_Z);
+
+ /* set to active low mode */
+ val = REG_RD(bp, MISC_REG_SPIO_INT);
+ val |= ((1 << MISC_REGISTERS_SPIO_5) <<
MISC_REGISTERS_SPIO_INT_OLD_SET_POS);
- REG_WR(bp, MISC_REG_SPIO_INT, val);
+ REG_WR(bp, MISC_REG_SPIO_INT, val);
- /* enable interrupt to signal the IGU */
- val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
- val |= (1 << MISC_REGISTERS_SPIO_5);
- REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
- break;
+ /* enable interrupt to signal the IGU */
+ val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
+ val |= (1 << MISC_REGISTERS_SPIO_5);
+ REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
- } /* end of common init */
+ /* clear PXP2 attentions */
+ REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR_0);
- /* per port init */
+ enable_blocks_attention(bp);
- /* the phys address is shifted right 12 bits and has an added
- 1=valid bit added to the 53rd bit
- then since this is a wide register(TM)
- we split it into two 32 bit writes
- */
-#define RQ_ONCHIP_AT_PORT_SIZE 384
-#define ONCHIP_ADDR1(x) ((u32)(((u64)x >> 12) & 0xFFFFFFFF))
-#define ONCHIP_ADDR2(x) ((u32)((1 << 20) | ((u64)x >> 44)))
-#define PXP_ONE_ILT(x) ((x << 10) | x)
+ return 0;
+}
- DP(BNX2X_MSG_MCP, "starting per-function init port is %x\n", func);
+static int bnx2x_init_port(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ u32 val;
- REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + func*4, 0);
+ DP(BNX2X_MSG_MCP, "starting port init port %x\n", port);
+
+ REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
/* Port PXP comes here */
/* Port PXP2 comes here */
-
- /* Offset is
- * Port0 0
- * Port1 384 */
- i = func * RQ_ONCHIP_AT_PORT_SIZE;
-#ifdef USE_DMAE
- wb_write[0] = ONCHIP_ADDR1(bnx2x_sp_mapping(bp, context));
- wb_write[1] = ONCHIP_ADDR2(bnx2x_sp_mapping(bp, context));
- REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2);
-#else
- REG_WR_IND(bp, PXP2_REG_RQ_ONCHIP_AT + i*8,
- ONCHIP_ADDR1(bnx2x_sp_mapping(bp, context)));
- REG_WR_IND(bp, PXP2_REG_RQ_ONCHIP_AT + i*8 + 4,
- ONCHIP_ADDR2(bnx2x_sp_mapping(bp, context)));
-#endif
- REG_WR(bp, PXP2_REG_PSWRQ_CDU0_L2P + func*4, PXP_ONE_ILT(i));
-
#ifdef BCM_ISCSI
/* Port0 1
* Port1 385 */
REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2);
REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i));
#endif
-
- /* Port TCM comes here */
- /* Port UCM comes here */
- /* Port CCM comes here */
- bnx2x_init_block(bp, func ? XCM_PORT1_START : XCM_PORT0_START,
- func ? XCM_PORT1_END : XCM_PORT0_END);
-
-#ifdef USE_DMAE
- wb_write[0] = 0;
- wb_write[1] = 0;
-#endif
- for (i = 0; i < 32; i++) {
- REG_WR(bp, QM_REG_BASEADDR + (func*32 + i)*4, 1024 * 4 * i);
-#ifdef USE_DMAE
- REG_WR_DMAE(bp, QM_REG_PTRTBL + (func*32 + i)*8, wb_write, 2);
-#else
- REG_WR_IND(bp, QM_REG_PTRTBL + (func*32 + i)*8, 0);
- REG_WR_IND(bp, QM_REG_PTRTBL + (func*32 + i)*8 + 4, 0);
-#endif
- }
- REG_WR(bp, QM_REG_CONNNUM_0 + func*4, 1024/16 - 1);
+ /* Port CMs come here */
/* Port QM comes here */
-
#ifdef BCM_ISCSI
REG_WR(bp, TM_REG_LIN0_SCAN_TIME + func*4, 1024/64*20);
REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + func*4, 31);
/* Port CSDM comes here */
/* Port USDM comes here */
/* Port XSDM comes here */
- bnx2x_init_block(bp, func ? TSEM_PORT1_START : TSEM_PORT0_START,
- func ? TSEM_PORT1_END : TSEM_PORT0_END);
- bnx2x_init_block(bp, func ? USEM_PORT1_START : USEM_PORT0_START,
- func ? USEM_PORT1_END : USEM_PORT0_END);
- bnx2x_init_block(bp, func ? CSEM_PORT1_START : CSEM_PORT0_START,
- func ? CSEM_PORT1_END : CSEM_PORT0_END);
- bnx2x_init_block(bp, func ? XSEM_PORT1_START : XSEM_PORT0_START,
- func ? XSEM_PORT1_END : XSEM_PORT0_END);
+ bnx2x_init_block(bp, port ? TSEM_PORT1_START : TSEM_PORT0_START,
+ port ? TSEM_PORT1_END : TSEM_PORT0_END);
+ bnx2x_init_block(bp, port ? USEM_PORT1_START : USEM_PORT0_START,
+ port ? USEM_PORT1_END : USEM_PORT0_END);
+ bnx2x_init_block(bp, port ? CSEM_PORT1_START : CSEM_PORT0_START,
+ port ? CSEM_PORT1_END : CSEM_PORT0_END);
+ bnx2x_init_block(bp, port ? XSEM_PORT1_START : XSEM_PORT0_START,
+ port ? XSEM_PORT1_END : XSEM_PORT0_END);
/* Port UPB comes here */
- /* Port XSDM comes here */
- bnx2x_init_block(bp, func ? PBF_PORT1_START : PBF_PORT0_START,
- func ? PBF_PORT1_END : PBF_PORT0_END);
+ /* Port XPB comes here */
+
+ bnx2x_init_block(bp, port ? PBF_PORT1_START : PBF_PORT0_START,
+ port ? PBF_PORT1_END : PBF_PORT0_END);
/* configure PBF to work without PAUSE mtu 9000 */
- REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + func*4, 0);
+ REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
/* update threshold */
- REG_WR(bp, PBF_REG_P0_ARB_THRSH + func*4, (9040/16));
+ REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, (9040/16));
/* update init credit */
- REG_WR(bp, PBF_REG_P0_INIT_CRD + func*4, (9040/16) + 553 - 22);
+ REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, (9040/16) + 553 - 22);
/* probe changes */
- REG_WR(bp, PBF_REG_INIT_P0 + func*4, 1);
+ REG_WR(bp, PBF_REG_INIT_P0 + port*4, 1);
msleep(5);
- REG_WR(bp, PBF_REG_INIT_P0 + func*4, 0);
+ REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
#ifdef BCM_ISCSI
/* tell the searcher where the T2 table is */
#endif
/* Port CDU comes here */
/* Port CFC comes here */
- bnx2x_init_block(bp, func ? HC_PORT1_START : HC_PORT0_START,
- func ? HC_PORT1_END : HC_PORT0_END);
- bnx2x_init_block(bp, func ? MISC_AEU_PORT1_START :
+
+ 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, port ? HC_PORT1_START : HC_PORT0_START,
+ port ? HC_PORT1_END : HC_PORT0_END);
+
+ bnx2x_init_block(bp, port ? MISC_AEU_PORT1_START :
MISC_AEU_PORT0_START,
- func ? MISC_AEU_PORT1_END : MISC_AEU_PORT0_END);
+ port ? MISC_AEU_PORT1_END : MISC_AEU_PORT0_END);
+ /* 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
+ * bits 4-7 are used for "per vn group attention" */
+ REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4,
+ (IS_E1HMF(bp) ? 0xF7 : 0x7));
+
/* Port PXPCS comes here */
/* Port EMAC0 comes here */
/* Port EMAC1 comes here */
/* Port DBU comes here */
/* Port DBG comes here */
- bnx2x_init_block(bp, func ? NIG_PORT1_START : NIG_PORT0_START,
- func ? NIG_PORT1_END : NIG_PORT0_END);
- REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + func*4, 1);
+ bnx2x_init_block(bp, port ? NIG_PORT1_START : NIG_PORT0_START,
+ port ? NIG_PORT1_END : NIG_PORT0_END);
+
+ REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
+
+ if (CHIP_IS_E1H(bp)) {
+ u32 wsum;
+ struct cmng_struct_per_port m_cmng_port;
+ int vn;
+
+ /* 0x2 disable e1hov, 0x1 enable */
+ REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
+ (IS_E1HMF(bp) ? 0x1 : 0x2));
+
+ /* Init RATE SHAPING and FAIRNESS contexts.
+ Initialize as if there is 10G link. */
+ wsum = bnx2x_calc_vn_wsum(bp);
+ bnx2x_init_port_minmax(bp, (int)wsum, 10000, &m_cmng_port);
+ if (IS_E1HMF(bp))
+ for (vn = VN_0; vn < E1HVN_MAX; vn++)
+ bnx2x_init_vn_minmax(bp, 2*vn + port,
+ wsum, 10000, &m_cmng_port);
+ }
+
/* Port MCP comes here */
/* Port DMAE comes here */
- switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
+ switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
/* add SPIO 5 to group 0 */
val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
bnx2x__link_reset(bp);
+ return 0;
+}
+
+#define ILT_PER_FUNC (768/2)
+#define FUNC_ILT_BASE(func) (func * ILT_PER_FUNC)
+/* the phys address is shifted right 12 bits and has an added
+ 1=valid bit added to the 53rd bit
+ then since this is a wide register(TM)
+ we split it into two 32 bit writes
+ */
+#define ONCHIP_ADDR1(x) ((u32)(((u64)x >> 12) & 0xFFFFFFFF))
+#define ONCHIP_ADDR2(x) ((u32)((1 << 20) | ((u64)x >> 44)))
+#define PXP_ONE_ILT(x) (((x) << 10) | x)
+#define PXP_ILT_RANGE(f, l) (((l) << 10) | f)
+
+#define CNIC_ILT_LINES 0
+
+static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr)
+{
+ int reg;
+
+ if (CHIP_IS_E1H(bp))
+ reg = PXP2_REG_RQ_ONCHIP_AT_B0 + index*8;
+ else /* E1 */
+ reg = PXP2_REG_RQ_ONCHIP_AT + index*8;
+
+ bnx2x_wb_wr(bp, reg, ONCHIP_ADDR1(addr), ONCHIP_ADDR2(addr));
+}
+
+static int bnx2x_init_func(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ int func = BP_FUNC(bp);
+ int i;
+
+ DP(BNX2X_MSG_MCP, "starting func init func %x\n", func);
+
+ i = FUNC_ILT_BASE(func);
+
+ bnx2x_ilt_wr(bp, i, bnx2x_sp_mapping(bp, context));
+ if (CHIP_IS_E1H(bp)) {
+ REG_WR(bp, PXP2_REG_RQ_CDU_FIRST_ILT, i);
+ REG_WR(bp, PXP2_REG_RQ_CDU_LAST_ILT, i + CNIC_ILT_LINES);
+ } else /* E1 */
+ REG_WR(bp, PXP2_REG_PSWRQ_CDU0_L2P + func*4,
+ PXP_ILT_RANGE(i, i + CNIC_ILT_LINES));
+
+
+ if (CHIP_IS_E1H(bp)) {
+ for (i = 0; i < 9; i++)
+ bnx2x_init_block(bp,
+ cm_start[func][i], cm_end[func][i]);
+
+ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
+ REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->e1hov);
+ }
+
+ /* HC init per function */
+ if (CHIP_IS_E1H(bp)) {
+ REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
+
+ 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_limits[func][0], hc_limits[func][1]);
+
+ if (CHIP_IS_E1H(bp))
+ REG_WR(bp, HC_REG_FUNC_NUM_P0 + port*4, func);
+
/* Reset PCIE errors for debug */
REG_WR(bp, 0x2114, 0xffffffff);
REG_WR(bp, 0x2120, 0xffffffff);
- REG_WR(bp, 0x2814, 0xffffffff);
- /* !!! move to init_values.h */
- REG_WR(bp, XSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1);
- REG_WR(bp, USDM_REG_INIT_CREDIT_PXP_CTRL, 0x1);
- REG_WR(bp, CSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1);
- REG_WR(bp, TSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1);
+ return 0;
+}
+
+static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
+{
+ int i, rc = 0;
- REG_WR(bp, DBG_REG_PCI_REQ_CREDIT, 0x1);
- REG_WR(bp, TM_REG_PCIARB_CRDCNT_VAL, 0x1);
- REG_WR(bp, CDU_REG_CDU_DEBUG, 0x264);
- REG_WR(bp, CDU_REG_CDU_DEBUG, 0x0);
+ DP(BNX2X_MSG_MCP, "function %d load_code %x\n",
+ BP_FUNC(bp), load_code);
- bnx2x_gunzip_end(bp);
+ bp->dmae_ready = 0;
+ mutex_init(&bp->dmae_mutex);
+ bnx2x_gunzip_init(bp);
- if (!nomcp) {
- port = bp->port;
+ switch (load_code) {
+ case FW_MSG_CODE_DRV_LOAD_COMMON:
+ rc = bnx2x_init_common(bp);
+ if (rc)
+ goto init_hw_err;
+ /* no break */
+
+ case FW_MSG_CODE_DRV_LOAD_PORT:
+ bp->dmae_ready = 1;
+ rc = bnx2x_init_port(bp);
+ if (rc)
+ goto init_hw_err;
+ /* no break */
+
+ case FW_MSG_CODE_DRV_LOAD_FUNCTION:
+ bp->dmae_ready = 1;
+ rc = bnx2x_init_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 func = BP_FUNC(bp);
bp->fw_drv_pulse_wr_seq =
- (SHMEM_RD(bp, func_mb[port].drv_pulse_mb) &
+ (SHMEM_RD(bp, func_mb[func].drv_pulse_mb) &
DRV_PULSE_SEQ_MASK);
- bp->fw_mb = SHMEM_RD(bp, func_mb[port].fw_mb_param);
- DP(BNX2X_MSG_MCP, "drv_pulse 0x%x fw_mb 0x%x\n",
- bp->fw_drv_pulse_wr_seq, bp->fw_mb);
- } else {
- bp->fw_mb = 0;
- }
+ bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param);
+ DP(BNX2X_MSG_MCP, "drv_pulse 0x%x func_stx 0x%x\n",
+ bp->fw_drv_pulse_wr_seq, bp->func_stx);
+ } else
+ bp->func_stx = 0;
- return 0;
+ /* this needs to be done before gunzip end */
+ bnx2x_zero_def_sb(bp);
+ for_each_queue(bp, i)
+ bnx2x_zero_sb(bp, BP_L_ID(bp) + i);
+
+init_hw_err:
+ bnx2x_gunzip_end(bp);
+
+ return rc;
}
/* send the MCP a request, block until there is a reply */
static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
{
- int port = bp->port;
+ int func = BP_FUNC(bp);
u32 seq = ++bp->fw_seq;
u32 rc = 0;
- SHMEM_WR(bp, func_mb[port].drv_mb_header, (command | seq));
+ SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
/* let the FW do it's magic ... */
if (CHIP_REV_IS_SLOW(bp))
msleep(900);
- rc = SHMEM_RD(bp, func_mb[port].fw_mb_header);
+ rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
DP(BNX2X_MSG_MCP, "read (%x) seq is (%x) from FW MB\n", rc, seq);
/* is this a reply to our command? */
NUM_RCQ_BD);
}
- BNX2X_FREE(bp->fp);
-
/* end of fastpath */
BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
- (sizeof(struct host_def_status_block)));
+ sizeof(struct host_def_status_block));
BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping,
- (sizeof(struct bnx2x_slowpath)));
+ sizeof(struct bnx2x_slowpath));
#ifdef BCM_ISCSI
BNX2X_PCI_FREE(bp->t1, bp->t1_mapping, 64*1024);
int i;
/* fastpath */
- BNX2X_ALLOC(bp->fp, sizeof(struct bnx2x_fastpath) * bp->num_queues);
-
for_each_queue(bp, i) {
bnx2x_fp(bp, i, bp) = bp;
u16 sw_prod = fp->tx_pkt_prod;
u16 sw_cons = fp->tx_pkt_cons;
- BUG_TRAP(fp->tx_buf_ring != NULL);
-
while (sw_cons != sw_prod) {
bd_cons = bnx2x_free_tx_pkt(bp, fp, TX_BD(sw_cons));
sw_cons++;
for_each_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
- BUG_TRAP(fp->rx_buf_ring != NULL);
-
for (i = 0; i < NUM_RX_BD; i++) {
struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[i];
struct sk_buff *skb = rx_buf->skb;
static void bnx2x_free_msix_irqs(struct bnx2x *bp)
{
- int i;
+ int i, offset = 1;
free_irq(bp->msix_table[0].vector, bp->dev);
DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
for_each_queue(bp, i) {
DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq "
- "state(%x)\n", i, bp->msix_table[i + 1].vector,
+ "state %x\n", i, bp->msix_table[i + offset].vector,
bnx2x_fp(bp, i, state));
if (bnx2x_fp(bp, i, state) != BNX2X_FP_STATE_CLOSED)
BNX2X_ERR("IRQ of fp #%d being freed while "
"state != closed\n", i);
- free_irq(bp->msix_table[i + 1].vector, &bp->fp[i]);
+ free_irq(bp->msix_table[i + offset].vector, &bp->fp[i]);
}
-
}
static void bnx2x_free_irq(struct bnx2x *bp)
{
-
if (bp->flags & USING_MSIX_FLAG) {
-
bnx2x_free_msix_irqs(bp);
pci_disable_msix(bp->pdev);
-
bp->flags &= ~USING_MSIX_FLAG;
} else
static int bnx2x_enable_msix(struct bnx2x *bp)
{
-
- int i;
+ int i, rc, offset;
bp->msix_table[0].entry = 0;
- for_each_queue(bp, i)
- bp->msix_table[i + 1].entry = i + 1;
+ offset = 1;
+ DP(NETIF_MSG_IFUP, "msix_table[0].entry = 0 (slowpath)\n");
- if (pci_enable_msix(bp->pdev, &bp->msix_table[0],
- bp->num_queues + 1)){
- BNX2X_LOG("failed to enable MSI-X\n");
- return -1;
+ for_each_queue(bp, i) {
+ int igu_vec = offset + i + BP_L_ID(bp);
+ bp->msix_table[i + offset].entry = igu_vec;
+ DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d "
+ "(fastpath #%u)\n", i + offset, igu_vec, i);
}
+ rc = pci_enable_msix(bp->pdev, &bp->msix_table[0],
+ bp->num_queues + offset);
+ if (rc) {
+ DP(NETIF_MSG_IFUP, "MSI-X is not attainable\n");
+ return -1;
+ }
bp->flags |= USING_MSIX_FLAG;
return 0;
-
}
-
static int bnx2x_req_msix_irqs(struct bnx2x *bp)
{
-
- int i, rc;
+ int i, rc, offset = 1;
rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0,
bp->dev->name, bp->dev);
-
if (rc) {
BNX2X_ERR("request sp irq failed\n");
return -EBUSY;
}
for_each_queue(bp, i) {
- rc = request_irq(bp->msix_table[i + 1].vector,
+ rc = request_irq(bp->msix_table[i + offset].vector,
bnx2x_msix_fp_int, 0,
bp->dev->name, &bp->fp[i]);
-
if (rc) {
- BNX2X_ERR("request fp #%d irq failed "
- "rc %d\n", i, rc);
+ BNX2X_ERR("request fp #%d irq failed rc %d\n",
+ i + offset, rc);
bnx2x_free_msix_irqs(bp);
return -EBUSY;
}
bnx2x_fp(bp, i, state) = BNX2X_FP_STATE_IRQ;
-
}
return 0;
-
}
static int bnx2x_req_irq(struct bnx2x *bp)
{
+ int rc;
- int rc = request_irq(bp->pdev->irq, bnx2x_interrupt,
- IRQF_SHARED, bp->dev->name, bp->dev);
+ rc = request_irq(bp->pdev->irq, bnx2x_interrupt, IRQF_SHARED,
+ bp->dev->name, bp->dev);
if (!rc)
bnx2x_fp(bp, 0, state) = BNX2X_FP_STATE_IRQ;
return rc;
-
}
/*
* Init service functions
*/
-static void bnx2x_set_mac_addr(struct bnx2x *bp)
+static void bnx2x_set_mac_addr_e1(struct bnx2x *bp)
{
struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config);
+ int port = BP_PORT(bp);
/* CAM allocation
* unicasts 0-31:port0 32-63:port1
* multicast 64-127:port0 128-191:port1
*/
config->hdr.length_6b = 2;
- config->hdr.offset = bp->port ? 31 : 0;
- config->hdr.reserved0 = 0;
+ config->hdr.offset = port ? 31 : 0;
+ config->hdr.client_id = BP_CL_ID(bp);
config->hdr.reserved1 = 0;
/* primary MAC */
swab16(*(u16 *)&bp->dev->dev_addr[2]);
config->config_table[0].cam_entry.lsb_mac_addr =
swab16(*(u16 *)&bp->dev->dev_addr[4]);
- config->config_table[0].cam_entry.flags = cpu_to_le16(bp->port);
+ config->config_table[0].cam_entry.flags = cpu_to_le16(port);
config->config_table[0].target_table_entry.flags = 0;
config->config_table[0].target_table_entry.client_id = 0;
config->config_table[0].target_table_entry.vlan_id = 0;
config->config_table[1].cam_entry.msb_mac_addr = 0xffff;
config->config_table[1].cam_entry.middle_mac_addr = 0xffff;
config->config_table[1].cam_entry.lsb_mac_addr = 0xffff;
- config->config_table[1].cam_entry.flags = cpu_to_le16(bp->port);
+ config->config_table[1].cam_entry.flags = cpu_to_le16(port);
config->config_table[1].target_table_entry.flags =
TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST;
config->config_table[1].target_table_entry.client_id = 0;
U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
}
+static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp)
+{
+ struct mac_configuration_cmd_e1h *config =
+ (struct mac_configuration_cmd_e1h *)bnx2x_sp(bp, mac_config);
+
+ if (bp->state != BNX2X_STATE_OPEN) {
+ DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
+ return;
+ }
+
+ /* CAM allocation for E1H
+ * unicasts: by func number
+ * multicast: 20+FUNC*20, 20 each
+ */
+ config->hdr.length_6b = 1;
+ config->hdr.offset = BP_FUNC(bp);
+ config->hdr.client_id = BP_CL_ID(bp);
+ config->hdr.reserved1 = 0;
+
+ /* primary MAC */
+ config->config_table[0].msb_mac_addr =
+ swab16(*(u16 *)&bp->dev->dev_addr[0]);
+ config->config_table[0].middle_mac_addr =
+ swab16(*(u16 *)&bp->dev->dev_addr[2]);
+ config->config_table[0].lsb_mac_addr =
+ swab16(*(u16 *)&bp->dev->dev_addr[4]);
+ config->config_table[0].client_id = BP_L_ID(bp);
+ config->config_table[0].vlan_id = 0;
+ config->config_table[0].e1hov_id = cpu_to_le16(bp->e1hov);
+ config->config_table[0].flags = BP_PORT(bp);
+
+ DP(NETIF_MSG_IFUP, "setting MAC (%04x:%04x:%04x) E1HOV %d CLID %d\n",
+ config->config_table[0].msb_mac_addr,
+ config->config_table[0].middle_mac_addr,
+ config->config_table[0].lsb_mac_addr, bp->e1hov, BP_L_ID(bp));
+
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
+ U64_HI(bnx2x_sp_mapping(bp, mac_config)),
+ U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
+}
+
static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
int *state_p, int poll)
{
/* can take a while if any port is running */
- int timeout = 500;
+ int cnt = 500;
DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n",
poll ? "polling" : "waiting", state, idx);
might_sleep();
-
- while (timeout) {
-
+ while (cnt--) {
if (poll) {
bnx2x_rx_int(bp->fp, 10);
- /* If index is different from 0
- * The reply for some commands will
+ /* if index is different from 0
+ * the reply for some commands will
* be on the none default queue
*/
if (idx)
bnx2x_rx_int(&bp->fp[idx], 10);
}
-
- mb(); /* state is changed by bnx2x_sp_event()*/
+ mb(); /* state is changed by bnx2x_sp_event() */
if (*state_p == state)
return 0;
- timeout--;
msleep(1);
-
}
/* 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 int bnx2x_setup_leading(struct bnx2x *bp)
{
+ int rc;
/* reset IGU state */
- bnx2x_ack_sb(bp, DEF_SB_ID, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+ bnx2x_ack_sb(bp, bp->fp[0].sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
/* SETUP ramrod */
bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_SETUP, 0, 0, 0, 0);
- return bnx2x_wait_ramrod(bp, BNX2X_STATE_OPEN, 0, &(bp->state), 0);
+ /* Wait for completion */
+ rc = bnx2x_wait_ramrod(bp, BNX2X_STATE_OPEN, 0, &(bp->state), 0);
+ return rc;
}
static int bnx2x_setup_multi(struct bnx2x *bp, int index)
{
-
/* reset IGU state */
- bnx2x_ack_sb(bp, index, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+ bnx2x_ack_sb(bp, bp->fp[index].sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
/* SETUP ramrod */
bp->fp[index].state = BNX2X_FP_STATE_OPENING;
/* Wait for completion */
return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_OPEN, index,
&(bp->fp[index].state), 0);
-
}
-
static int bnx2x_poll(struct napi_struct *napi, int budget);
static void bnx2x_set_rx_mode(struct net_device *dev);
-static int bnx2x_nic_load(struct bnx2x *bp, int req_irq)
+/* must be called with rtnl_lock */
+static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
{
u32 load_code;
- int i;
+ int i, rc;
+
+#ifdef BNX2X_STOP_ON_ERROR
+ if (unlikely(bp->panic))
+ return -EPERM;
+#endif
bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
- /* Send LOAD_REQUEST command to MCP.
- Returns the type of LOAD command: if it is the
- first port to be initialized common blocks should be
- initialized, otherwise - not.
+ /* Send LOAD_REQUEST command to MCP
+ Returns the type of LOAD command:
+ if it is the first port to be initialized
+ common blocks should be initialized, otherwise - not
*/
- if (!nomcp) {
+ if (!BP_NOMCP(bp)) {
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
if (!load_code) {
BNX2X_ERR("MCP response failure, unloading\n");
return -EBUSY;
}
- if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
- BNX2X_ERR("MCP refused load request, unloading\n");
+ if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED)
return -EBUSY; /* other port in diagnostic mode */
- }
+
} else {
- load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
+ DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n",
+ load_count[0], load_count[1], load_count[2]);
+ load_count[0]++;
+ load_count[1 + BP_PORT(bp)]++;
+ DP(NETIF_MSG_IFUP, "NO MCP new load counts %d, %d, %d\n",
+ load_count[0], load_count[1], load_count[2]);
+ if (load_count[0] == 1)
+ load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
+ else if (load_count[1 + BP_PORT(bp)] == 1)
+ load_code = FW_MSG_CODE_DRV_LOAD_PORT;
+ else
+ load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
}
- /* if we can't use msix we only need one fp,
- * so try to enable msix with the requested number of fp's
+ if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
+ (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
+ bp->port.pmf = 1;
+ else
+ bp->port.pmf = 0;
+ DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
+
+ /* if we can't use MSI-X we only need one fp,
+ * so try to enable MSI-X with the requested number of fp's
* and fallback to inta with one fp
*/
- if (req_irq) {
- if (use_inta) {
+ if (use_inta) {
+ bp->num_queues = 1;
+
+ } else {
+ if ((use_multi > 1) && (use_multi <= BP_MAX_QUEUES(bp)))
+ /* user requested number */
+ bp->num_queues = use_multi;
+
+ else if (use_multi)
+ bp->num_queues = min_t(u32, num_online_cpus(),
+ BP_MAX_QUEUES(bp));
+ else
bp->num_queues = 1;
- } else {
- if ((use_multi > 1) && (use_multi <= 16))
- /* user requested number */
- bp->num_queues = use_multi;
- else if (use_multi == 1)
- bp->num_queues = num_online_cpus();
- else
- bp->num_queues = 1;
-
- if (bnx2x_enable_msix(bp)) {
- /* failed to enable msix */
- bp->num_queues = 1;
- if (use_multi)
- BNX2X_ERR("Multi requested but failed"
- " to enable MSI-X\n");
- }
+
+ if (bnx2x_enable_msix(bp)) {
+ /* failed to enable MSI-X */
+ bp->num_queues = 1;
+ if (use_multi)
+ BNX2X_ERR("Multi requested but failed"
+ " to enable MSI-X\n");
}
}
-
- DP(NETIF_MSG_IFUP, "set number of queues to %d\n", bp->num_queues);
+ DP(NETIF_MSG_IFUP,
+ "set number of queues to %d\n", bp->num_queues);
if (bnx2x_alloc_mem(bp))
return -ENOMEM;
- if (req_irq) {
- if (bp->flags & USING_MSIX_FLAG) {
- if (bnx2x_req_msix_irqs(bp)) {
- pci_disable_msix(bp->pdev);
- goto load_error;
- }
+ /* Disable interrupt handling until HW is initialized */
+ atomic_set(&bp->intr_sem, 1);
- } else {
- if (bnx2x_req_irq(bp)) {
- BNX2X_ERR("IRQ request failed, aborting\n");
- goto load_error;
- }
+ if (bp->flags & USING_MSIX_FLAG) {
+ rc = bnx2x_req_msix_irqs(bp);
+ if (rc) {
+ pci_disable_msix(bp->pdev);
+ goto load_error;
+ }
+ } else {
+ bnx2x_ack_int(bp);
+ rc = bnx2x_req_irq(bp);
+ if (rc) {
+ BNX2X_ERR("IRQ request failed, aborting\n");
+ goto load_error;
}
}
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, 128);
-
/* Initialize HW */
- if (bnx2x_function_init(bp,
- (load_code == FW_MSG_CODE_DRV_LOAD_COMMON))) {
+ rc = bnx2x_init_hw(bp, load_code);
+ if (rc) {
BNX2X_ERR("HW init failed, aborting\n");
goto load_error;
}
-
+ /* Enable interrupt handling */
atomic_set(&bp->intr_sem, 0);
-
/* Setup NIC internals and enable interrupts */
bnx2x_nic_init(bp);
/* Send LOAD_DONE command to MCP */
- if (!nomcp) {
+ if (!BP_NOMCP(bp)) {
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
if (!load_code) {
BNX2X_ERR("MCP response failure, unloading\n");
+ rc = -EBUSY;
goto load_int_disable;
}
}
for_each_queue(bp, i)
napi_enable(&bnx2x_fp(bp, i, napi));
- if (bnx2x_setup_leading(bp))
+ rc = bnx2x_setup_leading(bp);
+ if (rc) {
+#ifdef BNX2X_STOP_ON_ERROR
+ bp->panic = 1;
+#endif
goto load_stop_netif;
+ }
- for_each_nondefault_queue(bp, i)
- if (bnx2x_setup_multi(bp, i))
- goto load_stop_netif;
+ if (CHIP_IS_E1H(bp))
+ if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) {
+ BNX2X_ERR("!!! mf_cfg function disabled\n");
+ bp->state = BNX2X_STATE_DISABLED;
+ }
- bnx2x_set_mac_addr(bp);
+ if (bp->state == BNX2X_STATE_OPEN)
+ for_each_nondefault_queue(bp, i) {
+ rc = bnx2x_setup_multi(bp, i);
+ if (rc)
+ goto load_stop_netif;
+ }
- bnx2x_initial_phy_init(bp);
+ if (CHIP_IS_E1(bp))
+ bnx2x_set_mac_addr_e1(bp);
+ else
+ bnx2x_set_mac_addr_e1h(bp);
+
+ if (bp->port.pmf)
+ bnx2x_initial_phy_init(bp);
/* Start fast path */
- if (req_irq) { /* IRQ is only requested from bnx2x_open */
+ switch (load_mode) {
+ case LOAD_NORMAL:
+ /* Tx queue should be only reenabled */
+ netif_wake_queue(bp->dev);
+ bnx2x_set_rx_mode(bp->dev);
+ break;
+
+ case LOAD_OPEN:
+ /* IRQ is only requested from bnx2x_open */
netif_start_queue(bp->dev);
+ bnx2x_set_rx_mode(bp->dev);
if (bp->flags & USING_MSIX_FLAG)
printk(KERN_INFO PFX "%s: using MSI-X\n",
bp->dev->name);
+ break;
- /* Otherwise Tx queue should be only reenabled */
- } else if (netif_running(bp->dev)) {
- netif_wake_queue(bp->dev);
+ case LOAD_DIAG:
bnx2x_set_rx_mode(bp->dev);
+ bp->state = BNX2X_STATE_DIAG;
+ break;
+
+ default:
+ break;
}
+ if (!bp->port.pmf)
+ bnx2x__link_status_update(bp);
+
/* start the timer */
mod_timer(&bp->timer, jiffies + bp->current_interval);
+
return 0;
load_stop_netif:
load_int_disable:
bnx2x_int_disable_sync(bp);
- bnx2x_free_skbs(bp);
+ /* Release IRQs */
bnx2x_free_irq(bp);
load_error:
/* TBD we really need to reset the chip
if we want to recover from this */
- return -EBUSY;
-}
-
-
-static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
-{
- int port = bp->port;
-#ifdef USE_DMAE
- u32 wb_write[2];
-#endif
- int base, i;
-
- DP(NETIF_MSG_IFDOWN, "reset called with code %x\n", reset_code);
-
- /* Do not rcv packets to BRB */
- REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK + port*4, 0x0);
- /* Do not direct rcv packets that are not for MCP to the BRB */
- REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
- NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
-
- /* Configure IGU and AEU */
- REG_WR(bp, HC_REG_CONFIG_0 + port*4, 0x1000);
- REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, 0);
-
- /* TODO: Close Doorbell port? */
-
- /* Clear ILT */
-#ifdef USE_DMAE
- wb_write[0] = 0;
- wb_write[1] = 0;
-#endif
- base = port * RQ_ONCHIP_AT_PORT_SIZE;
- for (i = base; i < base + RQ_ONCHIP_AT_PORT_SIZE; i++) {
-#ifdef USE_DMAE
- REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2);
-#else
- REG_WR_IND(bp, PXP2_REG_RQ_ONCHIP_AT, 0);
- REG_WR_IND(bp, PXP2_REG_RQ_ONCHIP_AT + 4, 0);
-#endif
- }
-
- if (reset_code == FW_MSG_CODE_DRV_UNLOAD_COMMON) {
- /* 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);
- }
+ return rc;
}
static int bnx2x_stop_multi(struct bnx2x *bp, int index)
{
-
int rc;
/* halt the connection */
bp->fp[index].state = BNX2X_FP_STATE_HALTING;
bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, 0, 0);
-
+ /* Wait for completion */
rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, index,
- &(bp->fp[index].state), 1);
+ &(bp->fp[index].state), 1);
if (rc) /* timeout */
return rc;
/* delete cfc entry */
bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CFC_DEL, index, 0, 0, 1);
- return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, index,
- &(bp->fp[index].state), 1);
-
+ /* Wait for completion */
+ rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, index,
+ &(bp->fp[index].state), 1);
+ return rc;
}
-
static void bnx2x_stop_leading(struct bnx2x *bp)
{
u16 dsb_sp_prod_idx;
/* if the other port is handling traffic,
this can take a lot of time */
- int timeout = 500;
+ int cnt = 500;
+ int rc;
might_sleep();
/* Send HALT ramrod */
bp->fp[0].state = BNX2X_FP_STATE_HALTING;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, 0, 0, 0, 0);
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, 0, 0, BP_CL_ID(bp), 0);
- if (bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, 0,
- &(bp->fp[0].state), 1))
+ /* Wait for completion */
+ rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, 0,
+ &(bp->fp[0].state), 1);
+ if (rc) /* timeout */
return;
dsb_sp_prod_idx = *bp->dsb_sp_prod;
we are going to reset the chip anyway
so there is not much to do if this times out
*/
- while ((dsb_sp_prod_idx == *bp->dsb_sp_prod) && timeout) {
- timeout--;
+ while (dsb_sp_prod_idx == *bp->dsb_sp_prod) {
msleep(1);
- }
- if (!timeout) {
- DP(NETIF_MSG_IFDOWN, "timeout polling for completion "
- "dsb_sp_prod 0x%x != dsb_sp_prod_idx 0x%x\n",
- *bp->dsb_sp_prod, dsb_sp_prod_idx);
+ if (!cnt) {
+ DP(NETIF_MSG_IFDOWN, "timeout waiting for port del "
+ "dsb_sp_prod 0x%x != dsb_sp_prod_idx 0x%x\n",
+ *bp->dsb_sp_prod, dsb_sp_prod_idx);
+#ifdef BNX2X_STOP_ON_ERROR
+ bnx2x_panic();
+#endif
+ break;
+ }
+ cnt--;
}
bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
bp->fp[0].state = BNX2X_FP_STATE_CLOSED;
}
+static void bnx2x_reset_func(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ int func = BP_FUNC(bp);
+ int base, i;
+
+ /* Configure IGU */
+ REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+ REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+
+ REG_WR(bp, HC_REG_CONFIG_0 + port*4, 0x1000);
+
+ /* Clear ILT */
+ base = FUNC_ILT_BASE(func);
+ for (i = base; i < base + ILT_PER_FUNC; i++)
+ bnx2x_ilt_wr(bp, i, 0);
+}
+
+static void bnx2x_reset_port(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ u32 val;
+
+ REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
+
+ /* Do not rcv packets to BRB */
+ REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK + port*4, 0x0);
+ /* Do not direct rcv packets that are not for MCP to the BRB */
+ REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
+ NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
+
+ /* Configure AEU */
+ REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, 0);
+
+ msleep(100);
+ /* Check for BRB port occupancy */
+ val = REG_RD(bp, BRB1_REG_PORT_NUM_OCC_BLOCKS_0 + port*4);
+ if (val)
+ DP(NETIF_MSG_IFDOWN,
+ "BRB1 is not empty %d blooks are occupied\n", val);
+
+ /* TODO: Close Doorbell port? */
+}
+
+static void bnx2x_reset_common(struct bnx2x *bp)
+{
+ /* 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);
+}
+
+static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
+{
+ DP(BNX2X_MSG_MCP, "function %d reset_code %x\n",
+ BP_FUNC(bp), reset_code);
+
+ 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;
-static int bnx2x_nic_unload(struct bnx2x *bp, int free_irq)
+ default:
+ BNX2X_ERR("Unknown reset_code (0x%x) from MCP\n", reset_code);
+ break;
+ }
+}
+
+/* msut be called with rtnl_lock */
+static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
{
u32 reset_code = 0;
- int i, timeout;
+ int i, cnt;
bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
- del_timer_sync(&bp->timer);
-
bp->rx_mode = BNX2X_RX_MODE_NONE;
bnx2x_set_storm_rx_mode(bp);
bp->dev->trans_start = jiffies; /* prevent tx timeout */
}
+ del_timer_sync(&bp->timer);
+ SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb,
+ (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
+
/* Wait until all fast path tasks complete */
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- timeout = 1000;
- while (bnx2x_has_work(fp) && (timeout--))
+#ifdef BNX2X_STOP_ON_ERROR
+#ifdef __powerpc64__
+ DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%lx\n",
+#else
+ DP(NETIF_MSG_IFDOWN, "fp->tpa_queue_used = 0x%llx\n",
+#endif
+ fp->tpa_queue_used);
+#endif
+ cnt = 1000;
+ smp_rmb();
+ while (bnx2x_has_work(fp)) {
msleep(1);
- if (!timeout)
- BNX2X_ERR("timeout waiting for queue[%d]\n", i);
+ if (!cnt) {
+ BNX2X_ERR("timeout waiting for queue[%d]\n",
+ i);
+#ifdef BNX2X_STOP_ON_ERROR
+ bnx2x_panic();
+ return -EBUSY;
+#else
+ break;
+#endif
+ }
+ cnt--;
+ smp_rmb();
+ }
}
- /* Wait until stat ramrod returns and all SP tasks complete */
- timeout = 1000;
- while ((bp->stat_pending || (bp->spq_left != MAX_SPQ_PENDING)) &&
- (timeout--))
+ /* Wait until all slow path tasks complete */
+ cnt = 1000;
+ while ((bp->spq_left != MAX_SPQ_PENDING) && cnt--)
msleep(1);
for_each_queue(bp, i)
/* Disable interrupts after Tx and Rx are disabled on stack level */
bnx2x_int_disable_sync(bp);
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+
if (bp->flags & NO_WOL_FLAG)
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
else if (bp->wol) {
- u32 emac_base = bp->port ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
+ u32 emac_base = BP_PORT(bp) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
u8 *mac_addr = bp->dev->dev_addr;
- u32 val = (EMAC_MODE_MPKT | EMAC_MODE_MPKT_RCVD |
- EMAC_MODE_ACPI_RCVD);
-
- EMAC_WR(EMAC_REG_EMAC_MODE, val);
+ u32 val;
+ /* The mac address is written to entries 1-4 to
+ preserve entry 0 which is used by the PMF */
val = (mac_addr[0] << 8) | mac_addr[1];
- EMAC_WR(EMAC_REG_EMAC_MAC_MATCH, val);
+ EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + (BP_E1HVN(bp) + 1)*8, val);
val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
(mac_addr[4] << 8) | mac_addr[5];
- EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + 4, val);
+ EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + (BP_E1HVN(bp) + 1)*8 + 4,
+ val);
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN;
} else
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
- /* Close multi and leading connections */
+ /* Close multi and leading connections
+ Completions for ramrods are collected in a synchronous way */
for_each_nondefault_queue(bp, i)
if (bnx2x_stop_multi(bp, i))
goto unload_error;
- bnx2x_stop_leading(bp);
+ if (CHIP_IS_E1H(bp))
+ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + BP_PORT(bp)*8, 0);
+
+ bnx2x_stop_leading(bp);
+#ifdef BNX2X_STOP_ON_ERROR
+ /* If ramrod completion timed out - break here! */
+ if (bp->panic) {
+ BNX2X_ERR("Stop leading failed!\n");
+ return -EBUSY;
+ }
+#endif
+
if ((bp->state != BNX2X_STATE_CLOSING_WAIT4_UNLOAD) ||
(bp->fp[0].state != BNX2X_FP_STATE_CLOSED)) {
- DP(NETIF_MSG_IFDOWN, "failed to close leading properly!"
- "state 0x%x fp[0].state 0x%x",
+ DP(NETIF_MSG_IFDOWN, "failed to close leading properly! "
+ "state 0x%x fp[0].state 0x%x\n",
bp->state, bp->fp[0].state);
}
unload_error:
- bnx2x__link_reset(bp);
-
- if (!nomcp)
+ if (!BP_NOMCP(bp))
reset_code = bnx2x_fw_command(bp, reset_code);
- else
- reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
+ else {
+ DP(NETIF_MSG_IFDOWN, "NO MCP load counts %d, %d, %d\n",
+ load_count[0], load_count[1], load_count[2]);
+ load_count[0]--;
+ load_count[1 + BP_PORT(bp)]--;
+ DP(NETIF_MSG_IFDOWN, "NO MCP new load counts %d, %d, %d\n",
+ load_count[0], load_count[1], load_count[2]);
+ if (load_count[0] == 0)
+ reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
+ else if (load_count[1 + BP_PORT(bp)] == 0)
+ reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
+ else
+ reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
+ }
- /* Release IRQs */
- if (free_irq)
- bnx2x_free_irq(bp);
+ if ((reset_code == FW_MSG_CODE_DRV_UNLOAD_COMMON) ||
+ (reset_code == FW_MSG_CODE_DRV_UNLOAD_PORT))
+ bnx2x__link_reset(bp);
/* Reset the chip */
bnx2x_reset_chip(bp, reset_code);
/* Report UNLOAD_DONE to MCP */
- if (!nomcp)
+ if (!BP_NOMCP(bp))
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
/* Free SKBs and driver internals */
return 0;
}
+static void bnx2x_reset_task(struct work_struct *work)
+{
+ struct bnx2x *bp = container_of(work, struct bnx2x, reset_task);
+
+#ifdef BNX2X_STOP_ON_ERROR
+ BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
+ " so reset not done to allow debug dump,\n"
+ KERN_ERR " you will need to reboot when done\n");
+ return;
+#endif
+
+ rtnl_lock();
+
+ if (!netif_running(bp->dev))
+ goto reset_task_exit;
+
+ bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+ bnx2x_nic_load(bp, LOAD_NORMAL);
+
+reset_task_exit:
+ rtnl_unlock();
+}
+
/* end of nic load/unload */
/* ethtool_ops */
* Init service functions
*/
-static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
+static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
+{
+ u32 val;
+
+ /* Check if there is any driver already loaded */
+ val = REG_RD(bp, MISC_REG_UNPREPARED);
+ if (val == 0x1) {
+ /* Check if it is the UNDI driver
+ * UNDI driver initializes CID offset for normal bell to 0x7
+ */
+ val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
+ if (val == 0x7) {
+ u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
+ /* save our func and fw_seq */
+ int func = BP_FUNC(bp);
+ u16 fw_seq = bp->fw_seq;
+
+ BNX2X_DEV_INFO("UNDI is active! reset device\n");
+
+ /* try unload UNDI on port 0 */
+ bp->func = 0;
+ bp->fw_seq = (SHMEM_RD(bp,
+ func_mb[bp->func].drv_mb_header) &
+ DRV_MSG_SEQ_NUMBER_MASK);
+
+ reset_code = bnx2x_fw_command(bp, reset_code);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+
+ /* if UNDI is loaded on the other port */
+ if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
+
+ bp->func = 1;
+ bp->fw_seq = (SHMEM_RD(bp,
+ func_mb[bp->func].drv_mb_header) &
+ DRV_MSG_SEQ_NUMBER_MASK);
+
+ bnx2x_fw_command(bp,
+ DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS);
+ bnx2x_fw_command(bp,
+ DRV_MSG_CODE_UNLOAD_DONE);
+
+ /* restore our func and fw_seq */
+ bp->func = func;
+ bp->fw_seq = fw_seq;
+ }
+
+ /* reset device */
+ REG_WR(bp,
+ GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+ 0xd3ffff7f);
+ REG_WR(bp,
+ GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ 0x1403);
+ }
+ }
+}
+
+static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
+{
+ u32 val, val2, val3, val4, id;
+
+ /* Get the chip revision id and number. */
+ /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
+ val = REG_RD(bp, MISC_REG_CHIP_NUM);
+ id = ((val & 0xffff) << 16);
+ val = REG_RD(bp, MISC_REG_CHIP_REV);
+ id |= ((val & 0xf) << 12);
+ val = REG_RD(bp, MISC_REG_CHIP_METAL);
+ id |= ((val & 0xff) << 4);
+ REG_RD(bp, MISC_REG_BOND_ID);
+ id |= (val & 0xf);
+ bp->common.chip_id = id;
+ bp->link_params.chip_id = bp->common.chip_id;
+ BNX2X_DEV_INFO("chip ID is 0x%x\n", id);
+
+ val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4);
+ bp->common.flash_size = (NVRAM_1MB_SIZE <<
+ (val & MCPR_NVM_CFG4_FLASH_SIZE));
+ BNX2X_DEV_INFO("flash_size 0x%x (%d)\n",
+ bp->common.flash_size, bp->common.flash_size);
+
+ bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
+ bp->link_params.shmem_base = bp->common.shmem_base;
+ BNX2X_DEV_INFO("shmem offset is 0x%x\n", bp->common.shmem_base);
+
+ if (!bp->common.shmem_base ||
+ (bp->common.shmem_base < 0xA0000) ||
+ (bp->common.shmem_base >= 0xC0000)) {
+ BNX2X_DEV_INFO("MCP not active\n");
+ bp->flags |= NO_MCP_FLAG;
+ return;
+ }
+
+ val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]);
+ if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
+ != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
+ BNX2X_ERR("BAD MCP validity signature\n");
+
+ bp->common.hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config);
+ bp->common.board = SHMEM_RD(bp, dev_info.shared_hw_config.board);
+
+ BNX2X_DEV_INFO("hw_config 0x%08x board 0x%08x\n",
+ bp->common.hw_config, bp->common.board);
+
+ bp->link_params.hw_led_mode = ((bp->common.hw_config &
+ SHARED_HW_CFG_LED_MODE_MASK) >>
+ SHARED_HW_CFG_LED_MODE_SHIFT);
+
+ val = SHMEM_RD(bp, dev_info.bc_rev) >> 8;
+ bp->common.bc_ver = val;
+ BNX2X_DEV_INFO("bc_ver %X\n", val);
+ if (val < BNX2X_BC_VER) {
+ /* for now only warn
+ * later we might need to enforce this */
+ BNX2X_ERR("This driver needs bc_ver %X but found %X,"
+ " please upgrade BC\n", BNX2X_BC_VER, val);
+ }
+ BNX2X_DEV_INFO("%sWoL Capable\n",
+ (bp->flags & NO_WOL_FLAG)? "Not " : "");
+
+ val = SHMEM_RD(bp, dev_info.shared_hw_config.part_num);
+ val2 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[4]);
+ val3 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[8]);
+ val4 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[12]);
+
+ printk(KERN_INFO PFX "part number %X-%X-%X-%X\n",
+ val, val2, val3, val4);
+}
+
+static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
+ u32 switch_cfg)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
u32 ext_phy_type;
switch (switch_cfg) {
BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
ext_phy_type);
- bp->supported |= (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_2500baseX_Full |
- SUPPORTED_TP | SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
+ bp->port.supported |= (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_2500baseX_Full |
+ SUPPORTED_TP |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
break;
case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
BNX2X_DEV_INFO("ext_phy_type 0x%x (5482)\n",
ext_phy_type);
- bp->supported |= (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_TP | SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
+ bp->port.supported |= (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_TP |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
break;
default:
return;
}
- bp->phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR +
- port*0x10);
- BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->phy_addr);
+ 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:
BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
ext_phy_type);
- bp->supported |= (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_2500baseX_Full |
- SUPPORTED_10000baseT_Full |
- SUPPORTED_TP | SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
+ bp->port.supported |= (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_2500baseX_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_TP |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n",
- ext_phy_type);
+ ext_phy_type);
- bp->supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_FIBRE |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
+ bp->port.supported |= (SUPPORTED_10000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
BNX2X_DEV_INFO("ext_phy_type 0x%x (8706)\n",
ext_phy_type);
- bp->supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_Autoneg |
- SUPPORTED_FIBRE |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
+ bp->port.supported |= (SUPPORTED_10000baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
BNX2X_DEV_INFO("ext_phy_type 0x%x (8072)\n",
ext_phy_type);
- bp->supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
+ bp->port.supported |= (SUPPORTED_10000baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
BNX2X_DEV_INFO("ext_phy_type 0x%x (8073)\n",
ext_phy_type);
- bp->supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_2500baseX_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
+ bp->port.supported |= (SUPPORTED_10000baseT_Full |
+ SUPPORTED_2500baseX_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
BNX2X_DEV_INFO("ext_phy_type 0x%x (SFX7101)\n",
ext_phy_type);
- bp->supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_TP |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
+ bp->port.supported |= (SUPPORTED_10000baseT_Full |
+ SUPPORTED_TP |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
return;
}
- bp->phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR +
- port*0x18);
- BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->phy_addr);
+ 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->link_config);
+ bp->port.link_config);
return;
}
- bp->link_params.phy_addr = bp->phy_addr;
+ bp->link_params.phy_addr = bp->port.phy_addr;
/* mask what we support according to speed_cap_mask */
if (!(bp->link_params.speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF))
- bp->supported &= ~SUPPORTED_10baseT_Half;
+ bp->port.supported &= ~SUPPORTED_10baseT_Half;
if (!(bp->link_params.speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL))
- bp->supported &= ~SUPPORTED_10baseT_Full;
+ bp->port.supported &= ~SUPPORTED_10baseT_Full;
if (!(bp->link_params.speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))
- bp->supported &= ~SUPPORTED_100baseT_Half;
+ bp->port.supported &= ~SUPPORTED_100baseT_Half;
if (!(bp->link_params.speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL))
- bp->supported &= ~SUPPORTED_100baseT_Full;
+ bp->port.supported &= ~SUPPORTED_100baseT_Full;
if (!(bp->link_params.speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))
- bp->supported &= ~(SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full);
+ bp->port.supported &= ~(SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full);
if (!(bp->link_params.speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
- bp->supported &= ~SUPPORTED_2500baseX_Full;
+ bp->port.supported &= ~SUPPORTED_2500baseX_Full;
if (!(bp->link_params.speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10G))
- bp->supported &= ~SUPPORTED_10000baseT_Full;
+ bp->port.supported &= ~SUPPORTED_10000baseT_Full;
- BNX2X_DEV_INFO("supported 0x%x\n", bp->supported);
+ BNX2X_DEV_INFO("supported 0x%x\n", bp->port.supported);
}
-static void bnx2x_link_settings_requested(struct bnx2x *bp)
+static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
{
bp->link_params.req_duplex = DUPLEX_FULL;
- switch (bp->link_config & PORT_FEATURE_LINK_SPEED_MASK) {
+ switch (bp->port.link_config & PORT_FEATURE_LINK_SPEED_MASK) {
case PORT_FEATURE_LINK_SPEED_AUTO:
- if (bp->supported & SUPPORTED_Autoneg) {
+ if (bp->port.supported & SUPPORTED_Autoneg) {
bp->link_params.req_line_speed = SPEED_AUTO_NEG;
- bp->advertising = bp->supported;
+ bp->port.advertising = bp->port.supported;
} else {
u32 ext_phy_type =
XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706)) {
/* force 10G, no AN */
bp->link_params.req_line_speed = SPEED_10000;
- bp->advertising =
+ bp->port.advertising =
(ADVERTISED_10000baseT_Full |
ADVERTISED_FIBRE);
break;
BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" Autoneg not supported\n",
- bp->link_config);
+ bp->port.link_config);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_10M_FULL:
- if (bp->supported & SUPPORTED_10baseT_Full) {
+ if (bp->port.supported & SUPPORTED_10baseT_Full) {
bp->link_params.req_line_speed = SPEED_10;
- bp->advertising = (ADVERTISED_10baseT_Full |
- ADVERTISED_TP);
+ bp->port.advertising = (ADVERTISED_10baseT_Full |
+ ADVERTISED_TP);
} else {
BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->link_config,
+ bp->port.link_config,
bp->link_params.speed_cap_mask);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_10M_HALF:
- if (bp->supported & SUPPORTED_10baseT_Half) {
+ if (bp->port.supported & SUPPORTED_10baseT_Half) {
bp->link_params.req_line_speed = SPEED_10;
bp->link_params.req_duplex = DUPLEX_HALF;
- bp->advertising = (ADVERTISED_10baseT_Half |
- ADVERTISED_TP);
+ bp->port.advertising = (ADVERTISED_10baseT_Half |
+ ADVERTISED_TP);
} else {
BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->link_config,
+ bp->port.link_config,
bp->link_params.speed_cap_mask);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_100M_FULL:
- if (bp->supported & SUPPORTED_100baseT_Full) {
+ if (bp->port.supported & SUPPORTED_100baseT_Full) {
bp->link_params.req_line_speed = SPEED_100;
- bp->advertising = (ADVERTISED_100baseT_Full |
- ADVERTISED_TP);
+ bp->port.advertising = (ADVERTISED_100baseT_Full |
+ ADVERTISED_TP);
} else {
BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->link_config,
+ bp->port.link_config,
bp->link_params.speed_cap_mask);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_100M_HALF:
- if (bp->supported & SUPPORTED_100baseT_Half) {
+ if (bp->port.supported & SUPPORTED_100baseT_Half) {
bp->link_params.req_line_speed = SPEED_100;
bp->link_params.req_duplex = DUPLEX_HALF;
- bp->advertising = (ADVERTISED_100baseT_Half |
- ADVERTISED_TP);
+ bp->port.advertising = (ADVERTISED_100baseT_Half |
+ ADVERTISED_TP);
} else {
BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->link_config,
+ bp->port.link_config,
bp->link_params.speed_cap_mask);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_1G:
- if (bp->supported & SUPPORTED_1000baseT_Full) {
+ if (bp->port.supported & SUPPORTED_1000baseT_Full) {
bp->link_params.req_line_speed = SPEED_1000;
- bp->advertising = (ADVERTISED_1000baseT_Full |
- ADVERTISED_TP);
+ bp->port.advertising = (ADVERTISED_1000baseT_Full |
+ ADVERTISED_TP);
} else {
BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->link_config,
+ bp->port.link_config,
bp->link_params.speed_cap_mask);
return;
}
break;
case PORT_FEATURE_LINK_SPEED_2_5G:
- if (bp->supported & SUPPORTED_2500baseX_Full) {
+ if (bp->port.supported & SUPPORTED_2500baseX_Full) {
bp->link_params.req_line_speed = SPEED_2500;
- bp->advertising = (ADVERTISED_2500baseX_Full |
- ADVERTISED_TP);
+ bp->port.advertising = (ADVERTISED_2500baseX_Full |
+ ADVERTISED_TP);
} else {
BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->link_config,
+ bp->port.link_config,
bp->link_params.speed_cap_mask);
return;
}
case PORT_FEATURE_LINK_SPEED_10G_CX4:
case PORT_FEATURE_LINK_SPEED_10G_KX4:
case PORT_FEATURE_LINK_SPEED_10G_KR:
- if (bp->supported & SUPPORTED_10000baseT_Full) {
+ if (bp->port.supported & SUPPORTED_10000baseT_Full) {
bp->link_params.req_line_speed = SPEED_10000;
- bp->advertising = (ADVERTISED_10000baseT_Full |
- ADVERTISED_FIBRE);
+ bp->port.advertising = (ADVERTISED_10000baseT_Full |
+ ADVERTISED_FIBRE);
} else {
BNX2X_ERR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->link_config,
+ bp->port.link_config,
bp->link_params.speed_cap_mask);
return;
}
default:
BNX2X_ERR("NVRAM config error. "
"BAD link speed link_config 0x%x\n",
- bp->link_config);
+ bp->port.link_config);
bp->link_params.req_line_speed = SPEED_AUTO_NEG;
- bp->advertising = bp->supported;
+ bp->port.advertising = bp->port.supported;
break;
}
- bp->link_params.req_flow_ctrl = (bp->link_config &
- PORT_FEATURE_FLOW_CONTROL_MASK);
+ bp->link_params.req_flow_ctrl = (bp->port.link_config &
+ PORT_FEATURE_FLOW_CONTROL_MASK);
if ((bp->link_params.req_flow_ctrl == FLOW_CTRL_AUTO) &&
- (!bp->supported & SUPPORTED_Autoneg))
+ (!bp->port.supported & SUPPORTED_Autoneg))
bp->link_params.req_flow_ctrl = FLOW_CTRL_NONE;
BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl 0x%x"
" advertising 0x%x\n",
bp->link_params.req_line_speed,
bp->link_params.req_duplex,
- bp->link_params.req_flow_ctrl, bp->advertising);
+ bp->link_params.req_flow_ctrl, bp->port.advertising);
}
-static void bnx2x_get_hwinfo(struct bnx2x *bp)
+static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
{
- u32 val, val2, val3, val4, id;
- int port = bp->port;
-
- bp->shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
- BNX2X_DEV_INFO("shmem offset is %x\n", bp->shmem_base);
-
- /* Get the chip revision id and number. */
- /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
- val = REG_RD(bp, MISC_REG_CHIP_NUM);
- id = ((val & 0xffff) << 16);
- val = REG_RD(bp, MISC_REG_CHIP_REV);
- id |= ((val & 0xf) << 12);
- val = REG_RD(bp, MISC_REG_CHIP_METAL);
- id |= ((val & 0xff) << 4);
- REG_RD(bp, MISC_REG_BOND_ID);
- id |= (val & 0xf);
- bp->chip_id = id;
- BNX2X_DEV_INFO("chip ID is %x\n", id);
+ int port = BP_PORT(bp);
+ u32 val, val2;
bp->link_params.bp = bp;
+ bp->link_params.port = port;
- if (!bp->shmem_base || (bp->shmem_base != 0xAF900)) {
- BNX2X_DEV_INFO("MCP not active\n");
- nomcp = 1;
- goto set_mac;
- }
-
- val = SHMEM_RD(bp, validity_map[port]);
- if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
- != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
- BNX2X_ERR("BAD MCP validity signature\n");
-
- bp->fw_seq = (SHMEM_RD(bp, func_mb[port].drv_mb_header) &
- DRV_MSG_SEQ_NUMBER_MASK);
-
- bp->hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config);
- bp->board = SHMEM_RD(bp, dev_info.shared_hw_config.board);
bp->link_params.serdes_config =
SHMEM_RD(bp, dev_info.port_hw_config[port].serdes_config);
bp->link_params.lane_config =
SHMEM_RD(bp,
dev_info.port_hw_config[port].speed_capability_mask);
- bp->link_config =
+ bp->port.link_config =
SHMEM_RD(bp, dev_info.port_feature_config[port].link_config);
- BNX2X_DEV_INFO("serdes_config (%08x) lane_config (%08x)\n"
- KERN_INFO " ext_phy_config (%08x) speed_cap_mask (%08x)"
- " link_config (%08x)\n",
+ BNX2X_DEV_INFO("serdes_config 0x%08x lane_config 0x%08x\n"
+ KERN_INFO " ext_phy_config 0x%08x speed_cap_mask 0x%08x"
+ " link_config 0x%08x\n",
bp->link_params.serdes_config,
bp->link_params.lane_config,
bp->link_params.ext_phy_config,
- bp->link_params.speed_cap_mask,
- bp->link_config);
+ bp->link_params.speed_cap_mask, bp->port.link_config);
- bp->link_params.switch_cfg = (bp->link_config &
+ bp->link_params.switch_cfg = (bp->port.link_config &
PORT_FEATURE_CONNECTED_SWITCH_MASK);
bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg);
bp->dev->dev_addr[5] = (u8)(val & 0xff);
memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
+}
+
+static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
+{
+ int func = BP_FUNC(bp);
+ u32 val, val2;
+ int rc = 0;
+ bnx2x_get_common_hwinfo(bp);
+ bp->e1hov = 0;
+ bp->e1hmf = 0;
+ if (CHIP_IS_E1H(bp)) {
+ bp->mf_config =
+ SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
- val = SHMEM_RD(bp, dev_info.shared_hw_config.part_num);
- val2 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[4]);
- val3 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[8]);
- val4 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[12]);
+ val =
+ (SHMEM_RD(bp, mf_cfg.func_mf_config[func].e1hov_tag) &
+ FUNC_MF_CFG_E1HOV_TAG_MASK);
+ if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
- printk(KERN_INFO PFX "part number %X-%X-%X-%X\n",
- val, val2, val3, val4);
+ bp->e1hov = val;
+ bp->e1hmf = 1;
+ BNX2X_DEV_INFO("MF mode E1HOV for func %d is %d "
+ "(0x%04x)\n",
+ func, bp->e1hov, bp->e1hov);
+ } else {
+ BNX2X_DEV_INFO("Single function mode\n");
+ if (BP_E1HVN(bp)) {
+ BNX2X_ERR("!!! No valid E1HOV for func %d,"
+ " aborting\n", func);
+ rc = -EPERM;
+ }
+ }
+ }
- /* bc ver */
- if (!nomcp) {
- bp->bc_ver = val = ((SHMEM_RD(bp, dev_info.bc_rev)) >> 8);
- BNX2X_DEV_INFO("bc_ver %X\n", val);
- if (val < BNX2X_BC_VER) {
- /* for now only warn
- * later we might need to enforce this */
- BNX2X_ERR("This driver needs bc_ver %X but found %X,"
- " please upgrade BC\n", BNX2X_BC_VER, val);
+ if (!BP_NOMCP(bp)) {
+ bnx2x_get_port_hwinfo(bp);
+
+ bp->fw_seq = (SHMEM_RD(bp, func_mb[func].drv_mb_header) &
+ DRV_MSG_SEQ_NUMBER_MASK);
+ BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
+ }
+
+ if (IS_E1HMF(bp)) {
+ val2 = SHMEM_RD(bp, mf_cfg.func_mf_config[func].mac_upper);
+ val = SHMEM_RD(bp, mf_cfg.func_mf_config[func].mac_lower);
+ if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
+ (val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) {
+ bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff);
+ bp->dev->dev_addr[1] = (u8)(val2 & 0xff);
+ bp->dev->dev_addr[2] = (u8)(val >> 24 & 0xff);
+ bp->dev->dev_addr[3] = (u8)(val >> 16 & 0xff);
+ bp->dev->dev_addr[4] = (u8)(val >> 8 & 0xff);
+ bp->dev->dev_addr[5] = (u8)(val & 0xff);
+ memcpy(bp->link_params.mac_addr, bp->dev->dev_addr,
+ ETH_ALEN);
+ memcpy(bp->dev->perm_addr, bp->dev->dev_addr,
+ ETH_ALEN);
}
- } else {
- bp->bc_ver = 0;
+
+ return rc;
}
- val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4);
- bp->flash_size = (NVRAM_1MB_SIZE << (val & MCPR_NVM_CFG4_FLASH_SIZE));
- BNX2X_DEV_INFO("flash_size 0x%x (%d)\n",
- bp->flash_size, bp->flash_size);
+ if (BP_NOMCP(bp)) {
+ /* only supposed to happen on emulation/FPGA */
+ BNX2X_ERR("warning rendom MAC workaround active\n");
+ random_ether_addr(bp->dev->dev_addr);
+ memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
+ }
- return;
+ return rc;
+}
+
+static int __devinit bnx2x_init_bp(struct bnx2x *bp)
+{
+ int func = BP_FUNC(bp);
+ int rc;
+
+ if (nomcp)
+ bp->flags |= NO_MCP_FLAG;
-set_mac: /* only supposed to happen on emulation/FPGA */
- BNX2X_ERR("warning rendom MAC workaround active\n");
- random_ether_addr(bp->dev->dev_addr);
- memcpy(bp->dev->perm_addr, bp->dev->dev_addr, 6);
+ mutex_init(&bp->port.phy_mutex);
+ INIT_WORK(&bp->sp_task, bnx2x_sp_task);
+ INIT_WORK(&bp->reset_task, bnx2x_reset_task);
+
+ rc = bnx2x_get_hwinfo(bp);
+
+ /* need to reset chip if undi was active */
+ if (!BP_NOMCP(bp))
+ bnx2x_undi_unload(bp);
+
+ if (CHIP_REV_IS_FPGA(bp))
+ printk(KERN_ERR PFX "FPGA detected\n");
+
+ if (BP_NOMCP(bp) && (func == 0))
+ printk(KERN_ERR PFX
+ "MCP disabled, must load devices in order!\n");
+
+ bp->tx_ring_size = MAX_TX_AVAIL;
+ bp->rx_ring_size = MAX_RX_AVAIL;
+
+ bp->rx_csum = 1;
+ bp->rx_offset = 0;
+
+ bp->tx_ticks = 50;
+ bp->rx_ticks = 25;
+
+ bp->stats_ticks = 1000000 & 0xffff00;
+
+ bp->timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ);
+ bp->current_interval = (poll ? poll : bp->timer_interval);
+
+ init_timer(&bp->timer);
+ bp->timer.expires = jiffies + bp->current_interval;
+ bp->timer.data = (unsigned long) bp;
+ bp->timer.function = bnx2x_timer;
+
+ return rc;
}
/*
{
struct bnx2x *bp = netdev_priv(dev);
- cmd->supported = bp->supported;
- cmd->advertising = bp->advertising;
+ cmd->supported = bp->port.supported;
+ cmd->advertising = bp->port.advertising;
if (netif_carrier_ok(dev)) {
cmd->speed = bp->link_vars.line_speed;
cmd->speed = bp->link_params.req_line_speed;
cmd->duplex = bp->link_params.req_duplex;
}
+ if (IS_E1HMF(bp)) {
+ u16 vn_max_rate;
+
+ vn_max_rate = ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >>
+ FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
+ if (vn_max_rate < cmd->speed)
+ cmd->speed = vn_max_rate;
+ }
if (bp->link_params.switch_cfg == SWITCH_CFG_10G) {
u32 ext_phy_type =
} else
cmd->port = PORT_TP;
- cmd->phy_address = bp->phy_addr;
+ cmd->phy_address = bp->port.phy_addr;
cmd->transceiver = XCVR_INTERNAL;
if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
struct bnx2x *bp = netdev_priv(dev);
u32 advertising;
+ if (IS_E1HMF(bp))
+ return 0;
+
DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
DP_LEVEL " supported 0x%x advertising 0x%x speed %d\n"
DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n"
cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
if (cmd->autoneg == AUTONEG_ENABLE) {
- if (!(bp->supported & SUPPORTED_Autoneg)) {
- DP(NETIF_MSG_LINK, "Aotoneg not supported\n");
+ if (!(bp->port.supported & SUPPORTED_Autoneg)) {
+ DP(NETIF_MSG_LINK, "Autoneg not supported\n");
return -EINVAL;
}
/* advertise the requested speed and duplex if supported */
- cmd->advertising &= bp->supported;
+ cmd->advertising &= bp->port.supported;
bp->link_params.req_line_speed = SPEED_AUTO_NEG;
bp->link_params.req_duplex = DUPLEX_FULL;
- bp->advertising |= (ADVERTISED_Autoneg | cmd->advertising);
+ bp->port.advertising |= (ADVERTISED_Autoneg |
+ cmd->advertising);
} else { /* forced speed */
/* advertise the requested speed and duplex if supported */
switch (cmd->speed) {
case SPEED_10:
if (cmd->duplex == DUPLEX_FULL) {
- if (!(bp->supported &
+ if (!(bp->port.supported &
SUPPORTED_10baseT_Full)) {
DP(NETIF_MSG_LINK,
"10M full not supported\n");
advertising = (ADVERTISED_10baseT_Full |
ADVERTISED_TP);
} else {
- if (!(bp->supported &
+ if (!(bp->port.supported &
SUPPORTED_10baseT_Half)) {
DP(NETIF_MSG_LINK,
"10M half not supported\n");
case SPEED_100:
if (cmd->duplex == DUPLEX_FULL) {
- if (!(bp->supported &
+ if (!(bp->port.supported &
SUPPORTED_100baseT_Full)) {
DP(NETIF_MSG_LINK,
"100M full not supported\n");
advertising = (ADVERTISED_100baseT_Full |
ADVERTISED_TP);
} else {
- if (!(bp->supported &
+ if (!(bp->port.supported &
SUPPORTED_100baseT_Half)) {
DP(NETIF_MSG_LINK,
"100M half not supported\n");
return -EINVAL;
}
- if (!(bp->supported & SUPPORTED_1000baseT_Full)) {
+ if (!(bp->port.supported & SUPPORTED_1000baseT_Full)) {
DP(NETIF_MSG_LINK, "1G full not supported\n");
return -EINVAL;
}
return -EINVAL;
}
- if (!(bp->supported & SUPPORTED_2500baseX_Full)) {
+ if (!(bp->port.supported & SUPPORTED_2500baseX_Full)) {
DP(NETIF_MSG_LINK,
"2.5G full not supported\n");
return -EINVAL;
return -EINVAL;
}
- if (!(bp->supported & SUPPORTED_10000baseT_Full)) {
+ if (!(bp->port.supported & SUPPORTED_10000baseT_Full)) {
DP(NETIF_MSG_LINK, "10G full not supported\n");
return -EINVAL;
}
bp->link_params.req_line_speed = cmd->speed;
bp->link_params.req_duplex = cmd->duplex;
- bp->advertising = advertising;
+ bp->port.advertising = advertising;
}
DP(NETIF_MSG_LINK, "req_line_speed %d\n"
DP_LEVEL " req_duplex %d advertising 0x%x\n",
bp->link_params.req_line_speed, bp->link_params.req_duplex,
- bp->advertising);
+ bp->port.advertising);
- bnx2x_stop_stats(bp);
- bnx2x_link_set(bp);
+ if (netif_running(dev)) {
+ bnx2x_stop_stats(bp);
+ bnx2x_link_set(bp);
+ }
return 0;
}
strcpy(info->version, DRV_MODULE_VERSION);
phy_fw_ver[0] = '\0';
- bnx2x_phy_hw_lock(bp);
- bnx2x_get_ext_phy_fw_version(&bp->link_params,
- (bp->state != BNX2X_STATE_CLOSED),
- phy_fw_ver, PHY_FW_VER_LEN);
- bnx2x_phy_hw_unlock(bp);
+ if (bp->port.pmf) {
+ bnx2x_phy_hw_lock(bp);
+ bnx2x_get_ext_phy_fw_version(&bp->link_params,
+ (bp->state != BNX2X_STATE_CLOSED),
+ phy_fw_ver, PHY_FW_VER_LEN);
+ bnx2x_phy_hw_unlock(bp);
+ }
snprintf(info->fw_version, 32, "%d.%d.%d:%d BC:%x%s%s",
BCM_5710_FW_MAJOR_VERSION, BCM_5710_FW_MINOR_VERSION,
BCM_5710_FW_REVISION_VERSION,
- BCM_5710_FW_COMPILE_FLAGS, bp->bc_ver,
+ BCM_5710_FW_COMPILE_FLAGS, bp->common.bc_ver,
((phy_fw_ver[0] != '\0')? " PHY:":""), phy_fw_ver);
strcpy(info->bus_info, pci_name(bp->pdev));
info->n_stats = BNX2X_NUM_STATS;
info->testinfo_len = BNX2X_NUM_TESTS;
- info->eedump_len = bp->flash_size;
+ info->eedump_len = bp->common.flash_size;
info->regdump_len = 0;
}
return -EINVAL;
bp->wol = 1;
- } else {
+ } else
bp->wol = 0;
- }
+
return 0;
}
{
struct bnx2x *bp = netdev_priv(dev);
- if (bp->state != BNX2X_STATE_OPEN) {
- DP(NETIF_MSG_PROBE, "state is %x, returning\n", bp->state);
- return -EAGAIN;
- }
+ if (!bp->port.pmf)
+ return 0;
- bnx2x_stop_stats(bp);
- bnx2x_link_set(bp);
+ if (netif_running(dev)) {
+ bnx2x_stop_stats(bp);
+ bnx2x_link_set(bp);
+ }
return 0;
}
{
struct bnx2x *bp = netdev_priv(dev);
- return bp->flash_size;
+ return bp->common.flash_size;
}
static int bnx2x_acquire_nvram_lock(struct bnx2x *bp)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
int count, i;
u32 val = 0;
}
if (!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port))) {
- DP(NETIF_MSG_NVM, "cannot get access to nvram interface\n");
+ DP(BNX2X_MSG_NVM, "cannot get access to nvram interface\n");
return -EBUSY;
}
static int bnx2x_release_nvram_lock(struct bnx2x *bp)
{
- int port = bp->port;
+ int port = BP_PORT(bp);
int count, i;
u32 val = 0;
}
if (val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port)) {
- DP(NETIF_MSG_NVM, "cannot free access to nvram interface\n");
+ DP(BNX2X_MSG_NVM, "cannot free access to nvram interface\n");
return -EBUSY;
}
if (val & MCPR_NVM_COMMAND_DONE) {
val = REG_RD(bp, MCP_REG_MCPR_NVM_READ);
- DP(NETIF_MSG_NVM, "val 0x%08x\n", val);
/* we read nvram data in cpu order
* but ethtool sees it as an array of bytes
* converting to big-endian will do the work */
u32 val;
if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) {
- DP(NETIF_MSG_NVM,
+ DP(BNX2X_MSG_NVM,
"Invalid parameter: offset 0x%x buf_size 0x%x\n",
offset, buf_size);
return -EINVAL;
}
- if (offset + buf_size > bp->flash_size) {
- DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +"
+ if (offset + buf_size > bp->common.flash_size) {
+ DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +"
" buf_size (0x%x) > flash_size (0x%x)\n",
- offset, buf_size, bp->flash_size);
+ offset, buf_size, bp->common.flash_size);
return -EINVAL;
}
struct bnx2x *bp = netdev_priv(dev);
int rc;
- DP(NETIF_MSG_NVM, "ethtool_eeprom: cmd %d\n"
+ DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n",
eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
eeprom->len, eeprom->len);
u32 align_offset;
u32 val;
- if (offset + buf_size > bp->flash_size) {
- DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +"
+ if (offset + buf_size > bp->common.flash_size) {
+ DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +"
" buf_size (0x%x) > flash_size (0x%x)\n",
- offset, buf_size, bp->flash_size);
+ offset, buf_size, bp->common.flash_size);
return -EINVAL;
}
* convert it back to cpu order */
val = be32_to_cpu(val);
- DP(NETIF_MSG_NVM, "val 0x%08x\n", val);
-
rc = bnx2x_nvram_write_dword(bp, align_offset, val,
cmd_flags);
}
u32 val;
u32 written_so_far;
- if (buf_size == 1) { /* ethtool */
+ if (buf_size == 1) /* ethtool */
return bnx2x_nvram_write1(bp, offset, data_buf, buf_size);
- }
if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) {
- DP(NETIF_MSG_NVM,
+ DP(BNX2X_MSG_NVM,
"Invalid parameter: offset 0x%x buf_size 0x%x\n",
offset, buf_size);
return -EINVAL;
}
- if (offset + buf_size > bp->flash_size) {
- DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +"
+ if (offset + buf_size > bp->common.flash_size) {
+ DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +"
" buf_size (0x%x) > flash_size (0x%x)\n",
- offset, buf_size, bp->flash_size);
+ offset, buf_size, bp->common.flash_size);
return -EINVAL;
}
cmd_flags |= MCPR_NVM_COMMAND_FIRST;
memcpy(&val, data_buf, 4);
- DP(NETIF_MSG_NVM, "val 0x%08x\n", val);
rc = bnx2x_nvram_write_dword(bp, offset, val, cmd_flags);
struct bnx2x *bp = netdev_priv(dev);
int rc;
- DP(NETIF_MSG_NVM, "ethtool_eeprom: cmd %d\n"
+ DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n",
eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
eeprom->len, eeprom->len);
/* parameters already validated in ethtool_set_eeprom */
/* If the magic number is PHY (0x00504859) upgrade the PHY FW */
- if (eeprom->magic == 0x00504859) {
-
- bnx2x_phy_hw_lock(bp);
- rc = bnx2x_flash_download(bp, bp->port,
- bp->link_params.ext_phy_config,
- (bp->state != BNX2X_STATE_CLOSED),
- eebuf, eeprom->len);
- rc |= bnx2x_link_reset(&bp->link_params,
- &bp->link_vars);
- rc |= bnx2x_phy_init(&bp->link_params,
- &bp->link_vars);
- bnx2x_phy_hw_unlock(bp);
-
- } else
+ if (eeprom->magic == 0x00504859)
+ if (bp->port.pmf) {
+
+ bnx2x_phy_hw_lock(bp);
+ rc = bnx2x_flash_download(bp, BP_PORT(bp),
+ bp->link_params.ext_phy_config,
+ (bp->state != BNX2X_STATE_CLOSED),
+ eebuf, eeprom->len);
+ rc |= bnx2x_link_reset(&bp->link_params,
+ &bp->link_vars);
+ rc |= bnx2x_phy_init(&bp->link_params,
+ &bp->link_vars);
+ bnx2x_phy_hw_unlock(bp);
+
+ } else /* Only the PMF can access the PHY */
+ return -EINVAL;
+ else
rc = bnx2x_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
return rc;
bp->stats_ticks = 0xffff00;
bp->stats_ticks &= 0xffff00;
- if (netif_running(bp->dev))
+ if (netif_running(dev))
bnx2x_update_coalesce(bp);
return 0;
struct ethtool_ringparam *ering)
{
struct bnx2x *bp = netdev_priv(dev);
+ int rc = 0;
if ((ering->rx_pending > MAX_RX_AVAIL) ||
(ering->tx_pending > MAX_TX_AVAIL) ||
bp->rx_ring_size = ering->rx_pending;
bp->tx_ring_size = ering->tx_pending;
- if (netif_running(bp->dev)) {
- bnx2x_nic_unload(bp, 0);
- bnx2x_nic_load(bp, 0);
+ if (netif_running(dev)) {
+ bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+ rc = bnx2x_nic_load(bp, LOAD_NORMAL);
}
- return 0;
+ return rc;
}
static void bnx2x_get_pauseparam(struct net_device *dev,
{
struct bnx2x *bp = netdev_priv(dev);
+ if (IS_E1HMF(bp))
+ return 0;
+
DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n",
epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
bp->link_params.req_flow_ctrl = FLOW_CTRL_NONE;
if (epause->autoneg) {
- if (!(bp->supported & SUPPORTED_Autoneg)) {
+ if (!(bp->port.supported & SUPPORTED_Autoneg)) {
DP(NETIF_MSG_LINK, "Autoneg not supported\n");
return -EINVAL;
}
DP(NETIF_MSG_LINK,
"req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl);
- bnx2x_stop_stats(bp);
- bnx2x_link_set(bp);
+
+ if (netif_running(dev)) {
+ bnx2x_stop_stats(bp);
+ bnx2x_link_set(bp);
+ }
return 0;
}
static int bnx2x_phys_id(struct net_device *dev, u32 data)
{
struct bnx2x *bp = netdev_priv(dev);
+ int port = BP_PORT(bp);
int i;
+ if (!netif_running(dev))
+ return 0;
+
+ if (!bp->port.pmf)
+ return 0;
+
if (data == 0)
data = 2;
for (i = 0; i < (data * 2); i++) {
if ((i % 2) == 0)
- bnx2x_set_led(bp, bp->port, LED_MODE_OPER, SPEED_1000,
+ bnx2x_set_led(bp, port, LED_MODE_OPER, SPEED_1000,
bp->link_params.hw_led_mode,
bp->link_params.chip_id);
else
- bnx2x_set_led(bp, bp->port, LED_MODE_OFF, 0,
+ bnx2x_set_led(bp, port, LED_MODE_OFF, 0,
bp->link_params.hw_led_mode,
bp->link_params.chip_id);
}
if (bp->link_vars.link_up)
- bnx2x_set_led(bp, bp->port, LED_MODE_OPER,
+ bnx2x_set_led(bp, port, LED_MODE_OPER,
bp->link_vars.line_speed,
bp->link_params.hw_led_mode,
bp->link_params.chip_id);
switch (state) {
case PCI_D0:
- pci_write_config_word(bp->pdev,
- bp->pm_cap + PCI_PM_CTRL,
+ pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
((pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
PCI_PM_CTRL_PME_STATUS));
if (pmcsr & PCI_PM_CTRL_STATE_MASK)
/* delay required during transition out of D3hot */
msleep(20);
- break;
-
- case PCI_D3hot:
- pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
- pmcsr |= 3;
-
- if (bp->wol)
- pmcsr |= PCI_PM_CTRL_PME_ENABLE;
-
- pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
- pmcsr);
-
- /* No more memory access after this point until
- * device is brought back to D0.
- */
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-/*
- * net_device service functions
- */
-
-/* called with netif_tx_lock from set_multicast */
-static void bnx2x_set_rx_mode(struct net_device *dev)
-{
- struct bnx2x *bp = netdev_priv(dev);
- u32 rx_mode = BNX2X_RX_MODE_NORMAL;
-
- DP(NETIF_MSG_IFUP, "called dev->flags = %x\n", dev->flags);
-
- if (dev->flags & IFF_PROMISC)
- rx_mode = BNX2X_RX_MODE_PROMISC;
-
- else if ((dev->flags & IFF_ALLMULTI) ||
- (dev->mc_count > BNX2X_MAX_MULTICAST))
- rx_mode = BNX2X_RX_MODE_ALLMULTI;
-
- else { /* some multicasts */
- int i, old, offset;
- struct dev_mc_list *mclist;
- struct mac_configuration_cmd *config =
- bnx2x_sp(bp, mcast_config);
-
- for (i = 0, mclist = dev->mc_list;
- mclist && (i < dev->mc_count);
- i++, mclist = mclist->next) {
-
- config->config_table[i].cam_entry.msb_mac_addr =
- swab16(*(u16 *)&mclist->dmi_addr[0]);
- config->config_table[i].cam_entry.middle_mac_addr =
- swab16(*(u16 *)&mclist->dmi_addr[2]);
- config->config_table[i].cam_entry.lsb_mac_addr =
- swab16(*(u16 *)&mclist->dmi_addr[4]);
- config->config_table[i].cam_entry.flags =
- cpu_to_le16(bp->port);
- config->config_table[i].target_table_entry.flags = 0;
- config->config_table[i].target_table_entry.
- client_id = 0;
- config->config_table[i].target_table_entry.
- vlan_id = 0;
-
- DP(NETIF_MSG_IFUP,
- "setting MCAST[%d] (%04x:%04x:%04x)\n",
- i, config->config_table[i].cam_entry.msb_mac_addr,
- config->config_table[i].cam_entry.middle_mac_addr,
- config->config_table[i].cam_entry.lsb_mac_addr);
- }
- old = config->hdr.length_6b;
- if (old > i) {
- for (; i < old; i++) {
- if (CAM_IS_INVALID(config->config_table[i])) {
- i--; /* already invalidated */
- break;
- }
- /* invalidate */
- CAM_INVALIDATE(config->config_table[i]);
- }
- }
+ break;
- if (CHIP_REV_IS_SLOW(bp))
- offset = BNX2X_MAX_EMUL_MULTI*(1 + bp->port);
- else
- offset = BNX2X_MAX_MULTICAST*(1 + bp->port);
+ case PCI_D3hot:
+ pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ pmcsr |= 3;
- config->hdr.length_6b = i;
- config->hdr.offset = offset;
- config->hdr.reserved0 = 0;
- config->hdr.reserved1 = 0;
+ if (bp->wol)
+ pmcsr |= PCI_PM_CTRL_PME_ENABLE;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
- U64_HI(bnx2x_sp_mapping(bp, mcast_config)),
- U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0);
- }
+ pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
+ pmcsr);
- bp->rx_mode = rx_mode;
- bnx2x_set_storm_rx_mode(bp);
+ /* No more memory access after this point until
+ * device is brought back to D0.
+ */
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
}
+/*
+ * net_device service functions
+ */
+
static int bnx2x_poll(struct napi_struct *napi, int budget)
{
struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
- goto out_panic;
+ goto poll_panic;
#endif
prefetch(fp->tx_buf_ring[TX_BD(fp->tx_pkt_cons)].skb);
bnx2x_update_fpsb_idx(fp);
- if (le16_to_cpu(*fp->tx_cons_sb) != fp->tx_pkt_cons)
+ if ((fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) ||
+ (fp->tx_pkt_prod != fp->tx_pkt_cons))
bnx2x_tx_int(fp, budget);
-
if (le16_to_cpu(*fp->rx_cons_sb) != fp->rx_comp_cons)
work_done = bnx2x_rx_int(fp, budget);
-
rmb(); /* bnx2x_has_work() reads the status block */
/* must not complete if we consumed full budget */
if ((work_done < budget) && !bnx2x_has_work(fp)) {
#ifdef BNX2X_STOP_ON_ERROR
-out_panic:
+poll_panic:
#endif
netif_rx_complete(bp->dev, napi);
- bnx2x_ack_sb(bp, fp->index, USTORM_ID,
+ bnx2x_ack_sb(bp, FP_SB_ID(fp), USTORM_ID,
le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, fp->index, CSTORM_ID,
+ bnx2x_ack_sb(bp, FP_SB_ID(fp), CSTORM_ID,
le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1);
}
-
return work_done;
}
return 0;
}
-/* Called with rtnl_lock */
+/* called with netif_tx_lock from set_multicast */
+static void bnx2x_set_rx_mode(struct net_device *dev)
+{
+ struct bnx2x *bp = netdev_priv(dev);
+ u32 rx_mode = BNX2X_RX_MODE_NORMAL;
+ int port = BP_PORT(bp);
+
+ if (bp->state != BNX2X_STATE_OPEN) {
+ DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
+ return;
+ }
+
+ DP(NETIF_MSG_IFUP, "dev->flags = %x\n", dev->flags);
+
+ if (dev->flags & IFF_PROMISC)
+ rx_mode = BNX2X_RX_MODE_PROMISC;
+
+ else if ((dev->flags & IFF_ALLMULTI) ||
+ ((dev->mc_count > BNX2X_MAX_MULTICAST) && CHIP_IS_E1(bp)))
+ rx_mode = BNX2X_RX_MODE_ALLMULTI;
+
+ else { /* some multicasts */
+ if (CHIP_IS_E1(bp)) {
+ int i, old, offset;
+ struct dev_mc_list *mclist;
+ struct mac_configuration_cmd *config =
+ bnx2x_sp(bp, mcast_config);
+
+ for (i = 0, mclist = dev->mc_list;
+ mclist && (i < dev->mc_count);
+ i++, mclist = mclist->next) {
+
+ config->config_table[i].
+ cam_entry.msb_mac_addr =
+ swab16(*(u16 *)&mclist->dmi_addr[0]);
+ config->config_table[i].
+ cam_entry.middle_mac_addr =
+ swab16(*(u16 *)&mclist->dmi_addr[2]);
+ config->config_table[i].
+ cam_entry.lsb_mac_addr =
+ swab16(*(u16 *)&mclist->dmi_addr[4]);
+ config->config_table[i].cam_entry.flags =
+ cpu_to_le16(port);
+ config->config_table[i].
+ target_table_entry.flags = 0;
+ config->config_table[i].
+ target_table_entry.client_id = 0;
+ config->config_table[i].
+ target_table_entry.vlan_id = 0;
+
+ DP(NETIF_MSG_IFUP,
+ "setting MCAST[%d] (%04x:%04x:%04x)\n", i,
+ config->config_table[i].
+ cam_entry.msb_mac_addr,
+ config->config_table[i].
+ cam_entry.middle_mac_addr,
+ config->config_table[i].
+ cam_entry.lsb_mac_addr);
+ }
+ old = config->hdr.length_6b;
+ if (old > i) {
+ for (; i < old; i++) {
+ if (CAM_IS_INVALID(config->
+ config_table[i])) {
+ i--; /* already invalidated */
+ break;
+ }
+ /* invalidate */
+ CAM_INVALIDATE(config->
+ config_table[i]);
+ }
+ }
+
+ if (CHIP_REV_IS_SLOW(bp))
+ offset = BNX2X_MAX_EMUL_MULTI*(1 + port);
+ else
+ offset = BNX2X_MAX_MULTICAST*(1 + port);
+
+ config->hdr.length_6b = i;
+ config->hdr.offset = offset;
+ config->hdr.client_id = BP_CL_ID(bp);
+ config->hdr.reserved1 = 0;
+
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
+ U64_HI(bnx2x_sp_mapping(bp, mcast_config)),
+ U64_LO(bnx2x_sp_mapping(bp, mcast_config)),
+ 0);
+ } else { /* E1H */
+ /* Accept one or more multicasts */
+ struct dev_mc_list *mclist;
+ u32 mc_filter[MC_HASH_SIZE];
+ u32 crc, bit, regidx;
+ int i;
+
+ memset(mc_filter, 0, 4 * MC_HASH_SIZE);
+
+ for (i = 0, mclist = dev->mc_list;
+ mclist && (i < dev->mc_count);
+ i++, mclist = mclist->next) {
+
+ DP(NETIF_MSG_IFUP, "Adding mcast MAC: "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ mclist->dmi_addr[0], mclist->dmi_addr[1],
+ mclist->dmi_addr[2], mclist->dmi_addr[3],
+ mclist->dmi_addr[4], mclist->dmi_addr[5]);
+
+ crc = crc32c_le(0, mclist->dmi_addr, ETH_ALEN);
+ bit = (crc >> 24) & 0xff;
+ regidx = bit >> 5;
+ bit &= 0x1f;
+ mc_filter[regidx] |= (1 << bit);
+ }
+
+ for (i = 0; i < MC_HASH_SIZE; i++)
+ REG_WR(bp, MC_HASH_OFFSET(bp, i),
+ mc_filter[i]);
+ }
+ }
+
+ bp->rx_mode = rx_mode;
+ bnx2x_set_storm_rx_mode(bp);
+}
+
+/* called with rtnl_lock */
static int bnx2x_change_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
struct bnx2x *bp = netdev_priv(dev);
- if (!is_valid_ether_addr(addr->sa_data))
+ if (!is_valid_ether_addr((u8 *)(addr->sa_data)))
return -EINVAL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- if (netif_running(dev))
- bnx2x_set_mac_addr(bp);
+ if (netif_running(dev)) {
+ if (CHIP_IS_E1(bp))
+ bnx2x_set_mac_addr_e1(bp);
+ else
+ bnx2x_set_mac_addr_e1h(bp);
+ }
return 0;
}
switch (cmd) {
case SIOCGMIIPHY:
- data->phy_id = bp->phy_addr;
+ data->phy_id = bp->port.phy_addr;
/* fallthrough */
if (!netif_running(dev))
return -EAGAIN;
- mutex_lock(&bp->phy_mutex);
- err = bnx2x_cl45_read(bp, bp->port, 0, bp->phy_addr,
+ mutex_lock(&bp->port.phy_mutex);
+ err = bnx2x_cl45_read(bp, BP_PORT(bp), 0, bp->port.phy_addr,
DEFAULT_PHY_DEV_ADDR,
(data->reg_num & 0x1f), &mii_regval);
data->val_out = mii_regval;
- mutex_unlock(&bp->phy_mutex);
+ mutex_unlock(&bp->port.phy_mutex);
return err;
}
if (!netif_running(dev))
return -EAGAIN;
- mutex_lock(&bp->phy_mutex);
- err = bnx2x_cl45_write(bp, bp->port, 0, bp->phy_addr,
+ mutex_lock(&bp->port.phy_mutex);
+ err = bnx2x_cl45_write(bp, BP_PORT(bp), 0, bp->port.phy_addr,
DEFAULT_PHY_DEV_ADDR,
(data->reg_num & 0x1f), data->val_in);
- mutex_unlock(&bp->phy_mutex);
+ mutex_unlock(&bp->port.phy_mutex);
return err;
default:
return -EOPNOTSUPP;
}
-/* Called with rtnl_lock */
+/* called with rtnl_lock */
static int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
{
struct bnx2x *bp = netdev_priv(dev);
+ int rc = 0;
if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) ||
((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE))
dev->mtu = new_mtu;
if (netif_running(dev)) {
- bnx2x_nic_unload(bp, 0);
- bnx2x_nic_load(bp, 0);
+ bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+ rc = bnx2x_nic_load(bp, LOAD_NORMAL);
}
- return 0;
+
+ return rc;
}
static void bnx2x_tx_timeout(struct net_device *dev)
}
#ifdef BCM_VLAN
-/* Called with rtnl_lock */
+/* called with rtnl_lock */
static void bnx2x_vlan_rx_register(struct net_device *dev,
struct vlan_group *vlgrp)
{
if (netif_running(dev))
bnx2x_set_client_config(bp);
}
+
#endif
#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
}
#endif
-static void bnx2x_reset_task(struct work_struct *work)
-{
- struct bnx2x *bp = container_of(work, struct bnx2x, reset_task);
-
-#ifdef BNX2X_STOP_ON_ERROR
- BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
- " so reset not done to allow debug dump,\n"
- KERN_ERR " you will need to reboot when done\n");
- return;
-#endif
-
- if (!netif_running(bp->dev))
- return;
-
- rtnl_lock();
-
- if (bp->state != BNX2X_STATE_OPEN) {
- DP(NETIF_MSG_TX_ERR, "state is %x, returning\n", bp->state);
- goto reset_task_exit;
- }
-
- bnx2x_nic_unload(bp, 0);
- bnx2x_nic_load(bp, 0);
-
-reset_task_exit:
- rtnl_unlock();
-}
-
-static int __devinit bnx2x_init_board(struct pci_dev *pdev,
- struct net_device *dev)
+static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
+ struct net_device *dev)
{
struct bnx2x *bp;
int rc;
SET_NETDEV_DEV(dev, &pdev->dev);
bp = netdev_priv(dev);
+ bp->dev = dev;
+ bp->pdev = pdev;
bp->flags = 0;
- bp->port = PCI_FUNC(pdev->devfn);
+ bp->func = PCI_FUNC(pdev->devfn);
rc = pci_enable_device(pdev);
if (rc) {
goto err_out_disable;
}
- rc = pci_request_regions(pdev, DRV_MODULE_NAME);
- if (rc) {
- printk(KERN_ERR PFX "Cannot obtain PCI resources,"
- " aborting\n");
- goto err_out_disable;
- }
+ if (atomic_read(&pdev->enable_cnt) == 1) {
+ rc = pci_request_regions(pdev, DRV_MODULE_NAME);
+ if (rc) {
+ printk(KERN_ERR PFX "Cannot obtain PCI resources,"
+ " aborting\n");
+ goto err_out_disable;
+ }
- pci_set_master(pdev);
+ pci_set_master(pdev);
+ pci_save_state(pdev);
+ }
bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
if (bp->pm_cap == 0) {
goto err_out_release;
}
- bp->dev = dev;
- bp->pdev = pdev;
-
- INIT_WORK(&bp->reset_task, bnx2x_reset_task);
- INIT_WORK(&bp->sp_task, bnx2x_sp_task);
-
- dev->base_addr = pci_resource_start(pdev, 0);
+ dev->mem_start = pci_resource_start(pdev, 0);
+ dev->base_addr = dev->mem_start;
+ dev->mem_end = pci_resource_end(pdev, 0);
dev->irq = pdev->irq;
goto err_out_release;
}
- bp->doorbells = ioremap_nocache(pci_resource_start(pdev , 2),
- pci_resource_len(pdev, 2));
+ bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
+ min_t(u64, BNX2X_DB_SIZE,
+ pci_resource_len(pdev, 2)));
if (!bp->doorbells) {
printk(KERN_ERR PFX "Cannot map doorbell space, aborting\n");
rc = -ENOMEM;
bnx2x_set_power_state(bp, PCI_D0);
- bnx2x_get_hwinfo(bp);
-
-
- if (nomcp) {
- printk(KERN_ERR PFX "MCP disabled, will only"
- " init first device\n");
- onefunc = 1;
- }
-
- if (onefunc && bp->port) {
- printk(KERN_ERR PFX "Second device disabled, exiting\n");
- rc = -ENODEV;
- goto err_out_unmap;
- }
-
- bp->tx_ring_size = MAX_TX_AVAIL;
- bp->rx_ring_size = MAX_RX_AVAIL;
-
- bp->rx_csum = 1;
-
- bp->rx_offset = 0;
-
- bp->tx_quick_cons_trip_int = 0xff;
- bp->tx_quick_cons_trip = 0xff;
- bp->tx_ticks_int = 50;
- bp->tx_ticks = 50;
+ /* clean indirect addresses */
+ pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS,
+ PCICFG_VENDOR_ID_OFFSET);
+ REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0 + BP_PORT(bp)*16, 0);
+ REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0 + BP_PORT(bp)*16, 0);
+ 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);
- bp->rx_quick_cons_trip_int = 0xff;
- bp->rx_quick_cons_trip = 0xff;
- bp->rx_ticks_int = 25;
- bp->rx_ticks = 25;
+ dev->hard_start_xmit = bnx2x_start_xmit;
+ dev->watchdog_timeo = TX_TIMEOUT;
- bp->stats_ticks = 1000000 & 0xffff00;
+ dev->ethtool_ops = &bnx2x_ethtool_ops;
+ dev->open = bnx2x_open;
+ dev->stop = bnx2x_close;
+ dev->set_multicast_list = bnx2x_set_rx_mode;
+ dev->set_mac_address = bnx2x_change_mac_addr;
+ dev->do_ioctl = bnx2x_ioctl;
+ dev->change_mtu = bnx2x_change_mtu;
+ dev->tx_timeout = bnx2x_tx_timeout;
+#ifdef BCM_VLAN
+ dev->vlan_rx_register = bnx2x_vlan_rx_register;
+#endif
+#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+ dev->poll_controller = poll_bnx2x;
+#endif
+ dev->features |= NETIF_F_SG;
+ dev->features |= NETIF_F_HW_CSUM;
+ if (bp->flags & USING_DAC_FLAG)
+ dev->features |= NETIF_F_HIGHDMA;
+#ifdef BCM_VLAN
+ dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+#endif
+ dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
bp->timer_interval = HZ;
bp->current_interval = (poll ? poll : HZ);
- init_timer(&bp->timer);
- bp->timer.expires = jiffies + bp->current_interval;
- bp->timer.data = (unsigned long) bp;
- bp->timer.function = bnx2x_timer;
return 0;
iounmap(bp->regview);
bp->regview = NULL;
}
-
if (bp->doorbells) {
iounmap(bp->doorbells);
bp->doorbells = NULL;
}
err_out_release:
- pci_release_regions(pdev);
+ if (atomic_read(&pdev->enable_cnt) == 1)
+ pci_release_regions(pdev);
err_out_disable:
pci_disable_device(pdev);
struct net_device *dev = NULL;
struct bnx2x *bp;
int rc;
- int port = PCI_FUNC(pdev->devfn);
DECLARE_MAC_BUF(mac);
if (version_printed++ == 0)
/* dev zeroed in init_etherdev */
dev = alloc_etherdev(sizeof(*bp));
- if (!dev)
+ if (!dev) {
+ printk(KERN_ERR PFX "Cannot allocate net device\n");
return -ENOMEM;
+ }
netif_carrier_off(dev);
bp = netdev_priv(dev);
bp->msglevel = debug;
- if (port && onefunc) {
- printk(KERN_ERR PFX "second function disabled. exiting\n");
- free_netdev(dev);
- return 0;
- }
-
- rc = bnx2x_init_board(pdev, dev);
+ rc = bnx2x_init_dev(pdev, dev);
if (rc < 0) {
free_netdev(dev);
return rc;
}
- dev->hard_start_xmit = bnx2x_start_xmit;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- dev->ethtool_ops = &bnx2x_ethtool_ops;
- dev->open = bnx2x_open;
- dev->stop = bnx2x_close;
- dev->set_multicast_list = bnx2x_set_rx_mode;
- dev->set_mac_address = bnx2x_change_mac_addr;
- dev->do_ioctl = bnx2x_ioctl;
- dev->change_mtu = bnx2x_change_mtu;
- dev->tx_timeout = bnx2x_tx_timeout;
-#ifdef BCM_VLAN
- dev->vlan_rx_register = bnx2x_vlan_rx_register;
-#endif
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
- dev->poll_controller = poll_bnx2x;
-#endif
- dev->features |= NETIF_F_SG;
- if (bp->flags & USING_DAC_FLAG)
- dev->features |= NETIF_F_HIGHDMA;
- dev->features |= NETIF_F_IP_CSUM;
-#ifdef BCM_VLAN
- dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
- dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
-
rc = register_netdev(dev);
if (rc) {
dev_err(&pdev->dev, "Cannot register net device\n");
- if (bp->regview)
- iounmap(bp->regview);
- if (bp->doorbells)
- iounmap(bp->doorbells);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
- free_netdev(dev);
- return rc;
+ goto init_one_exit;
}
pci_set_drvdata(pdev, dev);
- bp->name = board_info[ent->driver_data].name;
+ rc = bnx2x_init_bp(bp);
+ if (rc) {
+ unregister_netdev(dev);
+ goto init_one_exit;
+ }
+
+ bp->common.name = board_info[ent->driver_data].name;
printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx,"
- " IRQ %d, ", dev->name, bp->name,
- ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
- ((CHIP_ID(bp) & 0x0ff0) >> 4),
+ " IRQ %d, ", dev->name, bp->common.name,
+ (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
bnx2x_get_pcie_width(bp),
(bnx2x_get_pcie_speed(bp) == 2) ? "5GHz (Gen2)" : "2.5GHz",
dev->base_addr, bp->pdev->irq);
printk(KERN_CONT "node addr %s\n", print_mac(mac, dev->dev_addr));
return 0;
+
+init_one_exit:
+ if (bp->regview)
+ iounmap(bp->regview);
+
+ if (bp->doorbells)
+ iounmap(bp->doorbells);
+
+ free_netdev(dev);
+
+ if (atomic_read(&pdev->enable_cnt) == 1)
+ pci_release_regions(pdev);
+
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+ return rc;
}
static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
struct bnx2x *bp;
if (!dev) {
- /* we get here if init_one() fails */
printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
return;
}
-
bp = netdev_priv(dev);
unregister_netdev(dev);
iounmap(bp->doorbells);
free_netdev(dev);
- pci_release_regions(pdev);
+
+ if (atomic_read(&pdev->enable_cnt) == 1)
+ pci_release_regions(pdev);
+
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
}
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2x *bp;
- if (!dev)
- return 0;
+ if (!dev) {
+ printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
+ return -ENODEV;
+ }
+ bp = netdev_priv(dev);
- if (!netif_running(dev))
- return 0;
+ rtnl_lock();
- bp = netdev_priv(dev);
+ pci_save_state(pdev);
- bnx2x_nic_unload(bp, 0);
+ if (!netif_running(dev)) {
+ rtnl_unlock();
+ return 0;
+ }
netif_device_detach(dev);
- pci_save_state(pdev);
+ bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+
bnx2x_set_power_state(bp, pci_choose_state(pdev, state));
+ rtnl_unlock();
+
return 0;
}
printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
return -ENODEV;
}
-
- if (!netif_running(dev))
- return 0;
-
bp = netdev_priv(dev);
+ rtnl_lock();
+
pci_restore_state(pdev);
+
+ if (!netif_running(dev)) {
+ rtnl_unlock();
+ return 0;
+ }
+
bnx2x_set_power_state(bp, PCI_D0);
netif_device_attach(dev);
- rc = bnx2x_nic_load(bp, 0);
- if (rc)
- return rc;
+ rc = bnx2x_nic_load(bp, LOAD_NORMAL);
- return 0;
+ rtnl_unlock();
+
+ return rc;
}
static struct pci_driver bnx2x_pci_driver = {