patch-2.4.26 linux-2.4.26/drivers/net/tg3.c

Next file: linux-2.4.26/drivers/net/tg3.h
Previous file: linux-2.4.26/drivers/net/sungem.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.25/drivers/net/tg3.c linux-2.4.26/drivers/net/tg3.c
@@ -55,8 +55,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"2.6"
-#define DRV_MODULE_RELDATE	"February 3, 2004"
+#define DRV_MODULE_VERSION	"2.9"
+#define DRV_MODULE_RELDATE	"March 8, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -191,6 +191,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ 0, }
 };
 
@@ -212,8 +214,46 @@
 	}
 }
 
+static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
+{
+	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&tp->indirect_lock, flags);
+		pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+		pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+		spin_unlock_irqrestore(&tp->indirect_lock, flags);
+	} else {
+		unsigned long dest = tp->regs + off;
+		writel(val, dest);
+		readl(dest);    /* always flush PCI write */
+	}
+}
+
+static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
+{
+	unsigned long mbox = tp->regs + off;
+	writel(val, mbox);
+	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+		readl(mbox);
+}
+
+static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
+{
+	unsigned long mbox = tp->regs + off;
+	writel(val, mbox);
+	if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
+		writel(val, mbox);
+	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+		readl(mbox);
+}
+
+#define tw32_mailbox(reg, val)  writel(((val) & 0xffffffff), tp->regs + (reg))
+#define tw32_rx_mbox(reg, val)  _tw32_rx_mbox(tp, reg, val)
+#define tw32_tx_mbox(reg, val)  _tw32_tx_mbox(tp, reg, val)
+
 #define tw32(reg,val)		tg3_write_indirect_reg32(tp,(reg),(val))
-#define tw32_mailbox(reg, val)	writel(((val) & 0xffffffff), tp->regs + (reg))
+#define tw32_f(reg,val)		_tw32_flush(tp,(reg),(val))
 #define tw16(reg,val)		writew(((val) & 0xffff), tp->regs + (reg))
 #define tw8(reg,val)		writeb(((val) & 0xff), tp->regs + (reg))
 #define tr32(reg)		readl(tp->regs + (reg))
@@ -300,18 +340,15 @@
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
 	    (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
-		tw32(TG3PCI_CLOCK_CTRL,
+		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl |
 		     (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
-		tr32(TG3PCI_CLOCK_CTRL);
 		udelay(40);
-		tw32(TG3PCI_CLOCK_CTRL,
+		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl | (CLOCK_CTRL_ALTCLK));
-		tr32(TG3PCI_CLOCK_CTRL);
 		udelay(40);
 	}
-	tw32(TG3PCI_CLOCK_CTRL, clock_ctrl);
-	tr32(TG3PCI_CLOCK_CTRL);
+	tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl);
 	udelay(40);
 }
 
@@ -323,9 +360,8 @@
 	int loops, ret;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE,
+		tw32_f(MAC_MI_MODE,
 		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
-		tr32(MAC_MI_MODE);
 		udelay(40);
 	}
 
@@ -337,8 +373,7 @@
 		      MI_COM_REG_ADDR_MASK);
 	frame_val |= (MI_COM_CMD_READ | MI_COM_START);
 	
-	tw32(MAC_MI_COM, frame_val);
-	tr32(MAC_MI_COM);
+	tw32_f(MAC_MI_COM, frame_val);
 
 	loops = PHY_BUSY_LOOPS;
 	while (loops-- > 0) {
@@ -359,8 +394,7 @@
 	}
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE, tp->mi_mode);
-		tr32(MAC_MI_MODE);
+		tw32_f(MAC_MI_MODE, tp->mi_mode);
 		udelay(40);
 	}
 
@@ -373,9 +407,8 @@
 	int loops, ret;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE,
+		tw32_f(MAC_MI_MODE,
 		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
-		tr32(MAC_MI_MODE);
 		udelay(40);
 	}
 
@@ -386,8 +419,7 @@
 	frame_val |= (val & MI_COM_DATA_MASK);
 	frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
 	
-	tw32(MAC_MI_COM, frame_val);
-	tr32(MAC_MI_COM);
+	tw32_f(MAC_MI_COM, frame_val);
 
 	loops = PHY_BUSY_LOOPS;
 	while (loops-- > 0) {
@@ -405,8 +437,7 @@
 		ret = 0;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE, tp->mi_mode);
-		tr32(MAC_MI_MODE);
+		tw32_f(MAC_MI_MODE, tp->mi_mode);
 		udelay(40);
 	}
 
@@ -655,6 +686,18 @@
 		return err;
 
 out:
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
+		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa);
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0323);
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+	}
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_5704_A0_BUG) {
+		tg3_writephy(tp, 0x1c, 0x8d68);
+		tg3_writephy(tp, 0x1c, 0x8d68);
+	}
 	tg3_phy_set_wirespeed(tp);
 	return 0;
 }
@@ -677,45 +720,41 @@
 	    (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT0 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 		} else {
 			if (tp_peer != tp &&
 			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
 				return;
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT2));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT0 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT2));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT0 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 		}
 	} else {
@@ -725,27 +764,24 @@
 			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
 				return;
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 		}
 	}
 }
 
-static int tg3_setup_phy(struct tg3 *);
+static int tg3_setup_phy(struct tg3 *, int);
 
 static int tg3_set_power_state(struct tg3 *tp, int state)
 {
@@ -771,8 +807,7 @@
 		pci_write_config_word(tp->pdev,
 				      pm + PCI_PM_CTRL,
 				      power_control);
-		tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-		tr32(GRC_LOCAL_CTRL);
+		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 		udelay(100);
 
 		return 0;
@@ -813,7 +848,7 @@
 		tp->link_config.speed = SPEED_10;
 		tp->link_config.duplex = DUPLEX_HALF;
 		tp->link_config.autoneg = AUTONEG_ENABLE;
-		tg3_setup_phy(tp);
+		tg3_setup_phy(tp, 0);
 	}
 
 	pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
@@ -839,12 +874,10 @@
 		     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)))
 			mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
 
-		tw32(MAC_MODE, mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, mac_mode);
 		udelay(100);
 
-		tw32(MAC_RX_MODE, RX_MODE_ENABLE);
-		tr32(MAC_RX_MODE);
+		tw32_f(MAC_RX_MODE, RX_MODE_ENABLE);
 		udelay(10);
 	}
 
@@ -857,10 +890,9 @@
 		base_val |= (CLOCK_CTRL_RXCLK_DISABLE |
 			     CLOCK_CTRL_TXCLK_DISABLE);
 
-		tw32(TG3PCI_CLOCK_CTRL, base_val |
+		tw32_f(TG3PCI_CLOCK_CTRL, base_val |
 		     CLOCK_CTRL_ALTCLK |
 		     CLOCK_CTRL_PWRDOWN_PLL133);
-		tr32(TG3PCI_CLOCK_CTRL);
 		udelay(40);
 	} else {
 		u32 newbits1, newbits2;
@@ -879,12 +911,10 @@
 			newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
 		}
 
-		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1);
-		tr32(TG3PCI_CLOCK_CTRL);
+		tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1);
 		udelay(40);
 
-		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2);
-		tr32(TG3PCI_CLOCK_CTRL);
+		tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2);
 		udelay(40);
 
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
@@ -899,8 +929,8 @@
 				newbits3 = CLOCK_CTRL_44MHZ_CORE;
 			}
 
-			tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits3);
-			tr32(TG3PCI_CLOCK_CTRL);
+			tw32_f(TG3PCI_CLOCK_CTRL,
+					 tp->pci_clock_ctrl | newbits3);
 			udelay(40);
 		}
 	}
@@ -1014,7 +1044,7 @@
 	};
 }
 
-static int tg3_phy_copper_begin(struct tg3 *tp, int wait_for_link)
+static int tg3_phy_copper_begin(struct tg3 *tp)
 {
 	u32 new_adv;
 	int i;
@@ -1132,7 +1162,7 @@
 		tg3_readphy(tp, MII_BMCR, &orig_bmcr);
 		if (bmcr != orig_bmcr) {
 			tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK);
-			for (i = 0; i < 15000; i++) {
+			for (i = 0; i < 1500; i++) {
 				u32 tmp;
 
 				udelay(10);
@@ -1151,27 +1181,6 @@
 			     BMCR_ANENABLE | BMCR_ANRESTART);
 	}
 
-	if (wait_for_link) {
-		tp->link_config.active_speed = SPEED_INVALID;
-		tp->link_config.active_duplex = DUPLEX_INVALID;
-		for (i = 0; i < 300000; i++) {
-			u32 tmp;
-
-			udelay(10);
-			tg3_readphy(tp, MII_BMSR, &tmp);
-			tg3_readphy(tp, MII_BMSR, &tmp);
-			if (!(tmp & BMSR_LSTATUS))
-				continue;
-
-			tg3_readphy(tp, MII_TG3_AUX_STAT, &tmp);
-			tg3_aux_stat_to_speed_duplex(tp, tmp,
-						     &tp->link_config.active_speed,
-						     &tp->link_config.active_duplex);
-		}
-		if (tp->link_config.active_speed == SPEED_INVALID)
-			return -EINVAL;
-	}
-
 	return 0;
 }
 
@@ -1202,7 +1211,7 @@
 	return err;
 }
 
-static int tg3_setup_copper_phy(struct tg3 *tp)
+static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
 	int current_link_up;
 	u32 bmsr, dummy;
@@ -1210,15 +1219,17 @@
 	u8 current_duplex;
 	int i, err;
 
-	tw32(MAC_STATUS,
+	tw32(MAC_EVENT, 0);
+
+	tw32_f(MAC_STATUS,
 	     (MAC_STATUS_SYNC_CHANGED |
-	      MAC_STATUS_CFG_CHANGED));
-	tr32(MAC_STATUS);
+	      MAC_STATUS_CFG_CHANGED |
+	      MAC_STATUS_MI_COMPLETION |
+	      MAC_STATUS_LNKSTATE_CHANGED));
 	udelay(40);
 
 	tp->mi_mode = MAC_MI_MODE_BASE;
-	tw32(MAC_MI_MODE, tp->mi_mode);
-	tr32(MAC_MI_MODE);
+	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(40);
 
 	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
@@ -1233,8 +1244,10 @@
 		tg3_readphy(tp, MII_BMSR, &bmsr);
 		tg3_readphy(tp, MII_BMSR, &bmsr);
 		if (!(bmsr & BMSR_LSTATUS))
-			tg3_phy_reset(tp, 1);
+			force_reset = 1;
 	}
+	if (force_reset)
+		tg3_phy_reset(tp, 1);
 
 	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
 		tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -1370,7 +1383,7 @@
 	if (current_link_up == 0) {
 		u32 tmp;
 
-		tg3_phy_copper_begin(tp, 0);
+		tg3_phy_copper_begin(tp);
 
 		tg3_readphy(tp, MII_BMSR, &tmp);
 		tg3_readphy(tp, MII_BMSR, &tmp);
@@ -1410,24 +1423,19 @@
 	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 &&
 	    tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
 		tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
-		tw32(MAC_MI_MODE, tp->mi_mode);
-		tr32(MAC_MI_MODE);
+		tw32_f(MAC_MI_MODE, tp->mi_mode);
 		udelay(40);
 	}
 
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
-	if (tp->tg3_flags &
-	    (TG3_FLAG_USE_LINKCHG_REG |
-	     TG3_FLAG_POLL_SERDES)) {
+	if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) {
 		/* Polled via timer. */
-		tw32(MAC_EVENT, 0);
+		tw32_f(MAC_EVENT, 0);
 	} else {
-		tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
 	}
-	tr32(MAC_EVENT);
 	udelay(40);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
@@ -1436,10 +1444,9 @@
 	    ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ||
 	     (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) {
 		udelay(120);
-		tw32(MAC_STATUS,
+		tw32_f(MAC_STATUS,
 		     (MAC_STATUS_SYNC_CHANGED |
 		      MAC_STATUS_CFG_CHANGED));
-		tr32(MAC_STATUS);
 		udelay(40);
 		tg3_write_mem(tp,
 			      NIC_SRAM_FIRMWARE_MBOX,
@@ -1601,8 +1608,7 @@
 		ap->txconfig = 0;
 		tw32(MAC_TX_AUTO_NEG, 0);
 		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ret = ANEG_TIMER_ENAB;
@@ -1627,8 +1633,7 @@
 		ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);
 		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
 		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ap->state = ANEG_STATE_ABILITY_DETECT;
@@ -1644,8 +1649,7 @@
 		ap->txconfig |= ANEG_CFG_ACK;
 		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
 		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ap->state = ANEG_STATE_ACK_DETECT;
@@ -1731,8 +1735,7 @@
 	case ANEG_STATE_IDLE_DETECT_INIT:
 		ap->link_time = ap->cur_time;
 		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ap->state = ANEG_STATE_IDLE_DETECT;
@@ -1773,7 +1776,7 @@
 	return ret;
 }
 
-static int tg3_setup_fiber_phy(struct tg3 *tp)
+static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
 {
 	u32 orig_pause_cfg;
 	u16 orig_active_speed;
@@ -1789,8 +1792,7 @@
 
 	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
 	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
 	/* Reset when initting first time or we have a link. */
@@ -1838,10 +1840,9 @@
 
 	/* Enable link change interrupt unless serdes polling.  */
 	if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES))
-		tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
 	else
-		tw32(MAC_EVENT, 0);
-	tr32(MAC_EVENT);
+		tw32_f(MAC_EVENT, 0);
 	udelay(40);
 
 	current_link_up = 0;
@@ -1859,12 +1860,10 @@
 			tw32(MAC_TX_AUTO_NEG, 0);
 
 			tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
-			tw32(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
 			udelay(40);
 
-			tw32(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
 			udelay(40);
 
 			aninfo.state = ANEG_STATE_UNKNOWN;
@@ -1880,8 +1879,7 @@
 			}
 
 			tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-			tw32(MAC_MODE, tp->mac_mode);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tp->mac_mode);
 			udelay(40);
 
 			if (status == ANEG_DONE &&
@@ -1905,10 +1903,9 @@
 			}
 			for (i = 0; i < 60; i++) {
 				udelay(20);
-				tw32(MAC_STATUS,
+				tw32_f(MAC_STATUS,
 				     (MAC_STATUS_SYNC_CHANGED |
 				      MAC_STATUS_CFG_CHANGED));
-				tr32(MAC_STATUS);
 				udelay(40);
 				if ((tr32(MAC_STATUS) &
 				     (MAC_STATUS_SYNC_CHANGED |
@@ -1926,8 +1923,7 @@
 	}
 
 	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
 	tp->hw_status->status =
@@ -1936,10 +1932,9 @@
 
 	for (i = 0; i < 100; i++) {
 		udelay(20);
-		tw32(MAC_STATUS,
+		tw32_f(MAC_STATUS,
 		     (MAC_STATUS_SYNC_CHANGED |
 		      MAC_STATUS_CFG_CHANGED));
-		tr32(MAC_STATUS);
 		udelay(40);
 		if ((tr32(MAC_STATUS) &
 		     (MAC_STATUS_SYNC_CHANGED |
@@ -1975,12 +1970,10 @@
 	}
 
 	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
-		tw32(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
 		udelay(40);
 		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
-			tw32(MAC_MODE, tp->mac_mode);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tp->mac_mode);
 			udelay(40);
 		}
 	}
@@ -1988,14 +1981,14 @@
 	return 0;
 }
 
-static int tg3_setup_phy(struct tg3 *tp)
+static int tg3_setup_phy(struct tg3 *tp, int force_reset)
 {
 	int err;
 
 	if (tp->phy_id == PHY_ID_SERDES) {
-		err = tg3_setup_fiber_phy(tp);
+		err = tg3_setup_fiber_phy(tp, force_reset);
 	} else {
-		err = tg3_setup_copper_phy(tp);
+		err = tg3_setup_copper_phy(tp, force_reset);
 	}
 
 	if (tp->link_config.active_speed == SPEED_1000 &&
@@ -2324,25 +2317,19 @@
 
 	/* ACK the status ring. */
 	tp->rx_rcb_ptr = rx_rcb_ptr;
-	tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW,
+	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW,
 		     (rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp)));
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW);
 
 	/* Refill RX ring(s). */
 	if (work_mask & RXD_OPAQUE_RING_STD) {
 		sw_idx = tp->rx_std_ptr % TG3_RX_RING_SIZE;
-		tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
+		tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
 			     sw_idx);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW);
 	}
 	if (work_mask & RXD_OPAQUE_RING_JUMBO) {
 		sw_idx = tp->rx_jumbo_ptr % TG3_RX_JUMBO_RING_SIZE;
-		tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
+		tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
 			     sw_idx);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW);
 	}
 
 	return received;
@@ -2364,7 +2351,7 @@
 		if (sblk->status & SD_STATUS_LINK_CHG) {
 			sblk->status = SD_STATUS_UPDATED |
 				(sblk->status & ~SD_STATUS_LINK_CHG);
-			tg3_setup_phy(tp);
+			tg3_setup_phy(tp, 0);
 		}
 	}
 
@@ -2794,32 +2781,17 @@
 
 	/* Packets are ready, update Tx producer idx local and on card. */
 	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
-			tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
-				      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDHOST_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	} else {
 		/* First, make sure tg3 sees last descriptor fully
 		 * in SRAM.
 		 */
 		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
+			tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
 
-		tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
-			tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
-				      TG3_64BIT_REG_LOW), entry);
-
-		/* Now post the mailbox write itself.  */
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	}
 
 	tp->tx_prod = entry;
@@ -2964,11 +2936,8 @@
 	 * the double-write bug tests.
 	 */
 	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDHOST_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	} else {
 		/* First, make sure tg3 sees last descriptor fully
 		 * in SRAM.
@@ -2977,13 +2946,8 @@
 			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
 			     TG3_64BIT_REG_LOW);
 
-		tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-
-		/* Now post the mailbox write itself.  */
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	}
 
 	tp->tx_prod = entry;
@@ -3337,8 +3301,7 @@
 
 	val = tr32(ofs);
 	val &= ~enable_bit;
-	tw32(ofs, val);
-	tr32(ofs);
+	tw32_f(ofs, val);
 
 	for (i = 0; i < MAX_WAIT_CNT; i++) {
 		udelay(100);
@@ -3365,8 +3328,7 @@
 	tg3_disable_ints(tp);
 
 	tp->rx_mode &= ~RX_MODE_ENABLE;
-	tw32(MAC_RX_MODE, tp->rx_mode);
-	tr32(MAC_RX_MODE);
+	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
 	err  = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
@@ -3387,13 +3349,11 @@
 		goto out;
 
 	tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
 	tp->tx_mode &= ~TX_MODE_ENABLE;
-	tw32(MAC_TX_MODE, tp->tx_mode);
-	tr32(MAC_TX_MODE);
+	tw32_f(MAC_TX_MODE, tp->tx_mode);
 
 	for (i = 0; i < MAX_WAIT_CNT; i++) {
 		udelay(100);
@@ -3419,7 +3379,10 @@
 	if (err)
 		goto out;
 
-	memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+	if (tp->hw_status)
+		memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+	if (tp->hw_stats)
+		memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
 
 out:
 	return err;
@@ -3716,8 +3679,7 @@
 		}
 
 		tw32(offset + CPU_STATE, 0xffffffff);
-		tw32(offset + CPU_MODE,  CPU_MODE_HALT);
-		tr32(offset + CPU_MODE);
+		tw32_f(offset + CPU_MODE,  CPU_MODE_HALT);
 		udelay(10);
 	} else {
 		for (i = 0; i < 10000; i++) {
@@ -3840,20 +3802,14 @@
 
 	/* Now startup only the RX cpu. */
 	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-	tw32(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
+	tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
 
-	/* Flush posted writes. */
-	tr32(RX_CPU_BASE + CPU_PC);
 	for (i = 0; i < 5; i++) {
 		if (tr32(RX_CPU_BASE + CPU_PC) == TG3_FW_TEXT_ADDR)
 			break;
 		tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
 		tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
-		tw32(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
-
-		/* Flush posted writes. */
-		tr32(RX_CPU_BASE + CPU_PC);
-
+		tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
 		udelay(1000);
 	}
 	if (i >= 5) {
@@ -3864,10 +3820,7 @@
 		return -ENODEV;
 	}
 	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-	tw32(RX_CPU_BASE + CPU_MODE,  0x00000000);
-
-	/* Flush posted writes. */
-	tr32(RX_CPU_BASE + CPU_MODE);
+	tw32_f(RX_CPU_BASE + CPU_MODE,  0x00000000);
 
 	return 0;
 }
@@ -4425,20 +4378,14 @@
 
 	/* Now startup the cpu. */
 	tw32(cpu_base + CPU_STATE, 0xffffffff);
-	tw32(cpu_base + CPU_PC,    info.text_base);
+	tw32_f(cpu_base + CPU_PC,    info.text_base);
 
-	/* Flush posted writes. */
-	tr32(cpu_base + CPU_PC);
 	for (i = 0; i < 5; i++) {
 		if (tr32(cpu_base + CPU_PC) == info.text_base)
 			break;
 		tw32(cpu_base + CPU_STATE, 0xffffffff);
 		tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
-		tw32(cpu_base + CPU_PC,    info.text_base);
-
-		/* Flush posted writes. */
-		tr32(cpu_base + CPU_PC);
-
+		tw32_f(cpu_base + CPU_PC,    info.text_base);
 		udelay(1000);
 	}
 	if (i >= 5) {
@@ -4449,11 +4396,7 @@
 		return -ENODEV;
 	}
 	tw32(cpu_base + CPU_STATE, 0xffffffff);
-	tw32(cpu_base + CPU_MODE,  0x00000000);
-
-	/* Flush posted writes. */
-	tr32(cpu_base + CPU_MODE);
-
+	tw32_f(cpu_base + CPU_MODE,  0x00000000);
 	return 0;
 }
 
@@ -4500,9 +4443,6 @@
 	struct tg3 *tp = dev->priv;
 	struct sockaddr *addr = p;
 
-	if (netif_running(dev))
-		return -EBUSY;
-
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
 	spin_lock_irq(&tp->lock);
@@ -4562,10 +4502,9 @@
 		      NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
 	if (tp->phy_id == PHY_ID_SERDES) {
 		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
-		tw32(MAC_MODE, tp->mac_mode);
+		tw32_f(MAC_MODE, tp->mac_mode);
 	} else
-		tw32(MAC_MODE, 0);
-	tr32(MAC_MODE);
+		tw32_f(MAC_MODE, 0);
 	udelay(40);
 
 	/* Wait for firmware initialization to complete. */
@@ -4595,8 +4534,7 @@
 	 * other revision.
 	 */
 	tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
-	tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
-	tr32(TG3PCI_CLOCK_CTRL);
+	tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
 	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
@@ -4793,9 +4731,7 @@
 	tp->tx_prod = 0;
 	tp->tx_cons = 0;
 	tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-	tw32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+	tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
 
 	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
 		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
@@ -4822,9 +4758,7 @@
 	}
 
 	tp->rx_rcb_ptr = 0;
-	tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW);
+	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
 
 	tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB,
 		       tp->rx_rcb_mapping,
@@ -4833,19 +4767,13 @@
 		       0);
 
 	tp->rx_std_ptr = tp->rx_pending;
-	tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
+	tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
 		     tp->rx_std_ptr);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW);
 
-	if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)
-		tp->rx_jumbo_ptr = tp->rx_jumbo_pending;
-	else
-		tp->rx_jumbo_ptr = 0;
-	tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
+	tp->rx_jumbo_ptr = (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) ?
+						tp->rx_jumbo_pending : 0;
+	tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
 		     tp->rx_jumbo_ptr);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW);
 
 	/* Initialize MAC address and backoff seed. */
 	__tg3_set_mac_addr(tp);
@@ -4950,24 +4878,21 @@
 
 	tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
 		MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
-	tw32(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
 	udelay(40);
 
 	tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
 		tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
 				       GRC_LCLCTRL_GPIO_OUTPUT1);
-	tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-	tr32(GRC_LOCAL_CTRL);
+	tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 	udelay(100);
 
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
 	tr32(MAILBOX_INTERRUPT_0);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
-		tw32(DMAC_MODE, DMAC_MODE_ENABLE);
-		tr32(DMAC_MODE);
+		tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
 		udelay(40);
 	}
 
@@ -4980,8 +4905,7 @@
 	    (tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0 &&
 	    !(tp->tg3_flags2 & TG3_FLG2_IS_5788))
 		val |= WDMAC_MODE_RX_ACCEL;
-	tw32(WDMAC_MODE, val);
-	tr32(WDMAC_MODE);
+	tw32_f(WDMAC_MODE, val);
 	udelay(40);
 
 	if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
@@ -4999,8 +4923,7 @@
 		tw32(TG3PCI_X_CAPS, val);
 	}
 
-	tw32(RDMAC_MODE, rdmac_mode);
-	tr32(RDMAC_MODE);
+	tw32_f(RDMAC_MODE, rdmac_mode);
 	udelay(40);
 
 	tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
@@ -5029,13 +4952,11 @@
 #endif
 
 	tp->tx_mode = TX_MODE_ENABLE;
-	tw32(MAC_TX_MODE, tp->tx_mode);
-	tr32(MAC_TX_MODE);
+	tw32_f(MAC_TX_MODE, tp->tx_mode);
 	udelay(100);
 
 	tp->rx_mode = RX_MODE_ENABLE;
-	tw32(MAC_RX_MODE, tp->rx_mode);
-	tr32(MAC_RX_MODE);
+	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
 	if (tp->link_config.phy_is_low_power) {
@@ -5046,19 +4967,16 @@
 	}
 
 	tp->mi_mode = MAC_MI_MODE_BASE;
-	tw32(MAC_MI_MODE, tp->mi_mode);
-	tr32(MAC_MI_MODE);
+	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(40);
 
 	tw32(MAC_LED_CTRL, 0);
 	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
 	if (tp->phy_id == PHY_ID_SERDES) {
-		tw32(MAC_RX_MODE, RX_MODE_RESET);
-		tr32(MAC_RX_MODE);
+		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
 		udelay(10);
 	}
-	tw32(MAC_RX_MODE, tp->rx_mode);
-	tr32(MAC_RX_MODE);
+	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
@@ -5067,10 +4985,9 @@
 	/* Prevent chip from dropping frames when flow control
 	 * is enabled.
 	 */
-	tw32(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
-	tr32(MAC_LOW_WMARK_MAX_RX_FRAME);
+	tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
 
-	err = tg3_setup_phy(tp);
+	err = tg3_setup_phy(tp, 1);
 	if (err)
 		return err;
 
@@ -5252,7 +5169,7 @@
 				phy_event = 1;
 
 			if (phy_event)
-				tg3_setup_phy(tp);
+				tg3_setup_phy(tp, 0);
 		} else if (tp->tg3_flags & TG3_FLAG_POLL_SERDES) {
 			u32 mac_stat = tr32(MAC_STATUS);
 			int need_setup = 0;
@@ -5266,15 +5183,13 @@
 				need_setup = 1;
 			}
 			if (need_setup) {
-				tw32(MAC_MODE,
+				tw32_f(MAC_MODE,
 				     (tp->mac_mode &
 				      ~MAC_MODE_PORT_MODE_MASK));
-				tr32(MAC_MODE);
 				udelay(40);
-				tw32(MAC_MODE, tp->mac_mode);
-				tr32(MAC_MODE);
+				tw32_f(MAC_MODE, tp->mac_mode);
 				udelay(40);
-				tg3_setup_phy(tp);
+				tg3_setup_phy(tp, 0);
 			}
 		}
 
@@ -5827,8 +5742,7 @@
 
 	if (rx_mode != tp->rx_mode) {
 		tp->rx_mode = rx_mode;
-		tw32(MAC_RX_MODE, rx_mode);
-		tr32(MAC_RX_MODE);
+		tw32_f(MAC_RX_MODE, rx_mode);
 		udelay(10);
 	}
 }
@@ -5954,7 +5868,7 @@
 	struct tg3 *tp = dev->priv;
   
 	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
-					tp->link_config.phy_is_low_power)
+	    tp->link_config.phy_is_low_power)
 		return -EAGAIN;
 
 	spin_lock_irq(&tp->lock);
@@ -5970,7 +5884,7 @@
 		tp->link_config.duplex = cmd->duplex;
   	}
   
-	tg3_setup_phy(tp);
+	tg3_setup_phy(tp, 1);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
   
@@ -6295,7 +6209,7 @@
 	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704)
 		return;
 
-	tw32(GRC_EEPROM_ADDR,
+	tw32_f(GRC_EEPROM_ADDR,
 	     (EEPROM_ADDR_FSM_RESET |
 	      (EEPROM_DEFAULT_CLOCK_PERIOD <<
 	       EEPROM_ADDR_CLKPERD_SHIFT)));
@@ -6305,9 +6219,8 @@
 		udelay(10);
 
 	/* Enable seeprom accesses. */
-	tw32(GRC_LOCAL_CTRL,
+	tw32_f(GRC_LOCAL_CTRL,
 	     tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
-	tr32(GRC_LOCAL_CTRL);
 	udelay(100);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
@@ -6916,6 +6829,12 @@
 	     (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)))
 		tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
 
+	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX ||
+	    GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX)
+		tp->tg3_flags2 |= TG3_FLG2_PHY_ADC_BUG;
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
+		tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
+
 	/* Only 5701 and later support tagged irq status mode.
 	 * Also, 5788 chips cannot use tagged irq status.
 	 *
@@ -6930,8 +6849,7 @@
 		tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
 
 	/* Initialize MAC MI mode, polling disabled. */
-	tw32(MAC_MI_MODE, tp->mi_mode);
-	tr32(MAC_MI_MODE);
+	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(40);
 
 	/* Initialize data/descriptor byte/word swapping. */
@@ -7207,14 +7125,12 @@
 	if (to_device) {
 		test_desc.cqid_sqid = (13 << 8) | 2;
 
-		tw32(RDMAC_MODE, RDMAC_MODE_ENABLE);
-		tr32(RDMAC_MODE);
+		tw32_f(RDMAC_MODE, RDMAC_MODE_ENABLE);
 		udelay(40);
 	} else {
 		test_desc.cqid_sqid = (16 << 8) | 7;
 
-		tw32(WDMAC_MODE, WDMAC_MODE_ENABLE);
-		tr32(WDMAC_MODE);
+		tw32_f(WDMAC_MODE, WDMAC_MODE_ENABLE);
 		udelay(40);
 	}
 	test_desc.flags = 0x00000005;
@@ -7415,17 +7331,18 @@
 			break;
 		}
 
+#if 0
 		/* validate data reached card RAM correctly. */
 		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
 			u32 val;
 			tg3_read_mem(tp, 0x2100 + (i*4), &val);
-			if (val != p[i]) {
-				printk( KERN_ERR "  tg3_test_dma()  Card buffer currupted on write! (%d != %d)\n", val, i);
+			if (le32_to_cpu(val) != p[i]) {
+				printk(KERN_ERR "  tg3_test_dma()  Card buffer corrupted on write! (%d != %d)\n", val, i);
 				/* ret = -ENODEV here? */
 			}
 			p[i] = 0;
 		}
-
+#endif
 		/* Now read it back. */
 		ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0);
 		if (ret) {
@@ -7740,6 +7657,18 @@
 		goto err_out_iounmap;
 	}
 
+	/*
+	 * Reset chip in case UNDI or EFI driver did not shutdown
+	 * DMA self test will enable WDMAC and we'll see (spurious)
+	 * pending DMA on the PCI bus at that point.
+	 */
+	if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
+	    (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+		pci_save_state(tp->pdev, tp->pci_cfg_state);
+		tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+		tg3_halt(tp);
+	}
+
 	err = tg3_test_dma(tp);
 	if (err) {
 		printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)