提交 f2e0899f 编写于 作者: D Dmitry Kravkov 提交者: David S. Miller

bnx2x: Add 57712 support

57712 HW supported with same set of features as for 57710/57711
Signed-off-by: NDmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: NEilon Greenstein <eilong@broadcom.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 8fe23fbd
......@@ -180,10 +180,16 @@ void bnx2x_panic_dump(struct bnx2x *bp);
#define SHMEM2_WR(bp, field, val) REG_WR(bp, SHMEM2_ADDR(bp, field), val)
#define MF_CFG_ADDR(bp, field) (bp->common.mf_cfg_base + \
offsetof(struct mf_cfg, field))
#define MF2_CFG_ADDR(bp, field) (bp->common.mf2_cfg_base + \
offsetof(struct mf2_cfg, field))
#define MF_CFG_RD(bp, field) REG_RD(bp, MF_CFG_ADDR(bp, field))
#define MF_CFG_WR(bp, field, val) REG_WR(bp,\
MF_CFG_ADDR(bp, field), (val))
#define MF2_CFG_RD(bp, field) REG_RD(bp, MF2_CFG_ADDR(bp, field))
#define SHMEM2_HAS(bp, field) ((bp)->common.shmem2_base && \
(SHMEM2_RD((bp), size) > \
offsetof(struct shmem2_region, field)))
#define EMAC_RD(bp, reg) REG_RD(bp, emac_base + reg)
#define EMAC_WR(bp, reg, val) REG_WR(bp, emac_base + reg, val)
......@@ -296,6 +302,8 @@ union db_prod {
union host_hc_status_block {
/* pointer to fp status block e1x */
struct host_hc_status_block_e1x *e1x_sb;
/* pointer to fp status block e2 */
struct host_hc_status_block_e2 *e2_sb;
};
struct bnx2x_fastpath {
......@@ -564,12 +572,19 @@ struct bnx2x_common {
#define CHIP_NUM_57710 0x164e
#define CHIP_NUM_57711 0x164f
#define CHIP_NUM_57711E 0x1650
#define CHIP_NUM_57712 0x1662
#define CHIP_NUM_57712E 0x1663
#define CHIP_IS_E1(bp) (CHIP_NUM(bp) == CHIP_NUM_57710)
#define CHIP_IS_57711(bp) (CHIP_NUM(bp) == CHIP_NUM_57711)
#define CHIP_IS_57711E(bp) (CHIP_NUM(bp) == CHIP_NUM_57711E)
#define CHIP_IS_57712(bp) (CHIP_NUM(bp) == CHIP_NUM_57712)
#define CHIP_IS_57712E(bp) (CHIP_NUM(bp) == CHIP_NUM_57712E)
#define CHIP_IS_E1H(bp) (CHIP_IS_57711(bp) || \
CHIP_IS_57711E(bp))
#define IS_E1H_OFFSET CHIP_IS_E1H(bp)
#define CHIP_IS_E2(bp) (CHIP_IS_57712(bp) || \
CHIP_IS_57712E(bp))
#define CHIP_IS_E1x(bp) (CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
#define IS_E1H_OFFSET (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp))
#define CHIP_REV(bp) (bp->common.chip_id & 0x0000f000)
#define CHIP_REV_Ax 0x00000000
......@@ -596,6 +611,7 @@ struct bnx2x_common {
u32 shmem_base;
u32 shmem2_base;
u32 mf_cfg_base;
u32 mf2_cfg_base;
u32 hw_config;
......@@ -603,10 +619,25 @@ struct bnx2x_common {
u8 int_block;
#define INT_BLOCK_HC 0
#define INT_BLOCK_IGU 1
#define INT_BLOCK_MODE_NORMAL 0
#define INT_BLOCK_MODE_BW_COMP 2
#define CHIP_INT_MODE_IS_NBC(bp) \
(CHIP_IS_E2(bp) && \
!((bp)->common.int_block & INT_BLOCK_MODE_BW_COMP))
#define CHIP_INT_MODE_IS_BC(bp) (!CHIP_INT_MODE_IS_NBC(bp))
u8 chip_port_mode;
#define CHIP_4_PORT_MODE 0x0
#define CHIP_2_PORT_MODE 0x1
#define CHIP_PORT_MODE_NONE 0x2
#define CHIP_MODE(bp) (bp->common.chip_port_mode)
#define CHIP_MODE_IS_4_PORT(bp) (CHIP_MODE(bp) == CHIP_4_PORT_MODE)
};
/* IGU MSIX STATISTICS on 57712: 64 for VFs; 4 for PFs; 4 for Attentions */
#define BNX2X_IGU_STAS_MSG_VF_CNT 64
#define BNX2X_IGU_STAS_MSG_PF_CNT 4
/* end of common */
......@@ -670,7 +701,7 @@ enum {
*/
#define FP_SB_MAX_E1x 16 /* fast-path interrupt contexts E1x */
#define MAX_CONTEXT FP_SB_MAX_E1x
#define FP_SB_MAX_E2 16 /* fast-path interrupt contexts E2 */
/*
* cid_cnt paramter below refers to the value returned by
......@@ -754,7 +785,7 @@ struct bnx2x_slowpath {
#define MAX_DYNAMIC_ATTN_GRPS 8
struct attn_route {
u32 sig[4];
u32 sig[5];
};
struct iro {
......@@ -896,13 +927,20 @@ struct bnx2x {
#define HW_VLAN_RX_FLAG 0x800
#define MF_FUNC_DIS 0x1000
int func;
int pf_num; /* absolute PF number */
int pfid; /* per-path PF number */
int base_fw_ndsb;
#define BP_PORT(bp) (bp->func % PORT_MAX)
#define BP_FUNC(bp) (bp->func)
#define BP_E1HVN(bp) (bp->func >> 1)
#define BP_PATH(bp) (!CHIP_IS_E2(bp) ? \
0 : (bp->pf_num & 1))
#define BP_PORT(bp) (bp->pfid & 1)
#define BP_FUNC(bp) (bp->pfid)
#define BP_ABS_FUNC(bp) (bp->pf_num)
#define BP_E1HVN(bp) (bp->pfid >> 1)
#define BP_VN(bp) (CHIP_MODE_IS_4_PORT(bp) ? \
0 : BP_E1HVN(bp))
#define BP_L_ID(bp) (BP_E1HVN(bp) << 2)
#define BP_FW_MB_IDX(bp) (BP_PORT(bp) +\
BP_VN(bp) * (CHIP_IS_E1x(bp) ? 2 : 1))
#ifdef BCM_CNIC
#define BCM_CNIC_CID_START 16
......@@ -932,7 +970,8 @@ struct bnx2x {
struct cmng_struct_per_port cmng;
u32 vn_weight_sum;
u32 mf_config;
u32 mf_config[E1HVN_MAX];
u32 mf2_config[E2_FUNC_MAX];
u16 mf_ov;
u8 mf_mode;
#define IS_MF(bp) (bp->mf_mode != 0)
......@@ -1127,11 +1166,11 @@ struct bnx2x {
#define RSS_IPV6_CAP 0x0004
#define RSS_IPV6_TCP_CAP 0x0008
#define BNX2X_MAX_QUEUES(bp) (IS_MF(bp) ? (MAX_CONTEXT/E1HVN_MAX) \
: MAX_CONTEXT)
#define BNX2X_NUM_QUEUES(bp) (bp->num_queues)
#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1)
#define BNX2X_MAX_QUEUES(bp) (bp->igu_sb_cnt - CNIC_CONTEXT_USE)
#define is_eth_multi(bp) (BNX2X_NUM_ETH_QUEUES(bp) > 1)
#define RSS_IPV4_CAP_MASK \
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY
......@@ -1342,14 +1381,40 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
/* DMAE command defines */
#define DMAE_CMD_SRC_PCI 0
#define DMAE_CMD_SRC_GRC DMAE_COMMAND_SRC
#define DMAE_TIMEOUT -1
#define DMAE_PCI_ERROR -2 /* E2 and onward */
#define DMAE_NOT_RDY -3
#define DMAE_PCI_ERR_FLAG 0x80000000
#define DMAE_SRC_PCI 0
#define DMAE_SRC_GRC 1
#define DMAE_DST_NONE 0
#define DMAE_DST_PCI 1
#define DMAE_DST_GRC 2
#define DMAE_COMP_PCI 0
#define DMAE_COMP_GRC 1
/* E2 and onward - PCI error handling in the completion */
#define DMAE_COMP_REGULAR 0
#define DMAE_COM_SET_ERR 1
#define DMAE_CMD_DST_PCI (1 << DMAE_COMMAND_DST_SHIFT)
#define DMAE_CMD_DST_GRC (2 << DMAE_COMMAND_DST_SHIFT)
#define DMAE_CMD_SRC_PCI (DMAE_SRC_PCI << \
DMAE_COMMAND_SRC_SHIFT)
#define DMAE_CMD_SRC_GRC (DMAE_SRC_GRC << \
DMAE_COMMAND_SRC_SHIFT)
#define DMAE_CMD_C_DST_PCI 0
#define DMAE_CMD_C_DST_GRC (1 << DMAE_COMMAND_C_DST_SHIFT)
#define DMAE_CMD_DST_PCI (DMAE_DST_PCI << \
DMAE_COMMAND_DST_SHIFT)
#define DMAE_CMD_DST_GRC (DMAE_DST_GRC << \
DMAE_COMMAND_DST_SHIFT)
#define DMAE_CMD_C_DST_PCI (DMAE_COMP_PCI << \
DMAE_COMMAND_C_DST_SHIFT)
#define DMAE_CMD_C_DST_GRC (DMAE_COMP_GRC << \
DMAE_COMMAND_C_DST_SHIFT)
#define DMAE_CMD_C_ENABLE DMAE_COMMAND_C_TYPE_ENABLE
......@@ -1365,10 +1430,20 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define DMAE_CMD_DST_RESET DMAE_COMMAND_DST_RESET
#define DMAE_CMD_E1HVN_SHIFT DMAE_COMMAND_E1HVN_SHIFT
#define DMAE_SRC_PF 0
#define DMAE_SRC_VF 1
#define DMAE_DST_PF 0
#define DMAE_DST_VF 1
#define DMAE_C_SRC 0
#define DMAE_C_DST 1
#define DMAE_LEN32_RD_MAX 0x80
#define DMAE_LEN32_WR_MAX(bp) (CHIP_IS_E1(bp) ? 0x400 : 0x2000)
#define DMAE_COMP_VAL 0xe0d0d0ae
#define DMAE_COMP_VAL 0x60d0d0ae /* E2 and on - upper bit
indicates eror */
#define MAX_DMAE_C_PER_PORT 8
#define INIT_DMAE_C(bp) (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
......@@ -1534,6 +1609,9 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define GET_FLAG(value, mask) \
(((value) &= (mask)) >> (mask##_SHIFT))
#define GET_FIELD(value, fname) \
(((value) & (fname##_MASK)) >> (fname##_SHIFT))
#define CAM_IS_INVALID(x) \
(GET_FLAG(x.flags, \
MAC_CONFIGURATION_ENTRY_ACTION_TYPE) == \
......@@ -1553,6 +1631,9 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define PXP2_REG_PXP2_INT_STS PXP2_REG_PXP2_INT_STS_0
#endif
#ifndef ETH_MAX_RX_CLIENTS_E2
#define ETH_MAX_RX_CLIENTS_E2 ETH_MAX_RX_CLIENTS_E1H
#endif
#define BNX2X_VPD_LEN 128
#define VENDOR_ID_LEN 4
......@@ -1570,13 +1651,18 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define BNX2X_EXTERN extern
#endif
BNX2X_EXTERN int load_count[3]; /* 0-common, 1-port0, 2-port1 */
BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
/* MISC_REG_RESET_REG - this is here for the hsi to work don't touch */
extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx);
u32 bnx2x_dmae_opcode_add_comp(u32 opcode, u8 comp_type);
u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode);
u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
bool with_comp, u8 comp_type);
#define WAIT_RAMROD_POLL 0x01
#define WAIT_RAMROD_COMMON 0x02
......
......@@ -18,7 +18,7 @@
#include <linux/etherdevice.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <net/ipv6.h>
#include <net/ip6_checksum.h>
#include <linux/firmware.h>
#include "bnx2x_cmn.h"
......@@ -118,16 +118,10 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp)
pkt_cons = TX_BD(sw_cons);
/* prefetch(bp->tx_buf_ring[pkt_cons].skb); */
DP(NETIF_MSG_TX_DONE, "queue[%d]: hw_cons %u sw_cons %u "
" pkt_cons %u\n",
fp->index, hw_cons, sw_cons, pkt_cons);
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) {
rmb();
prefetch(fp->tx_buf_ring[NEXT_TX_IDX(sw_cons)].skb);
}
*/
bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons);
sw_cons++;
}
......@@ -749,8 +743,9 @@ void bnx2x_link_report(struct bnx2x *bp)
u16 vn_max_rate;
vn_max_rate =
((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >>
FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
((bp->mf_config[BP_VN(bp)] &
FUNC_MF_CFG_MAX_BW_MASK) >>
FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
if (vn_max_rate < line_speed)
line_speed = vn_max_rate;
}
......@@ -912,14 +907,15 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
if (j != 0)
continue;
REG_WR(bp, BAR_USTRORM_INTMEM +
USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
U64_LO(fp->rx_comp_mapping));
REG_WR(bp, BAR_USTRORM_INTMEM +
USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4,
U64_HI(fp->rx_comp_mapping));
if (!CHIP_IS_E2(bp)) {
REG_WR(bp, BAR_USTRORM_INTMEM +
USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
U64_LO(fp->rx_comp_mapping));
REG_WR(bp, BAR_USTRORM_INTMEM +
USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4,
U64_HI(fp->rx_comp_mapping));
}
}
}
static void bnx2x_free_tx_skbs(struct bnx2x *bp)
{
......@@ -1308,23 +1304,27 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
}
} else {
int path = BP_PATH(bp);
int port = BP_PORT(bp);
DP(NETIF_MSG_IFUP, "NO MCP - load counts %d, %d, %d\n",
load_count[0], load_count[1], load_count[2]);
load_count[0]++;
load_count[1 + port]++;
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)
DP(NETIF_MSG_IFUP, "NO MCP - load counts[%d] %d, %d, %d\n",
path, load_count[path][0], load_count[path][1],
load_count[path][2]);
load_count[path][0]++;
load_count[path][1 + port]++;
DP(NETIF_MSG_IFUP, "NO MCP - new load counts[%d] %d, %d, %d\n",
path, load_count[path][0], load_count[path][1],
load_count[path][2]);
if (load_count[path][0] == 1)
load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
else if (load_count[1 + port] == 1)
else if (load_count[path][1 + port] == 1)
load_code = FW_MSG_CODE_DRV_LOAD_PORT;
else
load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
}
if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
(load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
(load_code == FW_MSG_CODE_DRV_LOAD_PORT))
bp->port.pmf = 1;
else
......@@ -1349,7 +1349,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Setup NIC internals and enable interrupts */
bnx2x_nic_init(bp, load_code);
if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) &&
if (((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
(load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP)) &&
(bp->common.shmem2_base))
SHMEM2_WR(bp, dcc_support,
(SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
......@@ -1389,11 +1390,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
#endif
}
if (CHIP_IS_E1H(bp))
if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) {
DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
bp->flags |= MF_FUNC_DIS;
}
if (!CHIP_IS_E1(bp) &&
(bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED)) {
DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
bp->flags |= MF_FUNC_DIS;
}
#ifdef BCM_CNIC
/* Enable Timer scan */
......@@ -1527,8 +1528,10 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bp->rx_mode = BNX2X_RX_MODE_NONE;
bnx2x_set_storm_rx_mode(bp);
/* Stop Tx */
bnx2x_tx_disable(bp);
del_timer_sync(&bp->timer);
SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb,
SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
(DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
......@@ -1855,6 +1858,120 @@ static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb,
}
#endif
static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb,
struct eth_tx_parse_bd_e2 *pbd,
u32 xmit_type)
{
pbd->parsing_data |= cpu_to_le16(skb_shinfo(skb)->gso_size) <<
ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT;
if ((xmit_type & XMIT_GSO_V6) &&
(ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
pbd->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
}
/**
* Update PBD in GSO case.
*
* @param skb
* @param tx_start_bd
* @param pbd
* @param xmit_type
*/
static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
struct eth_tx_parse_bd_e1x *pbd,
u32 xmit_type)
{
pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
pbd->tcp_send_seq = swab32(tcp_hdr(skb)->seq);
pbd->tcp_flags = pbd_tcp_flags(skb);
if (xmit_type & XMIT_GSO_V4) {
pbd->ip_id = swab16(ip_hdr(skb)->id);
pbd->tcp_pseudo_csum =
swab16(~csum_tcpudp_magic(ip_hdr(skb)->saddr,
ip_hdr(skb)->daddr,
0, IPPROTO_TCP, 0));
} else
pbd->tcp_pseudo_csum =
swab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr,
0, IPPROTO_TCP, 0));
pbd->global_data |= ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN;
}
/**
*
* @param skb
* @param tx_start_bd
* @param pbd_e2
* @param xmit_type
*
* @return header len
*/
static inline u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
struct eth_tx_parse_bd_e2 *pbd,
u32 xmit_type)
{
pbd->parsing_data |= cpu_to_le16(tcp_hdrlen(skb)/4) <<
ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT;
pbd->parsing_data |= cpu_to_le16(((unsigned char *)tcp_hdr(skb) -
skb->data) / 2) <<
ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT;
return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
}
/**
*
* @param skb
* @param tx_start_bd
* @param pbd
* @param xmit_type
*
* @return Header length
*/
static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
struct eth_tx_parse_bd_e1x *pbd,
u32 xmit_type)
{
u8 hlen = (skb_network_header(skb) - skb->data) / 2;
/* for now NS flag is not used in Linux */
pbd->global_data =
(hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT));
pbd->ip_hlen_w = (skb_transport_header(skb) -
skb_network_header(skb)) / 2;
hlen += pbd->ip_hlen_w + tcp_hdrlen(skb) / 2;
pbd->total_hlen_w = cpu_to_le16(hlen);
hlen = hlen*2;
if (xmit_type & XMIT_CSUM_TCP) {
pbd->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check);
} else {
s8 fix = SKB_CS_OFF(skb); /* signed! */
DP(NETIF_MSG_TX_QUEUED,
"hlen %d fix %d csum before fix %x\n",
le16_to_cpu(pbd->total_hlen_w), fix, SKB_CS(skb));
/* HW bug: fixup the CSUM */
pbd->tcp_pseudo_csum =
bnx2x_csum_fix(skb_transport_header(skb),
SKB_CS(skb), fix);
DP(NETIF_MSG_TX_QUEUED, "csum after fix %x\n",
pbd->tcp_pseudo_csum);
}
return hlen;
}
/* called with netif_tx_lock
* bnx2x_tx_int() runs without netif_tx_lock unless it needs to call
* netif_wake_queue()
......@@ -1868,6 +1985,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct eth_tx_start_bd *tx_start_bd;
struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
u16 pkt_prod, bd_prod;
int nbd, fp_index;
dma_addr_t mapping;
......@@ -1895,9 +2013,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
DP(NETIF_MSG_TX_QUEUED, "SKB: summed %x protocol %x protocol(%x,%x)"
" gso type %x xmit_type %x\n",
skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
DP(NETIF_MSG_TX_QUEUED, "queue[%d]: SKB: summed %x protocol %x "
"protocol(%x,%x) gso type %x xmit_type %x\n",
fp_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type);
eth = (struct ethhdr *)skb->data;
......@@ -1988,44 +2106,21 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_start_bd->bd_flags.as_bitfield |=
ETH_TX_BD_FLAGS_IS_UDP;
}
pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
/* Set PBD in checksum offload case */
if (xmit_type & XMIT_CSUM) {
hlen = (skb_network_header(skb) - skb->data) / 2;
/* for now NS flag is not used in Linux */
pbd_e1x->global_data =
(hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT));
pbd_e1x->ip_hlen_w = (skb_transport_header(skb) -
skb_network_header(skb)) / 2;
hlen += pbd_e1x->ip_hlen_w + tcp_hdrlen(skb) / 2;
pbd_e1x->total_hlen_w = cpu_to_le16(hlen);
hlen = hlen*2;
if (xmit_type & XMIT_CSUM_TCP) {
pbd_e1x->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check);
} else {
s8 fix = SKB_CS_OFF(skb); /* signed! */
DP(NETIF_MSG_TX_QUEUED,
"hlen %d fix %d csum before fix %x\n",
le16_to_cpu(pbd_e1x->total_hlen_w),
fix, SKB_CS(skb));
/* HW bug: fixup the CSUM */
pbd_e1x->tcp_pseudo_csum =
bnx2x_csum_fix(skb_transport_header(skb),
SKB_CS(skb), fix);
if (CHIP_IS_E2(bp)) {
pbd_e2 = &fp->tx_desc_ring[bd_prod].parse_bd_e2;
memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
/* Set PBD in checksum offload case */
if (xmit_type & XMIT_CSUM)
hlen = bnx2x_set_pbd_csum_e2(bp,
skb, pbd_e2, xmit_type);
} else {
pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
/* Set PBD in checksum offload case */
if (xmit_type & XMIT_CSUM)
hlen = bnx2x_set_pbd_csum(bp, skb, pbd_e1x, xmit_type);
DP(NETIF_MSG_TX_QUEUED, "csum after fix %x\n",
pbd_e1x->tcp_pseudo_csum);
}
}
mapping = dma_map_single(&bp->pdev->dev, skb->data,
......@@ -2057,26 +2152,10 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(skb_headlen(skb) > hlen))
bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
hlen, bd_prod, ++nbd);
pbd_e1x->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
pbd_e1x->tcp_send_seq = swab32(tcp_hdr(skb)->seq);
pbd_e1x->tcp_flags = pbd_tcp_flags(skb);
if (xmit_type & XMIT_GSO_V4) {
pbd_e1x->ip_id = swab16(ip_hdr(skb)->id);
pbd_e1x->tcp_pseudo_csum =
swab16(~csum_tcpudp_magic(ip_hdr(skb)->saddr,
ip_hdr(skb)->daddr,
0, IPPROTO_TCP, 0));
} else
pbd_e1x->tcp_pseudo_csum =
swab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr,
0, IPPROTO_TCP, 0));
pbd_e1x->global_data |=
ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN;
if (CHIP_IS_E2(bp))
bnx2x_set_pbd_gso_e2(skb, pbd_e2, xmit_type);
else
bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type);
}
tx_data_bd = (struct eth_tx_bd *)tx_start_bd;
......@@ -2124,7 +2203,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
pbd_e1x->ip_id, pbd_e1x->lso_mss, pbd_e1x->tcp_flags,
pbd_e1x->tcp_pseudo_csum, pbd_e1x->tcp_send_seq,
le16_to_cpu(pbd_e1x->total_hlen_w));
if (pbd_e2)
DP(NETIF_MSG_TX_QUEUED,
"PBD (E2) @%p dst %x %x %x src %x %x %x parsing_data %x\n",
pbd_e2, pbd_e2->dst_mac_addr_hi, pbd_e2->dst_mac_addr_mid,
pbd_e2->dst_mac_addr_lo, pbd_e2->src_mac_addr_hi,
pbd_e2->src_mac_addr_mid, pbd_e2->src_mac_addr_lo,
pbd_e2->parsing_data);
DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod);
/*
......@@ -2327,6 +2412,8 @@ int bnx2x_resume(struct pci_dev *pdev)
bnx2x_set_power_state(bp, PCI_D0);
netif_device_attach(dev);
/* Since the chip was reset, clear the FW sequence number */
bp->fw_seq = 0;
rc = bnx2x_nic_load(bp, LOAD_OPEN);
rtnl_unlock();
......
......@@ -366,10 +366,77 @@ static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
fp->index, bd_prod, rx_comp_prod, rx_sge_prod);
}
static inline void bnx2x_igu_ack_sb_gen(struct bnx2x *bp, u8 igu_sb_id,
u8 segment, u16 index, u8 op,
u8 update, u32 igu_addr)
{
struct igu_regular cmd_data = {0};
cmd_data.sb_id_and_flags =
((index << IGU_REGULAR_SB_INDEX_SHIFT) |
(segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) |
(update << IGU_REGULAR_BUPDATE_SHIFT) |
(op << IGU_REGULAR_ENABLE_INT_SHIFT));
DP(NETIF_MSG_HW, "write 0x%08x to IGU addr 0x%x\n",
cmd_data.sb_id_and_flags, igu_addr);
REG_WR(bp, igu_addr, cmd_data.sb_id_and_flags);
/* Make sure that ACK is written */
mmiowb();
barrier();
}
static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
u8 storm, u16 index, u8 op, u8 update)
static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp,
u8 idu_sb_id, bool is_Pf)
{
u32 data, ctl, cnt = 100;
u32 igu_addr_data = IGU_REG_COMMAND_REG_32LSB_DATA;
u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
u32 igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id/32)*4;
u32 sb_bit = 1 << (idu_sb_id%32);
u32 func_encode = BP_FUNC(bp) |
((is_Pf == true ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT);
u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id;
/* Not supported in BC mode */
if (CHIP_INT_MODE_IS_BC(bp))
return;
data = (IGU_USE_REGISTER_cstorm_type_0_sb_cleanup
<< IGU_REGULAR_CLEANUP_TYPE_SHIFT) |
IGU_REGULAR_CLEANUP_SET |
IGU_REGULAR_BCLEANUP;
ctl = addr_encode << IGU_CTRL_REG_ADDRESS_SHIFT |
func_encode << IGU_CTRL_REG_FID_SHIFT |
IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT;
DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
data, igu_addr_data);
REG_WR(bp, igu_addr_data, data);
mmiowb();
barrier();
DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
ctl, igu_addr_ctl);
REG_WR(bp, igu_addr_ctl, ctl);
mmiowb();
barrier();
/* wait for clean up to finish */
while (!(REG_RD(bp, igu_addr_ack) & sb_bit) && --cnt)
msleep(20);
if (!(REG_RD(bp, igu_addr_ack) & sb_bit)) {
DP(NETIF_MSG_HW, "Unable to finish IGU cleanup: "
"idu_sb_id %d offset %d bit %d (cnt %d)\n",
idu_sb_id, idu_sb_id/32, idu_sb_id%32, cnt);
}
}
static inline void bnx2x_hc_ack_sb(struct bnx2x *bp, u8 sb_id,
u8 storm, u16 index, u8 op, u8 update)
{
u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
COMMAND_REG_INT_ACK);
......@@ -390,7 +457,37 @@ static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
mmiowb();
barrier();
}
static inline u16 bnx2x_ack_int(struct bnx2x *bp)
static inline void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
u16 index, u8 op, u8 update)
{
u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
igu_addr);
}
static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 storm,
u16 index, u8 op, u8 update)
{
if (bp->common.int_block == INT_BLOCK_HC)
bnx2x_hc_ack_sb(bp, igu_sb_id, storm, index, op, update);
else {
u8 segment;
if (CHIP_INT_MODE_IS_BC(bp))
segment = storm;
else if (igu_sb_id != bp->igu_dsb_id)
segment = IGU_SEG_ACCESS_DEF;
else if (storm == ATTENTION_ID)
segment = IGU_SEG_ACCESS_ATTN;
else
segment = IGU_SEG_ACCESS_DEF;
bnx2x_igu_ack_sb(bp, igu_sb_id, segment, index, op, update);
}
}
static inline u16 bnx2x_hc_ack_int(struct bnx2x *bp)
{
u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
COMMAND_REG_SIMD_MASK);
......@@ -399,13 +496,34 @@ static inline u16 bnx2x_ack_int(struct bnx2x *bp)
DP(BNX2X_MSG_OFF, "read 0x%08x from HC addr 0x%x\n",
result, hc_addr);
barrier();
return result;
}
static inline u16 bnx2x_igu_ack_int(struct bnx2x *bp)
{
u32 igu_addr = (BAR_IGU_INTMEM + IGU_REG_SISR_MDPC_WMASK_LSB_UPPER*8);
u32 result = REG_RD(bp, igu_addr);
DP(NETIF_MSG_HW, "read 0x%08x from IGU addr 0x%x\n",
result, igu_addr);
barrier();
return result;
}
static inline u16 bnx2x_ack_int(struct bnx2x *bp)
{
barrier();
if (bp->common.int_block == INT_BLOCK_HC)
return bnx2x_hc_ack_int(bp);
else
return bnx2x_igu_ack_int(bp);
}
/*
* fast path service functions
*/
static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp)
{
/* Tell compiler that consumer and producer can change */
......@@ -456,6 +574,17 @@ static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
rx_cons_sb++;
return (fp->rx_comp_cons != rx_cons_sb);
}
/**
* disables tx from stack point of view
*
* @param bp
*/
static inline void bnx2x_tx_disable(struct bnx2x *bp)
{
netif_tx_disable(bp->dev);
netif_carrier_off(bp->dev);
}
static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
struct bnx2x_fastpath *fp, u16 index)
{
......
......@@ -31,14 +31,24 @@ struct dump_sign {
#define RI_E1 0x1
#define RI_E1H 0x2
#define RI_E2 0x4
#define RI_ONLINE 0x100
#define RI_PATH0_DUMP 0x200
#define RI_PATH1_DUMP 0x400
#define RI_E1_OFFLINE (RI_E1)
#define RI_E1_ONLINE (RI_E1 | RI_ONLINE)
#define RI_E1H_OFFLINE (RI_E1H)
#define RI_E1H_ONLINE (RI_E1H | RI_ONLINE)
#define RI_ALL_OFFLINE (RI_E1 | RI_E1H)
#define RI_ALL_ONLINE (RI_E1 | RI_E1H | RI_ONLINE)
#define RI_E2_OFFLINE (RI_E2)
#define RI_E2_ONLINE (RI_E2 | RI_ONLINE)
#define RI_E1E1H_OFFLINE (RI_E1 | RI_E1H)
#define RI_E1E1H_ONLINE (RI_E1 | RI_E1H | RI_ONLINE)
#define RI_E1HE2_OFFLINE (RI_E2 | RI_E1H)
#define RI_E1HE2_ONLINE (RI_E2 | RI_E1H | RI_ONLINE)
#define RI_E1E2_OFFLINE (RI_E2 | RI_E1)
#define RI_E1E2_ONLINE (RI_E2 | RI_E1 | RI_ONLINE)
#define RI_ALL_OFFLINE (RI_E1 | RI_E1H | RI_E2)
#define RI_ALL_ONLINE (RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
#define MAX_TIMER_PENDING 200
#define TIMER_SCAN_DONT_CARE 0xFF
......@@ -513,6 +523,12 @@ static const struct wreg_addr wreg_addrs_e1h[WREGS_COUNT_E1H] = {
{ 0x1b0c00, 256, 2, read_reg_e1h_0, RI_E1H_OFFLINE }
};
#define WREGS_COUNT_E2 1
static const u32 read_reg_e2_0[] = { 0x1b1040, 0x1b1000 };
static const struct wreg_addr wreg_addrs_e2[WREGS_COUNT_E2] = {
{ 0x1b0c00, 128, 2, read_reg_e2_0, RI_E2_OFFLINE }
};
static const struct dump_sign dump_sign_all = { 0x49aa93ee, 0x40835, 0x22 };
......@@ -531,4 +547,17 @@ static const u32 timer_scan_regs_e1h[TIMER_REGS_COUNT_E1H] =
{ 0x1640d0, 0x1640d4 };
#define PAGE_MODE_VALUES_E2 2
#define PAGE_READ_REGS_E2 1
#define PAGE_WRITE_REGS_E2 1
static const u32 page_vals_e2[PAGE_MODE_VALUES_E2] = { 0, 128 };
static const u32 page_write_regs_e2[PAGE_WRITE_REGS_E2] = { 328476 };
static const struct reg_addr page_read_regs_e2[PAGE_READ_REGS_E2] = {
{ 0x58000, 4608, RI_E2_ONLINE } };
#endif /* BNX2X_DUMP_H */
......@@ -41,19 +41,19 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
(bp->link_vars.link_up)) {
cmd->speed = bp->link_vars.line_speed;
cmd->duplex = bp->link_vars.duplex;
if (IS_MF(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;
}
} else {
cmd->speed = bp->link_params.req_line_speed[cfg_idx];
cmd->duplex = bp->link_params.req_duplex[cfg_idx];
}
if (IS_MF(bp)) {
u16 vn_max_rate = ((bp->mf_config[BP_VN(bp)] &
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->port.supported[cfg_idx] & SUPPORTED_TP)
cmd->port = PORT_TP;
......@@ -298,6 +298,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
#define IS_E1_ONLINE(info) (((info) & RI_E1_ONLINE) == RI_E1_ONLINE)
#define IS_E1H_ONLINE(info) (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE)
#define IS_E2_ONLINE(info) (((info) & RI_E2_ONLINE) == RI_E2_ONLINE)
static int bnx2x_get_regs_len(struct net_device *dev)
{
......@@ -315,7 +316,7 @@ static int bnx2x_get_regs_len(struct net_device *dev)
regdump_len += wreg_addrs_e1[i].size *
(1 + wreg_addrs_e1[i].read_regs_count);
} else { /* E1H */
} else if (CHIP_IS_E1H(bp)) {
for (i = 0; i < REGS_COUNT; i++)
if (IS_E1H_ONLINE(reg_addrs[i].info))
regdump_len += reg_addrs[i].size;
......@@ -324,6 +325,15 @@ static int bnx2x_get_regs_len(struct net_device *dev)
if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info))
regdump_len += wreg_addrs_e1h[i].size *
(1 + wreg_addrs_e1h[i].read_regs_count);
} else if (CHIP_IS_E2(bp)) {
for (i = 0; i < REGS_COUNT; i++)
if (IS_E2_ONLINE(reg_addrs[i].info))
regdump_len += reg_addrs[i].size;
for (i = 0; i < WREGS_COUNT_E2; i++)
if (IS_E2_ONLINE(wreg_addrs_e2[i].info))
regdump_len += wreg_addrs_e2[i].size *
(1 + wreg_addrs_e2[i].read_regs_count);
}
regdump_len *= 4;
regdump_len += sizeof(struct dump_hdr);
......@@ -331,6 +341,23 @@ static int bnx2x_get_regs_len(struct net_device *dev)
return regdump_len;
}
static inline void bnx2x_read_pages_regs_e2(struct bnx2x *bp, u32 *p)
{
u32 i, j, k, n;
for (i = 0; i < PAGE_MODE_VALUES_E2; i++) {
for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
REG_WR(bp, page_write_regs_e2[j], page_vals_e2[i]);
for (k = 0; k < PAGE_READ_REGS_E2; k++)
if (IS_E2_ONLINE(page_read_regs_e2[k].info))
for (n = 0; n <
page_read_regs_e2[k].size; n++)
*p++ = REG_RD(bp,
page_read_regs_e2[k].addr + n*4);
}
}
}
static void bnx2x_get_regs(struct net_device *dev,
struct ethtool_regs *regs, void *_p)
{
......@@ -350,7 +377,14 @@ static void bnx2x_get_regs(struct net_device *dev,
dump_hdr.tstorm_waitp = REG_RD(bp, TSTORM_WAITP_ADDR);
dump_hdr.ustorm_waitp = REG_RD(bp, USTORM_WAITP_ADDR);
dump_hdr.cstorm_waitp = REG_RD(bp, CSTORM_WAITP_ADDR);
dump_hdr.info = CHIP_IS_E1(bp) ? RI_E1_ONLINE : RI_E1H_ONLINE;
if (CHIP_IS_E1(bp))
dump_hdr.info = RI_E1_ONLINE;
else if (CHIP_IS_E1H(bp))
dump_hdr.info = RI_E1H_ONLINE;
else if (CHIP_IS_E2(bp))
dump_hdr.info = RI_E2_ONLINE |
(BP_PATH(bp) ? RI_PATH1_DUMP : RI_PATH0_DUMP);
memcpy(p, &dump_hdr, sizeof(struct dump_hdr));
p += dump_hdr.hdr_size + 1;
......@@ -362,16 +396,25 @@ static void bnx2x_get_regs(struct net_device *dev,
*p++ = REG_RD(bp,
reg_addrs[i].addr + j*4);
} else { /* E1H */
} else if (CHIP_IS_E1H(bp)) {
for (i = 0; i < REGS_COUNT; i++)
if (IS_E1H_ONLINE(reg_addrs[i].info))
for (j = 0; j < reg_addrs[i].size; j++)
*p++ = REG_RD(bp,
reg_addrs[i].addr + j*4);
} else if (CHIP_IS_E2(bp)) {
for (i = 0; i < REGS_COUNT; i++)
if (IS_E2_ONLINE(reg_addrs[i].info))
for (j = 0; j < reg_addrs[i].size; j++)
*p++ = REG_RD(bp,
reg_addrs[i].addr + j*4);
bnx2x_read_pages_regs_e2(bp, p);
}
}
#define PHY_FW_VER_LEN 10
#define PHY_FW_VER_LEN 20
static void bnx2x_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
......@@ -474,7 +517,7 @@ static u32 bnx2x_get_link(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
if (bp->flags & MF_FUNC_DIS)
if (bp->flags & MF_FUNC_DIS || (bp->state != BNX2X_STATE_OPEN))
return 0;
return bp->link_vars.link_up;
......@@ -1235,6 +1278,9 @@ static int bnx2x_test_registers(struct bnx2x *bp)
for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) {
u32 offset, mask, save_val, val;
if (CHIP_IS_E2(bp) &&
reg_tbl[i].offset0 == HC_REG_AGG_INT_0)
continue;
offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1;
mask = reg_tbl[i].mask;
......@@ -1286,20 +1332,33 @@ static int bnx2x_test_memory(struct bnx2x *bp)
u32 offset;
u32 e1_mask;
u32 e1h_mask;
u32 e2_mask;
} prty_tbl[] = {
{ "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0 },
{ "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2 },
{ "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0 },
{ "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0 },
{ "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0 },
{ "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0 },
{ NULL, 0xffffffff, 0, 0 }
{ "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0, 0 },
{ "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2, 0 },
{ "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0, 0 },
{ "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0, 0 },
{ "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0, 0 },
{ "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0, 0 },
{ NULL, 0xffffffff, 0, 0, 0 }
};
if (!netif_running(bp->dev))
return rc;
/* pre-Check the parity status */
for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
val = REG_RD(bp, prty_tbl[i].offset);
if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
(CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
(CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
DP(NETIF_MSG_HW,
"%s is 0x%x\n", prty_tbl[i].name, val);
goto test_mem_exit;
}
}
/* Go through all the memories */
for (i = 0; mem_tbl[i].offset != 0xffffffff; i++)
for (j = 0; j < mem_tbl[i].size; j++)
......@@ -1309,7 +1368,8 @@ static int bnx2x_test_memory(struct bnx2x *bp)
for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
val = REG_RD(bp, prty_tbl[i].offset);
if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
(CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask)))) {
(CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
(CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
DP(NETIF_MSG_HW,
"%s is 0x%x\n", prty_tbl[i].name, val);
goto test_mem_exit;
......@@ -1324,7 +1384,7 @@ static int bnx2x_test_memory(struct bnx2x *bp)
static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes)
{
int cnt = 1000;
int cnt = 1400;
if (link_up)
while (bnx2x_link_test(bp, is_serdes) && cnt--)
......@@ -1343,7 +1403,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
u16 pkt_prod, bd_prod;
struct sw_tx_bd *tx_buf;
struct eth_tx_start_bd *tx_start_bd;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
dma_addr_t mapping;
union eth_rx_cqe *cqe;
u8 cqe_fp_flags;
......@@ -1411,7 +1472,9 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
/* turn on parsing and get a BD */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
pbd_e1x = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e1x;
pbd_e2 = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e2;
memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
wmb();
......@@ -1431,6 +1494,13 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
if (tx_idx != tx_start_idx + num_pkts)
goto test_loopback_exit;
/* Unlike HC IGU won't generate an interrupt for status block
* updates that have been performed while interrupts were
* disabled.
*/
if (bp->common.int_block == INT_BLOCK_IGU)
bnx2x_tx_int(fp_tx);
rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
if (rx_idx != rx_start_idx + num_pkts)
goto test_loopback_exit;
......@@ -1573,8 +1643,7 @@ static int bnx2x_test_intr(struct bnx2x *bp)
config->hdr.length = 0;
if (CHIP_IS_E1(bp))
/* use last unicast entries */
config->hdr.offset = (BP_PORT(bp) ? 63 : 31);
config->hdr.offset = (BP_PORT(bp) ? 32 : 0);
else
config->hdr.offset = BP_FUNC(bp);
config->hdr.client_id = bp->fp->cl_id;
......
......@@ -663,6 +663,7 @@ struct shm_dev_info { /* size */
#define FUNC_7 7
#define E1_FUNC_MAX 2
#define E1H_FUNC_MAX 8
#define E2_FUNC_MAX 4 /* per path */
#define VN_0 0
#define VN_1 1
......@@ -821,6 +822,9 @@ struct drv_func_mb {
#define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000
#define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000
#define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000
/* Load common chip is supported from bc 6.0.0 */
#define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP 0x00060000
#define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP 0x10130000
#define FW_MSG_CODE_DRV_LOAD_REFUSED 0x10200000
#define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000
#define FW_MSG_CODE_DRV_UNLOAD_COMMON 0x20100000
......@@ -1026,7 +1030,17 @@ struct shmem_region { /* SharedMem Offset (size) */
}; /* 57710 = 0x6dc | 57711 = 0x7E4 | 57712 = 0x734 */
struct fw_flr_ack {
u32 pf_ack;
u32 vf_ack[1];
u32 iov_dis_ack;
};
struct fw_flr_mb {
u32 aggint;
u32 opgen_addr;
struct fw_flr_ack ack;
};
struct shmem2_region {
......@@ -1046,7 +1060,20 @@ struct shmem2_region {
* For backwards compatibility, if the mf_cfg_addr does not exist
* (the size filed is smaller than 0xc) the mf_cfg resides at the
* end of struct shmem_region
*/
u32 mf_cfg_addr;
#define SHMEM_MF_CFG_ADDR_NONE 0x00000000
struct fw_flr_mb flr_mb;
u32 reserved[3];
/*
* The other shmemX_base_addr holds the other path's shmem address
* required for example in case of common phy init, or for path1 to know
* the address of mcp debug trace which is located in offset from shmem
* of path0
*/
u32 other_shmem_base_addr;
u32 other_shmem2_base_addr;
};
......@@ -1206,10 +1233,126 @@ struct bmac1_stats {
u32 rx_stat_gripj_hi;
};
struct bmac2_stats {
u32 tx_stat_gtpk_lo; /* gtpok */
u32 tx_stat_gtpk_hi; /* gtpok */
u32 tx_stat_gtxpf_lo; /* gtpf */
u32 tx_stat_gtxpf_hi; /* gtpf */
u32 tx_stat_gtpp_lo; /* NEW BMAC2 */
u32 tx_stat_gtpp_hi; /* NEW BMAC2 */
u32 tx_stat_gtfcs_lo;
u32 tx_stat_gtfcs_hi;
u32 tx_stat_gtuca_lo; /* NEW BMAC2 */
u32 tx_stat_gtuca_hi; /* NEW BMAC2 */
u32 tx_stat_gtmca_lo;
u32 tx_stat_gtmca_hi;
u32 tx_stat_gtbca_lo;
u32 tx_stat_gtbca_hi;
u32 tx_stat_gtovr_lo;
u32 tx_stat_gtovr_hi;
u32 tx_stat_gtfrg_lo;
u32 tx_stat_gtfrg_hi;
u32 tx_stat_gtpkt1_lo; /* gtpkt */
u32 tx_stat_gtpkt1_hi; /* gtpkt */
u32 tx_stat_gt64_lo;
u32 tx_stat_gt64_hi;
u32 tx_stat_gt127_lo;
u32 tx_stat_gt127_hi;
u32 tx_stat_gt255_lo;
u32 tx_stat_gt255_hi;
u32 tx_stat_gt511_lo;
u32 tx_stat_gt511_hi;
u32 tx_stat_gt1023_lo;
u32 tx_stat_gt1023_hi;
u32 tx_stat_gt1518_lo;
u32 tx_stat_gt1518_hi;
u32 tx_stat_gt2047_lo;
u32 tx_stat_gt2047_hi;
u32 tx_stat_gt4095_lo;
u32 tx_stat_gt4095_hi;
u32 tx_stat_gt9216_lo;
u32 tx_stat_gt9216_hi;
u32 tx_stat_gt16383_lo;
u32 tx_stat_gt16383_hi;
u32 tx_stat_gtmax_lo;
u32 tx_stat_gtmax_hi;
u32 tx_stat_gtufl_lo;
u32 tx_stat_gtufl_hi;
u32 tx_stat_gterr_lo;
u32 tx_stat_gterr_hi;
u32 tx_stat_gtbyt_lo;
u32 tx_stat_gtbyt_hi;
u32 rx_stat_gr64_lo;
u32 rx_stat_gr64_hi;
u32 rx_stat_gr127_lo;
u32 rx_stat_gr127_hi;
u32 rx_stat_gr255_lo;
u32 rx_stat_gr255_hi;
u32 rx_stat_gr511_lo;
u32 rx_stat_gr511_hi;
u32 rx_stat_gr1023_lo;
u32 rx_stat_gr1023_hi;
u32 rx_stat_gr1518_lo;
u32 rx_stat_gr1518_hi;
u32 rx_stat_gr2047_lo;
u32 rx_stat_gr2047_hi;
u32 rx_stat_gr4095_lo;
u32 rx_stat_gr4095_hi;
u32 rx_stat_gr9216_lo;
u32 rx_stat_gr9216_hi;
u32 rx_stat_gr16383_lo;
u32 rx_stat_gr16383_hi;
u32 rx_stat_grmax_lo;
u32 rx_stat_grmax_hi;
u32 rx_stat_grpkt_lo;
u32 rx_stat_grpkt_hi;
u32 rx_stat_grfcs_lo;
u32 rx_stat_grfcs_hi;
u32 rx_stat_gruca_lo;
u32 rx_stat_gruca_hi;
u32 rx_stat_grmca_lo;
u32 rx_stat_grmca_hi;
u32 rx_stat_grbca_lo;
u32 rx_stat_grbca_hi;
u32 rx_stat_grxpf_lo; /* grpf */
u32 rx_stat_grxpf_hi; /* grpf */
u32 rx_stat_grpp_lo;
u32 rx_stat_grpp_hi;
u32 rx_stat_grxuo_lo; /* gruo */
u32 rx_stat_grxuo_hi; /* gruo */
u32 rx_stat_grjbr_lo;
u32 rx_stat_grjbr_hi;
u32 rx_stat_grovr_lo;
u32 rx_stat_grovr_hi;
u32 rx_stat_grxcf_lo; /* grcf */
u32 rx_stat_grxcf_hi; /* grcf */
u32 rx_stat_grflr_lo;
u32 rx_stat_grflr_hi;
u32 rx_stat_grpok_lo;
u32 rx_stat_grpok_hi;
u32 rx_stat_grmeg_lo;
u32 rx_stat_grmeg_hi;
u32 rx_stat_grmeb_lo;
u32 rx_stat_grmeb_hi;
u32 rx_stat_grbyt_lo;
u32 rx_stat_grbyt_hi;
u32 rx_stat_grund_lo;
u32 rx_stat_grund_hi;
u32 rx_stat_grfrg_lo;
u32 rx_stat_grfrg_hi;
u32 rx_stat_grerb_lo; /* grerrbyt */
u32 rx_stat_grerb_hi; /* grerrbyt */
u32 rx_stat_grfre_lo; /* grfrerr */
u32 rx_stat_grfre_hi; /* grfrerr */
u32 rx_stat_gripj_lo;
u32 rx_stat_gripj_hi;
};
union mac_stats {
struct emac_stats emac_stats;
struct bmac1_stats bmac1_stats;
struct emac_stats emac_stats;
struct bmac1_stats bmac1_stats;
struct bmac2_stats bmac2_stats;
};
......@@ -1593,6 +1736,24 @@ union igu_consprod_reg {
};
/*
* Control register for the IGU command register
*/
struct igu_ctrl_reg {
u32 ctrl_data;
#define IGU_CTRL_REG_ADDRESS (0xFFF<<0)
#define IGU_CTRL_REG_ADDRESS_SHIFT 0
#define IGU_CTRL_REG_FID (0x7F<<12)
#define IGU_CTRL_REG_FID_SHIFT 12
#define IGU_CTRL_REG_RESERVED (0x1<<19)
#define IGU_CTRL_REG_RESERVED_SHIFT 19
#define IGU_CTRL_REG_TYPE (0x1<<20)
#define IGU_CTRL_REG_TYPE_SHIFT 20
#define IGU_CTRL_REG_UNUSED (0x7FF<<21)
#define IGU_CTRL_REG_UNUSED_SHIFT 21
};
/*
* Parser parsing flags field
*/
......@@ -1923,6 +2084,27 @@ struct eth_tx_parse_bd_e1x {
__le32 tcp_send_seq;
};
/*
* Tx parsing BD structure for ETH E2
*/
struct eth_tx_parse_bd_e2 {
__le16 dst_mac_addr_lo;
__le16 dst_mac_addr_mid;
__le16 dst_mac_addr_hi;
__le16 src_mac_addr_lo;
__le16 src_mac_addr_mid;
__le16 src_mac_addr_hi;
__le32 parsing_data;
#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x1FFF<<0)
#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0
#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<13)
#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 13
#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<17)
#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 17
#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<31)
#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 31
};
/*
* The last BD in the BD memory will hold a pointer to the next BD memory
*/
......@@ -1939,6 +2121,7 @@ union eth_tx_bd_types {
struct eth_tx_start_bd start_bd;
struct eth_tx_bd reg_bd;
struct eth_tx_parse_bd_e1x parse_bd_e1x;
struct eth_tx_parse_bd_e2 parse_bd_e2;
struct eth_tx_next_bd next_bd;
};
......
......@@ -97,6 +97,9 @@
#define MISC_AEU_BLOCK 35
#define PGLUE_B_BLOCK 36
#define IGU_BLOCK 37
#define ATC_BLOCK 38
#define QM_4PORT_BLOCK 39
#define XSEM_4PORT_BLOCK 40
/* Returns the index of start or end of a specific block stage in ops array*/
......
......@@ -486,18 +486,30 @@ static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);
if (r_order == MAX_RD_ORD)
if ((CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) && (r_order == MAX_RD_ORD))
REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
if (CHIP_IS_E2(bp))
REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order));
else
REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
if (CHIP_IS_E1H(bp)) {
if (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp)) {
/* MPS w_order optimal TH presently TH
* 128 0 0 2
* 256 1 1 3
* >=512 2 2 3
*/
val = ((w_order == 0) ? 2 : 3);
/* DMAE is special */
if (CHIP_IS_E2(bp)) {
/* E2 can use optimal TH */
val = w_order;
REG_WR(bp, PXP2_REG_WR_DMAE_MPS, val);
} else {
val = ((w_order == 0) ? 2 : 3);
REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2);
}
REG_WR(bp, PXP2_REG_WR_HC_MPS, val);
REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);
REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val);
......@@ -507,9 +519,15 @@ static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
REG_WR(bp, PXP2_REG_WR_TM_MPS, val);
REG_WR(bp, PXP2_REG_WR_SRC_MPS, val);
REG_WR(bp, PXP2_REG_WR_DBG_MPS, val);
REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */
REG_WR(bp, PXP2_REG_WR_CDU_MPS, val);
}
/* Validate number of tags suppoted by device */
#define PCIE_REG_PCIER_TL_HDR_FC_ST 0x2980
val = REG_RD(bp, PCIE_REG_PCIER_TL_HDR_FC_ST);
val &= 0xFF;
if (val <= 0x20)
REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x20);
}
/****************************************************************************
......
......@@ -377,9 +377,60 @@ static u8 bnx2x_emac_enable(struct link_params *params,
return 0;
}
static void bnx2x_update_bmac2(struct link_params *params,
struct link_vars *vars,
u8 is_lb)
{
/*
* Set rx control: Strip CRC and enable BigMAC to relay
* control packets to the system as well
*/
u32 wb_data[2];
struct bnx2x *bp = params->bp;
u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
NIG_REG_INGRESS_BMAC0_MEM;
u32 val = 0x14;
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
/* Enable BigMAC to react on received Pause packets */
val |= (1<<5);
wb_data[0] = val;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL,
wb_data, 2);
udelay(30);
static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
/* Tx control */
val = 0xc0;
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
val |= 0x800000;
wb_data[0] = val;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL,
wb_data, 2);
val = 0x8000;
wb_data[0] = val;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
wb_data, 2);
/* mac control */
val = 0x3; /* Enable RX and TX */
if (is_lb) {
val |= 0x4; /* Local loopback */
DP(NETIF_MSG_LINK, "enable bmac loopback\n");
}
wb_data[0] = val;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL,
wb_data, 2);
}
static u8 bnx2x_bmac1_enable(struct link_params *params,
struct link_vars *vars,
u8 is_lb)
{
struct bnx2x *bp = params->bp;
......@@ -389,17 +440,7 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
u32 wb_data[2];
u32 val;
DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
/* reset and unreset the BigMac */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
msleep(1);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
/* enable access for bmac registers */
REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
DP(NETIF_MSG_LINK, "Enabling BigMAC1\n");
/* XGXS control */
wb_data[0] = 0x3c;
......@@ -479,6 +520,103 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
wb_data, 2);
}
return 0;
}
static u8 bnx2x_bmac2_enable(struct link_params *params,
struct link_vars *vars,
u8 is_lb)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
NIG_REG_INGRESS_BMAC0_MEM;
u32 wb_data[2];
DP(NETIF_MSG_LINK, "Enabling BigMAC2\n");
wb_data[0] = 0;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL,
wb_data, 2);
udelay(30);
/* XGXS control: Reset phy HW, MDIO registers, PHY PLL and BMAC */
wb_data[0] = 0x3c;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr +
BIGMAC2_REGISTER_BMAC_XGXS_CONTROL,
wb_data, 2);
udelay(30);
/* tx MAC SA */
wb_data[0] = ((params->mac_addr[2] << 24) |
(params->mac_addr[3] << 16) |
(params->mac_addr[4] << 8) |
params->mac_addr[5]);
wb_data[1] = ((params->mac_addr[0] << 8) |
params->mac_addr[1]);
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_SOURCE_ADDR,
wb_data, 2);
udelay(30);
/* Configure SAFC */
wb_data[0] = 0x1000200;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS,
wb_data, 2);
udelay(30);
/* set rx mtu */
wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE,
wb_data, 2);
udelay(30);
/* set tx mtu */
wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE,
wb_data, 2);
udelay(30);
/* set cnt max size */
wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD - 2;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE,
wb_data, 2);
udelay(30);
bnx2x_update_bmac2(params, vars, is_lb);
return 0;
}
u8 bnx2x_bmac_enable(struct link_params *params,
struct link_vars *vars,
u8 is_lb)
{
u8 rc, port = params->port;
struct bnx2x *bp = params->bp;
u32 val;
/* reset and unreset the BigMac */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
udelay(10);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
/* enable access for bmac registers */
REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
/* Enable BMAC according to BMAC type*/
if (CHIP_IS_E2(bp))
rc = bnx2x_bmac2_enable(params, vars, is_lb);
else
rc = bnx2x_bmac1_enable(params, vars, is_lb);
REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
......@@ -493,7 +631,7 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
vars->mac_type = MAC_TYPE_BMAC;
return 0;
return rc;
}
......@@ -519,13 +657,25 @@ static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
nig_bmac_enable) {
/* Clear Rx Enable bit in BMAC_CONTROL register */
REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
wb_data, 2);
wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
wb_data, 2);
if (CHIP_IS_E2(bp)) {
/* Clear Rx Enable bit in BMAC_CONTROL register */
REG_RD_DMAE(bp, bmac_addr +
BIGMAC2_REGISTER_BMAC_CONTROL,
wb_data, 2);
wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
REG_WR_DMAE(bp, bmac_addr +
BIGMAC2_REGISTER_BMAC_CONTROL,
wb_data, 2);
} else {
/* Clear Rx Enable bit in BMAC_CONTROL register */
REG_RD_DMAE(bp, bmac_addr +
BIGMAC_REGISTER_BMAC_CONTROL,
wb_data, 2);
wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
REG_WR_DMAE(bp, bmac_addr +
BIGMAC_REGISTER_BMAC_CONTROL,
wb_data, 2);
}
msleep(1);
}
}
......@@ -821,23 +971,31 @@ u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
return -EINVAL;
}
static void bnx2x_set_aer_mmd(struct link_params *params,
struct bnx2x_phy *phy)
static void bnx2x_set_aer_mmd_xgxs(struct link_params *params,
struct bnx2x_phy *phy)
{
struct bnx2x *bp = params->bp;
u32 ser_lane;
u16 offset;
u16 offset, aer_val;
struct bnx2x *bp = params->bp;
ser_lane = ((params->lane_config &
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
offset = (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ?
(phy->addr + ser_lane) : 0;
offset = phy->addr + ser_lane;
if (CHIP_IS_E2(bp))
aer_val = 0x2800 + offset - 1;
else
aer_val = 0x3800 + offset;
CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_AER_BLOCK,
MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
MDIO_REG_BANK_AER_BLOCK,
MDIO_AER_BLOCK_AER_REG, aer_val);
}
static void bnx2x_set_aer_mmd_serdes(struct bnx2x *bp,
struct bnx2x_phy *phy)
{
CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_AER_BLOCK,
MDIO_AER_BLOCK_AER_REG, 0x3800);
}
/******************************************************************/
......@@ -2046,12 +2204,12 @@ static u8 bnx2x_init_serdes(struct bnx2x_phy *phy,
u8 rc;
vars->phy_flags |= PHY_SGMII_FLAG;
bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
bnx2x_set_aer_mmd(params, phy);
bnx2x_set_aer_mmd_serdes(params->bp, phy);
rc = bnx2x_reset_unicore(params, phy, 1);
/* reset the SerDes and wait for reset bit return low */
if (rc != 0)
return rc;
bnx2x_set_aer_mmd(params, phy);
bnx2x_set_aer_mmd_serdes(params->bp, phy);
return rc;
}
......@@ -2076,7 +2234,7 @@ static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
vars->phy_flags &= ~PHY_SGMII_FLAG;
bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
bnx2x_set_aer_mmd(params, phy);
bnx2x_set_aer_mmd_xgxs(params, phy);
bnx2x_set_master_ln(params, phy);
rc = bnx2x_reset_unicore(params, phy, 0);
......@@ -2084,7 +2242,7 @@ static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
if (rc != 0)
return rc;
bnx2x_set_aer_mmd(params, phy);
bnx2x_set_aer_mmd_xgxs(params, phy);
/* setting the masterLn_def again after the reset */
bnx2x_set_master_ln(params, phy);
......@@ -2358,7 +2516,7 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
0x6041);
msleep(200);
/* set aer mmd back */
bnx2x_set_aer_mmd(params, phy);
bnx2x_set_aer_mmd_xgxs(params, phy);
/* and md_devad */
REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
......@@ -2721,7 +2879,10 @@ static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp;
u8 gpio_port;
/* HW reset */
gpio_port = params->port;
if (CHIP_IS_E2(bp))
gpio_port = BP_PATH(bp);
else
gpio_port = params->port;
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
MISC_REGISTERS_GPIO_OUTPUT_LOW,
gpio_port);
......@@ -2799,8 +2960,9 @@ static u8 bnx2x_update_link_up(struct link_params *params,
}
/* PBF - link up */
rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
vars->line_speed);
if (!(CHIP_IS_E2(bp)))
rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
vars->line_speed);
/* disable drain */
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
......@@ -3443,7 +3605,10 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
u8 gpio_port;
DP(NETIF_MSG_LINK, "Init 8073\n");
gpio_port = params->port;
if (CHIP_IS_E2(bp))
gpio_port = BP_PATH(bp);
else
gpio_port = params->port;
/* Restore normal power mode*/
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
......@@ -3680,7 +3845,10 @@ static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
{
struct bnx2x *bp = params->bp;
u8 gpio_port;
gpio_port = params->port;
if (CHIP_IS_E2(bp))
gpio_port = BP_PATH(bp);
else
gpio_port = params->port;
DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n",
gpio_port);
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
......@@ -6371,7 +6539,10 @@ static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
phy->mdio_ctrl = bnx2x_get_emac_base(bp,
SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH,
port);
phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
if (CHIP_IS_E2(bp))
phy->def_md_devad = E2_DEFAULT_PHY_DEV_ADDR;
else
phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
DP(NETIF_MSG_LINK, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x\n",
port, phy->addr, phy->mdio_ctrl);
......@@ -6742,7 +6913,9 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
}
bnx2x_emac_enable(params, vars, 0);
bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
if (!(CHIP_IS_E2(bp)))
bnx2x_pbf_update(params, vars->flow_ctrl,
vars->line_speed);
/* disable drain */
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
......@@ -6932,18 +7105,34 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
/****************************************************************************/
/* Common function */
/****************************************************************************/
static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base, u8 phy_index)
static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
u32 shmem_base_path[],
u32 shmem2_base_path[], u8 phy_index,
u32 chip_id)
{
struct bnx2x_phy phy[PORT_MAX];
struct bnx2x_phy *phy_blk[PORT_MAX];
u16 val;
s8 port;
s8 port_of_path = 0;
/* PART1 - Reset both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
u32 shmem_base, shmem2_base;
/* In E2, same phy is using for port0 of the two paths */
if (CHIP_IS_E2(bp)) {
shmem_base = shmem_base_path[port];
shmem2_base = shmem2_base_path[port];
port_of_path = 0;
} else {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
port_of_path = port;
}
/* Extract the ext phy address for the port */
if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
port, &phy[port]) !=
port_of_path, &phy[port]) !=
0) {
DP(NETIF_MSG_LINK, "populate_phy failed\n");
return -EINVAL;
......@@ -6981,9 +7170,15 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem
/* PART2 - Download firmware to both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
u16 fw_ver1;
if (CHIP_IS_E2(bp))
port_of_path = 0;
else
port_of_path = port;
DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
phy_blk[port]->addr);
bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
port);
port_of_path);
bnx2x_cl45_read(bp, phy_blk[port],
MDIO_PMA_DEVAD,
......@@ -7039,9 +7234,10 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem
}
return 0;
}
static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base, u8 phy_index)
static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp,
u32 shmem_base_path[],
u32 shmem2_base_path[], u8 phy_index,
u32 chip_id)
{
u32 val;
s8 port;
......@@ -7056,6 +7252,16 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base,
bnx2x_ext_phy_hw_reset(bp, 1);
msleep(5);
for (port = 0; port < PORT_MAX; port++) {
u32 shmem_base, shmem2_base;
/* In E2, same phy is using for port0 of the two paths */
if (CHIP_IS_E2(bp)) {
shmem_base = shmem_base_path[port];
shmem2_base = shmem2_base_path[port];
} else {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
}
/* Extract the ext phy address for the port */
if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
port, &phy) !=
......@@ -7077,14 +7283,16 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base,
return 0;
}
static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base, u8 phy_index)
static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
u32 shmem_base_path[],
u32 shmem2_base_path[], u8 phy_index,
u32 chip_id)
{
s8 port;
u32 swap_val, swap_override;
struct bnx2x_phy phy[PORT_MAX];
struct bnx2x_phy *phy_blk[PORT_MAX];
DP(NETIF_MSG_LINK, "Executing BCM8727 common init\n");
s8 port_of_path;
swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
......@@ -7099,19 +7307,33 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base,
/* PART1 - Reset both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
u32 shmem_base, shmem2_base;
/* In E2, same phy is using for port0 of the two paths */
if (CHIP_IS_E2(bp)) {
shmem_base = shmem_base_path[port];
shmem2_base = shmem2_base_path[port];
port_of_path = 0;
} else {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
port_of_path = port;
}
/* Extract the ext phy address for the port */
if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
port, &phy[port]) !=
port_of_path, &phy[port]) !=
0) {
DP(NETIF_MSG_LINK, "populate phy failed\n");
return -EINVAL;
}
/* disable attentions */
bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
(NIG_MASK_XGXS0_LINK_STATUS |
NIG_MASK_XGXS0_LINK10G |
NIG_MASK_SERDES0_LINK_STATUS |
NIG_MASK_MI_INT));
bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 +
port_of_path*4,
(NIG_MASK_XGXS0_LINK_STATUS |
NIG_MASK_XGXS0_LINK10G |
NIG_MASK_SERDES0_LINK_STATUS |
NIG_MASK_MI_INT));
/* Reset the phy */
......@@ -7133,9 +7355,14 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base,
/* PART2 - Download firmware to both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
u16 fw_ver1;
if (CHIP_IS_E2(bp))
port_of_path = 0;
else
port_of_path = port;
DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
phy_blk[port]->addr);
bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
port);
port_of_path);
bnx2x_cl45_read(bp, phy_blk[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER1, &fw_ver1);
......@@ -7151,29 +7378,32 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base,
return 0;
}
static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base, u8 phy_index,
u32 ext_phy_type)
static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
u32 shmem2_base_path[], u8 phy_index,
u32 ext_phy_type, u32 chip_id)
{
u8 rc = 0;
switch (ext_phy_type) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
rc = bnx2x_8073_common_init_phy(bp, shmem_base,
shmem2_base, phy_index);
rc = bnx2x_8073_common_init_phy(bp, shmem_base_path,
shmem2_base_path,
phy_index, chip_id);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
rc = bnx2x_8727_common_init_phy(bp, shmem_base,
shmem2_base, phy_index);
rc = bnx2x_8727_common_init_phy(bp, shmem_base_path,
shmem2_base_path,
phy_index, chip_id);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
/* GPIO1 affects both ports, so there's need to pull
it for single port alone */
rc = bnx2x_8726_common_init_phy(bp, shmem_base,
shmem2_base, phy_index);
rc = bnx2x_8726_common_init_phy(bp, shmem_base_path,
shmem2_base_path,
phy_index, chip_id);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
rc = -EINVAL;
......@@ -7188,8 +7418,8 @@ static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base,
return rc;
}
u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base)
u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
u32 shmem2_base_path[], u32 chip_id)
{
u8 rc = 0;
u8 phy_index;
......@@ -7203,12 +7433,13 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base,
for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
phy_index++) {
ext_phy_config = bnx2x_get_ext_phy_config(bp,
shmem_base,
shmem_base_path[0],
phy_index, 0);
ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
rc |= bnx2x_ext_phy_common_init(bp, shmem_base,
shmem2_base,
phy_index, ext_phy_type);
rc |= bnx2x_ext_phy_common_init(bp, shmem_base_path,
shmem2_base_path,
phy_index, ext_phy_type,
chip_id);
}
return rc;
}
......
......@@ -22,7 +22,8 @@
/***********************************************************/
/* Defines */
/***********************************************************/
#define DEFAULT_PHY_DEV_ADDR 3
#define DEFAULT_PHY_DEV_ADDR 3
#define E2_DEFAULT_PHY_DEV_ADDR 5
......@@ -315,7 +316,8 @@ u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars,
u8 is_serdes);
/* One-time initialization for external phy after power up */
u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base);
u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
u32 shmem2_base_path[], u32 chip_id);
/* Reset the external PHY using GPIO */
void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -33,7 +33,8 @@ fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \
fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin
fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw
fw-shipped-$(CONFIG_BNX2X) += bnx2x/bnx2x-e1-6.0.34.0.fw \
bnx2x/bnx2x-e1h-6.0.34.0.fw
bnx2x/bnx2x-e1h-6.0.34.0.fw \
bnx2x/bnx2x-e2-6.0.34.0.fw
fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-5.0.0.j15.fw \
bnx2/bnx2-rv2p-09-5.0.0.j10.fw \
bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册