aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sky2.c123
-rw-r--r--drivers/net/sky2.h2
2 files changed, 43 insertions, 82 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 7ce0663baf4..a3a4ab26044 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -289,7 +289,7 @@ static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port)
static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
{
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
- u16 ctrl, ct1000, adv, pg, ledctrl, ledover;
+ u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
if (sky2->autoneg == AUTONEG_ENABLE &&
!(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) {
@@ -358,6 +358,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
ctrl = 0;
ct1000 = 0;
adv = PHY_AN_CSMA;
+ reg = 0;
if (sky2->autoneg == AUTONEG_ENABLE) {
if (hw->copper) {
@@ -390,21 +391,46 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
/* forced speed/duplex settings */
ct1000 = PHY_M_1000C_MSE;
- if (sky2->duplex == DUPLEX_FULL)
- ctrl |= PHY_CT_DUP_MD;
+ /* Disable auto update for duplex flow control and speed */
+ reg |= GM_GPCR_AU_ALL_DIS;
switch (sky2->speed) {
case SPEED_1000:
ctrl |= PHY_CT_SP1000;
+ reg |= GM_GPCR_SPEED_1000;
break;
case SPEED_100:
ctrl |= PHY_CT_SP100;
+ reg |= GM_GPCR_SPEED_100;
break;
}
+ if (sky2->duplex == DUPLEX_FULL) {
+ reg |= GM_GPCR_DUP_FULL;
+ ctrl |= PHY_CT_DUP_MD;
+ } else if (sky2->speed != SPEED_1000 && hw->chip_id != CHIP_ID_YUKON_EC_U) {
+ /* Turn off flow control for 10/100mbps */
+ sky2->rx_pause = 0;
+ sky2->tx_pause = 0;
+ }
+
+ if (!sky2->rx_pause)
+ reg |= GM_GPCR_FC_RX_DIS;
+
+ if (!sky2->tx_pause)
+ reg |= GM_GPCR_FC_TX_DIS;
+
+ /* Forward pause packets to GMAC? */
+ if (sky2->tx_pause || sky2->rx_pause)
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+ else
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+
ctrl |= PHY_CT_RESET;
}
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+
if (hw->chip_id != CHIP_ID_YUKON_FE)
gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
@@ -508,6 +534,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
}
+
/* Enable phy interrupt on auto-negotiation complete (or link up) */
if (sky2->autoneg == AUTONEG_ENABLE)
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
@@ -570,49 +597,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
gm_phy_read(hw, 1, PHY_MARV_INT_MASK) != 0);
}
- if (sky2->autoneg == AUTONEG_DISABLE) {
- reg = gma_read16(hw, port, GM_GP_CTRL);
- reg |= GM_GPCR_AU_ALL_DIS;
- gma_write16(hw, port, GM_GP_CTRL, reg);
- gma_read16(hw, port, GM_GP_CTRL);
-
- switch (sky2->speed) {
- case SPEED_1000:
- reg &= ~GM_GPCR_SPEED_100;
- reg |= GM_GPCR_SPEED_1000;
- break;
- case SPEED_100:
- reg &= ~GM_GPCR_SPEED_1000;
- reg |= GM_GPCR_SPEED_100;
- break;
- case SPEED_10:
- reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
- break;
- }
-
- if (sky2->duplex == DUPLEX_FULL)
- reg |= GM_GPCR_DUP_FULL;
-
- /* turn off pause in 10/100mbps half duplex */
- else if (sky2->speed != SPEED_1000 &&
- hw->chip_id != CHIP_ID_YUKON_EC_U)
- sky2->tx_pause = sky2->rx_pause = 0;
- } else
- reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
-
- if (!sky2->tx_pause && !sky2->rx_pause) {
- sky2_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
- reg |=
- GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
- } else if (sky2->tx_pause && !sky2->rx_pause) {
- /* disable Rx flow-control */
- reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
- }
-
- gma_write16(hw, port, GM_GP_CTRL, reg);
-
sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
+ /* Enable Transmit FIFO Underrun */
+ sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
+
spin_lock_bh(&sky2->phy_lock);
sky2_phy_init(hw, port);
spin_unlock_bh(&sky2->phy_lock);
@@ -1529,40 +1518,10 @@ static void sky2_link_up(struct sky2_port *sky2)
unsigned port = sky2->port;
u16 reg;
- /* Enable Transmit FIFO Underrun */
- sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
-
- reg = gma_read16(hw, port, GM_GP_CTRL);
- if (sky2->autoneg == AUTONEG_DISABLE) {
- reg |= GM_GPCR_AU_ALL_DIS;
-
- /* Is write/read necessary? Copied from sky2_mac_init */
- gma_write16(hw, port, GM_GP_CTRL, reg);
- gma_read16(hw, port, GM_GP_CTRL);
-
- switch (sky2->speed) {
- case SPEED_1000:
- reg &= ~GM_GPCR_SPEED_100;
- reg |= GM_GPCR_SPEED_1000;
- break;
- case SPEED_100:
- reg &= ~GM_GPCR_SPEED_1000;
- reg |= GM_GPCR_SPEED_100;
- break;
- case SPEED_10:
- reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
- break;
- }
- } else
- reg &= ~GM_GPCR_AU_ALL_DIS;
-
- if (sky2->duplex == DUPLEX_FULL || sky2->autoneg == AUTONEG_ENABLE)
- reg |= GM_GPCR_DUP_FULL;
-
/* enable Rx/Tx */
+ reg = gma_read16(hw, port, GM_GP_CTRL);
reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
gma_write16(hw, port, GM_GP_CTRL, reg);
- gma_read16(hw, port, GM_GP_CTRL);
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
@@ -1616,7 +1575,6 @@ static void sky2_link_down(struct sky2_port *sky2)
reg = gma_read16(hw, port, GM_GP_CTRL);
reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
gma_write16(hw, port, GM_GP_CTRL, reg);
- gma_read16(hw, port, GM_GP_CTRL); /* PCI post */
if (sky2->rx_pause && !sky2->tx_pause) {
/* restore Asymmetric Pause bit */
@@ -1633,6 +1591,7 @@ static void sky2_link_down(struct sky2_port *sky2)
if (netif_msg_link(sky2))
printk(KERN_INFO PFX "%s: Link is down.\n", sky2->netdev->name);
+
sky2_phy_init(hw, port);
}
@@ -1673,8 +1632,11 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0;
sky2->tx_pause = (aux & PHY_M_PS_TX_P_EN) != 0;
- if ((sky2->tx_pause || sky2->rx_pause)
- && !(sky2->speed < SPEED_1000 && sky2->duplex == DUPLEX_HALF))
+ if (sky2->duplex == DUPLEX_HALF && sky2->speed != SPEED_1000
+ && hw->chip_id != CHIP_ID_YUKON_EC_U)
+ sky2->rx_pause = sky2->tx_pause = 0;
+
+ if (sky2->rx_pause || sky2->tx_pause)
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
else
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -1700,7 +1662,7 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n",
sky2->netdev->name, istatus, phystat);
- if (istatus & PHY_M_IS_AN_COMPL) {
+ if (sky2->autoneg == AUTONEG_ENABLE && (istatus & PHY_M_IS_AN_COMPL)) {
if (sky2_autoneg_done(sky2, phystat) == 0)
sky2_link_up(sky2);
goto out;
@@ -2890,7 +2852,6 @@ static int sky2_set_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *ecmd)
{
struct sky2_port *sky2 = netdev_priv(dev);
- int err = 0;
sky2->autoneg = ecmd->autoneg;
sky2->tx_pause = ecmd->tx_pause != 0;
@@ -2898,7 +2859,7 @@ static int sky2_set_pauseparam(struct net_device *dev,
sky2_phy_reinit(sky2);
- return err;
+ return 0;
}
static int sky2_get_coalesce(struct net_device *dev,
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index fa8af9f503e..a27194c874f 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1566,7 +1566,7 @@ enum {
GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
- GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC |
+ GMR_FS_MII_ERR | GMR_FS_BAD_FC |
GMR_FS_UN_SIZE | GMR_FS_JABBER,
};