[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:
Родитель
c535a9dd26
Коммит
46a60f2d71
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче