]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
some more .23 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 14 Nov 2007 19:25:42 +0000 (11:25 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 14 Nov 2007 19:25:42 +0000 (11:25 -0800)
queue-2.6.23/series
queue-2.6.23/skge-ram-buffer-fix.patch [new file with mode: 0644]
queue-2.6.23/skge-xm-phy-poll.patch [new file with mode: 0644]
queue-2.6.23/sky2-ethdump.patch [new file with mode: 0644]
queue-2.6.23/sky2-phy-power.patch [new file with mode: 0644]
queue-2.6.23/sky2-status-race.patch [new file with mode: 0644]

index 6836a8c7bd616b9a04fd34832bc52fbb497c67c0..f465356e972fa04ab25936bc0b7f1a4f34720de9 100644 (file)
@@ -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 (file)
index 0000000..ab2554b
--- /dev/null
@@ -0,0 +1,123 @@
+From stable-bounces@linux.kernel.org Tue Nov  6 14:18:31 2007
+From: Stephen Hemminger <shemminger@linux-foundation.org>
+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 <shemminger@linux-foundation.org>
+
+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 <shemminger@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+Signed-off-by: Jeff Garzik <jeff@garzik.org>
+
+---
+ 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 (file)
index 0000000..aaa8453
--- /dev/null
@@ -0,0 +1,254 @@
+From stable-bounces@linux.kernel.org Tue Nov  6 14:18:53 2007
+From: Stephen Hemminger <shemminger@linux-foundation.org>
+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 <shemminger@linux-foundation.org>
+
+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 <shemminger@linux-foundation.org>
+Signed-off-by: Jeff Garzik <jeff@garzik.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ 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 <shemminger@linux-foundation.org>");
+@@ -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 (file)
index 0000000..22d4019
--- /dev/null
@@ -0,0 +1,105 @@
+From stable-bounces@linux.kernel.org Tue Nov  6 14:19:17 2007
+From: Stephen Hemminger <shemminger@linux-foundation.org>
+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 <shemminger@linux-foundation.org>
+
+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 <shemminger@linux-foundation.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ 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 (file)
index 0000000..438fa6b
--- /dev/null
@@ -0,0 +1,54 @@
+From stable-bounces@linux.kernel.org Tue Nov  6 14:18:53 2007
+From: Stephen Hemminger <shemminger@linux-foundation.org>
+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 <shemminger@linux-foundation.org>
+
+patch ff35164e72648e0bf0b10ec4410c195e8607e88b in mainline.
+
+Make sure PCI register for PHY power gets set correctly.
+
+Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ 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 (file)
index 0000000..27559ca
--- /dev/null
@@ -0,0 +1,63 @@
+From stable-bounces@linux.kernel.org Tue Nov  6 14:19:11 2007
+From: Stephen Hemminger <shemminger@linux-foundation.org>
+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 <shemminger@linux-foundation.org>
+Signed-off-by: Jeff Garzik <jeff@garzik.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ 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);
+               }
+       }