diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/bnx2x/bnx2x.h | 9 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_cmn.c | 9 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_cmn.h | 5 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_dcb.c | 171 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_ethtool.c | 2 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_hsi.h | 1 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_main.c | 123 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_sp.c | 178 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_sp.h | 14 | ||||
-rw-r--r-- | drivers/net/r8169.c | 8 |
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, ¶ms->flags) * + data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, ¶ms->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, ¶ms->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, ¶ms->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, ¶ms->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 = + ¶ms->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]; |