aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sungem.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-12-15 23:03:50 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-15 23:03:50 -0500
commiteb14f019597cd86c21a6c601d7e900f40030c2e7 (patch)
tree36fb2f36a1747f98988f87215db1eef3a71d45eb /drivers/net/sungem.c
parent9a4a84294b0d60b8c287131478f743ba2bc68949 (diff)
parenta3dd15444baa9c7522c8457ab564c41219dfb44c (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/e1000e/ich8lan.c
Diffstat (limited to 'drivers/net/sungem.c')
-rw-r--r--drivers/net/sungem.c144
1 files changed, 88 insertions, 56 deletions
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 6f935cd30176..f4b0beec4d19 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -1141,6 +1141,70 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
1141 return NETDEV_TX_OK; 1141 return NETDEV_TX_OK;
1142} 1142}
1143 1143
1144static void gem_pcs_reset(struct gem *gp)
1145{
1146 int limit;
1147 u32 val;
1148
1149 /* Reset PCS unit. */
1150 val = readl(gp->regs + PCS_MIICTRL);
1151 val |= PCS_MIICTRL_RST;
1152 writel(val, gp->regs + PCS_MIICTRL);
1153
1154 limit = 32;
1155 while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) {
1156 udelay(100);
1157 if (limit-- <= 0)
1158 break;
1159 }
1160 if (limit <= 0)
1161 printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
1162 gp->dev->name);
1163}
1164
1165static void gem_pcs_reinit_adv(struct gem *gp)
1166{
1167 u32 val;
1168
1169 /* Make sure PCS is disabled while changing advertisement
1170 * configuration.
1171 */
1172 val = readl(gp->regs + PCS_CFG);
1173 val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO);
1174 writel(val, gp->regs + PCS_CFG);
1175
1176 /* Advertise all capabilities except assymetric
1177 * pause.
1178 */
1179 val = readl(gp->regs + PCS_MIIADV);
1180 val |= (PCS_MIIADV_FD | PCS_MIIADV_HD |
1181 PCS_MIIADV_SP | PCS_MIIADV_AP);
1182 writel(val, gp->regs + PCS_MIIADV);
1183
1184 /* Enable and restart auto-negotiation, disable wrapback/loopback,
1185 * and re-enable PCS.
1186 */
1187 val = readl(gp->regs + PCS_MIICTRL);
1188 val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE);
1189 val &= ~PCS_MIICTRL_WB;
1190 writel(val, gp->regs + PCS_MIICTRL);
1191
1192 val = readl(gp->regs + PCS_CFG);
1193 val |= PCS_CFG_ENABLE;
1194 writel(val, gp->regs + PCS_CFG);
1195
1196 /* Make sure serialink loopback is off. The meaning
1197 * of this bit is logically inverted based upon whether
1198 * you are in Serialink or SERDES mode.
1199 */
1200 val = readl(gp->regs + PCS_SCTRL);
1201 if (gp->phy_type == phy_serialink)
1202 val &= ~PCS_SCTRL_LOOP;
1203 else
1204 val |= PCS_SCTRL_LOOP;
1205 writel(val, gp->regs + PCS_SCTRL);
1206}
1207
1144#define STOP_TRIES 32 1208#define STOP_TRIES 32
1145 1209
1146/* Must be invoked under gp->lock and gp->tx_lock. */ 1210/* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1167,6 +1231,9 @@ static void gem_reset(struct gem *gp)
1167 1231
1168 if (limit <= 0) 1232 if (limit <= 0)
1169 printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name); 1233 printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
1234
1235 if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes)
1236 gem_pcs_reinit_adv(gp);
1170} 1237}
1171 1238
1172/* Must be invoked under gp->lock and gp->tx_lock. */ 1239/* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1323,7 +1390,7 @@ static int gem_set_link_modes(struct gem *gp)
1323 gp->phy_type == phy_serdes) { 1390 gp->phy_type == phy_serdes) {
1324 u32 pcs_lpa = readl(gp->regs + PCS_MIILP); 1391 u32 pcs_lpa = readl(gp->regs + PCS_MIILP);
1325 1392
1326 if (pcs_lpa & PCS_MIIADV_FD) 1393 if ((pcs_lpa & PCS_MIIADV_FD) || gp->phy_type == phy_serdes)
1327 full_duplex = 1; 1394 full_duplex = 1;
1328 speed = SPEED_1000; 1395 speed = SPEED_1000;
1329 } 1396 }
@@ -1487,6 +1554,9 @@ static void gem_link_timer(unsigned long data)
1487 val = readl(gp->regs + PCS_MIISTAT); 1554 val = readl(gp->regs + PCS_MIISTAT);
1488 1555
1489 if ((val & PCS_MIISTAT_LS) != 0) { 1556 if ((val & PCS_MIISTAT_LS) != 0) {
1557 if (gp->lstate == link_up)
1558 goto restart;
1559
1490 gp->lstate = link_up; 1560 gp->lstate = link_up;
1491 netif_carrier_on(gp->dev); 1561 netif_carrier_on(gp->dev);
1492 (void)gem_set_link_modes(gp); 1562 (void)gem_set_link_modes(gp);
@@ -1707,61 +1777,8 @@ static void gem_init_phy(struct gem *gp)
1707 if (gp->phy_mii.def && gp->phy_mii.def->ops->init) 1777 if (gp->phy_mii.def && gp->phy_mii.def->ops->init)
1708 gp->phy_mii.def->ops->init(&gp->phy_mii); 1778 gp->phy_mii.def->ops->init(&gp->phy_mii);
1709 } else { 1779 } else {
1710 u32 val; 1780 gem_pcs_reset(gp);
1711 int limit; 1781 gem_pcs_reinit_adv(gp);
1712
1713 /* Reset PCS unit. */
1714 val = readl(gp->regs + PCS_MIICTRL);
1715 val |= PCS_MIICTRL_RST;
1716 writel(val, gp->regs + PCS_MIICTRL);
1717
1718 limit = 32;
1719 while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) {
1720 udelay(100);
1721 if (limit-- <= 0)
1722 break;
1723 }
1724 if (limit <= 0)
1725 printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
1726 gp->dev->name);
1727
1728 /* Make sure PCS is disabled while changing advertisement
1729 * configuration.
1730 */
1731 val = readl(gp->regs + PCS_CFG);
1732 val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO);
1733 writel(val, gp->regs + PCS_CFG);
1734
1735 /* Advertise all capabilities except assymetric
1736 * pause.
1737 */
1738 val = readl(gp->regs + PCS_MIIADV);
1739 val |= (PCS_MIIADV_FD | PCS_MIIADV_HD |
1740 PCS_MIIADV_SP | PCS_MIIADV_AP);
1741 writel(val, gp->regs + PCS_MIIADV);
1742
1743 /* Enable and restart auto-negotiation, disable wrapback/loopback,
1744 * and re-enable PCS.
1745 */
1746 val = readl(gp->regs + PCS_MIICTRL);
1747 val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE);
1748 val &= ~PCS_MIICTRL_WB;
1749 writel(val, gp->regs + PCS_MIICTRL);
1750
1751 val = readl(gp->regs + PCS_CFG);
1752 val |= PCS_CFG_ENABLE;
1753 writel(val, gp->regs + PCS_CFG);
1754
1755 /* Make sure serialink loopback is off. The meaning
1756 * of this bit is logically inverted based upon whether
1757 * you are in Serialink or SERDES mode.
1758 */
1759 val = readl(gp->regs + PCS_SCTRL);
1760 if (gp->phy_type == phy_serialink)
1761 val &= ~PCS_SCTRL_LOOP;
1762 else
1763 val |= PCS_SCTRL_LOOP;
1764 writel(val, gp->regs + PCS_SCTRL);
1765 } 1782 }
1766 1783
1767 /* Default aneg parameters */ 1784 /* Default aneg parameters */
@@ -2679,6 +2696,21 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
2679 cmd->speed = 0; 2696 cmd->speed = 0;
2680 cmd->duplex = cmd->port = cmd->phy_address = 2697 cmd->duplex = cmd->port = cmd->phy_address =
2681 cmd->transceiver = cmd->autoneg = 0; 2698 cmd->transceiver = cmd->autoneg = 0;
2699
2700 /* serdes means usually a Fibre connector, with most fixed */
2701 if (gp->phy_type == phy_serdes) {
2702 cmd->port = PORT_FIBRE;
2703 cmd->supported = (SUPPORTED_1000baseT_Half |
2704 SUPPORTED_1000baseT_Full |
2705 SUPPORTED_FIBRE | SUPPORTED_Autoneg |
2706 SUPPORTED_Pause | SUPPORTED_Asym_Pause);
2707 cmd->advertising = cmd->supported;
2708 cmd->transceiver = XCVR_INTERNAL;
2709 if (gp->lstate == link_up)
2710 cmd->speed = SPEED_1000;
2711 cmd->duplex = DUPLEX_FULL;
2712 cmd->autoneg = 1;
2713 }
2682 } 2714 }
2683 cmd->maxtxpkt = cmd->maxrxpkt = 0; 2715 cmd->maxtxpkt = cmd->maxrxpkt = 0;
2684 2716