diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom')
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 30 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 60 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 62 | 
4 files changed, 120 insertions, 34 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 01588b66a38..f771ddfba64 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -80,12 +80,37 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to)  		new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET;  	} -	memcpy(&bp->bnx2x_txq[old_txdata_index], -	       &bp->bnx2x_txq[new_txdata_index], +	memcpy(&bp->bnx2x_txq[new_txdata_index], +	       &bp->bnx2x_txq[old_txdata_index],  	       sizeof(struct bnx2x_fp_txdata));  	to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index];  } +/** + * bnx2x_shrink_eth_fp - guarantees fastpath structures stay intact + * + * @bp:	driver handle + * @delta:	number of eth queues which were not allocated + */ +static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta) +{ +	int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp); + +	/* Queue pointer cannot be re-set on an fp-basis, as moving pointer +	 * backward along the array could cause memory to be overriden +	 */ +	for (cos = 1; cos < bp->max_cos; cos++) { +		for (i = 0; i < old_eth_num - delta; i++) { +			struct bnx2x_fastpath *fp = &bp->fp[i]; +			int new_idx = cos * (old_eth_num - delta) + i; + +			memcpy(&bp->bnx2x_txq[new_idx], fp->txdata_ptr[cos], +			       sizeof(struct bnx2x_fp_txdata)); +			fp->txdata_ptr[cos] = &bp->bnx2x_txq[new_idx]; +		} +	} +} +  int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */  /* free skb in the packet ring at pos idx @@ -3863,6 +3888,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)  		int delta = BNX2X_NUM_ETH_QUEUES(bp) - i;  		WARN_ON(delta < 0); +		bnx2x_shrink_eth_fp(bp, delta);  		if (CNIC_SUPPORT(bp))  			/* move non eth FPs next to last eth FP  			 * must be done in that order diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 277f17e3c8f..a427b49a886 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -2777,10 +2777,10 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)  		} else if ((info->flow_type == UDP_V6_FLOW) &&  			   (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) {  			bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; -			return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);  			DP(BNX2X_MSG_ETHTOOL,  			   "rss re-configured, UDP 4-tupple %s\n",  			   udp_rss_requested ? "enabled" : "disabled"); +			return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);  		} else {  			return 0;  		} diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 940ef859dc6..5523da3afcd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -127,6 +127,17 @@ MODULE_PARM_DESC(debug, " Default debug msglevel");  struct workqueue_struct *bnx2x_wq; +struct bnx2x_mac_vals { +	u32 xmac_addr; +	u32 xmac_val; +	u32 emac_addr; +	u32 emac_val; +	u32 umac_addr; +	u32 umac_val; +	u32 bmac_addr; +	u32 bmac_val[2]; +}; +  enum bnx2x_board_type {  	BCM57710 = 0,  	BCM57711, @@ -9420,12 +9431,19 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp)  		bnx2x_undi_int_disable_e1h(bp);  } -static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) +static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, +					struct bnx2x_mac_vals *vals)  {  	u32 val, base_addr, offset, mask, reset_reg;  	bool mac_stopped = false;  	u8 port = BP_PORT(bp); +	/* reset addresses as they also mark which values were changed */ +	vals->bmac_addr = 0; +	vals->umac_addr = 0; +	vals->xmac_addr = 0; +	vals->emac_addr = 0; +  	reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2);  	if (!CHIP_IS_E3(bp)) { @@ -9447,14 +9465,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp)  			 */  			wb_data[0] = REG_RD(bp, base_addr + offset);  			wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); +			vals->bmac_addr = base_addr + offset; +			vals->bmac_val[0] = wb_data[0]; +			vals->bmac_val[1] = wb_data[1];  			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; -			REG_WR(bp, base_addr + offset, wb_data[0]); -			REG_WR(bp, base_addr + offset + 0x4, wb_data[1]); +			REG_WR(bp, vals->bmac_addr, wb_data[0]); +			REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]);  		}  		BNX2X_DEV_INFO("Disable emac Rx\n"); -		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0); - +		vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4; +		vals->emac_val = REG_RD(bp, vals->emac_addr); +		REG_WR(bp, vals->emac_addr, 0);  		mac_stopped = true;  	} else {  		if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { @@ -9465,14 +9487,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp)  			       val & ~(1 << 1));  			REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI,  			       val | (1 << 1)); -			REG_WR(bp, base_addr + XMAC_REG_CTRL, 0); +			vals->xmac_addr = base_addr + XMAC_REG_CTRL; +			vals->xmac_val = REG_RD(bp, vals->xmac_addr); +			REG_WR(bp, vals->xmac_addr, 0);  			mac_stopped = true;  		}  		mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port;  		if (mask & reset_reg) {  			BNX2X_DEV_INFO("Disable umac Rx\n");  			base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; -			REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0); +			vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; +			vals->umac_val = REG_RD(bp, vals->umac_addr); +			REG_WR(bp, vals->umac_addr, 0);  			mac_stopped = true;  		}  	} @@ -9664,12 +9690,16 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)  {  	u32 reset_reg, tmp_reg = 0, rc;  	bool prev_undi = false; +	struct bnx2x_mac_vals mac_vals; +  	/* It is possible a previous function received 'common' answer,  	 * but hasn't loaded yet, therefore creating a scenario of  	 * multiple functions receiving 'common' on the same path.  	 */  	BNX2X_DEV_INFO("Common unload Flow\n"); +	memset(&mac_vals, 0, sizeof(mac_vals)); +  	if (bnx2x_prev_is_path_marked(bp))  		return bnx2x_prev_mcp_done(bp); @@ -9680,7 +9710,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)  		u32 timer_count = 1000;  		/* Close the MAC Rx to prevent BRB from filling up */ -		bnx2x_prev_unload_close_mac(bp); +		bnx2x_prev_unload_close_mac(bp, &mac_vals); + +		/* close LLH filters towards the BRB */ +		bnx2x_set_rx_filter(&bp->link_params, 0);  		/* Check if the UNDI driver was previously loaded  		 * UNDI driver initializes CID offset for normal bell to 0x7 @@ -9727,6 +9760,17 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)  	/* No packets are in the pipeline, path is ready for reset */  	bnx2x_reset_common(bp); +	if (mac_vals.xmac_addr) +		REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val); +	if (mac_vals.umac_addr) +		REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val); +	if (mac_vals.emac_addr) +		REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val); +	if (mac_vals.bmac_addr) { +		REG_WR(bp, mac_vals.bmac_addr, mac_vals.bmac_val[0]); +		REG_WR(bp, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]); +	} +  	rc = bnx2x_prev_mark_path(bp, prev_undi);  	if (rc) {  		bnx2x_prev_mcp_done(bp); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 78ea90c40e1..bdb086934cd 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -1283,14 +1283,26 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set)  	return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg);  } -#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ -	tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ -			     MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ -			     MII_TG3_AUXCTL_ACTL_TX_6DB) +static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable) +{ +	u32 val; +	int err; -#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ -	tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ -			     MII_TG3_AUXCTL_ACTL_TX_6DB); +	err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); + +	if (err) +		return err; +	if (enable) + +		val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA; +	else +		val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + +	err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, +				   val | MII_TG3_AUXCTL_ACTL_TX_6DB); + +	return err; +}  static int tg3_bmcr_reset(struct tg3 *tp)  { @@ -2223,7 +2235,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp)  	otp = tp->phy_otp; -	if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) +	if (tg3_phy_toggle_auxctl_smdsp(tp, true))  		return;  	phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); @@ -2248,7 +2260,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp)  	      ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);  	tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); -	TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); +	tg3_phy_toggle_auxctl_smdsp(tp, false);  }  static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) @@ -2284,9 +2296,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)  	if (!tp->setlpicnt) {  		if (current_link_up == 1 && -		   !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { +		   !tg3_phy_toggle_auxctl_smdsp(tp, true)) {  			tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); -			TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); +			tg3_phy_toggle_auxctl_smdsp(tp, false);  		}  		val = tr32(TG3_CPMU_EEE_MODE); @@ -2302,11 +2314,11 @@ static void tg3_phy_eee_enable(struct tg3 *tp)  	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||  	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||  	     tg3_flag(tp, 57765_CLASS)) && -	    !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { +	    !tg3_phy_toggle_auxctl_smdsp(tp, true)) {  		val = MII_TG3_DSP_TAP26_ALNOKO |  		      MII_TG3_DSP_TAP26_RMRXSTO;  		tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); -		TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); +		tg3_phy_toggle_auxctl_smdsp(tp, false);  	}  	val = tr32(TG3_CPMU_EEE_MODE); @@ -2450,7 +2462,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)  		tg3_writephy(tp, MII_CTRL1000,  			     CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); -		err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); +		err = tg3_phy_toggle_auxctl_smdsp(tp, true);  		if (err)  			return err; @@ -2471,7 +2483,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)  	tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);  	tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); -	TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); +	tg3_phy_toggle_auxctl_smdsp(tp, false);  	tg3_writephy(tp, MII_CTRL1000, phy9_orig); @@ -2572,10 +2584,10 @@ static int tg3_phy_reset(struct tg3 *tp)  out:  	if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && -	    !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { +	    !tg3_phy_toggle_auxctl_smdsp(tp, true)) {  		tg3_phydsp_write(tp, 0x201f, 0x2aaa);  		tg3_phydsp_write(tp, 0x000a, 0x0323); -		TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); +		tg3_phy_toggle_auxctl_smdsp(tp, false);  	}  	if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { @@ -2584,14 +2596,14 @@ out:  	}  	if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { -		if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { +		if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) {  			tg3_phydsp_write(tp, 0x000a, 0x310b);  			tg3_phydsp_write(tp, 0x201f, 0x9506);  			tg3_phydsp_write(tp, 0x401f, 0x14e2); -			TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); +			tg3_phy_toggle_auxctl_smdsp(tp, false);  		}  	} else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { -		if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { +		if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) {  			tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);  			if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {  				tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); @@ -2600,7 +2612,7 @@ out:  			} else  				tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); -			TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); +			tg3_phy_toggle_auxctl_smdsp(tp, false);  		}  	} @@ -4009,7 +4021,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)  	tw32(TG3_CPMU_EEE_MODE,  	     tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); -	err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); +	err = tg3_phy_toggle_auxctl_smdsp(tp, true);  	if (!err) {  		u32 err2; @@ -4042,7 +4054,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)  						 MII_TG3_DSP_CH34TP2_HIBW01);  		} -		err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); +		err2 = tg3_phy_toggle_auxctl_smdsp(tp, false);  		if (!err)  			err = err2;  	} @@ -6950,6 +6962,9 @@ static void tg3_poll_controller(struct net_device *dev)  	int i;  	struct tg3 *tp = netdev_priv(dev); +	if (tg3_irq_sync(tp)) +		return; +  	for (i = 0; i < tp->irq_cnt; i++)  		tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]);  } @@ -16367,6 +16382,7 @@ static int tg3_init_one(struct pci_dev *pdev,  	tp->pm_cap = pm_cap;  	tp->rx_mode = TG3_DEF_RX_MODE;  	tp->tx_mode = TG3_DEF_TX_MODE; +	tp->irq_sync = 1;  	if (tg3_debug > 0)  		tp->msg_enable = tg3_debug;  |