diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/tg3.c')
| -rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 1548 | 
1 files changed, 768 insertions, 780 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 423d0235a87..76f33d5c727 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -4,7 +4,7 @@   * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)   * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)   * Copyright (C) 2004 Sun Microsystems Inc. - * Copyright (C) 2005-2011 Broadcom Corporation. + * Copyright (C) 2005-2012 Broadcom Corporation.   *   * Firmware is:   *	Derived from proprietary unpublished source code, @@ -204,6 +204,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)  #define TG3_RAW_IP_ALIGN 2  #define TG3_FW_UPDATE_TIMEOUT_SEC	5 +#define TG3_FW_UPDATE_FREQ_SEC		(TG3_FW_UPDATE_TIMEOUT_SEC / 2)  #define FIRMWARE_TG3		"tigon/tg3.bin"  #define FIRMWARE_TG3TSO		"tigon/tg3_tso.bin" @@ -1453,33 +1454,23 @@ static void tg3_wait_for_event_ack(struct tg3 *tp)  }  /* tp->lock is held. */ -static void tg3_ump_link_report(struct tg3 *tp) +static void tg3_phy_gather_ump_data(struct tg3 *tp, u32 *data)  { -	u32 reg; -	u32 val; - -	if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF)) -		return; - -	tg3_wait_for_event_ack(tp); - -	tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE); - -	tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14); +	u32 reg, val;  	val = 0;  	if (!tg3_readphy(tp, MII_BMCR, ®))  		val = reg << 16;  	if (!tg3_readphy(tp, MII_BMSR, ®))  		val |= (reg & 0xffff); -	tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val); +	*data++ = val;  	val = 0;  	if (!tg3_readphy(tp, MII_ADVERTISE, ®))  		val = reg << 16;  	if (!tg3_readphy(tp, MII_LPA, ®))  		val |= (reg & 0xffff); -	tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val); +	*data++ = val;  	val = 0;  	if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) { @@ -1488,13 +1479,33 @@ static void tg3_ump_link_report(struct tg3 *tp)  		if (!tg3_readphy(tp, MII_STAT1000, ®))  			val |= (reg & 0xffff);  	} -	tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val); +	*data++ = val;  	if (!tg3_readphy(tp, MII_PHYADDR, ®))  		val = reg << 16;  	else  		val = 0; -	tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val); +	*data++ = val; +} + +/* tp->lock is held. */ +static void tg3_ump_link_report(struct tg3 *tp) +{ +	u32 data[4]; + +	if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF)) +		return; + +	tg3_phy_gather_ump_data(tp, data); + +	tg3_wait_for_event_ack(tp); + +	tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE); +	tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14); +	tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x0, data[0]); +	tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x4, data[1]); +	tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x8, data[2]); +	tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0xc, data[3]);  	tg3_generate_fw_event(tp);  } @@ -1809,13 +1820,13 @@ static void tg3_adjust_link(struct net_device *dev)  		      (6 << TX_LENGTHS_IPG_SHIFT) |  		      (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); -	if ((phydev->link && tp->link_config.active_speed == SPEED_INVALID) || -	    (!phydev->link && tp->link_config.active_speed != SPEED_INVALID) || +	if (phydev->link != tp->old_link ||  	    phydev->speed != tp->link_config.active_speed ||  	    phydev->duplex != tp->link_config.active_duplex ||  	    oldflowctrl != tp->link_config.active_flowctrl)  		linkmesg = 1; +	tp->old_link = phydev->link;  	tp->link_config.active_speed = phydev->speed;  	tp->link_config.active_duplex = phydev->duplex; @@ -1884,10 +1895,10 @@ static void tg3_phy_start(struct tg3 *tp)  	if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {  		tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER; -		phydev->speed = tp->link_config.orig_speed; -		phydev->duplex = tp->link_config.orig_duplex; -		phydev->autoneg = tp->link_config.orig_autoneg; -		phydev->advertising = tp->link_config.orig_advertising; +		phydev->speed = tp->link_config.speed; +		phydev->duplex = tp->link_config.duplex; +		phydev->autoneg = tp->link_config.autoneg; +		phydev->advertising = tp->link_config.advertising;  	}  	phy_start(phydev); @@ -2709,9 +2720,6 @@ static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)  	return 0;  } -static int tg3_setup_phy(struct tg3 *, int); -static int tg3_halt_cpu(struct tg3 *, u32); -  static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)  {  	u32 val; @@ -2978,6 +2986,259 @@ static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, __be32 *val)  	return res;  } +static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, +				    u32 offset, u32 len, u8 *buf) +{ +	int i, j, rc = 0; +	u32 val; + +	for (i = 0; i < len; i += 4) { +		u32 addr; +		__be32 data; + +		addr = offset + i; + +		memcpy(&data, buf + i, 4); + +		/* +		 * The SEEPROM interface expects the data to always be opposite +		 * the native endian format.  We accomplish this by reversing +		 * all the operations that would have been performed on the +		 * data from a call to tg3_nvram_read_be32(). +		 */ +		tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data))); + +		val = tr32(GRC_EEPROM_ADDR); +		tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); + +		val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | +			EEPROM_ADDR_READ); +		tw32(GRC_EEPROM_ADDR, val | +			(0 << EEPROM_ADDR_DEVID_SHIFT) | +			(addr & EEPROM_ADDR_ADDR_MASK) | +			EEPROM_ADDR_START | +			EEPROM_ADDR_WRITE); + +		for (j = 0; j < 1000; j++) { +			val = tr32(GRC_EEPROM_ADDR); + +			if (val & EEPROM_ADDR_COMPLETE) +				break; +			msleep(1); +		} +		if (!(val & EEPROM_ADDR_COMPLETE)) { +			rc = -EBUSY; +			break; +		} +	} + +	return rc; +} + +/* offset and length are dword aligned */ +static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, +		u8 *buf) +{ +	int ret = 0; +	u32 pagesize = tp->nvram_pagesize; +	u32 pagemask = pagesize - 1; +	u32 nvram_cmd; +	u8 *tmp; + +	tmp = kmalloc(pagesize, GFP_KERNEL); +	if (tmp == NULL) +		return -ENOMEM; + +	while (len) { +		int j; +		u32 phy_addr, page_off, size; + +		phy_addr = offset & ~pagemask; + +		for (j = 0; j < pagesize; j += 4) { +			ret = tg3_nvram_read_be32(tp, phy_addr + j, +						  (__be32 *) (tmp + j)); +			if (ret) +				break; +		} +		if (ret) +			break; + +		page_off = offset & pagemask; +		size = pagesize; +		if (len < size) +			size = len; + +		len -= size; + +		memcpy(tmp + page_off, buf, size); + +		offset = offset + (pagesize - page_off); + +		tg3_enable_nvram_access(tp); + +		/* +		 * Before we can erase the flash page, we need +		 * to issue a special "write enable" command. +		 */ +		nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; + +		if (tg3_nvram_exec_cmd(tp, nvram_cmd)) +			break; + +		/* Erase the target page */ +		tw32(NVRAM_ADDR, phy_addr); + +		nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | +			NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; + +		if (tg3_nvram_exec_cmd(tp, nvram_cmd)) +			break; + +		/* Issue another write enable to start the write. */ +		nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; + +		if (tg3_nvram_exec_cmd(tp, nvram_cmd)) +			break; + +		for (j = 0; j < pagesize; j += 4) { +			__be32 data; + +			data = *((__be32 *) (tmp + j)); + +			tw32(NVRAM_WRDATA, be32_to_cpu(data)); + +			tw32(NVRAM_ADDR, phy_addr + j); + +			nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | +				NVRAM_CMD_WR; + +			if (j == 0) +				nvram_cmd |= NVRAM_CMD_FIRST; +			else if (j == (pagesize - 4)) +				nvram_cmd |= NVRAM_CMD_LAST; + +			ret = tg3_nvram_exec_cmd(tp, nvram_cmd); +			if (ret) +				break; +		} +		if (ret) +			break; +	} + +	nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; +	tg3_nvram_exec_cmd(tp, nvram_cmd); + +	kfree(tmp); + +	return ret; +} + +/* offset and length are dword aligned */ +static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, +		u8 *buf) +{ +	int i, ret = 0; + +	for (i = 0; i < len; i += 4, offset += 4) { +		u32 page_off, phy_addr, nvram_cmd; +		__be32 data; + +		memcpy(&data, buf + i, 4); +		tw32(NVRAM_WRDATA, be32_to_cpu(data)); + +		page_off = offset % tp->nvram_pagesize; + +		phy_addr = tg3_nvram_phys_addr(tp, offset); + +		nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; + +		if (page_off == 0 || i == 0) +			nvram_cmd |= NVRAM_CMD_FIRST; +		if (page_off == (tp->nvram_pagesize - 4)) +			nvram_cmd |= NVRAM_CMD_LAST; + +		if (i == (len - 4)) +			nvram_cmd |= NVRAM_CMD_LAST; + +		if ((nvram_cmd & NVRAM_CMD_FIRST) || +		    !tg3_flag(tp, FLASH) || +		    !tg3_flag(tp, 57765_PLUS)) +			tw32(NVRAM_ADDR, phy_addr); + +		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && +		    !tg3_flag(tp, 5755_PLUS) && +		    (tp->nvram_jedecnum == JEDEC_ST) && +		    (nvram_cmd & NVRAM_CMD_FIRST)) { +			u32 cmd; + +			cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; +			ret = tg3_nvram_exec_cmd(tp, cmd); +			if (ret) +				break; +		} +		if (!tg3_flag(tp, FLASH)) { +			/* We always do complete word writes to eeprom. */ +			nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); +		} + +		ret = tg3_nvram_exec_cmd(tp, nvram_cmd); +		if (ret) +			break; +	} +	return ret; +} + +/* offset and length are dword aligned */ +static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) +{ +	int ret; + +	if (tg3_flag(tp, EEPROM_WRITE_PROT)) { +		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & +		       ~GRC_LCLCTRL_GPIO_OUTPUT1); +		udelay(40); +	} + +	if (!tg3_flag(tp, NVRAM)) { +		ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); +	} else { +		u32 grc_mode; + +		ret = tg3_nvram_lock(tp); +		if (ret) +			return ret; + +		tg3_enable_nvram_access(tp); +		if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) +			tw32(NVRAM_WRITE1, 0x406); + +		grc_mode = tr32(GRC_MODE); +		tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); + +		if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) { +			ret = tg3_nvram_write_block_buffered(tp, offset, len, +				buf); +		} else { +			ret = tg3_nvram_write_block_unbuffered(tp, offset, len, +				buf); +		} + +		grc_mode = tr32(GRC_MODE); +		tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); + +		tg3_disable_nvram_access(tp); +		tg3_nvram_unlock(tp); +	} + +	if (tg3_flag(tp, EEPROM_WRITE_PROT)) { +		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); +		udelay(40); +	} + +	return ret; +} +  #define RX_CPU_SCRATCH_BASE	0x30000  #define RX_CPU_SCRATCH_SIZE	0x04000  #define TX_CPU_SCRATCH_BASE	0x34000 @@ -3264,6 +3525,8 @@ static int tg3_power_up(struct tg3 *tp)  	return err;  } +static int tg3_setup_phy(struct tg3 *, int); +  static int tg3_power_down_prepare(struct tg3 *tp)  {  	u32 misc_host_ctrl; @@ -3302,10 +3565,10 @@ static int tg3_power_down_prepare(struct tg3 *tp)  			tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER; -			tp->link_config.orig_speed = phydev->speed; -			tp->link_config.orig_duplex = phydev->duplex; -			tp->link_config.orig_autoneg = phydev->autoneg; -			tp->link_config.orig_advertising = phydev->advertising; +			tp->link_config.speed = phydev->speed; +			tp->link_config.duplex = phydev->duplex; +			tp->link_config.autoneg = phydev->autoneg; +			tp->link_config.advertising = phydev->advertising;  			advertising = ADVERTISED_TP |  				      ADVERTISED_Pause | @@ -3338,19 +3601,11 @@ static int tg3_power_down_prepare(struct tg3 *tp)  	} else {  		do_low_power = true; -		if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { +		if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER))  			tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER; -			tp->link_config.orig_speed = tp->link_config.speed; -			tp->link_config.orig_duplex = tp->link_config.duplex; -			tp->link_config.orig_autoneg = tp->link_config.autoneg; -		} -		if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) { -			tp->link_config.speed = SPEED_10; -			tp->link_config.duplex = DUPLEX_HALF; -			tp->link_config.autoneg = AUTONEG_ENABLE; +		if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))  			tg3_setup_phy(tp, 0); -		}  	}  	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { @@ -3559,8 +3814,8 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8  				  DUPLEX_HALF;  			break;  		} -		*speed = SPEED_INVALID; -		*duplex = DUPLEX_INVALID; +		*speed = SPEED_UNKNOWN; +		*duplex = DUPLEX_UNKNOWN;  		break;  	}  } @@ -3640,51 +3895,33 @@ done:  static void tg3_phy_copper_begin(struct tg3 *tp)  { -	u32 new_adv; -	int i; - -	if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { -		new_adv = ADVERTISED_10baseT_Half | -			  ADVERTISED_10baseT_Full; -		if (tg3_flag(tp, WOL_SPEED_100MB)) -			new_adv |= ADVERTISED_100baseT_Half | -				   ADVERTISED_100baseT_Full; +	if (tp->link_config.autoneg == AUTONEG_ENABLE || +	    (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { +		u32 adv, fc; -		tg3_phy_autoneg_cfg(tp, new_adv, -				    FLOW_CTRL_TX | FLOW_CTRL_RX); -	} else if (tp->link_config.speed == SPEED_INVALID) { -		if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) -			tp->link_config.advertising &= -				~(ADVERTISED_1000baseT_Half | -				  ADVERTISED_1000baseT_Full); +		if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { +			adv = ADVERTISED_10baseT_Half | +			      ADVERTISED_10baseT_Full; +			if (tg3_flag(tp, WOL_SPEED_100MB)) +				adv |= ADVERTISED_100baseT_Half | +				       ADVERTISED_100baseT_Full; -		tg3_phy_autoneg_cfg(tp, tp->link_config.advertising, -				    tp->link_config.flowctrl); -	} else { -		/* Asking for a specific link mode. */ -		if (tp->link_config.speed == SPEED_1000) { -			if (tp->link_config.duplex == DUPLEX_FULL) -				new_adv = ADVERTISED_1000baseT_Full; -			else -				new_adv = ADVERTISED_1000baseT_Half; -		} else if (tp->link_config.speed == SPEED_100) { -			if (tp->link_config.duplex == DUPLEX_FULL) -				new_adv = ADVERTISED_100baseT_Full; -			else -				new_adv = ADVERTISED_100baseT_Half; +			fc = FLOW_CTRL_TX | FLOW_CTRL_RX;  		} else { -			if (tp->link_config.duplex == DUPLEX_FULL) -				new_adv = ADVERTISED_10baseT_Full; -			else -				new_adv = ADVERTISED_10baseT_Half; +			adv = tp->link_config.advertising; +			if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) +				adv &= ~(ADVERTISED_1000baseT_Half | +					 ADVERTISED_1000baseT_Full); + +			fc = tp->link_config.flowctrl;  		} -		tg3_phy_autoneg_cfg(tp, new_adv, -				    tp->link_config.flowctrl); -	} +		tg3_phy_autoneg_cfg(tp, adv, fc); -	if (tp->link_config.autoneg == AUTONEG_DISABLE && -	    tp->link_config.speed != SPEED_INVALID) { +		tg3_writephy(tp, MII_BMCR, +			     BMCR_ANENABLE | BMCR_ANRESTART); +	} else { +		int i;  		u32 bmcr, orig_bmcr;  		tp->link_config.active_speed = tp->link_config.speed; @@ -3726,9 +3963,6 @@ static void tg3_phy_copper_begin(struct tg3 *tp)  			tg3_writephy(tp, MII_BMCR, bmcr);  			udelay(40);  		} -	} else { -		tg3_writephy(tp, MII_BMCR, -			     BMCR_ANENABLE | BMCR_ANRESTART);  	}  } @@ -3778,7 +4012,16 @@ static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv)  		if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl))  			return false; -		tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL); +		if (tgtadv && +		    (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || +		     tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)) { +			tgtadv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER; +			tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL | +				     CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); +		} else { +			tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL); +		} +  		if (tg3_ctrl != tgtadv)  			return false;  	} @@ -3909,8 +4152,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)  	}  	current_link_up = 0; -	current_speed = SPEED_INVALID; -	current_duplex = DUPLEX_INVALID; +	current_speed = SPEED_UNKNOWN; +	current_duplex = DUPLEX_UNKNOWN;  	tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE;  	tp->link_config.rmt_adv = 0; @@ -4806,8 +5049,8 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)  				    LED_CTRL_LNKLED_OVERRIDE |  				    LED_CTRL_1000MBPS_ON));  	} else { -		tp->link_config.active_speed = SPEED_INVALID; -		tp->link_config.active_duplex = DUPLEX_INVALID; +		tp->link_config.active_speed = SPEED_UNKNOWN; +		tp->link_config.active_duplex = DUPLEX_UNKNOWN;  		tw32(MAC_LED_CTRL, (tp->led_ctrl |  				    LED_CTRL_LNKLED_OVERRIDE |  				    LED_CTRL_TRAFFIC_OVERRIDE)); @@ -4855,8 +5098,8 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)  		tg3_phy_reset(tp);  	current_link_up = 0; -	current_speed = SPEED_INVALID; -	current_duplex = DUPLEX_INVALID; +	current_speed = SPEED_UNKNOWN; +	current_duplex = DUPLEX_UNKNOWN;  	tp->link_config.rmt_adv = 0;  	err |= tg3_readphy(tp, MII_BMSR, &bmsr); @@ -5921,6 +6164,7 @@ static inline void tg3_reset_task_cancel(struct tg3 *tp)  {  	cancel_work_sync(&tp->reset_task);  	tg3_flag_clear(tp, RESET_TASK_PENDING); +	tg3_flag_clear(tp, TX_RECOVERY_PENDING);  }  static int tg3_poll_msix(struct napi_struct *napi, int budget) @@ -6292,33 +6536,6 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id)  	return IRQ_RETVAL(0);  } -static int tg3_init_hw(struct tg3 *, int); -static int tg3_halt(struct tg3 *, int, int); - -/* Restart hardware after configuration changes, self-test, etc. - * Invoked with tp->lock held. - */ -static int tg3_restart_hw(struct tg3 *tp, int reset_phy) -	__releases(tp->lock) -	__acquires(tp->lock) -{ -	int err; - -	err = tg3_init_hw(tp, reset_phy); -	if (err) { -		netdev_err(tp->dev, -			   "Failed to re-initialize device, aborting\n"); -		tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); -		tg3_full_unlock(tp); -		del_timer_sync(&tp->timer); -		tp->irq_sync = 0; -		tg3_napi_enable(tp); -		dev_close(tp->dev); -		tg3_full_lock(tp, 0); -	} -	return err; -} -  #ifdef CONFIG_NET_POLL_CONTROLLER  static void tg3_poll_controller(struct net_device *dev)  { @@ -6330,50 +6547,6 @@ static void tg3_poll_controller(struct net_device *dev)  }  #endif -static void tg3_reset_task(struct work_struct *work) -{ -	struct tg3 *tp = container_of(work, struct tg3, reset_task); -	int err; - -	tg3_full_lock(tp, 0); - -	if (!netif_running(tp->dev)) { -		tg3_flag_clear(tp, RESET_TASK_PENDING); -		tg3_full_unlock(tp); -		return; -	} - -	tg3_full_unlock(tp); - -	tg3_phy_stop(tp); - -	tg3_netif_stop(tp); - -	tg3_full_lock(tp, 1); - -	if (tg3_flag(tp, TX_RECOVERY_PENDING)) { -		tp->write32_tx_mbox = tg3_write32_tx_mbox; -		tp->write32_rx_mbox = tg3_write_flush_reg32; -		tg3_flag_set(tp, MBOX_WRITE_REORDER); -		tg3_flag_clear(tp, TX_RECOVERY_PENDING); -	} - -	tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); -	err = tg3_init_hw(tp, 1); -	if (err) -		goto out; - -	tg3_netif_start(tp); - -out: -	tg3_full_unlock(tp); - -	if (!err) -		tg3_phy_start(tp); - -	tg3_flag_clear(tp, RESET_TASK_PENDING); -} -  static void tg3_tx_timeout(struct net_device *dev)  {  	struct tg3 *tp = netdev_priv(dev); @@ -6745,7 +6918,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)  			  ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0),  			    mss, vlan)) {  		would_hit_hwbug = 1; -	/* Now loop through additional data fragments, and queue them. */  	} else if (skb_shinfo(skb)->nr_frags > 0) {  		u32 tmp_mss = mss; @@ -6754,6 +6926,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)  		    !tg3_flag(tp, HW_TSO_3))  			tmp_mss = 0; +		/* Now loop through additional data +		 * fragments, and queue them. +		 */  		last = skb_shinfo(skb)->nr_frags - 1;  		for (i = 0; i <= last; i++) {  			skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -6993,66 +7168,6 @@ static int tg3_set_features(struct net_device *dev, netdev_features_t features)  	return 0;  } -static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, -			       int new_mtu) -{ -	dev->mtu = new_mtu; - -	if (new_mtu > ETH_DATA_LEN) { -		if (tg3_flag(tp, 5780_CLASS)) { -			netdev_update_features(dev); -			tg3_flag_clear(tp, TSO_CAPABLE); -		} else { -			tg3_flag_set(tp, JUMBO_RING_ENABLE); -		} -	} else { -		if (tg3_flag(tp, 5780_CLASS)) { -			tg3_flag_set(tp, TSO_CAPABLE); -			netdev_update_features(dev); -		} -		tg3_flag_clear(tp, JUMBO_RING_ENABLE); -	} -} - -static int tg3_change_mtu(struct net_device *dev, int new_mtu) -{ -	struct tg3 *tp = netdev_priv(dev); -	int err; - -	if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) -		return -EINVAL; - -	if (!netif_running(dev)) { -		/* We'll just catch it later when the -		 * device is up'd. -		 */ -		tg3_set_mtu(dev, tp, new_mtu); -		return 0; -	} - -	tg3_phy_stop(tp); - -	tg3_netif_stop(tp); - -	tg3_full_lock(tp, 1); - -	tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - -	tg3_set_mtu(dev, tp, new_mtu); - -	err = tg3_restart_hw(tp, 0); - -	if (!err) -		tg3_netif_start(tp); - -	tg3_full_unlock(tp); - -	if (!err) -		tg3_phy_start(tp); - -	return err; -} -  static void tg3_rx_prodring_free(struct tg3 *tp,  				 struct tg3_rx_prodring_set *tpr)  { @@ -7908,7 +8023,7 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent)  	if (tp->hw_stats) {  		/* Save the stats across chip resets... */ -		tg3_get_nstats(tp, &tp->net_stats_prev), +		tg3_get_nstats(tp, &tp->net_stats_prev);  		tg3_get_estats(tp, &tp->estats_prev);  		/* And make sure the next sample is new data */ @@ -7928,7 +8043,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)  	int err = 0, skip_mac_1 = 0;  	if (!is_valid_ether_addr(addr->sa_data)) -		return -EINVAL; +		return -EADDRNOTAVAIL;  	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); @@ -7976,7 +8091,6 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,  			      nic_addr);  } -static void __tg3_set_rx_mode(struct net_device *);  static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)  {  	int i; @@ -8213,6 +8327,93 @@ static void tg3_setup_rxbd_thresholds(struct tg3 *tp)  		tw32(JMB_REPLENISH_LWM, bdcache_maxcnt);  } +static inline u32 calc_crc(unsigned char *buf, int len) +{ +	u32 reg; +	u32 tmp; +	int j, k; + +	reg = 0xffffffff; + +	for (j = 0; j < len; j++) { +		reg ^= buf[j]; + +		for (k = 0; k < 8; k++) { +			tmp = reg & 0x01; + +			reg >>= 1; + +			if (tmp) +				reg ^= 0xedb88320; +		} +	} + +	return ~reg; +} + +static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all) +{ +	/* accept or reject all multicast frames */ +	tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0); +	tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0); +	tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0); +	tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0); +} + +static void __tg3_set_rx_mode(struct net_device *dev) +{ +	struct tg3 *tp = netdev_priv(dev); +	u32 rx_mode; + +	rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC | +				  RX_MODE_KEEP_VLAN_TAG); + +#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE) +	/* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG +	 * flag clear. +	 */ +	if (!tg3_flag(tp, ENABLE_ASF)) +		rx_mode |= RX_MODE_KEEP_VLAN_TAG; +#endif + +	if (dev->flags & IFF_PROMISC) { +		/* Promiscuous mode. */ +		rx_mode |= RX_MODE_PROMISC; +	} else if (dev->flags & IFF_ALLMULTI) { +		/* Accept all multicast. */ +		tg3_set_multi(tp, 1); +	} else if (netdev_mc_empty(dev)) { +		/* Reject all multicast. */ +		tg3_set_multi(tp, 0); +	} else { +		/* Accept one or more multicast(s). */ +		struct netdev_hw_addr *ha; +		u32 mc_filter[4] = { 0, }; +		u32 regidx; +		u32 bit; +		u32 crc; + +		netdev_for_each_mc_addr(ha, dev) { +			crc = calc_crc(ha->addr, ETH_ALEN); +			bit = ~crc & 0x7f; +			regidx = (bit & 0x60) >> 5; +			bit &= 0x1f; +			mc_filter[regidx] |= (1 << bit); +		} + +		tw32(MAC_HASH_REG_0, mc_filter[0]); +		tw32(MAC_HASH_REG_1, mc_filter[1]); +		tw32(MAC_HASH_REG_2, mc_filter[2]); +		tw32(MAC_HASH_REG_3, mc_filter[3]); +	} + +	if (rx_mode != tp->rx_mode) { +		tp->rx_mode = rx_mode; +		tw32_f(MAC_RX_MODE, rx_mode); +		udelay(10); +	} +} +  static void tg3_rss_init_dflt_indir_tbl(struct tg3 *tp)  {  	int i; @@ -8688,9 +8889,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)  	if (tg3_flag(tp, PCI_EXPRESS))  		rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; -	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) -		rdmac_mode |= RDMAC_MODE_JMB_2K_MMRR; -  	if (tg3_flag(tp, HW_TSO_1) ||  	    tg3_flag(tp, HW_TSO_2) ||  	    tg3_flag(tp, HW_TSO_3)) @@ -9037,12 +9235,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)  	}  	if (!tg3_flag(tp, USE_PHYLIB)) { -		if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { +		if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)  			tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER; -			tp->link_config.speed = tp->link_config.orig_speed; -			tp->link_config.duplex = tp->link_config.orig_duplex; -			tp->link_config.autoneg = tp->link_config.orig_autoneg; -		}  		err = tg3_setup_phy(tp, 0);  		if (err) @@ -9345,6 +9539,108 @@ restart_timer:  	add_timer(&tp->timer);  } +static void __devinit tg3_timer_init(struct tg3 *tp) +{ +	if (tg3_flag(tp, TAGGED_STATUS) && +	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && +	    !tg3_flag(tp, 57765_CLASS)) +		tp->timer_offset = HZ; +	else +		tp->timer_offset = HZ / 10; + +	BUG_ON(tp->timer_offset > HZ); + +	tp->timer_multiplier = (HZ / tp->timer_offset); +	tp->asf_multiplier = (HZ / tp->timer_offset) * +			     TG3_FW_UPDATE_FREQ_SEC; + +	init_timer(&tp->timer); +	tp->timer.data = (unsigned long) tp; +	tp->timer.function = tg3_timer; +} + +static void tg3_timer_start(struct tg3 *tp) +{ +	tp->asf_counter   = tp->asf_multiplier; +	tp->timer_counter = tp->timer_multiplier; + +	tp->timer.expires = jiffies + tp->timer_offset; +	add_timer(&tp->timer); +} + +static void tg3_timer_stop(struct tg3 *tp) +{ +	del_timer_sync(&tp->timer); +} + +/* Restart hardware after configuration changes, self-test, etc. + * Invoked with tp->lock held. + */ +static int tg3_restart_hw(struct tg3 *tp, int reset_phy) +	__releases(tp->lock) +	__acquires(tp->lock) +{ +	int err; + +	err = tg3_init_hw(tp, reset_phy); +	if (err) { +		netdev_err(tp->dev, +			   "Failed to re-initialize device, aborting\n"); +		tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); +		tg3_full_unlock(tp); +		tg3_timer_stop(tp); +		tp->irq_sync = 0; +		tg3_napi_enable(tp); +		dev_close(tp->dev); +		tg3_full_lock(tp, 0); +	} +	return err; +} + +static void tg3_reset_task(struct work_struct *work) +{ +	struct tg3 *tp = container_of(work, struct tg3, reset_task); +	int err; + +	tg3_full_lock(tp, 0); + +	if (!netif_running(tp->dev)) { +		tg3_flag_clear(tp, RESET_TASK_PENDING); +		tg3_full_unlock(tp); +		return; +	} + +	tg3_full_unlock(tp); + +	tg3_phy_stop(tp); + +	tg3_netif_stop(tp); + +	tg3_full_lock(tp, 1); + +	if (tg3_flag(tp, TX_RECOVERY_PENDING)) { +		tp->write32_tx_mbox = tg3_write32_tx_mbox; +		tp->write32_rx_mbox = tg3_write_flush_reg32; +		tg3_flag_set(tp, MBOX_WRITE_REORDER); +		tg3_flag_clear(tp, TX_RECOVERY_PENDING); +	} + +	tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); +	err = tg3_init_hw(tp, 1); +	if (err) +		goto out; + +	tg3_netif_start(tp); + +out: +	tg3_full_unlock(tp); + +	if (!err) +		tg3_phy_start(tp); + +	tg3_flag_clear(tp, RESET_TASK_PENDING); +} +  static int tg3_request_irq(struct tg3 *tp, int irq_num)  {  	irq_handler_t fn; @@ -9399,7 +9695,7 @@ static int tg3_test_interrupt(struct tg3 *tp)  	}  	err = request_irq(tnapi->irq_vec, tg3_test_isr, -			  IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi); +			  IRQF_SHARED, dev->name, tnapi);  	if (err)  		return err; @@ -9710,24 +10006,6 @@ static int tg3_open(struct net_device *dev)  	if (err) {  		tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);  		tg3_free_rings(tp); -	} else { -		if (tg3_flag(tp, TAGGED_STATUS) && -		    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && -		    !tg3_flag(tp, 57765_CLASS)) -			tp->timer_offset = HZ; -		else -			tp->timer_offset = HZ / 10; - -		BUG_ON(tp->timer_offset > HZ); -		tp->timer_counter = tp->timer_multiplier = -			(HZ / tp->timer_offset); -		tp->asf_counter = tp->asf_multiplier = -			((HZ / tp->timer_offset) * 2); - -		init_timer(&tp->timer); -		tp->timer.expires = jiffies + tp->timer_offset; -		tp->timer.data = (unsigned long) tp; -		tp->timer.function = tg3_timer;  	}  	tg3_full_unlock(tp); @@ -9759,7 +10037,7 @@ static int tg3_open(struct net_device *dev)  	tg3_full_lock(tp, 0); -	add_timer(&tp->timer); +	tg3_timer_start(tp);  	tg3_flag_set(tp, INIT_COMPLETE);  	tg3_enable_ints(tp); @@ -9804,7 +10082,7 @@ static int tg3_close(struct net_device *dev)  	netif_tx_stop_all_queues(dev); -	del_timer_sync(&tp->timer); +	tg3_timer_stop(tp);  	tg3_phy_stop(tp); @@ -9878,9 +10156,6 @@ static void tg3_get_estats(struct tg3 *tp, struct tg3_ethtool_stats *estats)  	struct tg3_ethtool_stats *old_estats = &tp->estats_prev;  	struct tg3_hw_stats *hw_stats = tp->hw_stats; -	if (!hw_stats) -		return; -  	ESTAT_ADD(rx_octets);  	ESTAT_ADD(rx_fragments);  	ESTAT_ADD(rx_ucast_packets); @@ -10016,105 +10291,6 @@ static void tg3_get_nstats(struct tg3 *tp, struct rtnl_link_stats64 *stats)  	stats->tx_dropped = tp->tx_dropped;  } -static inline u32 calc_crc(unsigned char *buf, int len) -{ -	u32 reg; -	u32 tmp; -	int j, k; - -	reg = 0xffffffff; - -	for (j = 0; j < len; j++) { -		reg ^= buf[j]; - -		for (k = 0; k < 8; k++) { -			tmp = reg & 0x01; - -			reg >>= 1; - -			if (tmp) -				reg ^= 0xedb88320; -		} -	} - -	return ~reg; -} - -static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all) -{ -	/* accept or reject all multicast frames */ -	tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0); -	tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0); -	tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0); -	tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0); -} - -static void __tg3_set_rx_mode(struct net_device *dev) -{ -	struct tg3 *tp = netdev_priv(dev); -	u32 rx_mode; - -	rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC | -				  RX_MODE_KEEP_VLAN_TAG); - -#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE) -	/* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG -	 * flag clear. -	 */ -	if (!tg3_flag(tp, ENABLE_ASF)) -		rx_mode |= RX_MODE_KEEP_VLAN_TAG; -#endif - -	if (dev->flags & IFF_PROMISC) { -		/* Promiscuous mode. */ -		rx_mode |= RX_MODE_PROMISC; -	} else if (dev->flags & IFF_ALLMULTI) { -		/* Accept all multicast. */ -		tg3_set_multi(tp, 1); -	} else if (netdev_mc_empty(dev)) { -		/* Reject all multicast. */ -		tg3_set_multi(tp, 0); -	} else { -		/* Accept one or more multicast(s). */ -		struct netdev_hw_addr *ha; -		u32 mc_filter[4] = { 0, }; -		u32 regidx; -		u32 bit; -		u32 crc; - -		netdev_for_each_mc_addr(ha, dev) { -			crc = calc_crc(ha->addr, ETH_ALEN); -			bit = ~crc & 0x7f; -			regidx = (bit & 0x60) >> 5; -			bit &= 0x1f; -			mc_filter[regidx] |= (1 << bit); -		} - -		tw32(MAC_HASH_REG_0, mc_filter[0]); -		tw32(MAC_HASH_REG_1, mc_filter[1]); -		tw32(MAC_HASH_REG_2, mc_filter[2]); -		tw32(MAC_HASH_REG_3, mc_filter[3]); -	} - -	if (rx_mode != tp->rx_mode) { -		tp->rx_mode = rx_mode; -		tw32_f(MAC_RX_MODE, rx_mode); -		udelay(10); -	} -} - -static void tg3_set_rx_mode(struct net_device *dev) -{ -	struct tg3 *tp = netdev_priv(dev); - -	if (!netif_running(dev)) -		return; - -	tg3_full_lock(tp, 0); -	__tg3_set_rx_mode(dev); -	tg3_full_unlock(tp); -} -  static int tg3_get_regs_len(struct net_device *dev)  {  	return TG3_REG_BLK_SIZE; @@ -10209,8 +10385,6 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,  	return 0;  } -static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); -  static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)  {  	struct tg3 *tp = netdev_priv(dev); @@ -10324,8 +10498,8 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)  				cmd->eth_tp_mdix = ETH_TP_MDI;  		}  	} else { -		ethtool_cmd_speed_set(cmd, SPEED_INVALID); -		cmd->duplex = DUPLEX_INVALID; +		ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); +		cmd->duplex = DUPLEX_UNKNOWN;  		cmd->eth_tp_mdix = ETH_TP_MDI_INVALID;  	}  	cmd->phy_address = tp->phy_addr; @@ -10407,18 +10581,14 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)  	if (cmd->autoneg == AUTONEG_ENABLE) {  		tp->link_config.advertising = (cmd->advertising |  					      ADVERTISED_Autoneg); -		tp->link_config.speed = SPEED_INVALID; -		tp->link_config.duplex = DUPLEX_INVALID; +		tp->link_config.speed = SPEED_UNKNOWN; +		tp->link_config.duplex = DUPLEX_UNKNOWN;  	} else {  		tp->link_config.advertising = 0;  		tp->link_config.speed = speed;  		tp->link_config.duplex = cmd->duplex;  	} -	tp->link_config.orig_speed = tp->link_config.speed; -	tp->link_config.orig_duplex = tp->link_config.duplex; -	tp->link_config.orig_autoneg = tp->link_config.autoneg; -  	if (netif_running(dev))  		tg3_setup_phy(tp, 1); @@ -10665,10 +10835,10 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam  			if (!epause->autoneg)  				tg3_setup_flow_control(tp, 0, 0);  		} else { -			tp->link_config.orig_advertising &= +			tp->link_config.advertising &=  					~(ADVERTISED_Pause |  					  ADVERTISED_Asym_Pause); -			tp->link_config.orig_advertising |= newadv; +			tp->link_config.advertising |= newadv;  		}  	} else {  		int irq_sync = 0; @@ -10845,7 +11015,10 @@ static void tg3_get_ethtool_stats(struct net_device *dev,  {  	struct tg3 *tp = netdev_priv(dev); -	tg3_get_estats(tp, (struct tg3_ethtool_stats *)tmp_stats); +	if (tp->hw_stats) +		tg3_get_estats(tp, (struct tg3_ethtool_stats *)tmp_stats); +	else +		memset(tmp_stats, 0, sizeof(struct tg3_ethtool_stats));  }  static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen) @@ -12026,6 +12199,111 @@ static const struct ethtool_ops tg3_ethtool_ops = {  	.set_rxfh_indir		= tg3_set_rxfh_indir,  }; +static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, +						struct rtnl_link_stats64 *stats) +{ +	struct tg3 *tp = netdev_priv(dev); + +	if (!tp->hw_stats) +		return &tp->net_stats_prev; + +	spin_lock_bh(&tp->lock); +	tg3_get_nstats(tp, stats); +	spin_unlock_bh(&tp->lock); + +	return stats; +} + +static void tg3_set_rx_mode(struct net_device *dev) +{ +	struct tg3 *tp = netdev_priv(dev); + +	if (!netif_running(dev)) +		return; + +	tg3_full_lock(tp, 0); +	__tg3_set_rx_mode(dev); +	tg3_full_unlock(tp); +} + +static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, +			       int new_mtu) +{ +	dev->mtu = new_mtu; + +	if (new_mtu > ETH_DATA_LEN) { +		if (tg3_flag(tp, 5780_CLASS)) { +			netdev_update_features(dev); +			tg3_flag_clear(tp, TSO_CAPABLE); +		} else { +			tg3_flag_set(tp, JUMBO_RING_ENABLE); +		} +	} else { +		if (tg3_flag(tp, 5780_CLASS)) { +			tg3_flag_set(tp, TSO_CAPABLE); +			netdev_update_features(dev); +		} +		tg3_flag_clear(tp, JUMBO_RING_ENABLE); +	} +} + +static int tg3_change_mtu(struct net_device *dev, int new_mtu) +{ +	struct tg3 *tp = netdev_priv(dev); +	int err; + +	if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) +		return -EINVAL; + +	if (!netif_running(dev)) { +		/* We'll just catch it later when the +		 * device is up'd. +		 */ +		tg3_set_mtu(dev, tp, new_mtu); +		return 0; +	} + +	tg3_phy_stop(tp); + +	tg3_netif_stop(tp); + +	tg3_full_lock(tp, 1); + +	tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); + +	tg3_set_mtu(dev, tp, new_mtu); + +	err = tg3_restart_hw(tp, 0); + +	if (!err) +		tg3_netif_start(tp); + +	tg3_full_unlock(tp); + +	if (!err) +		tg3_phy_start(tp); + +	return err; +} + +static const struct net_device_ops tg3_netdev_ops = { +	.ndo_open		= tg3_open, +	.ndo_stop		= tg3_close, +	.ndo_start_xmit		= tg3_start_xmit, +	.ndo_get_stats64	= tg3_get_stats64, +	.ndo_validate_addr	= eth_validate_addr, +	.ndo_set_rx_mode	= tg3_set_rx_mode, +	.ndo_set_mac_address	= tg3_set_mac_addr, +	.ndo_do_ioctl		= tg3_ioctl, +	.ndo_tx_timeout		= tg3_tx_timeout, +	.ndo_change_mtu		= tg3_change_mtu, +	.ndo_fix_features	= tg3_fix_features, +	.ndo_set_features	= tg3_set_features, +#ifdef CONFIG_NET_POLL_CONTROLLER +	.ndo_poll_controller	= tg3_poll_controller, +#endif +}; +  static void __devinit tg3_get_eeprom_size(struct tg3 *tp)  {  	u32 cursize, val, magic; @@ -12717,254 +12995,6 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)  	}  } -static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, -				    u32 offset, u32 len, u8 *buf) -{ -	int i, j, rc = 0; -	u32 val; - -	for (i = 0; i < len; i += 4) { -		u32 addr; -		__be32 data; - -		addr = offset + i; - -		memcpy(&data, buf + i, 4); - -		/* -		 * The SEEPROM interface expects the data to always be opposite -		 * the native endian format.  We accomplish this by reversing -		 * all the operations that would have been performed on the -		 * data from a call to tg3_nvram_read_be32(). -		 */ -		tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data))); - -		val = tr32(GRC_EEPROM_ADDR); -		tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); - -		val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | -			EEPROM_ADDR_READ); -		tw32(GRC_EEPROM_ADDR, val | -			(0 << EEPROM_ADDR_DEVID_SHIFT) | -			(addr & EEPROM_ADDR_ADDR_MASK) | -			EEPROM_ADDR_START | -			EEPROM_ADDR_WRITE); - -		for (j = 0; j < 1000; j++) { -			val = tr32(GRC_EEPROM_ADDR); - -			if (val & EEPROM_ADDR_COMPLETE) -				break; -			msleep(1); -		} -		if (!(val & EEPROM_ADDR_COMPLETE)) { -			rc = -EBUSY; -			break; -		} -	} - -	return rc; -} - -/* offset and length are dword aligned */ -static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, -		u8 *buf) -{ -	int ret = 0; -	u32 pagesize = tp->nvram_pagesize; -	u32 pagemask = pagesize - 1; -	u32 nvram_cmd; -	u8 *tmp; - -	tmp = kmalloc(pagesize, GFP_KERNEL); -	if (tmp == NULL) -		return -ENOMEM; - -	while (len) { -		int j; -		u32 phy_addr, page_off, size; - -		phy_addr = offset & ~pagemask; - -		for (j = 0; j < pagesize; j += 4) { -			ret = tg3_nvram_read_be32(tp, phy_addr + j, -						  (__be32 *) (tmp + j)); -			if (ret) -				break; -		} -		if (ret) -			break; - -		page_off = offset & pagemask; -		size = pagesize; -		if (len < size) -			size = len; - -		len -= size; - -		memcpy(tmp + page_off, buf, size); - -		offset = offset + (pagesize - page_off); - -		tg3_enable_nvram_access(tp); - -		/* -		 * Before we can erase the flash page, we need -		 * to issue a special "write enable" command. -		 */ -		nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; - -		if (tg3_nvram_exec_cmd(tp, nvram_cmd)) -			break; - -		/* Erase the target page */ -		tw32(NVRAM_ADDR, phy_addr); - -		nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | -			NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; - -		if (tg3_nvram_exec_cmd(tp, nvram_cmd)) -			break; - -		/* Issue another write enable to start the write. */ -		nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; - -		if (tg3_nvram_exec_cmd(tp, nvram_cmd)) -			break; - -		for (j = 0; j < pagesize; j += 4) { -			__be32 data; - -			data = *((__be32 *) (tmp + j)); - -			tw32(NVRAM_WRDATA, be32_to_cpu(data)); - -			tw32(NVRAM_ADDR, phy_addr + j); - -			nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | -				NVRAM_CMD_WR; - -			if (j == 0) -				nvram_cmd |= NVRAM_CMD_FIRST; -			else if (j == (pagesize - 4)) -				nvram_cmd |= NVRAM_CMD_LAST; - -			if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) -				break; -		} -		if (ret) -			break; -	} - -	nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; -	tg3_nvram_exec_cmd(tp, nvram_cmd); - -	kfree(tmp); - -	return ret; -} - -/* offset and length are dword aligned */ -static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, -		u8 *buf) -{ -	int i, ret = 0; - -	for (i = 0; i < len; i += 4, offset += 4) { -		u32 page_off, phy_addr, nvram_cmd; -		__be32 data; - -		memcpy(&data, buf + i, 4); -		tw32(NVRAM_WRDATA, be32_to_cpu(data)); - -		page_off = offset % tp->nvram_pagesize; - -		phy_addr = tg3_nvram_phys_addr(tp, offset); - -		tw32(NVRAM_ADDR, phy_addr); - -		nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; - -		if (page_off == 0 || i == 0) -			nvram_cmd |= NVRAM_CMD_FIRST; -		if (page_off == (tp->nvram_pagesize - 4)) -			nvram_cmd |= NVRAM_CMD_LAST; - -		if (i == (len - 4)) -			nvram_cmd |= NVRAM_CMD_LAST; - -		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && -		    !tg3_flag(tp, 5755_PLUS) && -		    (tp->nvram_jedecnum == JEDEC_ST) && -		    (nvram_cmd & NVRAM_CMD_FIRST)) { - -			if ((ret = tg3_nvram_exec_cmd(tp, -				NVRAM_CMD_WREN | NVRAM_CMD_GO | -				NVRAM_CMD_DONE))) - -				break; -		} -		if (!tg3_flag(tp, FLASH)) { -			/* We always do complete word writes to eeprom. */ -			nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); -		} - -		if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) -			break; -	} -	return ret; -} - -/* offset and length are dword aligned */ -static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) -{ -	int ret; - -	if (tg3_flag(tp, EEPROM_WRITE_PROT)) { -		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & -		       ~GRC_LCLCTRL_GPIO_OUTPUT1); -		udelay(40); -	} - -	if (!tg3_flag(tp, NVRAM)) { -		ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); -	} else { -		u32 grc_mode; - -		ret = tg3_nvram_lock(tp); -		if (ret) -			return ret; - -		tg3_enable_nvram_access(tp); -		if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) -			tw32(NVRAM_WRITE1, 0x406); - -		grc_mode = tr32(GRC_MODE); -		tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); - -		if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) { -			ret = tg3_nvram_write_block_buffered(tp, offset, len, -				buf); -		} else { -			ret = tg3_nvram_write_block_unbuffered(tp, offset, len, -				buf); -		} - -		grc_mode = tr32(GRC_MODE); -		tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); - -		tg3_disable_nvram_access(tp); -		tg3_nvram_unlock(tp); -	} - -	if (tg3_flag(tp, EEPROM_WRITE_PROT)) { -		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); -		udelay(40); -	} - -	return ret; -} -  struct subsys_tbl_ent {  	u16 subsys_vendor, subsys_devid;  	u32 phy_id; @@ -13315,14 +13345,13 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp)  		adv |= ADVERTISED_FIBRE;  	tp->link_config.advertising = adv; -	tp->link_config.speed = SPEED_INVALID; -	tp->link_config.duplex = DUPLEX_INVALID; +	tp->link_config.speed = SPEED_UNKNOWN; +	tp->link_config.duplex = DUPLEX_UNKNOWN;  	tp->link_config.autoneg = AUTONEG_ENABLE; -	tp->link_config.active_speed = SPEED_INVALID; -	tp->link_config.active_duplex = DUPLEX_INVALID; -	tp->link_config.orig_speed = SPEED_INVALID; -	tp->link_config.orig_duplex = DUPLEX_INVALID; -	tp->link_config.orig_autoneg = AUTONEG_INVALID; +	tp->link_config.active_speed = SPEED_UNKNOWN; +	tp->link_config.active_duplex = DUPLEX_UNKNOWN; + +	tp->old_link = -1;  }  static int __devinit tg3_phy_probe(struct tg3 *tp) @@ -13819,8 +13848,6 @@ done:  	tp->fw_ver[TG3_VER_SIZE - 1] = 0;  } -static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); -  static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)  {  	if (tg3_flag(tp, LRG_PROD_RING_CAP)) @@ -13838,49 +13865,50 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {  	{ },  }; -static int __devinit tg3_get_invariants(struct tg3 *tp) +static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)  { -	u32 misc_ctrl_reg; -	u32 pci_state_reg, grc_misc_cfg; -	u32 val; -	u16 pci_cmd; -	int err; +	struct pci_dev *peer; +	unsigned int func, devnr = tp->pdev->devfn & ~7; -	/* Force memory write invalidate off.  If we leave it on, -	 * then on 5700_BX chips we have to enable a workaround. -	 * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary -	 * to match the cacheline size.  The Broadcom driver have this -	 * workaround but turns MWI off all the times so never uses -	 * it.  This seems to suggest that the workaround is insufficient. +	for (func = 0; func < 8; func++) { +		peer = pci_get_slot(tp->pdev->bus, devnr | func); +		if (peer && peer != tp->pdev) +			break; +		pci_dev_put(peer); +	} +	/* 5704 can be configured in single-port mode, set peer to +	 * tp->pdev in that case.  	 */ -	pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); -	pci_cmd &= ~PCI_COMMAND_INVALIDATE; -	pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); +	if (!peer) { +		peer = tp->pdev; +		return peer; +	} -	/* Important! -- Make sure register accesses are byteswapped -	 * correctly.  Also, for those chips that require it, make -	 * sure that indirect register accesses are enabled before -	 * the first operation. +	/* +	 * We don't need to keep the refcount elevated; there's no way +	 * to remove one half of this device without removing the other  	 */ -	pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, -			      &misc_ctrl_reg); -	tp->misc_host_ctrl |= (misc_ctrl_reg & -			       MISC_HOST_CTRL_CHIPREV); -	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, -			       tp->misc_host_ctrl); +	pci_dev_put(peer); + +	return peer; +} -	tp->pci_chip_rev_id = (misc_ctrl_reg >> -			       MISC_HOST_CTRL_CHIPREV_SHIFT); +static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg) +{ +	tp->pci_chip_rev_id = misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT;  	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) { -		u32 prod_id_asic_rev; +		u32 reg; + +		/* All devices that use the alternate +		 * ASIC REV location have a CPMU. +		 */ +		tg3_flag_set(tp, CPMU_PRESENT);  		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||  		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||  		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||  		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) -			pci_read_config_dword(tp->pdev, -					      TG3PCI_GEN2_PRODID_ASICREV, -					      &prod_id_asic_rev); +			reg = TG3PCI_GEN2_PRODID_ASICREV;  		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 ||  			 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 ||  			 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 || @@ -13891,14 +13919,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)  			 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57766 ||  			 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57782 ||  			 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57786) -			pci_read_config_dword(tp->pdev, -					      TG3PCI_GEN15_PRODID_ASICREV, -					      &prod_id_asic_rev); +			reg = TG3PCI_GEN15_PRODID_ASICREV;  		else -			pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV, -					      &prod_id_asic_rev); +			reg = TG3PCI_PRODID_ASICREV; -		tp->pci_chip_rev_id = prod_id_asic_rev; +		pci_read_config_dword(tp->pdev, reg, &tp->pci_chip_rev_id);  	}  	/* Wrong chip ID in 5752 A0. This code can be removed later @@ -13907,6 +13932,77 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)  	if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)  		tp->pci_chip_rev_id = CHIPREV_ID_5752_A0; +	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) +		tg3_flag_set(tp, 5717_PLUS); + +	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) +		tg3_flag_set(tp, 57765_CLASS); + +	if (tg3_flag(tp, 57765_CLASS) || tg3_flag(tp, 5717_PLUS)) +		tg3_flag_set(tp, 57765_PLUS); + +	/* Intentionally exclude ASIC_REV_5906 */ +	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || +	    tg3_flag(tp, 57765_PLUS)) +		tg3_flag_set(tp, 5755_PLUS); + +	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) +		tg3_flag_set(tp, 5780_CLASS); + +	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || +	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 || +	    tg3_flag(tp, 5755_PLUS) || +	    tg3_flag(tp, 5780_CLASS)) +		tg3_flag_set(tp, 5750_PLUS); + +	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +	    tg3_flag(tp, 5750_PLUS)) +		tg3_flag_set(tp, 5705_PLUS); +} + +static int __devinit tg3_get_invariants(struct tg3 *tp) +{ +	u32 misc_ctrl_reg; +	u32 pci_state_reg, grc_misc_cfg; +	u32 val; +	u16 pci_cmd; +	int err; + +	/* Force memory write invalidate off.  If we leave it on, +	 * then on 5700_BX chips we have to enable a workaround. +	 * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary +	 * to match the cacheline size.  The Broadcom driver have this +	 * workaround but turns MWI off all the times so never uses +	 * it.  This seems to suggest that the workaround is insufficient. +	 */ +	pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); +	pci_cmd &= ~PCI_COMMAND_INVALIDATE; +	pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); + +	/* Important! -- Make sure register accesses are byteswapped +	 * correctly.  Also, for those chips that require it, make +	 * sure that indirect register accesses are enabled before +	 * the first operation. +	 */ +	pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, +			      &misc_ctrl_reg); +	tp->misc_host_ctrl |= (misc_ctrl_reg & +			       MISC_HOST_CTRL_CHIPREV); +	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, +			       tp->misc_host_ctrl); + +	tg3_detect_asic_rev(tp, misc_ctrl_reg); +  	/* If we have 5702/03 A1 or A2 on certain ICH chipsets,  	 * we need to disable memory and use config. cycles  	 * only to access all registers. The 5702/03 chips @@ -14003,9 +14099,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)  	 * Any tg3 device found behind the bridge will also need the 40-bit  	 * DMA workaround.  	 */ -	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { -		tg3_flag_set(tp, 5780_CLASS); +	if (tg3_flag(tp, 5780_CLASS)) {  		tg3_flag_set(tp, 40BIT_DMA_BUG);  		tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);  	} else { @@ -14031,39 +14125,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)  	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)  		tp->pdev_peer = tg3_find_peer(tp); -	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) -		tg3_flag_set(tp, 5717_PLUS); - -	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) -		tg3_flag_set(tp, 57765_CLASS); - -	if (tg3_flag(tp, 57765_CLASS) || tg3_flag(tp, 5717_PLUS)) -		tg3_flag_set(tp, 57765_PLUS); - -	/* Intentionally exclude ASIC_REV_5906 */ -	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || -	    tg3_flag(tp, 57765_PLUS)) -		tg3_flag_set(tp, 5755_PLUS); - -	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 || -	    tg3_flag(tp, 5755_PLUS) || -	    tg3_flag(tp, 5780_CLASS)) -		tg3_flag_set(tp, 5750_PLUS); - -	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || -	    tg3_flag(tp, 5750_PLUS)) -		tg3_flag_set(tp, 5705_PLUS); -  	/* Determine TSO capabilities */  	if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0)  		; /* Do nothing. HW bug. */ @@ -14135,8 +14196,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)  	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)  		tp->dma_limit = TG3_TX_BD_DMA_MAX_4K; -	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) -		tp->dma_limit = TG3_TX_BD_DMA_MAX_2K;  	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||  	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || @@ -14395,13 +14454,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)  		tg3_ape_lock_init(tp);  	} -	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || -	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || -	    tg3_flag(tp, 57765_PLUS)) -		tg3_flag_set(tp, CPMU_PRESENT); -  	/* Set up tp->grc_local_ctrl before calling  	 * tg3_pwrsrc_switch_to_vmain().  GPIO1 driven high  	 * will bring 5700's external PHY out of reset. @@ -15336,34 +15388,6 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)  	return str;  } -static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp) -{ -	struct pci_dev *peer; -	unsigned int func, devnr = tp->pdev->devfn & ~7; - -	for (func = 0; func < 8; func++) { -		peer = pci_get_slot(tp->pdev->bus, devnr | func); -		if (peer && peer != tp->pdev) -			break; -		pci_dev_put(peer); -	} -	/* 5704 can be configured in single-port mode, set peer to -	 * tp->pdev in that case. -	 */ -	if (!peer) { -		peer = tp->pdev; -		return peer; -	} - -	/* -	 * We don't need to keep the refcount elevated; there's no way -	 * to remove one half of this device without removing the other -	 */ -	pci_dev_put(peer); - -	return peer; -} -  static void __devinit tg3_init_coal(struct tg3 *tp)  {  	struct ethtool_coalesce *ec = &tp->coal; @@ -15395,39 +15419,6 @@ static void __devinit tg3_init_coal(struct tg3 *tp)  	}  } -static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, -						struct rtnl_link_stats64 *stats) -{ -	struct tg3 *tp = netdev_priv(dev); - -	if (!tp->hw_stats) -		return &tp->net_stats_prev; - -	spin_lock_bh(&tp->lock); -	tg3_get_nstats(tp, stats); -	spin_unlock_bh(&tp->lock); - -	return stats; -} - -static const struct net_device_ops tg3_netdev_ops = { -	.ndo_open		= tg3_open, -	.ndo_stop		= tg3_close, -	.ndo_start_xmit		= tg3_start_xmit, -	.ndo_get_stats64	= tg3_get_stats64, -	.ndo_validate_addr	= eth_validate_addr, -	.ndo_set_rx_mode	= tg3_set_rx_mode, -	.ndo_set_mac_address	= tg3_set_mac_addr, -	.ndo_do_ioctl		= tg3_ioctl, -	.ndo_tx_timeout		= tg3_tx_timeout, -	.ndo_change_mtu		= tg3_change_mtu, -	.ndo_fix_features	= tg3_fix_features, -	.ndo_set_features	= tg3_set_features, -#ifdef CONFIG_NET_POLL_CONTROLLER -	.ndo_poll_controller	= tg3_poll_controller, -#endif -}; -  static int __devinit tg3_init_one(struct pci_dev *pdev,  				  const struct pci_device_id *ent)  { @@ -15472,7 +15463,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,  	dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS);  	if (!dev) { -		dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n");  		err = -ENOMEM;  		goto err_out_power_down;  	} @@ -15729,6 +15719,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,  		tg3_frob_aux_power(tp, false);  	} +	tg3_timer_init(tp); +  	err = register_netdev(dev);  	if (err) {  		dev_err(&pdev->dev, "Cannot register net device, aborting\n"); @@ -15854,7 +15846,7 @@ static int tg3_suspend(struct device *device)  	tg3_phy_stop(tp);  	tg3_netif_stop(tp); -	del_timer_sync(&tp->timer); +	tg3_timer_stop(tp);  	tg3_full_lock(tp, 1);  	tg3_disable_ints(tp); @@ -15878,8 +15870,7 @@ static int tg3_suspend(struct device *device)  		if (err2)  			goto out; -		tp->timer.expires = jiffies + tp->timer_offset; -		add_timer(&tp->timer); +		tg3_timer_start(tp);  		netif_device_attach(dev);  		tg3_netif_start(tp); @@ -15913,8 +15904,7 @@ static int tg3_resume(struct device *device)  	if (err)  		goto out; -	tp->timer.expires = jiffies + tp->timer_offset; -	add_timer(&tp->timer); +	tg3_timer_start(tp);  	tg3_netif_start(tp); @@ -15962,11 +15952,10 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,  	tg3_netif_stop(tp); -	del_timer_sync(&tp->timer); +	tg3_timer_stop(tp);  	/* Want to make sure that the reset task doesn't run */  	tg3_reset_task_cancel(tp); -	tg3_flag_clear(tp, TX_RECOVERY_PENDING);  	netif_device_detach(netdev); @@ -16059,8 +16048,7 @@ static void tg3_io_resume(struct pci_dev *pdev)  	netif_device_attach(netdev); -	tp->timer.expires = jiffies + tp->timer_offset; -	add_timer(&tp->timer); +	tg3_timer_start(tp);  	tg3_netif_start(tp);  |