diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom')
| -rw-r--r-- | drivers/net/ethernet/broadcom/bgmac.c | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 10 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c | 18 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 89 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h | 7 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 7 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 29 | 
9 files changed, 142 insertions, 31 deletions
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 639049d7e92..da5f4397f87 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -301,12 +301,16 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,  			bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",  				  ring->start);  		} else { +			/* Omit CRC. */ +			len -= ETH_FCS_LEN; +  			new_skb = netdev_alloc_skb_ip_align(bgmac->net_dev, len);  			if (new_skb) {  				skb_put(new_skb, len);  				skb_copy_from_linear_data_offset(skb, BGMAC_RX_FRAME_OFFSET,  								 new_skb->data,  								 len); +				skb_checksum_none_assert(skb);  				new_skb->protocol =  					eth_type_trans(new_skb, bgmac->net_dev);  				netif_receive_skb(new_skb); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ecac04a3687..57619dd4a92 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2614,6 +2614,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)  			}  		} +		/* initialize FW coalescing state machines in RAM */ +		bnx2x_update_coalesce(bp); +  		/* setup the leading queue */  		rc = bnx2x_setup_leading(bp);  		if (rc) { @@ -2760,6 +2763,7 @@ load_error2:  	bp->port.pmf = 0;  load_error1:  	bnx2x_napi_disable(bp); +	bnx2x_del_all_napi(bp);  	/* clear pf_load status, as it was already set */  	if (IS_PF(bp)) @@ -3142,7 +3146,7 @@ static inline __le16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix)  		tsum = ~csum_fold(csum_add((__force __wsum) csum,  				  csum_partial(t_header, -fix, 0))); -	return bswab16(csum); +	return bswab16(tsum);  }  static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) @@ -4579,11 +4583,11 @@ static void storm_memset_hc_disable(struct bnx2x *bp, u8 port,  	u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);  	u32 addr = BAR_CSTRORM_INTMEM +  		   CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(fw_sb_id, sb_index); -	u16 flags = REG_RD16(bp, addr); +	u8 flags = REG_RD8(bp, addr);  	/* clear and set */  	flags &= ~HC_INDEX_DATA_HC_ENABLED;  	flags |= enable_flag; -	REG_WR16(bp, addr, flags); +	REG_WR8(bp, addr, flags);  	DP(NETIF_MSG_IFUP,  	   "port %x fw_sb_id %d sb_index %d disable %d\n",  	   port, fw_sb_id, sb_index, disable); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index c633402cbd2..4b077a7f16a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c @@ -2139,12 +2139,12 @@ static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)  			break;  		default:  			BNX2X_ERR("Non valid capability ID\n"); -			rval = -EINVAL; +			rval = 1;  			break;  		}  	} else {  		DP(BNX2X_MSG_DCB, "DCB disabled\n"); -		rval = -EINVAL; +		rval = 1;  	}  	DP(BNX2X_MSG_DCB, "capid %d:%x\n", capid, *cap); @@ -2170,12 +2170,12 @@ static int bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)  			break;  		default:  			BNX2X_ERR("Non valid TC-ID\n"); -			rval = -EINVAL; +			rval = 1;  			break;  		}  	} else {  		DP(BNX2X_MSG_DCB, "DCB disabled\n"); -		rval = -EINVAL; +		rval = 1;  	}  	return rval; @@ -2188,7 +2188,7 @@ static int bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num)  	return -EINVAL;  } -static u8  bnx2x_dcbnl_get_pfc_state(struct net_device *netdev) +static u8 bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)  {  	struct bnx2x *bp = netdev_priv(netdev);  	DP(BNX2X_MSG_DCB, "state = %d\n", bp->dcbx_local_feat.pfc.enabled); @@ -2390,12 +2390,12 @@ static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,  			break;  		default:  			BNX2X_ERR("Non valid featrue-ID\n"); -			rval = -EINVAL; +			rval = 1;  			break;  		}  	} else {  		DP(BNX2X_MSG_DCB, "DCB disabled\n"); -		rval = -EINVAL; +		rval = 1;  	}  	return rval; @@ -2431,12 +2431,12 @@ static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,  			break;  		default:  			BNX2X_ERR("Non valid featrue-ID\n"); -			rval = -EINVAL; +			rval = 1;  			break;  		}  	} else {  		DP(BNX2X_MSG_DCB, "dcbnl call not valid\n"); -		rval = -EINVAL; +		rval = 1;  	}  	return rval; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 9a674b14b40..edfa67adf2f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -281,6 +281,8 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)  			cmd->lp_advertising |= ADVERTISED_2500baseX_Full;  		if (status & LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE)  			cmd->lp_advertising |= ADVERTISED_10000baseT_Full; +		if (status & LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE) +			cmd->lp_advertising |= ADVERTISED_20000baseKR2_Full;  	}  	cmd->maxtxpkt = 0; @@ -463,6 +465,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)  						ADVERTISED_10000baseKR_Full))  				bp->link_params.speed_cap_mask[cfg_idx] |=  					PORT_HW_CFG_SPEED_CAPABILITY_D0_10G; + +			if (cmd->advertising & ADVERTISED_20000baseKR2_Full) +				bp->link_params.speed_cap_mask[cfg_idx] |= +					PORT_HW_CFG_SPEED_CAPABILITY_D0_20G;  		}  	} else { /* forced speed */  		/* advertise the requested speed and duplex if supported */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 1663e0b6b5a..0283f343b0d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -8647,7 +8647,9 @@ void bnx2x_handle_module_detect_int(struct link_params *params)  						MDIO_WC_DEVAD,  						MDIO_WC_REG_DIGITAL5_MISC6,  						&rx_tx_in_reset); -				if (!rx_tx_in_reset) { +				if ((!rx_tx_in_reset) && +				    (params->link_flags & +				     PHY_INITIALIZED)) {  					bnx2x_warpcore_reset_lane(bp, phy, 1);  					bnx2x_warpcore_config_sfi(phy, params);  					bnx2x_warpcore_reset_lane(bp, phy, 0); @@ -10422,6 +10424,28 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,  					 MDIO_PMA_DEVAD,  					 MDIO_PMA_REG_8481_LED1_MASK,  					 0x0); +			if (phy->type == +			    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { +				/* Disable MI_INT interrupt before setting LED4 +				 * source to constant off. +				 */ +				if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + +					   params->port*4) & +				    NIG_MASK_MI_INT) { +					params->link_flags |= +					LINK_FLAGS_INT_DISABLED; + +					bnx2x_bits_dis( +						bp, +						NIG_REG_MASK_INTERRUPT_PORT0 + +						params->port*4, +						NIG_MASK_MI_INT); +				} +				bnx2x_cl45_write(bp, phy, +						 MDIO_PMA_DEVAD, +						 MDIO_PMA_REG_8481_SIGNAL_MASK, +						 0x0); +			}  		}  		break;  	case LED_MODE_ON: @@ -10468,6 +10492,28 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,  					 MDIO_PMA_DEVAD,  					 MDIO_PMA_REG_8481_LED1_MASK,  					 0x20); +			if (phy->type == +			    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { +				/* Disable MI_INT interrupt before setting LED4 +				 * source to constant on. +				 */ +				if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + +					   params->port*4) & +				    NIG_MASK_MI_INT) { +					params->link_flags |= +					LINK_FLAGS_INT_DISABLED; + +					bnx2x_bits_dis( +						bp, +						NIG_REG_MASK_INTERRUPT_PORT0 + +						params->port*4, +						NIG_MASK_MI_INT); +				} +				bnx2x_cl45_write(bp, phy, +						 MDIO_PMA_DEVAD, +						 MDIO_PMA_REG_8481_SIGNAL_MASK, +						 0x20); +			}  		}  		break; @@ -10532,6 +10578,22 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,  					 MDIO_PMA_DEVAD,  					 MDIO_PMA_REG_8481_LINK_SIGNAL,  					 val); +			if (phy->type == +			    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { +				/* Restore LED4 source to external link, +				 * and re-enable interrupts. +				 */ +				bnx2x_cl45_write(bp, phy, +						 MDIO_PMA_DEVAD, +						 MDIO_PMA_REG_8481_SIGNAL_MASK, +						 0x40); +				if (params->link_flags & +				    LINK_FLAGS_INT_DISABLED) { +					bnx2x_link_int_enable(params); +					params->link_flags &= +						~LINK_FLAGS_INT_DISABLED; +				} +			}  		}  		break;  	} @@ -11791,6 +11853,8 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,  			phy->media_type = ETH_PHY_KR;  			phy->flags |= FLAGS_WC_DUAL_MODE;  			phy->supported &= (SUPPORTED_20000baseKR2_Full | +					   SUPPORTED_10000baseT_Full | +					   SUPPORTED_1000baseT_Full |  					   SUPPORTED_Autoneg |  					   SUPPORTED_FIBRE |  					   SUPPORTED_Pause | @@ -12465,6 +12529,8 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)  	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;  	vars->mac_type = MAC_TYPE_NONE;  	vars->phy_flags = 0; +	vars->check_kr2_recovery_cnt = 0; +	params->link_flags = PHY_INITIALIZED;  	/* Driver opens NIG-BRB filters */  	bnx2x_set_rx_filter(params, 1);  	/* Check if link flap can be avoided */ @@ -12629,6 +12695,7 @@ int bnx2x_lfa_reset(struct link_params *params,  	struct bnx2x *bp = params->bp;  	vars->link_up = 0;  	vars->phy_flags = 0; +	params->link_flags &= ~PHY_INITIALIZED;  	if (!params->lfa_base)  		return bnx2x_link_reset(params, vars, 1);  	/* @@ -13349,6 +13416,7 @@ static void bnx2x_disable_kr2(struct link_params *params,  	vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;  	bnx2x_update_link_attr(params, vars->link_attr_sync); +	vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;  	/* Restart AN on leading lane */  	bnx2x_warpcore_restart_AN_KR(phy, params);  } @@ -13369,11 +13437,24 @@ static void bnx2x_check_kr2_wa(struct link_params *params,  {  	struct bnx2x *bp = params->bp;  	u16 base_page, next_page, not_kr2_device, lane; -	int sigdet = bnx2x_warpcore_get_sigdet(phy, params); +	int sigdet; +	/* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery +	 * since some switches tend to reinit the AN process and clear the +	 * advertised BP/NP after ~2 seconds causing the KR2 to be disabled +	 * and recovered many times +	 */ +	if (vars->check_kr2_recovery_cnt > 0) { +		vars->check_kr2_recovery_cnt--; +		return; +	} + +	sigdet = bnx2x_warpcore_get_sigdet(phy, params);  	if (!sigdet) { -		if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) +		if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {  			bnx2x_kr2_recovery(params, vars, phy); +			DP(NETIF_MSG_LINK, "No sigdet\n"); +		}  		return;  	} @@ -13437,7 +13518,7 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)  		struct bnx2x_phy *phy = ¶ms->phy[INT_PHY];  		bnx2x_set_aer_mmd(params, phy);  		if ((phy->supported & SUPPORTED_20000baseKR2_Full) && -		    (phy->speed_cap_mask & SPEED_20000)) +		    (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G))  			bnx2x_check_kr2_wa(params, vars, phy);  		bnx2x_check_over_curr(params, vars);  		if (vars->rx_tx_asic_rst) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index d25c7d79787..56c2aae4e2c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h @@ -307,7 +307,9 @@ struct link_params {  	struct bnx2x *bp;  	u16 req_fc_auto_adv; /* Should be set to TX / BOTH when  				req_flow_ctrl is set to AUTO */ -	u16 rsrv1; +	u16 link_flags; +#define LINK_FLAGS_INT_DISABLED		(1<<0) +#define PHY_INITIALIZED		(1<<1)  	u32 lfa_base;  }; @@ -341,7 +343,8 @@ struct link_vars {  	u32 link_status;  	u32 eee_status;  	u8 fault_detected; -	u8 rsrv1; +	u8 check_kr2_recovery_cnt; +#define CHECK_KR2_RECOVERY_CNT	5  	u16 periodic_flags;  #define PERIODIC_FLAGS_LINK_EVENT	0x0001 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index e81a747ea8c..c50696b396f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -4947,7 +4947,7 @@ static void bnx2x_after_function_update(struct bnx2x *bp)  				  q);  	} -	if (!NO_FCOE(bp)) { +	if (!NO_FCOE(bp) && CNIC_ENABLED(bp)) {  		fp = &bp->fp[FCOE_IDX(bp)];  		queue_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj; @@ -9878,6 +9878,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)  				REG_RD(bp, NIG_REG_NIG_INT_STS_CLR_0);  			}  		} +		if (!CHIP_IS_E1x(bp)) +			/* block FW from writing to host */ +			REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0); +  		/* wait until BRB is empty */  		tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS);  		while (timer_count) { @@ -13354,6 +13358,7 @@ static int bnx2x_unregister_cnic(struct net_device *dev)  	RCU_INIT_POINTER(bp->cnic_ops, NULL);  	mutex_unlock(&bp->cnic_mutex);  	synchronize_rcu(); +	bp->cnic_enabled = false;  	kfree(bp->cnic_kwq);  	bp->cnic_kwq = NULL; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h index 364e37ecbc5..198f6f1c9ad 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h @@ -459,8 +459,9 @@ struct bnx2x_fw_port_stats_old {  #define UPDATE_QSTAT(s, t) \  	do { \ -		qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi); \  		qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \ +		qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi) \ +			+ ((qstats->t##_lo < qstats_old->t##_lo) ? 1 : 0); \  	} while (0)  #define UPDATE_QSTAT_OLD(f) \ diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index fdb9b565541..17a972734ba 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -1869,6 +1869,8 @@ static void tg3_link_report(struct tg3 *tp)  		tg3_ump_link_report(tp);  	} + +	tp->link_up = netif_carrier_ok(tp->dev);  }  static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) @@ -2522,12 +2524,6 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)  	return err;  } -static void tg3_carrier_on(struct tg3 *tp) -{ -	netif_carrier_on(tp->dev); -	tp->link_up = true; -} -  static void tg3_carrier_off(struct tg3 *tp)  {  	netif_carrier_off(tp->dev); @@ -2553,7 +2549,7 @@ static int tg3_phy_reset(struct tg3 *tp)  		return -EBUSY;  	if (netif_running(tp->dev) && tp->link_up) { -		tg3_carrier_off(tp); +		netif_carrier_off(tp->dev);  		tg3_link_report(tp);  	} @@ -4134,6 +4130,14 @@ static void tg3_phy_copper_begin(struct tg3 *tp)  		tp->link_config.active_speed = tp->link_config.speed;  		tp->link_config.active_duplex = tp->link_config.duplex; +		if (tg3_asic_rev(tp) == ASIC_REV_5714) { +			/* With autoneg disabled, 5715 only links up when the +			 * advertisement register has the configured speed +			 * enabled. +			 */ +			tg3_writephy(tp, MII_ADVERTISE, ADVERTISE_ALL); +		} +  		bmcr = 0;  		switch (tp->link_config.speed) {  		default: @@ -4262,9 +4266,9 @@ static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)  {  	if (curr_link_up != tp->link_up) {  		if (curr_link_up) { -			tg3_carrier_on(tp); +			netif_carrier_on(tp->dev);  		} else { -			tg3_carrier_off(tp); +			netif_carrier_off(tp->dev);  			if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)  				tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;  		} @@ -14600,8 +14604,11 @@ static void tg3_read_vpd(struct tg3 *tp)  		if (j + len > block_end)  			goto partno; -		memcpy(tp->fw_ver, &vpd_data[j], len); -		strncat(tp->fw_ver, " bc ", vpdlen - len - 1); +		if (len >= sizeof(tp->fw_ver)) +			len = sizeof(tp->fw_ver) - 1; +		memset(tp->fw_ver, 0, sizeof(tp->fw_ver)); +		snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len, +			 &vpd_data[j]);  	}  partno:  |