summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/bnx2x/bnx2x.h9
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.c9
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.h5
-rw-r--r--drivers/net/bnx2x/bnx2x_dcb.c171
-rw-r--r--drivers/net/bnx2x/bnx2x_ethtool.c2
-rw-r--r--drivers/net/bnx2x/bnx2x_hsi.h1
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c123
-rw-r--r--drivers/net/bnx2x/bnx2x_sp.c178
-rw-r--r--drivers/net/bnx2x/bnx2x_sp.h14
-rw-r--r--drivers/net/r8169.c8
10 files changed, 368 insertions, 152 deletions
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 53fa8ea983e9..4b255e5f8f16 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -966,6 +966,8 @@ struct bnx2x_slowpath {
union {
struct function_start_data func_start;
+ /* pfc configuration for DCBX ramrod */
+ struct flow_control_configuration pfc_config;
} func_rdata;
/* used by dmae command executer */
@@ -980,8 +982,6 @@ struct bnx2x_slowpath {
u32 wb_comp;
u32 wb_data[4];
- /* pfc configuration for DCBX ramrod */
- struct flow_control_configuration pfc_config;
};
#define bnx2x_sp(bp, var) (&bp->slowpath->var)
@@ -1104,7 +1104,7 @@ struct bnx2x {
#define BP_VN(bp) (BP_E1HVN(bp)) /*remove when approved*/
#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))
+ BP_VN(bp) * ((CHIP_IS_E1x(bp) || (CHIP_MODE_IS_4_PORT(bp))) ? 2 : 1))
struct net_device *dev;
struct pci_dev *pdev;
@@ -1417,9 +1417,6 @@ struct bnx2x {
char fw_ver[32];
const struct firmware *firmware;
- /* LLDP params */
- struct bnx2x_config_lldp_params lldp_config_params;
-
/* DCB support on/off */
u16 dcb_state;
#define BNX2X_DCB_STATE_OFF 0
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index b05ce9306dea..8b079dcd5b96 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -676,7 +676,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
/* non TPA */
len = le16_to_cpu(cqe_fp->pkt_len);
pad = cqe_fp->placement_offset;
- dma_sync_single_for_device(&bp->pdev->dev,
+ dma_sync_single_for_cpu(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
pad + RX_COPY_THRESH,
DMA_FROM_DEVICE);
@@ -1828,6 +1828,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = bnx2x_func_start(bp);
if (rc) {
BNX2X_ERR("Function start failed!\n");
+ bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
LOAD_ERROR_EXIT(bp, load_error3);
}
@@ -1988,6 +1989,9 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
return -EINVAL;
}
+ /* Stop Tx */
+ bnx2x_tx_disable(bp);
+
#ifdef BCM_CNIC
bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
#endif
@@ -1996,9 +2000,6 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bp->rx_mode = BNX2X_RX_MODE_NONE;
- /* Stop Tx */
- bnx2x_tx_disable(bp);
-
del_timer_sync(&bp->timer);
/* Set ALWAYS_ALIVE bit in shmem */
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h
index 595d4cdada3e..83d7d1bb7b12 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/bnx2x/bnx2x_cmn.h
@@ -936,16 +936,11 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp,
u16 cons, u16 prod)
{
- struct bnx2x *bp = fp->bp;
struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod];
struct eth_rx_bd *cons_bd = &fp->rx_desc_ring[cons];
struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod];
- dma_sync_single_for_device(&bp->pdev->dev,
- dma_unmap_addr(cons_rx_buf, mapping),
- RX_COPY_THRESH, DMA_FROM_DEVICE);
-
dma_unmap_addr_set(prod_rx_buf, mapping,
dma_unmap_addr(cons_rx_buf, mapping));
prod_rx_buf->skb = cons_rx_buf->skb;
diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c
index 3bfba44961d3..d028794a2298 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/bnx2x/bnx2x_dcb.c
@@ -29,10 +29,10 @@
#endif
/* forward declarations of dcbx related functions */
-static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
+static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
-static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
+static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
u32 *set_configuration_ets_pg,
u32 *pri_pg_tbl);
@@ -47,8 +47,25 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
struct cos_help_data *cos_data,
u32 *pg_pri_orginal_spread,
struct dcbx_ets_feature *ets);
-static void bnx2x_dcbx_fw_struct(struct bnx2x *bp);
+static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
+ struct bnx2x_func_tx_start_params*);
+/* helpers: read/write len bytes from addr into buff by REG_RD/REG_WR */
+static void bnx2x_read_data(struct bnx2x *bp, u32 *buff,
+ u32 addr, u32 len)
+{
+ int i;
+ for (i = 0; i < len; i += 4, buff++)
+ *buff = REG_RD(bp, addr + i);
+}
+
+static void bnx2x_write_data(struct bnx2x *bp, u32 *buff,
+ u32 addr, u32 len)
+{
+ int i;
+ for (i = 0; i < len; i += 4, buff++)
+ REG_WR(bp, addr + i, *buff);
+}
static void bnx2x_pfc_set(struct bnx2x *bp)
{
@@ -205,7 +222,11 @@ static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n");
- if (app->enabled && !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) {
+ if (GET_FLAGS(error, DCBX_LOCAL_APP_MISMATCH))
+ DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_MISMATCH\n");
+
+ if (app->enabled &&
+ !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR | DCBX_LOCAL_APP_MISMATCH)) {
bp->dcbx_port_params.app.enabled = true;
@@ -300,7 +321,7 @@ static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n");
if (bp->dcbx_port_params.app.enabled &&
- !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR) &&
+ !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR | DCBX_LOCAL_PFC_MISMATCH) &&
pfc->enabled) {
bp->dcbx_port_params.pfc.enabled = true;
bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
@@ -329,8 +350,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
u32 offset,
int read_mib_type)
{
- int max_try_read = 0, i;
- u32 *buff, mib_size, prefix_seq_num, suffix_seq_num;
+ int max_try_read = 0;
+ u32 mib_size, prefix_seq_num, suffix_seq_num;
struct lldp_remote_mib *remote_mib ;
struct lldp_local_mib *local_mib;
@@ -349,9 +370,7 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
offset += BP_PORT(bp) * mib_size;
do {
- buff = base_mib_addr;
- for (i = 0; i < mib_size; i += 4, buff++)
- *buff = REG_RD(bp, offset + i);
+ bnx2x_read_data(bp, base_mib_addr, offset, mib_size);
max_try_read++;
@@ -382,12 +401,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
{
- if (BP_PORT(bp)) {
- BNX2X_ERR("4 port mode is not supported");
- return;
- }
-
- if (bp->dcbx_port_params.pfc.enabled)
+ if (bp->dcbx_port_params.pfc.enabled &&
+ !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
/*
* 1. Fills up common PFC structures if required
* 2. Configure NIG, MAC and BRB via the elink
@@ -397,25 +412,30 @@ static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
bnx2x_pfc_clear(bp);
}
-static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
+static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
{
- DP(NETIF_MSG_LINK, "sending STOP TRAFFIC\n");
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
- 0 /* connectionless */,
- 0 /* dataHi is zero */,
- 0 /* dataLo is zero */,
- NONE_CONNECTION_TYPE);
+ struct bnx2x_func_state_params func_params = {0};
+
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_TX_STOP;
+
+ DP(NETIF_MSG_LINK, "STOP TRAFFIC\n");
+ return bnx2x_func_state_change(bp, &func_params);
}
-static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
+static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
{
- bnx2x_dcbx_fw_struct(bp);
- DP(NETIF_MSG_LINK, "sending START TRAFFIC\n");
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC,
- 0, /* connectionless */
- U64_HI(bnx2x_sp_mapping(bp, pfc_config)),
- U64_LO(bnx2x_sp_mapping(bp, pfc_config)),
- NONE_CONNECTION_TYPE);
+ struct bnx2x_func_state_params func_params = {0};
+ struct bnx2x_func_tx_start_params *tx_params =
+ &func_params.params.tx_start;
+
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_TX_START;
+
+ bnx2x_dcbx_fw_struct(bp, tx_params);
+
+ DP(NETIF_MSG_LINK, "START TRAFFIC\n");
+ return bnx2x_func_state_change(bp, &func_params);
}
static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
@@ -522,7 +542,8 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
{
bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
- if (!bp->dcbx_port_params.ets.enabled)
+ if (!bp->dcbx_port_params.ets.enabled ||
+ (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
return;
if (CHIP_IS_E3B0(bp))
@@ -739,61 +760,14 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
}
}
-
-#define LLDP_STATS_OFFSET(bp) (BP_PORT(bp)*\
- sizeof(struct lldp_dcbx_stat))
-
-/* calculate struct offset in array according to chip information */
-#define LLDP_PARAMS_OFFSET(bp) (BP_PORT(bp)*sizeof(struct lldp_params))
-
#define LLDP_ADMIN_MIB_OFFSET(bp) (PORT_MAX*sizeof(struct lldp_params) + \
BP_PORT(bp)*sizeof(struct lldp_admin_mib))
-static void bnx2x_dcbx_lldp_updated_params(struct bnx2x *bp,
- u32 dcbx_lldp_params_offset)
-{
- struct lldp_params lldp_params = {0};
- u32 i = 0, *buff = NULL;
- u32 offset = dcbx_lldp_params_offset + LLDP_PARAMS_OFFSET(bp);
-
- DP(NETIF_MSG_LINK, "lldp_offset 0x%x\n", offset);
-
- if ((bp->lldp_config_params.overwrite_settings ==
- BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE)) {
- /* Read the data first */
- buff = (u32 *)&lldp_params;
- for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
- *buff = REG_RD(bp, (offset + i));
-
- lldp_params.msg_tx_hold =
- (u8)bp->lldp_config_params.msg_tx_hold;
- lldp_params.msg_fast_tx_interval =
- (u8)bp->lldp_config_params.msg_fast_tx;
- lldp_params.tx_crd_max =
- (u8)bp->lldp_config_params.tx_credit_max;
- lldp_params.msg_tx_interval =
- (u8)bp->lldp_config_params.msg_tx_interval;
- lldp_params.tx_fast =
- (u8)bp->lldp_config_params.tx_fast;
-
- /* Write the data.*/
- buff = (u32 *)&lldp_params;
- for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
- REG_WR(bp, (offset + i) , *buff);
-
-
- } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
- bp->lldp_config_params.overwrite_settings)
- bp->lldp_config_params.overwrite_settings =
- BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
-}
-
static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
u32 dcbx_lldp_params_offset)
{
struct lldp_admin_mib admin_mib;
u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
- u32 *buff;
u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
/*shortcuts*/
@@ -801,18 +775,18 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
- buff = (u32 *)&admin_mib;
+
/* Read the data first */
- for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
- *buff = REG_RD(bp, (offset + i));
+ bnx2x_read_data(bp, (u32 *)&admin_mib, offset,
+ sizeof(struct lldp_admin_mib));
if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
else
RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
- if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
- dp->overwrite_settings)) {
+ if (dp->overwrite_settings == BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE) {
+
RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
admin_mib.ver_cfg_flags |=
(dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
@@ -908,19 +882,17 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
af->app.default_pri = (u8)dp->admin_default_priority;
- } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
- dp->overwrite_settings)
- dp->overwrite_settings = BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
+ }
/* Write the data. */
- buff = (u32 *)&admin_mib;
- for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
- REG_WR(bp, (offset + i), *buff);
+ bnx2x_write_data(bp, (u32 *)&admin_mib, offset,
+ sizeof(struct lldp_admin_mib));
+
}
void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
{
- if (!CHIP_IS_E1x(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
+ if (!CHIP_IS_E1x(bp)) {
bp->dcb_state = dcb_on;
bp->dcbx_enabled = dcbx_enabled;
} else {
@@ -1029,9 +1001,6 @@ void bnx2x_dcbx_init(struct bnx2x *bp)
bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 0);
if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
- bnx2x_dcbx_lldp_updated_params(bp,
- dcbx_lldp_params_offset);
-
bnx2x_dcbx_admin_mib_updated_params(bp,
dcbx_lldp_params_offset);
@@ -1043,7 +1012,7 @@ void bnx2x_dcbx_init(struct bnx2x *bp)
}
static void
bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
- struct flow_control_configuration *pfc_fw_cfg)
+ struct bnx2x_func_tx_start_params *pfc_fw_cfg)
{
u8 pri = 0;
u8 cos = 0;
@@ -1821,17 +1790,19 @@ static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
}
}
-static void bnx2x_dcbx_fw_struct(struct bnx2x *bp)
+static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
+ struct bnx2x_func_tx_start_params *pfc_fw_cfg)
{
- struct flow_control_configuration *pfc_fw_cfg = NULL;
u16 pri_bit = 0;
u8 cos = 0, pri = 0;
struct priority_cos *tt2cos;
u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
- pfc_fw_cfg = (struct flow_control_configuration *)
- bnx2x_sp(bp, pfc_config);
- memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration));
+ memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg));
+
+ /* to disable DCB - the structure must be zeroed */
+ if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)
+ return;
/*shortcut*/
tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index ac0223135b7c..eda0f7b82c54 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -1752,7 +1752,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
goto test_loopback_rx_exit;
rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)];
- dma_sync_single_for_device(&bp->pdev->dev,
+ dma_sync_single_for_cpu(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
fp_rx->rx_buf_size, DMA_FROM_DEVICE);
skb = rx_buf->skb;
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h
index ce3b5662ca5a..06727f32e505 100644
--- a/drivers/net/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/bnx2x/bnx2x_hsi.h
@@ -1834,6 +1834,7 @@ struct lldp_local_mib {
#define DCBX_LOCAL_APP_ERROR 0x00000004
#define DCBX_LOCAL_PFC_MISMATCH 0x00000010
#define DCBX_LOCAL_APP_MISMATCH 0x00000020
+ #define DCBX_REMOTE_MIB_ERROR 0x00000040
struct dcbx_features features;
u32 suffix_seq_num;
};
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 8a374a77cdc9..28ef7faf4480 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -2699,8 +2699,10 @@ static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
if (IS_FCOE_FP(fp))
__set_bit(BNX2X_Q_FLG_FCOE, &flags);
- if (!fp->disable_tpa)
+ if (!fp->disable_tpa) {
__set_bit(BNX2X_Q_FLG_TPA, &flags);
+ __set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags);
+ }
if (leading) {
__set_bit(BNX2X_Q_FLG_LEADING_RSS, &flags);
@@ -2982,8 +2984,12 @@ static inline void bnx2x_sp_prod_update(struct bnx2x *bp)
{
int func = BP_FUNC(bp);
- /* Make sure that BD data is updated before writing the producer */
- wmb();
+ /*
+ * Make sure that BD data is updated before writing the producer:
+ * BD data is written to the memory, the producer is read from the
+ * memory, thus we need a full memory barrier to ensure the ordering.
+ */
+ mb();
REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
bp->spq_prod_idx);
@@ -4403,11 +4409,17 @@ static void bnx2x_eq_int(struct bnx2x *bp)
case EVENT_RING_OPCODE_STOP_TRAFFIC:
DP(NETIF_MSG_IFUP, "got STOP TRAFFIC\n");
+ if (f_obj->complete_cmd(bp, f_obj,
+ BNX2X_F_CMD_TX_STOP))
+ break;
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED);
goto next_spqe;
case EVENT_RING_OPCODE_START_TRAFFIC:
DP(NETIF_MSG_IFUP, "got START TRAFFIC\n");
+ if (f_obj->complete_cmd(bp, f_obj,
+ BNX2X_F_CMD_TX_START))
+ break;
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
goto next_spqe;
case EVENT_RING_OPCODE_FUNCTION_START:
@@ -4514,8 +4526,15 @@ static void bnx2x_sp_task(struct work_struct *work)
struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
if ((!NO_FCOE(bp)) &&
- (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp)))
+ (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
+ /*
+ * Prevent local bottom-halves from running as
+ * we are going to change the local NAPI list.
+ */
+ local_bh_disable();
napi_schedule(&bnx2x_fcoe(bp, napi));
+ local_bh_enable();
+ }
#endif
/* Handle EQ completions */
bnx2x_eq_int(bp);
@@ -7536,6 +7555,71 @@ void bnx2x_send_unload_done(struct bnx2x *bp)
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
}
+static inline int bnx2x_func_wait_started(struct bnx2x *bp)
+{
+ int tout = 50;
+ int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
+
+ if (!bp->port.pmf)
+ return 0;
+
+ /*
+ * (assumption: No Attention from MCP at this stage)
+ * PMF probably in the middle of TXdisable/enable transaction
+ * 1. Sync IRS for default SB
+ * 2. Sync SP queue - this guarantes us that attention handling started
+ * 3. Wait, that TXdisable/enable transaction completes
+ *
+ * 1+2 guranty that if DCBx attention was scheduled it already changed
+ * pending bit of transaction from STARTED-->TX_STOPPED, if we alredy
+ * received complettion for the transaction the state is TX_STOPPED.
+ * State will return to STARTED after completion of TX_STOPPED-->STARTED
+ * transaction.
+ */
+
+ /* make sure default SB ISR is done */
+ if (msix)
+ synchronize_irq(bp->msix_table[0].vector);
+ else
+ synchronize_irq(bp->pdev->irq);
+
+ flush_workqueue(bnx2x_wq);
+
+ while (bnx2x_func_get_state(bp, &bp->func_obj) !=
+ BNX2X_F_STATE_STARTED && tout--)
+ msleep(20);
+
+ if (bnx2x_func_get_state(bp, &bp->func_obj) !=
+ BNX2X_F_STATE_STARTED) {
+#ifdef BNX2X_STOP_ON_ERROR
+ return -EBUSY;
+#else
+ /*
+ * Failed to complete the transaction in a "good way"
+ * Force both transactions with CLR bit
+ */
+ struct bnx2x_func_state_params func_params = {0};
+
+ DP(BNX2X_MSG_SP, "Hmmm... unexpected function state! "
+ "Forcing STARTED-->TX_ST0PPED-->STARTED\n");
+
+ func_params.f_obj = &bp->func_obj;
+ __set_bit(RAMROD_DRV_CLR_ONLY,
+ &func_params.ramrod_flags);
+
+ /* STARTED-->TX_ST0PPED */
+ func_params.cmd = BNX2X_F_CMD_TX_STOP;
+ bnx2x_func_state_change(bp, &func_params);
+
+ /* TX_ST0PPED-->STARTED */
+ func_params.cmd = BNX2X_F_CMD_TX_START;
+ return bnx2x_func_state_change(bp, &func_params);
+#endif
+ }
+
+ return 0;
+}
+
void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
{
int port = BP_PORT(bp);
@@ -7595,6 +7679,26 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
netif_addr_unlock_bh(bp->dev);
+
+ /*
+ * Send the UNLOAD_REQUEST to the MCP. This will return if
+ * this function should perform FUNC, PORT or COMMON HW
+ * reset.
+ */
+ reset_code = bnx2x_send_unload_req(bp, unload_mode);
+
+ /*
+ * (assumption: No Attention from MCP at this stage)
+ * PMF probably in the middle of TXdisable/enable transaction
+ */
+ rc = bnx2x_func_wait_started(bp);
+ if (rc) {
+ BNX2X_ERR("bnx2x_func_wait_started failed\n");
+#ifdef BNX2X_STOP_ON_ERROR
+ return;
+#endif
+ }
+
/* Close multi and leading connections
* Completions for ramrods are collected in a synchronous way
*/
@@ -7622,13 +7726,6 @@ unload_error:
#endif
}
- /*
- * Send the UNLOAD_REQUEST to the MCP. This will return if
- * this function should perform FUNC, PORT or COMMON HW
- * reset.
- */
- reset_code = bnx2x_send_unload_req(bp, unload_mode);
-
/* Disable HW interrupts, NAPI */
bnx2x_netif_stop(bp, 1);
@@ -10478,8 +10575,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
#ifdef BCM_CNIC
- /* disable FCOE L2 queue for E1x*/
- if (CHIP_IS_E1x(bp))
+ /* disable FCOE L2 queue for E1x and E3*/
+ if (CHIP_IS_E1x(bp) || CHIP_IS_E3(bp))
bp->flags |= NO_FCOE_FLAG;
#endif
diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c
index 358c33997536..cce87d5e7609 100644
--- a/drivers/net/bnx2x/bnx2x_sp.c
+++ b/drivers/net/bnx2x/bnx2x_sp.c
@@ -1563,8 +1563,13 @@ static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
idx++;
}
- /* Commit the data writes towards the memory */
- mb();
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid,
U64_HI(r->rdata_mapping),
@@ -2224,8 +2229,13 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
data->header.rule_cnt, p->rx_accept_flags,
p->tx_accept_flags);
- /* Commit writes towards the memory before sending a ramrod */
- mb();
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
/* Send a ramrod */
rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid,
@@ -2918,16 +2928,22 @@ static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
if (!o->total_pending_num)
bnx2x_mcast_refresh_registry_e2(bp, o);
- /* Commit writes towards the memory before sending a ramrod */
- mb();
-
- /* If CLEAR_ONLY was requested - don't send a ramrod and clear
+ /*
+ * If CLEAR_ONLY was requested - don't send a ramrod and clear
* RAMROD_PENDING status immediately.
*/
if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
raw->clear_pending(raw);
return 0;
} else {
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
/* Send a ramrod */
rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES,
raw->cid, U64_HI(raw->rdata_mapping),
@@ -3404,16 +3420,22 @@ static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
if (rc)
return rc;
- /* Commit writes towards the memory before sending a ramrod */
- mb();
-
- /* If CLEAR_ONLY was requested - don't send a ramrod and clear
+ /*
+ * If CLEAR_ONLY was requested - don't send a ramrod and clear
* RAMROD_PENDING status immediately.
*/
if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
raw->clear_pending(raw);
return 0;
} else {
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
/* Send a ramrod */
rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid,
U64_HI(raw->rdata_mapping),
@@ -4038,8 +4060,13 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
}
- /* Commit writes towards the memory before sending a ramrod */
- mb();
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
/* Send a ramrod */
rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid,
@@ -4240,7 +4267,7 @@ static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp,
/* Rx data */
/* IPv6 TPA supported for E2 and above only */
- data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA, &params->flags) *
+ data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, &params->flags) *
CLIENT_INIT_RX_DATA_TPA_EN_IPV6;
}
@@ -4505,7 +4532,13 @@ static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
/* Fill the ramrod data */
bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
- mb();
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
U64_HI(data_mapping),
@@ -4528,6 +4561,13 @@ static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
bnx2x_q_fill_setup_data_e2(bp, params, rdata);
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
U64_HI(data_mapping),
@@ -4665,7 +4705,13 @@ static inline int bnx2x_q_send_update(struct bnx2x *bp,
/* Fill the ramrod data */
bnx2x_q_fill_update_data(bp, o, update_params, rdata);
- mb();
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
o->cids[cid_index], U64_HI(data_mapping),
@@ -4874,6 +4920,22 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp,
&params->params.update;
u8 next_tx_only = o->num_tx_only;
+ /*
+ * Forget all pending for completion commands if a driver only state
+ * transition has been requested.
+ */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
+ o->pending = 0;
+ o->next_state = BNX2X_Q_STATE_MAX;
+ }
+
+ /*
+ * Don't allow a next state transition if we are in the middle of
+ * the previous one.
+ */
+ if (o->pending)
+ return -EBUSY;
+
switch (state) {
case BNX2X_Q_STATE_RESET:
if (cmd == BNX2X_Q_CMD_INIT)
@@ -5053,6 +5115,21 @@ void bnx2x_queue_set_cos_cid(struct bnx2x *bp,
}
/********************** Function state object *********************************/
+enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o)
+{
+ /* in the middle of transaction - return INVALID state */
+ if (o->pending)
+ return BNX2X_F_STATE_MAX;
+
+ /*
+ * unsure the order of reading of o->pending and o->state
+ * o->pending should be read first
+ */
+ rmb();
+
+ return o->state;
+}
static int bnx2x_func_wait_comp(struct bnx2x *bp,
struct bnx2x_func_sp_obj *o,
@@ -5143,6 +5220,22 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
enum bnx2x_func_cmd cmd = params->cmd;
+ /*
+ * Forget all pending for completion commands if a driver only state
+ * transition has been requested.
+ */
+ if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
+ o->pending = 0;
+ o->next_state = BNX2X_F_STATE_MAX;
+ }
+
+ /*
+ * Don't allow a next state transition if we are in the middle of
+ * the previous one.
+ */
+ if (o->pending)
+ return -EBUSY;
+
switch (state) {
case BNX2X_F_STATE_RESET:
if (cmd == BNX2X_F_CMD_HW_INIT)
@@ -5160,6 +5253,13 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
case BNX2X_F_STATE_STARTED:
if (cmd == BNX2X_F_CMD_STOP)
next_state = BNX2X_F_STATE_INITIALIZED;
+ else if (cmd == BNX2X_F_CMD_TX_STOP)
+ next_state = BNX2X_F_STATE_TX_STOPPED;
+
+ break;
+ case BNX2X_F_STATE_TX_STOPPED:
+ if (cmd == BNX2X_F_CMD_TX_START)
+ next_state = BNX2X_F_STATE_STARTED;
break;
default:
@@ -5430,7 +5530,13 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
rdata->path_id = BP_PATH(bp);
rdata->network_cos_mode = start_params->network_cos_mode;
- mb();
+ /*
+ * No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0,
U64_HI(data_mapping),
@@ -5444,6 +5550,38 @@ static inline int bnx2x_func_send_stop(struct bnx2x *bp,
NONE_CONNECTION_TYPE);
}
+static inline int bnx2x_func_send_tx_stop(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0,
+ NONE_CONNECTION_TYPE);
+}
+static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ struct flow_control_configuration *rdata =
+ (struct flow_control_configuration *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ struct bnx2x_func_tx_start_params *tx_start_params =
+ &params->params.tx_start;
+ int i;
+
+ memset(rdata, 0, sizeof(*rdata));
+
+ rdata->dcb_enabled = tx_start_params->dcb_enabled;
+ rdata->dcb_version = tx_start_params->dcb_version;
+ rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en;
+
+ for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++)
+ rdata->traffic_type_to_priority_cos[i] =
+ tx_start_params->traffic_type_to_priority_cos[i];
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
static int bnx2x_func_send_cmd(struct bnx2x *bp,
struct bnx2x_func_state_params *params)
{
@@ -5456,6 +5594,10 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp,
return bnx2x_func_send_stop(bp, params);
case BNX2X_F_CMD_HW_RESET:
return bnx2x_func_hw_reset(bp, params);
+ case BNX2X_F_CMD_TX_STOP:
+ return bnx2x_func_send_tx_stop(bp, params);
+ case BNX2X_F_CMD_TX_START:
+ return bnx2x_func_send_tx_start(bp, params);
default:
BNX2X_ERR("Unknown command: %d\n", params->cmd);
return -EINVAL;
diff --git a/drivers/net/bnx2x/bnx2x_sp.h b/drivers/net/bnx2x/bnx2x_sp.h
index 83f3b0b44211..9a517c2e9f1b 100644
--- a/drivers/net/bnx2x/bnx2x_sp.h
+++ b/drivers/net/bnx2x/bnx2x_sp.h
@@ -749,6 +749,7 @@ enum bnx2x_queue_cmd {
/* queue SETUP + INIT flags */
enum {
BNX2X_Q_FLG_TPA,
+ BNX2X_Q_FLG_TPA_IPV6,
BNX2X_Q_FLG_STATS,
BNX2X_Q_FLG_ZERO_STATS,
BNX2X_Q_FLG_ACTIVE,
@@ -996,6 +997,7 @@ enum bnx2x_func_state {
BNX2X_F_STATE_RESET,
BNX2X_F_STATE_INITIALIZED,
BNX2X_F_STATE_STARTED,
+ BNX2X_F_STATE_TX_STOPPED,
BNX2X_F_STATE_MAX,
};
@@ -1005,6 +1007,8 @@ enum bnx2x_func_cmd {
BNX2X_F_CMD_START,
BNX2X_F_CMD_STOP,
BNX2X_F_CMD_HW_RESET,
+ BNX2X_F_CMD_TX_STOP,
+ BNX2X_F_CMD_TX_START,
BNX2X_F_CMD_MAX,
};
@@ -1047,6 +1051,13 @@ struct bnx2x_func_start_params {
u8 network_cos_mode;
};
+struct bnx2x_func_tx_start_params {
+ struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
+ u8 dcb_enabled;
+ u8 dcb_version;
+ u8 dont_add_pri_0_en;
+};
+
struct bnx2x_func_state_params {
struct bnx2x_func_sp_obj *f_obj;
@@ -1061,6 +1072,7 @@ struct bnx2x_func_state_params {
struct bnx2x_func_hw_init_params hw_init;
struct bnx2x_func_hw_reset_params hw_reset;
struct bnx2x_func_start_params start;
+ struct bnx2x_func_tx_start_params tx_start;
} params;
};
@@ -1152,6 +1164,8 @@ void bnx2x_init_func_obj(struct bnx2x *bp,
int bnx2x_func_state_change(struct bnx2x *bp,
struct bnx2x_func_state_params *params);
+enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
+ struct bnx2x_func_sp_obj *o);
/******************* Queue State **************/
void bnx2x_init_queue_obj(struct bnx2x *bp,
struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids,
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 3ddd33936aa7..40bcb82d9116 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -435,6 +435,7 @@ enum rtl_register_content {
AcceptMulticast = 0x04,
AcceptMyPhys = 0x02,
AcceptAllPhys = 0x01,
+#define RX_CONFIG_ACCEPT_MASK 0x3f
/* TxConfigBits */
TxInterFrameGapShift = 24,
@@ -3943,11 +3944,8 @@ err_pm_runtime_put:
static void rtl_rx_close(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- u32 rxcfg = RTL_R32(RxConfig);
- rxcfg &= ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast |
- AcceptMyPhys | AcceptAllPhys);
- RTL_W32(RxConfig, rxcfg);
+ RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
}
static void rtl8169_hw_reset(struct rtl8169_private *tp)
@@ -5586,7 +5584,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
spin_lock_irqsave(&tp->lock, flags);
- tmp = RTL_R32(RxConfig) | rx_mode;
+ tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
u32 data = mc_filter[0];