SunGEM fixes from Banjamin.
Only depend upon BMSR_LSTATUS in gem_link_timer.
Call gem_init_pause_thresholds after gem_init_mac
not before or else we will lose the settings.
Set MIF_CFG bits correctly in gem_apple_powerup.
Make gem_ioctl take the pm_sem.
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 7bdf954..f7858a6 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -1,4 +1,4 @@
-/* $Id: sungem.c,v 1.42 2001-11-29 21:20:40 davem Exp $
+/* $Id: sungem.c,v 1.43 2001-12-05 08:40:54 davem Exp $
  * sungem.c: Sun GEM ethernet driver.
  *
  * Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com)
@@ -1139,16 +1139,22 @@
 	if (gp->phy_type == phy_mii_mdio0 ||
 	    gp->phy_type == phy_mii_mdio1) {
 		u16 val = phy_read(gp, MII_BMSR);
-		u16 cntl = phy_read(gp, MII_BMCR);
 		int up;
 
 		/* When using autoneg, we really wait for ANEGCOMPLETE or we may
 		 * get a "transcient" incorrect link state
 		 */
-		if (cntl & BMCR_ANENABLE)
-			up = (val & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS);
-		else
-			up = (val & BMSR_LSTATUS) != 0;
+#if 0
+		{
+			u16 cntl = phy_read(gp, MII_BMCR);
+			if (cntl & BMCR_ANENABLE)
+				up = (val & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS);
+			else
+				up = (val & BMSR_LSTATUS) != 0;
+		}
+#else
+		up = (val & BMSR_LSTATUS) != 0;
+#endif
 		if (up) {
 			/* Ok, here we got a link. If we had it due to a forced
 			 * fallback, and we were configured for autoneg, we do
@@ -1829,7 +1835,6 @@
 		gp->phy_type = phy_mii_mdio0;
 		gp->tx_fifo_sz = readl(gp->regs + TXDMA_FSZ) * 64;
 		gp->rx_fifo_sz = readl(gp->regs + RXDMA_FSZ) * 64;
-		gem_init_pause_thresholds(gp);
 		return 0;
 	}
 
@@ -1902,8 +1907,6 @@
 		}
 	}
 
-	gem_init_pause_thresholds(gp);
-
 	return 0;
 }
 
@@ -1919,6 +1922,7 @@
 		gem_init_phy(gp);
 	gem_init_dma(gp);
 	gem_init_mac(gp);
+	gem_init_pause_thresholds(gp);
 
 	spin_lock_irq(&gp->lock);
 	if (restart_link) {
@@ -1961,7 +1965,8 @@
 	mdelay(1);
 	
 	mif_cfg = readl(gp->regs + MIF_CFG);
-	mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI0);
+	mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1);
+	mif_cfg |= MIF_CFG_MDI0;
 	writel(mif_cfg, gp->regs + MIF_CFG);
 	writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE);
 	writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG);
@@ -2545,10 +2550,17 @@
 {
 	struct gem *gp = dev->priv;
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
-
+	int rc = -EOPNOTSUPP;
+	
+	/* Hold the PM semaphore while doing ioctl's or we may collide
+	 * with open/close and power management and oops.
+	 */
+	down(&gp->pm_sem);
+	
 	switch (cmd) {
 	case SIOCETHTOOL:
-		return gem_ethtool_ioctl(dev, ifr->ifr_data);
+		rc = gem_ethtool_ioctl(dev, ifr->ifr_data);
+		break;
 
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
 		data->phy_id = gp->mii_phy_addr;
@@ -2556,16 +2568,22 @@
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
 		data->val_out = __phy_read(gp, data->reg_num & 0x1f, data->phy_id & 0x1f);
-		return 0;
+		rc = 0;
+		break;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		__phy_write(gp, data->reg_num & 0x1f, data->val_in, data->phy_id & 0x1f);
-		return 0;
+		if (!capable(CAP_NET_ADMIN)) {
+			rc = -EPERM;
+		} else {
+			__phy_write(gp, data->reg_num & 0x1f, data->val_in, data->phy_id & 0x1f);
+			rc = 0;
+		}
+		break;
 	};
 
-	return -EOPNOTSUPP;
+	up(&gp->pm_sem);
+	
+	return rc;
 }
 
 static int __devinit gem_get_device_address(struct gem *gp)