|
|
|
@ -42,7 +42,7 @@
|
|
|
|
|
#include "skge.h"
|
|
|
|
|
|
|
|
|
|
#define DRV_NAME "skge"
|
|
|
|
|
#define DRV_VERSION "0.7"
|
|
|
|
|
#define DRV_VERSION "0.8"
|
|
|
|
|
#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,7 +75,6 @@ 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 */
|
|
|
|
@ -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)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
/* 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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
|
|
|
|
|
skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
|
|
|
|
|
|
|
|
|
|
/* Broadcom only */
|
|
|
|
|
xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
|
|
|
|
|
} 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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
int port = skge->port;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
spin_lock_bh(&hw->phy_lock);
|
|
|
|
|
if (hw->chip_id == CHIP_ID_GENESIS) {
|
|
|
|
|
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->blink_on = !skge->blink_on;
|
|
|
|
|
mod_timer(&skge->led_blink, jiffies + BLINK_HZ);
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
|
|
|
|
|
skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
@ -1028,7 +1041,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 +1112,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 +1207,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 +1215,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 +1224,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 +1573,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) {
|
|
|
|
@ -1641,32 +1644,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 +1673,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 +1683,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);
|
|
|
|
@ -1745,9 +1727,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,7 +1776,7 @@ 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);
|
|
|
|
@ -1813,19 +1793,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 +1836,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 +1877,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 +1885,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 +2080,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 +2101,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 +2126,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 +2159,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 +2614,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),
|
|
|
|
@ -3083,10 +3070,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;
|
|
|
|
|