Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2e0899f authored by Dmitry Kravkov's avatar Dmitry Kravkov Committed by David S. Miller
Browse files

bnx2x: Add 57712 support



57712 HW supported with same set of features as for 57710/57711

Signed-off-by: default avatarDmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8fe23fbd
Loading
Loading
Loading
Loading
+105 −19
Original line number Diff line number Diff line
@@ -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
+181 −94
Original line number Diff line number Diff line
@@ -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,7 +743,8 @@ void bnx2x_link_report(struct bnx2x *bp)
			u16 vn_max_rate;

			vn_max_rate =
				((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >>
				((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,6 +907,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
		if (j != 0)
			continue;

		if (!CHIP_IS_E2(bp)) {
			REG_WR(bp, BAR_USTRORM_INTMEM +
			       USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
			       U64_LO(fp->rx_comp_mapping));
@@ -919,7 +915,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
			       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,8 +1390,8 @@ 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) {
	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;
	}
@@ -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;
	}

	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 = (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 (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();
+133 −4
Original line number Diff line number Diff line
@@ -366,9 +366,76 @@ 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_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;

static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
	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 +
@@ -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)
{
+32 −3
Original line number Diff line number Diff line
@@ -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 */
+96 −27

File changed.

Preview size limit exceeded, changes collapsed.

Loading