summaryrefslogtreecommitdiffstats
path: root/drivers/net/skge.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r--drivers/net/skge.c296
1 files changed, 141 insertions, 155 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 5cacc7ad9e79..d7c98515fdfd 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -42,7 +42,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "0.7"
+#define DRV_VERSION "0.9"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -55,7 +55,7 @@
#define ETH_JUMBO_MTU 9000
#define TX_WATCHDOG (5 * HZ)
#define NAPI_WEIGHT 64
-#define BLINK_HZ (HZ/4)
+#define BLINK_MS 250
MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
@@ -75,13 +75,12 @@ static const struct pci_device_id skge_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) },
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
- { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
{ PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
- { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032) },
{ PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, skge_id_table);
@@ -190,7 +189,7 @@ static u32 skge_supported_modes(const struct skge_hw *hw)
{
u32 supported;
- if (iscopper(hw)) {
+ if (hw->copper) {
supported = SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
| SUPPORTED_100baseT_Half
@@ -223,7 +222,7 @@ static int skge_get_settings(struct net_device *dev,
ecmd->transceiver = XCVR_INTERNAL;
ecmd->supported = skge_supported_modes(hw);
- if (iscopper(hw)) {
+ if (hw->copper) {
ecmd->port = PORT_TP;
ecmd->phy_address = hw->phy_addr;
} else
@@ -249,7 +248,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
} else {
u32 setting;
- switch(ecmd->speed) {
+ switch (ecmd->speed) {
case SPEED_1000:
if (ecmd->duplex == DUPLEX_FULL)
setting = SUPPORTED_1000baseT_Full;
@@ -620,84 +619,98 @@ static int skge_set_coalesce(struct net_device *dev,
return 0;
}
-static void skge_led_on(struct skge_hw *hw, int port)
+enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST };
+static void skge_led(struct skge_port *skge, enum led_mode mode)
{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS) {
- skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
- skge_write8(hw, B0_LED, LED_STAT_ON);
+ switch (mode) {
+ case LED_MODE_OFF:
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
+ skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
+ break;
- skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
- skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
- skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+ case LED_MODE_ON:
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
- /* For Broadcom Phy only */
- xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
- } else {
- gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
- gm_phy_write(hw, port, PHY_MARV_LED_OVER,
- PHY_M_LED_MO_DUP(MO_LED_ON) |
- PHY_M_LED_MO_10(MO_LED_ON) |
- PHY_M_LED_MO_100(MO_LED_ON) |
- PHY_M_LED_MO_1000(MO_LED_ON) |
- PHY_M_LED_MO_RX(MO_LED_ON));
- }
-}
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+ skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
-static void skge_led_off(struct skge_hw *hw, int port)
-{
- if (hw->chip_id == CHIP_ID_GENESIS) {
- skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
- skge_write8(hw, B0_LED, LED_STAT_OFF);
+ break;
- skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
- skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
+ case LED_MODE_TST:
+ skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
+ skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
- /* Broadcom only */
- xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
+ break;
+ }
} else {
- gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
- gm_phy_write(hw, port, PHY_MARV_LED_OVER,
- PHY_M_LED_MO_DUP(MO_LED_OFF) |
- PHY_M_LED_MO_10(MO_LED_OFF) |
- PHY_M_LED_MO_100(MO_LED_OFF) |
- PHY_M_LED_MO_1000(MO_LED_OFF) |
- PHY_M_LED_MO_RX(MO_LED_OFF));
+ switch (mode) {
+ case LED_MODE_OFF:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_DUP(MO_LED_OFF) |
+ PHY_M_LED_MO_10(MO_LED_OFF) |
+ PHY_M_LED_MO_100(MO_LED_OFF) |
+ PHY_M_LED_MO_1000(MO_LED_OFF) |
+ PHY_M_LED_MO_RX(MO_LED_OFF));
+ break;
+ case LED_MODE_ON:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL,
+ PHY_M_LED_PULS_DUR(PULS_170MS) |
+ PHY_M_LED_BLINK_RT(BLINK_84MS) |
+ PHY_M_LEDC_TX_CTRL |
+ PHY_M_LEDC_DP_CTRL);
+
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_RX(MO_LED_OFF) |
+ (skge->speed == SPEED_100 ?
+ PHY_M_LED_MO_100(MO_LED_ON) : 0));
+ break;
+ case LED_MODE_TST:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_DUP(MO_LED_ON) |
+ PHY_M_LED_MO_10(MO_LED_ON) |
+ PHY_M_LED_MO_100(MO_LED_ON) |
+ PHY_M_LED_MO_1000(MO_LED_ON) |
+ PHY_M_LED_MO_RX(MO_LED_ON));
+ }
}
-}
-
-static void skge_blink_timer(unsigned long data)
-{
- struct skge_port *skge = (struct skge_port *) data;
- struct skge_hw *hw = skge->hw;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->phy_lock, flags);
- if (skge->blink_on)
- skge_led_on(hw, skge->port);
- else
- skge_led_off(hw, skge->port);
- spin_unlock_irqrestore(&hw->phy_lock, flags);
-
- skge->blink_on = !skge->blink_on;
- mod_timer(&skge->led_blink, jiffies + BLINK_HZ);
+ spin_unlock_bh(&hw->phy_lock);
}
/* blink LED's for finding board */
static int skge_phys_id(struct net_device *dev, u32 data)
{
struct skge_port *skge = netdev_priv(dev);
+ unsigned long ms;
+ enum led_mode mode = LED_MODE_TST;
if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
- data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+ ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000;
+ else
+ ms = data * 1000;
- /* start blinking */
- skge->blink_on = 1;
- mod_timer(&skge->led_blink, jiffies+1);
+ while (ms > 0) {
+ skge_led(skge, mode);
+ mode ^= LED_MODE_TST;
- msleep_interruptible(data * 1000);
- del_timer_sync(&skge->led_blink);
+ if (msleep_interruptible(BLINK_MS))
+ break;
+ ms -= BLINK_MS;
+ }
- skge_led_off(skge->hw, skge->port);
+ /* back to regular LED state */
+ skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF);
return 0;
}
@@ -863,6 +876,9 @@ static int skge_rx_fill(struct skge_port *skge)
static void skge_link_up(struct skge_port *skge)
{
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
+ LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
+
netif_carrier_on(skge->netdev);
if (skge->tx_avail > MAX_SKB_FRAGS + 1)
netif_wake_queue(skge->netdev);
@@ -881,6 +897,7 @@ static void skge_link_up(struct skge_port *skge)
static void skge_link_down(struct skge_port *skge)
{
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
netif_carrier_off(skge->netdev);
netif_stop_queue(skge->netdev);
@@ -1028,7 +1045,7 @@ static void bcom_check_link(struct skge_hw *hw, int port)
}
/* Check Duplex mismatch */
- switch(aux & PHY_B_AS_AN_RES_MSK) {
+ switch (aux & PHY_B_AS_AN_RES_MSK) {
case PHY_B_RES_1000FD:
skge->duplex = DUPLEX_FULL;
break;
@@ -1099,7 +1116,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
r |= XM_MMU_NO_PRE;
xm_write16(hw, port, XM_MMU_CMD,r);
- switch(id1) {
+ switch (id1) {
case PHY_BCOM_ID1_C0:
/*
* Workaround BCOM Errata for the C0 type.
@@ -1194,13 +1211,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
xm_write16(hw, port, XM_STAT_CMD,
XM_SC_CLR_RXC | XM_SC_CLR_TXC);
- /* initialize Rx, Tx and Link LED */
- skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
- skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
-
- skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
- skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
-
/* Unreset the XMAC. */
skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
@@ -1209,7 +1219,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
* namely for the 1000baseTX cards that use the XMAC's
* GMII mode.
*/
- spin_lock_bh(&hw->phy_lock);
/* Take external Phy out of reset */
r = skge_read32(hw, B2_GP_IO);
if (port == 0)
@@ -1219,7 +1228,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
skge_write32(hw, B2_GP_IO, r);
skge_read32(hw, B2_GP_IO);
- spin_unlock_bh(&hw->phy_lock);
/* Enable GMII interfac */
xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
@@ -1569,7 +1577,6 @@ static void yukon_init(struct skge_hw *hw, int port)
{
struct skge_port *skge = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv;
- u16 ledctrl, ledover;
pr_debug("yukon_init\n");
if (skge->autoneg == AUTONEG_ENABLE) {
@@ -1596,7 +1603,7 @@ static void yukon_init(struct skge_hw *hw, int port)
adv = PHY_AN_CSMA;
if (skge->autoneg == AUTONEG_ENABLE) {
- if (iscopper(hw)) {
+ if (hw->copper) {
if (skge->advertising & ADVERTISED_1000baseT_Full)
ct1000 |= PHY_M_1000C_AFD;
if (skge->advertising & ADVERTISED_1000baseT_Half)
@@ -1641,32 +1648,11 @@ static void yukon_init(struct skge_hw *hw, int port)
gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
- /* Setup Phy LED's */
- ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
- ledover = 0;
-
- ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
-
- /* turn off the Rx LED (LED_RX) */
- ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
-
- /* disable blink mode (LED_DUPLEX) on collisions */
- ctrl |= PHY_M_LEDC_DP_CTRL;
- gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
-
- if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) {
- /* turn on 100 Mbps LED (LED_LINK100) */
- ledover |= PHY_M_LED_MO_100(MO_LED_ON);
- }
-
- if (ledover)
- gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
-
/* Enable phy interrupt on autonegotiation complete (or link up) */
if (skge->autoneg == AUTONEG_ENABLE)
- gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK);
else
- gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
}
static void yukon_reset(struct skge_hw *hw, int port)
@@ -1691,7 +1677,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- set PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev == CHIP_REV_YU_LITE_A3)
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3)
skge_write32(hw, B2_GP_IO,
(skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
@@ -1701,7 +1687,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- clear PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev == CHIP_REV_YU_LITE_A3)
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3)
skge_write32(hw, B2_GP_IO,
(skge_read32(hw, B2_GP_IO) | GP_DIR_9)
& ~GP_IO_9);
@@ -1709,7 +1695,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* Set hardware config mode */
reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE;
- reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
+ reg |= hw->copper ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
/* Clear GMC reset */
skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
@@ -1745,9 +1731,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
gma_write16(hw, port, GM_GP_CTRL, reg);
skge_read16(hw, GMAC_IRQ_SRC);
- spin_lock_bh(&hw->phy_lock);
yukon_init(hw, port);
- spin_unlock_bh(&hw->phy_lock);
/* MIB clear */
reg = gma_read16(hw, port, GM_PHY_ADDR);
@@ -1796,11 +1780,16 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev == CHIP_REV_YU_LITE_A3)
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3)
reg &= ~GMF_RX_F_FL_ON;
skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
- skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+ /*
+ * because Pause Packet Truncation in GMAC is not working
+ * we have to increase the Flush Threshold to 64 bytes
+ * in order to flush pause packets in Rx FIFO on Yukon-1
+ */
+ skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
/* Configure Tx MAC FIFO */
skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
@@ -1813,19 +1802,19 @@ static void yukon_stop(struct skge_port *skge)
int port = skge->port;
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev == CHIP_REV_YU_LITE_A3) {
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
skge_write32(hw, B2_GP_IO,
skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
}
gma_write16(hw, port, GM_GP_CTRL,
gma_read16(hw, port, GM_GP_CTRL)
- & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA));
+ & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
gma_read16(hw, port, GM_GP_CTRL);
/* set GPHY Control reset */
- gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET);
- gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET);
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
}
static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1856,11 +1845,12 @@ static void yukon_mac_intr(struct skge_hw *hw, int port)
if (status & GM_IS_RX_FF_OR) {
++skge->net_stats.rx_fifo_errors;
- gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO);
+ skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
}
+
if (status & GM_IS_TX_FF_UR) {
++skge->net_stats.tx_fifo_errors;
- gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU);
+ skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU);
}
}
@@ -1896,7 +1886,7 @@ static void yukon_link_up(struct skge_port *skge)
reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
gma_write16(hw, port, GM_GP_CTRL, reg);
- gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
skge_link_up(skge);
}
@@ -1904,12 +1894,14 @@ static void yukon_link_down(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
int port = skge->port;
+ u16 ctrl;
pr_debug("yukon_link_down\n");
gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
- gm_phy_write(hw, port, GM_GP_CTRL,
- gm_phy_read(hw, port, GM_GP_CTRL)
- & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
+
+ ctrl = gma_read16(hw, port, GM_GP_CTRL);
+ ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+ gma_write16(hw, port, GM_GP_CTRL, ctrl);
if (skge->flow_control == FLOW_MODE_REM_SEND) {
/* restore Asymmetric Pause bit */
@@ -2097,10 +2089,12 @@ static int skge_up(struct net_device *dev)
skge_write32(hw, B0_IMSK, hw->intr_mask);
/* Initialze MAC */
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_mac_init(hw, port);
else
yukon_mac_init(hw, port);
+ spin_unlock_bh(&hw->phy_lock);
/* Configure RAMbuffers */
chunk = hw->ram_size / ((hw->ports + 1)*2);
@@ -2116,6 +2110,7 @@ static int skge_up(struct net_device *dev)
/* Start receiver BMU */
wmb();
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
+ skge_led(skge, LED_MODE_ON);
pr_debug("skge_up completed\n");
return 0;
@@ -2140,8 +2135,6 @@ static int skge_down(struct net_device *dev)
netif_stop_queue(dev);
- del_timer_sync(&skge->led_blink);
-
/* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
@@ -2175,15 +2168,12 @@ static int skge_down(struct net_device *dev)
if (hw->chip_id == CHIP_ID_GENESIS) {
skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
- skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP);
- skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP);
} else {
skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
}
- /* turn off led's */
- skge_write16(hw, B0_LED, LED_STAT_OFF);
+ skge_led(skge, LED_MODE_OFF);
skge_tx_clean(skge);
skge_rx_clean(skge);
@@ -2633,11 +2623,17 @@ static inline void skge_tx_intr(struct net_device *dev)
spin_unlock(&skge->tx_lock);
}
+/* Parity errors seem to happen when Genesis is connected to a switch
+ * with no other ports present. Heartbeat error??
+ */
static void skge_mac_parity(struct skge_hw *hw, int port)
{
- printk(KERN_ERR PFX "%s: mac data parity error\n",
- hw->dev[port] ? hw->dev[port]->name
- : (port == 0 ? "(port A)": "(port B"));
+ struct net_device *dev = hw->dev[port];
+
+ if (dev) {
+ struct skge_port *skge = netdev_priv(dev);
+ ++skge->net_stats.tx_heartbeat_errors;
+ }
if (hw->chip_id == CHIP_ID_GENESIS)
skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
@@ -2683,18 +2679,6 @@ static void skge_error_irq(struct skge_hw *hw)
/* Timestamp (unused) overflow */
if (hwstatus & IS_IRQ_TIST_OV)
skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
-
- if (hwstatus & IS_IRQ_SENSOR) {
- /* no sensors on 32-bit Yukon */
- if (!(skge_read16(hw, B0_CTST) & CS_BUS_SLOT_SZ)) {
- printk(KERN_ERR PFX "ignoring bogus sensor interrups\n");
- skge_write32(hw, B0_HWE_IMSK,
- IS_ERR_MSK & ~IS_IRQ_SENSOR);
- } else
- printk(KERN_WARNING PFX "sensor interrupt\n");
- }
-
-
}
if (hwstatus & IS_RAM_RD_PAR) {
@@ -2725,9 +2709,10 @@ static void skge_error_irq(struct skge_hw *hw)
skge_pci_clear(hw);
+ /* if error still set then just ignore it */
hwstatus = skge_read32(hw, B0_HWE_ISRC);
if (hwstatus & IS_IRQ_STAT) {
- printk(KERN_WARNING PFX "IRQ status %x: still set ignoring hardware errors\n",
+ pr_debug("IRQ status %x: still set ignoring hardware errors\n",
hwstatus);
hw->intr_mask &= ~IS_HW_ERR;
}
@@ -2889,7 +2874,7 @@ static const char *skge_board_name(const struct skge_hw *hw)
static int skge_reset(struct skge_hw *hw)
{
u16 ctst;
- u8 t8, mac_cfg;
+ u8 t8, mac_cfg, pmd_type, phy_type;
int i;
ctst = skge_read16(hw, B0_CTST);
@@ -2908,18 +2893,19 @@ static int skge_reset(struct skge_hw *hw)
ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
hw->chip_id = skge_read8(hw, B2_CHIP_ID);
- hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
- hw->pmd_type = skge_read8(hw, B2_PMD_TYP);
+ phy_type = skge_read8(hw, B2_E_1) & 0xf;
+ pmd_type = skge_read8(hw, B2_PMD_TYP);
+ hw->copper = (pmd_type == 'T' || pmd_type == '1');
switch (hw->chip_id) {
case CHIP_ID_GENESIS:
- switch (hw->phy_type) {
+ switch (phy_type) {
case SK_PHY_BCOM:
hw->phy_addr = PHY_ADDR_BCOM;
break;
default:
printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
- pci_name(hw->pdev), hw->phy_type);
+ pci_name(hw->pdev), phy_type);
return -EOPNOTSUPP;
}
break;
@@ -2927,13 +2913,10 @@ static int skge_reset(struct skge_hw *hw)
case CHIP_ID_YUKON:
case CHIP_ID_YUKON_LITE:
case CHIP_ID_YUKON_LP:
- if (hw->phy_type < SK_PHY_MARV_COPPER && hw->pmd_type != 'S')
- hw->phy_type = SK_PHY_MARV_COPPER;
+ if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+ hw->copper = 1;
hw->phy_addr = PHY_ADDR_MARV;
- if (!iscopper(hw))
- hw->phy_type = SK_PHY_MARV_FIBER;
-
break;
default:
@@ -2961,12 +2944,20 @@ static int skge_reset(struct skge_hw *hw)
else
hw->ram_size = t8 * 4096;
+ hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_init(hw);
else {
/* switch power to VCC (WA for VAUX problem) */
skge_write8(hw, B0_POWER_CTRL,
PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+ /* avoid boards with stuck Hardware error bits */
+ if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) &&
+ (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) {
+ printk(KERN_WARNING PFX "stuck hardware sensor bit\n");
+ hw->intr_mask &= ~IS_HW_ERR;
+ }
+
for (i = 0; i < hw->ports; i++) {
skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
@@ -3007,7 +2998,6 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
skge_write32(hw, B2_IRQM_CTRL, TIM_START);
- hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
skge_write32(hw, B0_IMSK, hw->intr_mask);
if (hw->chip_id != CHIP_ID_GENESIS)
@@ -3083,10 +3073,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
spin_lock_init(&skge->tx_lock);
- init_timer(&skge->led_blink);
- skge->led_blink.function = skge_blink_timer;
- skge->led_blink.data = (unsigned long) skge;
-
if (hw->chip_id != CHIP_ID_GENESIS) {
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
skge->rx_csum = 1;
OpenPOWER on IntegriCloud