Browse Source

[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>
Stephen Hemminger 19 years ago
parent
commit
46a60f2d71
3 changed files with 56 additions and 46 deletions
  1. 1 1
      drivers/net/Kconfig
  2. 54 44
      drivers/net/skge.c
  3. 1 1
      drivers/net/skge.h

+ 1 - 1
drivers/net/Kconfig

@@ -1951,7 +1951,7 @@ config SKGE
 	---help---
 	---help---
 	  This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
 	  This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
 	  and related Gigabit Ethernet adapters. It is a new smaller driver
 	  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 
 	  It does not support the link failover and network management 
 	  features that "portable" vendor supplied sk98lin driver does.
 	  features that "portable" vendor supplied sk98lin driver does.

+ 54 - 44
drivers/net/skge.c

@@ -42,7 +42,7 @@
 #include "skge.h"
 #include "skge.h"
 
 
 #define DRV_NAME		"skge"
 #define DRV_NAME		"skge"
-#define DRV_VERSION		"0.9"
+#define DRV_VERSION		"1.0"
 #define PFX			DRV_NAME " "
 #define PFX			DRV_NAME " "
 
 
 #define DEFAULT_TX_RING_SIZE	128
 #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_LED_BLINK_RT(BLINK_84MS) |
 				     PHY_M_LEDC_TX_CTRL |
 				     PHY_M_LEDC_TX_CTRL |
 				     PHY_M_LEDC_DP_CTRL);
 				     PHY_M_LEDC_DP_CTRL);
-		
+
 			gm_phy_write(hw, port, PHY_MARV_LED_OVER,
 			gm_phy_write(hw, port, PHY_MARV_LED_OVER,
 				     PHY_M_LED_MO_RX(MO_LED_OFF) |
 				     PHY_M_LED_MO_RX(MO_LED_OFF) |
 				     (skge->speed == SPEED_100 ?
 				     (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)
 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);
 		    LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
 
 
 	netif_carrier_on(skge->netdev);
 	netif_carrier_on(skge->netdev);
@@ -987,6 +987,8 @@ static void genesis_reset(struct skge_hw *hw, int port)
 {
 {
 	const u8 zero[8]  = { 0 };
 	const u8 zero[8]  = { 0 };
 
 
+	skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
 	/* reset the statistics module */
 	/* reset the statistics module */
 	xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
 	xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
 	xm_write16(hw, port, XM_IMSK, 0xffff);	/* disable XMAC IRQs */
 	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);
 	(void) xm_phy_read(hw, port, PHY_BCOM_STAT);
 	status = 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) {
 	if ((status & PHY_ST_LSYNC) == 0) {
 		u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
 		u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
 		cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
 		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 },
 		{ 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
 	};
 	};
 
 
-	pr_debug("bcom_phy_init\n");
-
 	/* read Id from external PHY (all have the same address) */
 	/* read Id from external PHY (all have the same address) */
 	id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
 	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;
 	int port = skge->port;
 	u32 reg;
 	u32 reg;
 
 
+	genesis_reset(hw, port);
+
 	/* Clear Tx packet arbiter timeout IRQ */
 	/* Clear Tx packet arbiter timeout IRQ */
 	skge_write16(hw, B3_PA_CTRL,
 	skge_write16(hw, B3_PA_CTRL,
 		     port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
 		     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;
 	u16 cmd;
 	u32 mode, msk;
 	u32 mode, msk;
 
 
-	pr_debug("genesis_link_up\n");
 	cmd = xm_read16(hw, port, XM_MMU_CMD);
 	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]);
 	struct skge_port *skge = netdev_priv(hw->dev[port]);
 	u16 ctrl, ct1000, adv;
 	u16 ctrl, ct1000, adv;
 
 
-	pr_debug("yukon_init\n");
 	if (skge->autoneg == AUTONEG_ENABLE) {
 	if (skge->autoneg == AUTONEG_ENABLE) {
 		u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
 		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 */
 	/* WA code for COMA mode -- set PHY reset */
 	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
 	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 */
 	/* hard reset */
 	skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
 	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 */
 	/* WA code for COMA mode -- clear PHY reset */
 	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
 	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 */
 	/* Set hardware config mode */
 	reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
 	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);
 	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);
 	yukon_init(hw, port);
 
 
@@ -1801,20 +1803,26 @@ static void yukon_stop(struct skge_port *skge)
 	struct skge_hw *hw = skge->hw;
 	struct skge_hw *hw = skge->hw;
 	int port = skge->port;
 	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_write16(hw, port, GM_GP_CTRL,
 			 gma_read16(hw, port, GM_GP_CTRL)
 			 gma_read16(hw, port, GM_GP_CTRL)
 			 & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
 			 & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
 	gma_read16(hw, port, GM_GP_CTRL);
 	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 */
 	/* 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)
 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;
 	int port = skge->port;
 	u16 reg;
 	u16 reg;
 
 
-	pr_debug("yukon_link_up\n");
-
 	/* Enable Transmit FIFO Underrun */
 	/* 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);
 	reg = gma_read16(hw, port, GM_GP_CTRL);
 	if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
 	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;
 	int port = skge->port;
 	u16 ctrl;
 	u16 ctrl;
 
 
-	pr_debug("yukon_link_down\n");
 	gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
 	gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
 
 
 	ctrl = gma_read16(hw, port, GM_GP_CTRL);
 	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_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
 	skge_led(skge, LED_MODE_ON);
 	skge_led(skge, LED_MODE_ON);
 
 
-	pr_debug("skge_up completed\n");
 	return 0;
 	return 0;
 
 
  free_rx_ring:
  free_rx_ring:
@@ -2135,15 +2139,20 @@ static int skge_down(struct net_device *dev)
 
 
 	netif_stop_queue(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 */
 	/* Stop transmitter */
 	skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
 	skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
 	skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
 	skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
 		     RB_RST_SET|RB_DIS_OP_MD);
 		     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 */
 	/* Disable Force Sync bit and Enable Alloc bit */
 	skge_write8(hw, SK_REG(port, TXA_CTRL),
 	skge_write8(hw, SK_REG(port, TXA_CTRL),
@@ -2367,8 +2376,6 @@ static void genesis_set_multicast(struct net_device *dev)
 	u32 mode;
 	u32 mode;
 	u8 filter[8];
 	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_read32(hw, port, XM_MODE);
 	mode |= XM_MD_ENA_HASH;
 	mode |= XM_MD_ENA_HASH;
 	if (dev->flags & IFF_PROMISC)
 	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 to_do = min(dev->quota, *budget);
 	unsigned int work_done = 0;
 	unsigned int work_done = 0;
 
 
-	pr_debug("skge_poll\n");
-
 	for (e = ring->to_clean; work_done < to_do; e = e->next) {
 	for (e = ring->to_clean; work_done < to_do; e = e->next) {
 		struct skge_rx_desc *rd = e->desc;
 		struct skge_rx_desc *rd = e->desc;
 		struct sk_buff *skb;
 		struct sk_buff *skb;
@@ -2672,9 +2677,9 @@ static void skge_error_irq(struct skge_hw *hw)
 	if (hw->chip_id == CHIP_ID_GENESIS) {
 	if (hw->chip_id == CHIP_ID_GENESIS) {
 		/* clear xmac errors */
 		/* clear xmac errors */
 		if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
 		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))
 		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 {
 	} else {
 		/* Timestamp (unused) overflow */
 		/* Timestamp (unused) overflow */
 		if (hwstatus & IS_IRQ_TIST_OV)
 		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);
 	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);
 	spin_lock_bh(&hw->phy_lock);
 	for (i = 0; i < hw->ports; i++) {
 	for (i = 0; i < hw->ports; i++) {
 		if (hw->chip_id == CHIP_ID_GENESIS)
 		if (hw->chip_id == CHIP_ID_GENESIS)
@@ -3230,6 +3232,11 @@ static void __devexit skge_remove(struct pci_dev *pdev)
 	dev0 = hw->dev[0];
 	dev0 = hw->dev[0];
 	unregister_netdev(dev0);
 	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);
 	tasklet_kill(&hw->ext_tasklet);
 
 
 	free_irq(pdev->irq, hw);
 	free_irq(pdev->irq, hw);
@@ -3238,7 +3245,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
 	if (dev1)
 	if (dev1)
 		free_netdev(dev1);
 		free_netdev(dev1);
 	free_netdev(dev0);
 	free_netdev(dev0);
-	skge_write16(hw, B0_LED, LED_STAT_OFF);
+
 	iounmap(hw->regs);
 	iounmap(hw->regs);
 	kfree(hw);
 	kfree(hw);
 	pci_set_drvdata(pdev, NULL);
 	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);
 			struct skge_port *skge = netdev_priv(dev);
 			if (netif_running(dev)) {
 			if (netif_running(dev)) {
 				netif_carrier_off(dev);
 				netif_carrier_off(dev);
-				skge_down(dev);
+				if (skge->wol)
+					netif_stop_queue(dev);
+				else
+					skge_down(dev);
 			}
 			}
 			netif_device_detach(dev);
 			netif_device_detach(dev);
 			wol |= skge->wol;
 			wol |= skge->wol;

+ 1 - 1
drivers/net/skge.h

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