[PATCH] skge: gmac register access errors in dual port

Merge of four previous patches and the Kconfig fix
 * Remove debug printk's
 * whitespace cleanup and version number change
 * clear interrupts, reset phy, and reset hardware on shutdown
 * ignore 64bit counter overflow interrupts
 * fix a couple of places where second port could clobber state
   of first port.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
Stephen Hemminger 2005-09-09 12:54:56 -07:00 committed by Jeff Garzik
parent c535a9dd26
commit 46a60f2d71
3 changed files with 56 additions and 46 deletions

View File

@ -1951,7 +1951,7 @@ config SKGE
---help---
This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
and related Gigabit Ethernet adapters. It is a new smaller driver
driver with better performance and more complete ethtool support.
with better performance and more complete ethtool support.
It does not support the link failover and network management
features that "portable" vendor supplied sk98lin driver does.

View File

@ -42,7 +42,7 @@
#include "skge.h"
#define DRV_NAME "skge"
#define DRV_VERSION "0.9"
#define DRV_VERSION "1.0"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@ -669,7 +669,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
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 ?
@ -876,7 +876,7 @@ 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),
skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
netif_carrier_on(skge->netdev);
@ -987,6 +987,8 @@ static void genesis_reset(struct skge_hw *hw, int port)
{
const u8 zero[8] = { 0 };
skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
/* reset the statistics module */
xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */
@ -1021,8 +1023,6 @@ static void bcom_check_link(struct skge_hw *hw, int port)
(void) xm_phy_read(hw, port, PHY_BCOM_STAT);
status = xm_phy_read(hw, port, PHY_BCOM_STAT);
pr_debug("bcom_check_link status=0x%x\n", status);
if ((status & PHY_ST_LSYNC) == 0) {
u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
@ -1106,8 +1106,6 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
{ 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
};
pr_debug("bcom_phy_init\n");
/* read Id from external PHY (all have the same address) */
id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
@ -1340,6 +1338,8 @@ static void genesis_stop(struct skge_port *skge)
int port = skge->port;
u32 reg;
genesis_reset(hw, port);
/* Clear Tx packet arbiter timeout IRQ */
skge_write16(hw, B3_PA_CTRL,
port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
@ -1465,7 +1465,6 @@ static void genesis_link_up(struct skge_port *skge)
u16 cmd;
u32 mode, msk;
pr_debug("genesis_link_up\n");
cmd = xm_read16(hw, port, XM_MMU_CMD);
/*
@ -1578,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;
pr_debug("yukon_init\n");
if (skge->autoneg == AUTONEG_ENABLE) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
@ -1677,9 +1675,11 @@ 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)
skge_write32(hw, B2_GP_IO,
(skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
reg = skge_read32(hw, B2_GP_IO);
reg |= GP_DIR_9 | GP_IO_9;
skge_write32(hw, B2_GP_IO, reg);
}
/* hard reset */
skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
@ -1687,10 +1687,12 @@ 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)
skge_write32(hw, B2_GP_IO,
(skge_read32(hw, B2_GP_IO) | GP_DIR_9)
& ~GP_IO_9);
hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
reg = skge_read32(hw, B2_GP_IO);
reg |= GP_DIR_9;
reg &= ~GP_IO_9;
skge_write32(hw, B2_GP_IO, reg);
}
/* Set hardware config mode */
reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
@ -1729,7 +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);
skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
yukon_init(hw, port);
@ -1801,20 +1803,26 @@ static void yukon_stop(struct skge_port *skge)
struct skge_hw *hw = skge->hw;
int port = skge->port;
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
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);
}
skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
yukon_reset(hw, port);
gma_write16(hw, port, GM_GP_CTRL,
gma_read16(hw, port, GM_GP_CTRL)
& ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
gma_read16(hw, port, GM_GP_CTRL);
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
u32 io = skge_read32(hw, B2_GP_IO);
io |= GP_DIR_9 | GP_IO_9;
skge_write32(hw, B2_GP_IO, io);
skge_read32(hw, B2_GP_IO);
}
/* set GPHY Control reset */
skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
}
static void yukon_get_stats(struct skge_port *skge, u64 *data)
@ -1873,10 +1881,8 @@ static void yukon_link_up(struct skge_port *skge)
int port = skge->port;
u16 reg;
pr_debug("yukon_link_up\n");
/* Enable Transmit FIFO Underrun */
skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
reg = gma_read16(hw, port, GM_GP_CTRL);
if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
@ -1896,7 +1902,6 @@ static void yukon_link_down(struct skge_port *skge)
int port = skge->port;
u16 ctrl;
pr_debug("yukon_link_down\n");
gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
ctrl = gma_read16(hw, port, GM_GP_CTRL);
@ -2112,7 +2117,6 @@ static int skge_up(struct net_device *dev)
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;
free_rx_ring:
@ -2135,15 +2139,20 @@ static int skge_down(struct net_device *dev)
netif_stop_queue(dev);
skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_stop(skge);
else
yukon_stop(skge);
hw->intr_mask &= ~portirqmask[skge->port];
skge_write32(hw, B0_IMSK, hw->intr_mask);
/* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
RB_RST_SET|RB_DIS_OP_MD);
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_stop(skge);
else
yukon_stop(skge);
/* Disable Force Sync bit and Enable Alloc bit */
skge_write8(hw, SK_REG(port, TXA_CTRL),
@ -2367,8 +2376,6 @@ static void genesis_set_multicast(struct net_device *dev)
u32 mode;
u8 filter[8];
pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count);
mode = xm_read32(hw, port, XM_MODE);
mode |= XM_MD_ENA_HASH;
if (dev->flags & IFF_PROMISC)
@ -2530,8 +2537,6 @@ static int skge_poll(struct net_device *dev, int *budget)
unsigned int to_do = min(dev->quota, *budget);
unsigned int work_done = 0;
pr_debug("skge_poll\n");
for (e = ring->to_clean; work_done < to_do; e = e->next) {
struct skge_rx_desc *rd = e->desc;
struct sk_buff *skb;
@ -2672,9 +2677,9 @@ static void skge_error_irq(struct skge_hw *hw)
if (hw->chip_id == CHIP_ID_GENESIS) {
/* clear xmac errors */
if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT);
} else {
/* Timestamp (unused) overflow */
if (hwstatus & IS_IRQ_TIST_OV)
@ -3000,9 +3005,6 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B0_IMSK, hw->intr_mask);
if (hw->chip_id != CHIP_ID_GENESIS)
skge_write8(hw, GMAC_IRQ_MSK, 0);
spin_lock_bh(&hw->phy_lock);
for (i = 0; i < hw->ports; i++) {
if (hw->chip_id == CHIP_ID_GENESIS)
@ -3230,6 +3232,11 @@ static void __devexit skge_remove(struct pci_dev *pdev)
dev0 = hw->dev[0];
unregister_netdev(dev0);
skge_write32(hw, B0_IMSK, 0);
skge_write16(hw, B0_LED, LED_STAT_OFF);
skge_pci_clear(hw);
skge_write8(hw, B0_CTST, CS_RST_SET);
tasklet_kill(&hw->ext_tasklet);
free_irq(pdev->irq, hw);
@ -3238,7 +3245,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
if (dev1)
free_netdev(dev1);
free_netdev(dev0);
skge_write16(hw, B0_LED, LED_STAT_OFF);
iounmap(hw->regs);
kfree(hw);
pci_set_drvdata(pdev, NULL);
@ -3257,7 +3264,10 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
struct skge_port *skge = netdev_priv(dev);
if (netif_running(dev)) {
netif_carrier_off(dev);
skge_down(dev);
if (skge->wol)
netif_stop_queue(dev);
else
skge_down(dev);
}
netif_device_detach(dev);
wol |= skge->wol;

View File

@ -2008,7 +2008,7 @@ enum {
GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR)
#define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR)
/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
/* Bits 15.. 2: reserved */