From 3e47add79cf239acdbfe52cb0ee2b9d8104bd615 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Nov 2007 11:25:42 -0800 Subject: [PATCH] some more .23 patches --- queue-2.6.23/series | 5 + queue-2.6.23/skge-ram-buffer-fix.patch | 123 ++++++++++++ queue-2.6.23/skge-xm-phy-poll.patch | 254 +++++++++++++++++++++++++ queue-2.6.23/sky2-ethdump.patch | 105 ++++++++++ queue-2.6.23/sky2-phy-power.patch | 54 ++++++ queue-2.6.23/sky2-status-race.patch | 63 ++++++ 6 files changed, 604 insertions(+) create mode 100644 queue-2.6.23/skge-ram-buffer-fix.patch create mode 100644 queue-2.6.23/skge-xm-phy-poll.patch create mode 100644 queue-2.6.23/sky2-ethdump.patch create mode 100644 queue-2.6.23/sky2-phy-power.patch create mode 100644 queue-2.6.23/sky2-status-race.patch diff --git a/queue-2.6.23/series b/queue-2.6.23/series index 6836a8c7bd6..f465356e972 100644 --- a/queue-2.6.23/series +++ b/queue-2.6.23/series @@ -79,3 +79,8 @@ uml-stop-using-libc-asm-page.h.patch uml-fix-kernel-vs-libc-symbols-clash.patch uml-stop-using-libc-asm-user.h.patch uml-kill-subprocesses-on-exit.patch +skge-ram-buffer-fix.patch +skge-xm-phy-poll.patch +sky2-status-race.patch +sky2-ethdump.patch +sky2-phy-power.patch diff --git a/queue-2.6.23/skge-ram-buffer-fix.patch b/queue-2.6.23/skge-ram-buffer-fix.patch new file mode 100644 index 00000000000..ab2554b5518 --- /dev/null +++ b/queue-2.6.23/skge-ram-buffer-fix.patch @@ -0,0 +1,123 @@ +From stable-bounces@linux.kernel.org Tue Nov 6 14:18:31 2007 +From: Stephen Hemminger +Date: Tue, 06 Nov 2007 14:12:29 -0800 +Subject: [stable] [PATCH 1/6] skge: fix ram buffer size calculation +To: stable@kernel.org +Message-ID: <20071106221308.286029028@linux-foundation.org> +Content-Disposition: inline; filename=skge-ram-buffer-fix.patch + +From: Stephen Hemminger + +patch 7fb7ac241162dc51ec0f7644d4a97b2855213c32 in mainline. + +This fixes problems with transmit hangs on older fiber based SysKonnect boards. + +Adjust ram buffer sizing calculation to make it correct on all boards +and make it like the code in sky2 driver. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Jeff Garzik + +--- + drivers/net/skge.c | 51 ++++++++++++++++++++++++--------------------------- + 1 file changed, 24 insertions(+), 27 deletions(-) + +--- a/drivers/net/skge.c ++++ b/drivers/net/skge.c +@@ -2400,32 +2400,31 @@ static int skge_ioctl(struct net_device + return err; + } + +-static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) ++/* Assign Ram Buffer allocation to queue */ ++static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, u32 space) + { + u32 end; + +- start /= 8; +- len /= 8; +- end = start + len - 1; ++ /* convert from K bytes to qwords used for hw register */ ++ start *= 1024/8; ++ space *= 1024/8; ++ end = start + space - 1; + + skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); + skge_write32(hw, RB_ADDR(q, RB_START), start); ++ skge_write32(hw, RB_ADDR(q, RB_END), end); + skge_write32(hw, RB_ADDR(q, RB_WP), start); + skge_write32(hw, RB_ADDR(q, RB_RP), start); +- skge_write32(hw, RB_ADDR(q, RB_END), end); + + if (q == Q_R1 || q == Q_R2) { ++ u32 tp = space - space/4; ++ + /* Set thresholds on receive queue's */ +- skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), +- start + (2*len)/3); +- skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), +- start + (len/3)); +- } else { +- /* Enable store & forward on Tx queue's because +- * Tx FIFO is only 4K on Genesis and 1K on Yukon +- */ ++ skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp); ++ skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4); ++ } else if (hw->chip_id != CHIP_ID_GENESIS) ++ /* Genesis Tx Fifo is too small for normal store/forward */ + skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); +- } + + skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); + } +@@ -2453,7 +2452,7 @@ static int skge_up(struct net_device *de + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int port = skge->port; +- u32 chunk, ram_addr; ++ u32 ramaddr, ramsize, rxspace; + size_t rx_size, tx_size; + int err; + +@@ -2508,14 +2507,15 @@ static int skge_up(struct net_device *de + spin_unlock_bh(&hw->phy_lock); + + /* Configure RAMbuffers */ +- chunk = hw->ram_size / ((hw->ports + 1)*2); +- ram_addr = hw->ram_offset + 2 * chunk * port; ++ ramsize = (hw->ram_size - hw->ram_offset) / hw->ports; ++ ramaddr = hw->ram_offset + port * ramsize; ++ rxspace = 8 + (2*(ramsize - 16))/3; + +- skge_ramset(hw, rxqaddr[port], ram_addr, chunk); +- skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean); ++ skge_ramset(hw, rxqaddr[port], ramaddr, rxspace); ++ skge_ramset(hw, txqaddr[port], ramaddr + rxspace, ramsize - rxspace); + ++ skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean); + BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean); +- skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk); + skge_qset(skge, txqaddr[port], skge->tx_ring.to_use); + + /* Start receiver BMU */ +@@ -3450,15 +3450,12 @@ static int skge_reset(struct skge_hw *hw + if (hw->chip_id == CHIP_ID_GENESIS) { + if (t8 == 3) { + /* special case: 4 x 64k x 36, offset = 0x80000 */ +- hw->ram_size = 0x100000; +- hw->ram_offset = 0x80000; ++ hw->ram_size = 1024; ++ hw->ram_offset = 512; + } else + hw->ram_size = t8 * 512; +- } +- else if (t8 == 0) +- hw->ram_size = 0x20000; +- else +- hw->ram_size = t8 * 4096; ++ } else /* Yukon */ ++ hw->ram_size = t8 ? t8 * 4 : 128; + + hw->intr_mask = IS_HW_ERR; + diff --git a/queue-2.6.23/skge-xm-phy-poll.patch b/queue-2.6.23/skge-xm-phy-poll.patch new file mode 100644 index 00000000000..aaa84531ba0 --- /dev/null +++ b/queue-2.6.23/skge-xm-phy-poll.patch @@ -0,0 +1,254 @@ +From stable-bounces@linux.kernel.org Tue Nov 6 14:18:53 2007 +From: Stephen Hemminger +Date: Tue, 06 Nov 2007 14:12:30 -0800 +Subject: skge: XM PHY handling fixes +To: stable@kernel.org +Message-ID: <20071106221308.364160885@linux-foundation.org> +Content-Disposition: inline; filename=skge-xm-phy-poll.patch + +From: Stephen Hemminger + +patch 501fb72d052d2a302b423bef7dec98d9d98c8a36 in mainline. + +Change how PHY is managed on SysKonnect fibre based boards. +Poll for PHY coming up 1 per second, but use interrupt to detect loss. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/skge.c | 90 ++++++++++++++++++++++++++++------------------------- + drivers/net/skge.h | 6 +-- + 2 files changed, 51 insertions(+), 45 deletions(-) + +--- a/drivers/net/skge.c ++++ b/drivers/net/skge.c +@@ -57,7 +57,7 @@ + #define TX_WATCHDOG (5 * HZ) + #define NAPI_WEIGHT 64 + #define BLINK_MS 250 +-#define LINK_HZ (HZ/2) ++#define LINK_HZ HZ + + MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); + MODULE_AUTHOR("Stephen Hemminger "); +@@ -992,19 +992,15 @@ static void xm_link_down(struct skge_hw + { + struct net_device *dev = hw->dev[port]; + struct skge_port *skge = netdev_priv(dev); +- u16 cmd, msk; ++ u16 cmd = xm_read16(hw, port, XM_MMU_CMD); + +- if (hw->phy_type == SK_PHY_XMAC) { +- msk = xm_read16(hw, port, XM_IMSK); +- msk |= XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND; +- xm_write16(hw, port, XM_IMSK, msk); +- } ++ xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); + +- cmd = xm_read16(hw, port, XM_MMU_CMD); + cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); + xm_write16(hw, port, XM_MMU_CMD, cmd); ++ + /* dummy read to ensure writing */ +- (void) xm_read16(hw, port, XM_MMU_CMD); ++ xm_read16(hw, port, XM_MMU_CMD); + + if (netif_carrier_ok(dev)) + skge_link_down(skge); +@@ -1100,7 +1096,7 @@ static void genesis_reset(struct skge_hw + + /* 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 */ ++ xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); + xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */ + xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */ + xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */ +@@ -1138,7 +1134,7 @@ static void bcom_check_link(struct skge_ + u16 status; + + /* read twice because of latch */ +- (void) xm_phy_read(hw, port, PHY_BCOM_STAT); ++ xm_phy_read(hw, port, PHY_BCOM_STAT); + status = xm_phy_read(hw, port, PHY_BCOM_STAT); + + if ((status & PHY_ST_LSYNC) == 0) { +@@ -1339,7 +1335,7 @@ static void xm_phy_init(struct skge_port + mod_timer(&skge->link_timer, jiffies + LINK_HZ); + } + +-static void xm_check_link(struct net_device *dev) ++static int xm_check_link(struct net_device *dev) + { + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; +@@ -1347,25 +1343,25 @@ static void xm_check_link(struct net_dev + u16 status; + + /* read twice because of latch */ +- (void) xm_phy_read(hw, port, PHY_XMAC_STAT); ++ xm_phy_read(hw, port, PHY_XMAC_STAT); + status = xm_phy_read(hw, port, PHY_XMAC_STAT); + + if ((status & PHY_ST_LSYNC) == 0) { + xm_link_down(hw, port); +- return; ++ return 0; + } + + if (skge->autoneg == AUTONEG_ENABLE) { + u16 lpa, res; + + if (!(status & PHY_ST_AN_OVER)) +- return; ++ return 0; + + lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); + if (lpa & PHY_B_AN_RF) { + printk(KERN_NOTICE PFX "%s: remote fault\n", + dev->name); +- return; ++ return 0; + } + + res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI); +@@ -1381,7 +1377,7 @@ static void xm_check_link(struct net_dev + default: + printk(KERN_NOTICE PFX "%s: duplex mismatch\n", + dev->name); +- return; ++ return 0; + } + + /* We are using IEEE 802.3z/D5.0 Table 37-4 */ +@@ -1405,11 +1401,14 @@ static void xm_check_link(struct net_dev + + if (!netif_carrier_ok(dev)) + genesis_link_up(skge); ++ return 1; + } + + /* Poll to check for link coming up. ++ * + * Since internal PHY is wired to a level triggered pin, can't +- * get an interrupt when carrier is detected. ++ * get an interrupt when carrier is detected, need to poll for ++ * link coming up. + */ + static void xm_link_timer(unsigned long arg) + { +@@ -1417,29 +1416,35 @@ static void xm_link_timer(unsigned long + struct net_device *dev = skge->netdev; + struct skge_hw *hw = skge->hw; + int port = skge->port; ++ int i; ++ unsigned long flags; + + if (!netif_running(dev)) + return; + +- if (netif_carrier_ok(dev)) { ++ spin_lock_irqsave(&hw->phy_lock, flags); ++ ++ /* ++ * Verify that the link by checking GPIO register three times. ++ * This pin has the signal from the link_sync pin connected to it. ++ */ ++ for (i = 0; i < 3; i++) { ++ if (xm_read16(hw, port, XM_GP_PORT) & XM_GP_INP_ASS) ++ goto link_down; ++ } ++ ++ /* Re-enable interrupt to detect link down */ ++ if (xm_check_link(dev)) { ++ u16 msk = xm_read16(hw, port, XM_IMSK); ++ msk &= ~XM_IS_INP_ASS; ++ xm_write16(hw, port, XM_IMSK, msk); + xm_read16(hw, port, XM_ISRC); +- if (!(xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)) +- goto nochange; + } else { +- if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS) +- goto nochange; +- xm_read16(hw, port, XM_ISRC); +- if (xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS) +- goto nochange; ++link_down: ++ mod_timer(&skge->link_timer, ++ round_jiffies(jiffies + LINK_HZ)); + } +- +- spin_lock(&hw->phy_lock); +- xm_check_link(dev); +- spin_unlock(&hw->phy_lock); +- +-nochange: +- if (netif_running(dev)) +- mod_timer(&skge->link_timer, jiffies + LINK_HZ); ++ spin_unlock_irqrestore(&hw->phy_lock, flags); + } + + static void genesis_mac_init(struct skge_hw *hw, int port) +@@ -1683,14 +1688,16 @@ static void genesis_mac_intr(struct skge + printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", + skge->netdev->name, status); + +- if (hw->phy_type == SK_PHY_XMAC && +- (status & (XM_IS_INP_ASS | XM_IS_LIPA_RC))) +- xm_link_down(hw, port); ++ if (hw->phy_type == SK_PHY_XMAC && (status & XM_IS_INP_ASS)) { ++ xm_link_down(hw, port); ++ mod_timer(&skge->link_timer, jiffies + 1); ++ } + + if (status & XM_IS_TXF_UR) { + xm_write32(hw, port, XM_MODE, XM_MD_FTF); + ++skge->net_stats.tx_fifo_errors; + } ++ + if (status & XM_IS_RXF_OV) { + xm_write32(hw, port, XM_MODE, XM_MD_FRF); + ++skge->net_stats.rx_fifo_errors; +@@ -1750,11 +1757,12 @@ static void genesis_link_up(struct skge_ + } + + xm_write32(hw, port, XM_MODE, mode); +- msk = XM_DEF_MSK; +- if (hw->phy_type != SK_PHY_XMAC) +- msk |= XM_IS_INP_ASS; /* disable GP0 interrupt bit */ + ++ /* Turn on detection of Tx underrun, Rx overrun */ ++ msk = xm_read16(hw, port, XM_IMSK); ++ msk &= ~(XM_IS_RXF_OV | XM_IS_TXF_UR); + xm_write16(hw, port, XM_IMSK, msk); ++ + xm_read16(hw, port, XM_ISRC); + + /* get MMU Command Reg. */ +@@ -2185,7 +2193,7 @@ static void yukon_mac_intr(struct skge_h + u8 status = skge_read8(hw, SK_REG(port, GMAC_IRQ_SRC)); + + if (netif_msg_intr(skge)) +- printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", ++ printk(KERN_DEBUG PFX "%s: yukon mac interrupt status 0x%x\n", + dev->name, status); + + if (status & GM_IS_RX_FF_OR) { +--- a/drivers/net/skge.h ++++ b/drivers/net/skge.h +@@ -2193,11 +2193,9 @@ enum { + XM_IS_TXF_UR = 1<<2, /* Bit 2: Transmit FIFO Underrun */ + XM_IS_TX_COMP = 1<<1, /* Bit 1: Frame Tx Complete */ + XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */ +-}; +- +-#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | \ +- XM_IS_RXF_OV | XM_IS_TXF_UR)) + ++ XM_IMSK_DISABLE = 0xffff, ++}; + + /* XM_HW_CFG 16 bit r/w Hardware Config Register */ + enum { diff --git a/queue-2.6.23/sky2-ethdump.patch b/queue-2.6.23/sky2-ethdump.patch new file mode 100644 index 00000000000..22d4019cad5 --- /dev/null +++ b/queue-2.6.23/sky2-ethdump.patch @@ -0,0 +1,105 @@ +From stable-bounces@linux.kernel.org Tue Nov 6 14:19:17 2007 +From: Stephen Hemminger +Date: Tue, 06 Nov 2007 14:12:32 -0800 +Subject: sky2: ethtool register reserved area blackout +To: stable@kernel.org +Message-ID: <20071106221308.515605644@linux-foundation.org> +Content-Disposition: inline; filename=sky2-ethdump.patch + +From: Stephen Hemminger + +patch 295b54c4902c52cd00d7c837d50a86e39e26caec in mainline. + +Make sure and not dump reserved areas of device space. +Touching some of these causes machine check exceptions on boards +like D-Link DGE-550SX. + +Coding note, used a complex switch statement rather than bitmap +because it is easier to relate the block values to the documentation +rather than looking at a encoded bitmask. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/net/sky2.c | 62 +++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 53 insertions(+), 9 deletions(-) + +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -3570,20 +3570,64 @@ static void sky2_get_regs(struct net_dev + { + const struct sky2_port *sky2 = netdev_priv(dev); + const void __iomem *io = sky2->hw->regs; ++ unsigned int b; + + regs->version = 1; +- memset(p, 0, regs->len); + +- memcpy_fromio(p, io, B3_RAM_ADDR); +- +- /* skip diagnostic ram region */ +- memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1); ++ for (b = 0; b < 128; b++) { ++ /* This complicated switch statement is to make sure and ++ * only access regions that are unreserved. ++ * Some blocks are only valid on dual port cards. ++ * and block 3 has some special diagnostic registers that ++ * are poison. ++ */ ++ switch (b) { ++ case 3: ++ /* skip diagnostic ram region */ ++ memcpy_fromio(p + 0x10, io + 0x10, 128 - 0x10); ++ break; + +- /* copy GMAC registers */ +- memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000); +- if (sky2->hw->ports > 1) +- memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000); ++ /* dual port cards only */ ++ case 5: /* Tx Arbiter 2 */ ++ case 9: /* RX2 */ ++ case 14 ... 15: /* TX2 */ ++ case 17: case 19: /* Ram Buffer 2 */ ++ case 22 ... 23: /* Tx Ram Buffer 2 */ ++ case 25: /* Rx MAC Fifo 1 */ ++ case 27: /* Tx MAC Fifo 2 */ ++ case 31: /* GPHY 2 */ ++ case 40 ... 47: /* Pattern Ram 2 */ ++ case 52: case 54: /* TCP Segmentation 2 */ ++ case 112 ... 116: /* GMAC 2 */ ++ if (sky2->hw->ports == 1) ++ goto reserved; ++ /* fall through */ ++ case 0: /* Control */ ++ case 2: /* Mac address */ ++ case 4: /* Tx Arbiter 1 */ ++ case 7: /* PCI express reg */ ++ case 8: /* RX1 */ ++ case 12 ... 13: /* TX1 */ ++ case 16: case 18:/* Rx Ram Buffer 1 */ ++ case 20 ... 21: /* Tx Ram Buffer 1 */ ++ case 24: /* Rx MAC Fifo 1 */ ++ case 26: /* Tx MAC Fifo 1 */ ++ case 28 ... 29: /* Descriptor and status unit */ ++ case 30: /* GPHY 1*/ ++ case 32 ... 39: /* Pattern Ram 1 */ ++ case 48: case 50: /* TCP Segmentation 1 */ ++ case 56 ... 60: /* PCI space */ ++ case 80 ... 84: /* GMAC 1 */ ++ memcpy_fromio(p, io, 128); ++ break; ++ default: ++reserved: ++ memset(p, 0, 128); ++ } + ++ p += 128; ++ io += 128; ++ } + } + + /* In order to do Jumbo packets on these chips, need to turn off the diff --git a/queue-2.6.23/sky2-phy-power.patch b/queue-2.6.23/sky2-phy-power.patch new file mode 100644 index 00000000000..438fa6b9d4d --- /dev/null +++ b/queue-2.6.23/sky2-phy-power.patch @@ -0,0 +1,54 @@ +From stable-bounces@linux.kernel.org Tue Nov 6 14:18:53 2007 +From: Stephen Hemminger +Date: Tue, 06 Nov 2007 14:12:33 -0800 +Subject: sky2: fix power settings on Yukon XL +To: stable@kernel.org +Message-ID: <20071106221308.578043016@linux-foundation.org> +Content-Disposition: inline; filename=sky2-phy-power.patch + +From: Stephen Hemminger + +patch ff35164e72648e0bf0b10ec4410c195e8607e88b in mainline. + +Make sure PCI register for PHY power gets set correctly. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/net/sky2.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -603,21 +603,22 @@ static void sky2_phy_init(struct sky2_hw + static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff) + { + u32 reg1; +- static const u32 phy_power[] +- = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD }; +- +- /* looks like this XL is back asswards .. */ +- if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) +- onoff = !onoff; ++ static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD }; ++ static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA }; + + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); ++ + if (onoff) + /* Turn off phy power saving */ + reg1 &= ~phy_power[port]; + else + reg1 |= phy_power[port]; + ++ if (onoff && hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) ++ reg1 |= coma_mode[port]; ++ ++ + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + sky2_pci_read32(hw, PCI_DEV_REG1); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); diff --git a/queue-2.6.23/sky2-status-race.patch b/queue-2.6.23/sky2-status-race.patch new file mode 100644 index 00000000000..27559cac32f --- /dev/null +++ b/queue-2.6.23/sky2-status-race.patch @@ -0,0 +1,63 @@ +From stable-bounces@linux.kernel.org Tue Nov 6 14:19:11 2007 +From: Stephen Hemminger +Date: Tue, 06 Nov 2007 14:12:34 -0800 +Subject: sky2: status ring race fix +To: stable@kernel.org +Message-ID: <20071106221308.629175444@linux-foundation.org> +Content-Disposition: inline; filename=sky2-status-race.patch + +patch ab5adecb2d02f3688719dfb5936a82833fcc3955 in mainline. + +The D-Link PCI-X board (and maybe others) can lie about status +ring entries. It seems it will update the register for last status +index before completing the DMA for the ring entry. To avoid reading +stale data, zap the old entry and check. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/sky2.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -2246,20 +2246,26 @@ static int sky2_status_intr(struct sky2_ + while (hw->st_idx != hwidx) { + struct sky2_port *sky2; + struct sky2_status_le *le = hw->st_le + hw->st_idx; +- unsigned port = le->css & CSS_LINK_BIT; ++ unsigned port; + struct net_device *dev; + struct sk_buff *skb; + u32 status; + u16 length; ++ u8 opcode = le->opcode; ++ ++ if (!(opcode & HW_OWNER)) ++ break; + + hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); + ++ port = le->css & CSS_LINK_BIT; + dev = hw->dev[port]; + sky2 = netdev_priv(dev); + length = le16_to_cpu(le->length); + status = le32_to_cpu(le->status); + +- switch (le->opcode & ~HW_OWNER) { ++ le->opcode = 0; ++ switch (opcode & ~HW_OWNER) { + case OP_RXSTAT: + ++rx[port]; + skb = sky2_receive(dev, length, status); +@@ -2352,7 +2358,7 @@ static int sky2_status_intr(struct sky2_ + default: + if (net_ratelimit()) + printk(KERN_WARNING PFX +- "unknown status opcode 0x%x\n", le->opcode); ++ "unknown status opcode 0x%x\n", opcode); + } + } + -- 2.47.3