dm-free-minor-after-unlink-gendisk.patch
ramfs-update-dir-mtime-and-ctime.patch
gbefb-ip32-gbefb-depth-change-fix.patch
+skge-speed-setting.patch
+skge-fix-napi-irq-race.patch
+skge-genesis-phy-initialization-fix.patch
+skge-fix-smp-race.patch
--- /dev/null
+From stable-bounces@linux.kernel.org Wed Feb 22 13:50:00 2006
+Date: Wed, 22 Feb 2006 13:52:33 -0800
+From: Stephen Hemminger <shemminger@osdl.org>
+To: stable@kernel.org
+Cc:
+Subject: [PATCH] skge: fix NAPI/irq race
+
+Fix a race in the receive NAPI, irq handling. The interrupt clear and the
+start need to be separated. Otherwise there is a window between the last
+frame received and the NAPI done level handling.
+
+Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ drivers/net/skge.c | 17 +++++------------
+ 1 files changed, 5 insertions(+), 12 deletions(-)
+
+--- linux-2.6.15.4.orig/drivers/net/skge.c
++++ linux-2.6.15.4/drivers/net/skge.c
+@@ -2675,8 +2675,7 @@ static int skge_poll(struct net_device *
+
+ /* restart receiver */
+ wmb();
+- skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR),
+- CSR_START | CSR_IRQ_CL_F);
++ skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_START);
+
+ *budget -= work_done;
+ dev->quota -= work_done;
+@@ -2853,14 +2852,6 @@ static void skge_extirq(unsigned long da
+ local_irq_enable();
+ }
+
+-static inline void skge_wakeup(struct net_device *dev)
+-{
+- struct skge_port *skge = netdev_priv(dev);
+-
+- prefetch(skge->rx_ring.to_clean);
+- netif_rx_schedule(dev);
+-}
+-
+ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
+ {
+ struct skge_hw *hw = dev_id;
+@@ -2871,13 +2862,15 @@ static irqreturn_t skge_intr(int irq, vo
+
+ status &= hw->intr_mask;
+ if (status & IS_R1_F) {
++ skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F);
+ hw->intr_mask &= ~IS_R1_F;
+- skge_wakeup(hw->dev[0]);
++ netif_rx_schedule(hw->dev[0]);
+ }
+
+ if (status & IS_R2_F) {
++ skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F);
+ hw->intr_mask &= ~IS_R2_F;
+- skge_wakeup(hw->dev[1]);
++ netif_rx_schedule(hw->dev[1]);
+ }
+
+ if (status & IS_XA1_F)
--- /dev/null
+From stable-bounces@linux.kernel.org Wed Feb 22 13:50:02 2006
+Date: Wed, 22 Feb 2006 13:52:35 -0800
+From: Stephen Hemminger <shemminger@osdl.org>
+To: stable@kernel.org
+Cc:
+Subject: [PATCH] skge: fix SMP race
+
+If skge is attached to a bad cable, that goes up/down.
+It exposes an SMP race with the management of IRQ mask
+
+Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ drivers/net/skge.c | 21 ++++++++++++++-------
+ drivers/net/skge.h | 1 +
+ 2 files changed, 15 insertions(+), 7 deletions(-)
+
+--- linux-2.6.15.4.orig/drivers/net/skge.c
++++ linux-2.6.15.4/drivers/net/skge.c
+@@ -2182,8 +2182,10 @@ static int skge_up(struct net_device *de
+ skge->tx_avail = skge->tx_ring.count - 1;
+
+ /* Enable IRQ from port */
++ spin_lock_irq(&hw->hw_lock);
+ hw->intr_mask |= portirqmask[port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
++ spin_unlock_irq(&hw->hw_lock);
+
+ /* Initialize MAC */
+ spin_lock_bh(&hw->phy_lock);
+@@ -2241,8 +2243,10 @@ static int skge_down(struct net_device *
+ else
+ yukon_stop(skge);
+
++ spin_lock_irq(&hw->hw_lock);
+ hw->intr_mask &= ~portirqmask[skge->port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
++ spin_unlock_irq(&hw->hw_lock);
+
+ /* Stop transmitter */
+ skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
+@@ -2698,10 +2702,11 @@ static int skge_poll(struct net_device *
+ if (work_done >= to_do)
+ return 1; /* not done */
+
+- netif_rx_complete(dev);
+- hw->intr_mask |= portirqmask[skge->port];
+- skge_write32(hw, B0_IMSK, hw->intr_mask);
+- skge_read32(hw, B0_IMSK);
++ spin_lock_irq(&hw->hw_lock);
++ __netif_rx_complete(dev);
++ hw->intr_mask |= portirqmask[skge->port];
++ skge_write32(hw, B0_IMSK, hw->intr_mask);
++ spin_unlock_irq(&hw->hw_lock);
+
+ return 0;
+ }
+@@ -2861,10 +2866,10 @@ static void skge_extirq(unsigned long da
+ }
+ spin_unlock(&hw->phy_lock);
+
+- local_irq_disable();
++ spin_lock_irq(&hw->hw_lock);
+ hw->intr_mask |= IS_EXT_REG;
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+- local_irq_enable();
++ spin_unlock_irq(&hw->hw_lock);
+ }
+
+ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
+@@ -2875,7 +2880,7 @@ static irqreturn_t skge_intr(int irq, vo
+ if (status == 0 || status == ~0) /* hotplug or shared irq */
+ return IRQ_NONE;
+
+- status &= hw->intr_mask;
++ spin_lock(&hw->hw_lock);
+ if (status & IS_R1_F) {
+ skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F);
+ hw->intr_mask &= ~IS_R1_F;
+@@ -2927,6 +2932,7 @@ static irqreturn_t skge_intr(int irq, vo
+ }
+
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
++ spin_unlock(&hw->hw_lock);
+
+ return IRQ_HANDLED;
+ }
+@@ -3285,6 +3291,7 @@ static int __devinit skge_probe(struct p
+
+ hw->pdev = pdev;
+ spin_lock_init(&hw->phy_lock);
++ spin_lock_init(&hw->hw_lock);
+ tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw);
+
+ hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
+--- linux-2.6.15.4.orig/drivers/net/skge.h
++++ linux-2.6.15.4/drivers/net/skge.h
+@@ -2473,6 +2473,7 @@ struct skge_hw {
+
+ struct tasklet_struct ext_tasklet;
+ spinlock_t phy_lock;
++ spinlock_t hw_lock;
+ };
+
+ enum {
--- /dev/null
+From stable-bounces@linux.kernel.org Wed Feb 22 13:50:00 2006
+Date: Wed, 22 Feb 2006 13:52:34 -0800
+From: Stephen Hemminger <shemminger@osdl.org>
+To: stable@kernel.org
+Cc:
+Subject: [PATCH] skge: genesis phy initialization fix
+
+The SysKonnect Genesis based board would fail on initialization
+with phy_read errors caused by not waiting for last phy write.
+
+Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ drivers/net/skge.c | 37 ++++++++++++++++++++++++++-----------
+ 1 files changed, 26 insertions(+), 11 deletions(-)
+
+--- linux-2.6.15.4.orig/drivers/net/skge.c
++++ linux-2.6.15.4/drivers/net/skge.c
+@@ -880,13 +880,12 @@ static int __xm_phy_read(struct skge_hw
+ int i;
+
+ xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
+- xm_read16(hw, port, XM_PHY_DATA);
++ *val = xm_read16(hw, port, XM_PHY_DATA);
+
+- /* Need to wait for external PHY */
+ for (i = 0; i < PHY_RETRIES; i++) {
+- udelay(1);
+ if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY)
+ goto ready;
++ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+@@ -919,7 +918,12 @@ static int xm_phy_write(struct skge_hw *
+
+ ready:
+ xm_write16(hw, port, XM_PHY_DATA, val);
+- return 0;
++ for (i = 0; i < PHY_RETRIES; i++) {
++ if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
++ return 0;
++ udelay(1);
++ }
++ return -ETIMEDOUT;
+ }
+
+ static void genesis_init(struct skge_hw *hw)
+@@ -1169,13 +1173,17 @@ static void genesis_mac_init(struct skge
+ u32 r;
+ const u8 zero[6] = { 0 };
+
+- /* Clear MIB counters */
+- xm_write16(hw, port, XM_STAT_CMD,
+- XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+- /* Clear two times according to Errata #3 */
+- xm_write16(hw, port, XM_STAT_CMD,
+- XM_SC_CLR_RXC | XM_SC_CLR_TXC);
++ for (i = 0; i < 10; i++) {
++ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
++ MFF_SET_MAC_RST);
++ if (skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST)
++ goto reset_ok;
++ udelay(1);
++ }
+
++ printk(KERN_WARNING PFX "%s: genesis reset failed\n", dev->name);
++
++ reset_ok:
+ /* Unreset the XMAC. */
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+
+@@ -1192,7 +1200,7 @@ static void genesis_mac_init(struct skge
+ r |= GP_DIR_2|GP_IO_2;
+
+ skge_write32(hw, B2_GP_IO, r);
+- skge_read32(hw, B2_GP_IO);
++
+
+ /* Enable GMII interface */
+ xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
+@@ -1206,6 +1214,13 @@ static void genesis_mac_init(struct skge
+ for (i = 1; i < 16; i++)
+ xm_outaddr(hw, port, XM_EXM(i), zero);
+
++ /* Clear MIB counters */
++ xm_write16(hw, port, XM_STAT_CMD,
++ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
++ /* Clear two times according to Errata #3 */
++ xm_write16(hw, port, XM_STAT_CMD,
++ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
++
+ /* configure Rx High Water Mark (XM_RX_HI_WM) */
+ xm_write16(hw, port, XM_RX_HI_WM, 1450);
+
--- /dev/null
+From stable-bounces@linux.kernel.org Wed Feb 22 13:50:07 2006
+Date: Wed, 22 Feb 2006 13:52:32 -0800
+From: Stephen Hemminger <shemminger@osdl.org>
+To: stable@kernel.org
+Cc:
+Subject: [PATCH] skge: speed setting
+
+This is a clone of John Linville's fixed for speed setting on sky2 driver.
+The skge driver has the same code (and bug). It would not allow manually forcing
+100 and 10 mbit.
+
+Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ drivers/net/skge.c | 10 +++++++++-
+ 1 files changed, 9 insertions(+), 1 deletion(-)
+
+--- linux-2.6.15.4.orig/drivers/net/skge.c
++++ linux-2.6.15.4/drivers/net/skge.c
+@@ -1698,6 +1698,7 @@ static void yukon_mac_init(struct skge_h
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR);
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
++
+ if (skge->autoneg == AUTONEG_DISABLE) {
+ reg = GM_GPCR_AU_ALL_DIS;
+ gma_write16(hw, port, GM_GP_CTRL,
+@@ -1705,16 +1706,23 @@ static void yukon_mac_init(struct skge_h
+
+ switch (skge->speed) {
+ case SPEED_1000:
++ reg &= ~GM_GPCR_SPEED_100;
+ reg |= GM_GPCR_SPEED_1000;
+- /* fallthru */
++ break;
+ case SPEED_100:
++ reg &= ~GM_GPCR_SPEED_1000;
+ reg |= GM_GPCR_SPEED_100;
++ break;
++ case SPEED_10:
++ reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
++ break;
+ }
+
+ if (skge->duplex == DUPLEX_FULL)
+ reg |= GM_GPCR_DUP_FULL;
+ } else
+ reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
++
+ switch (skge->flow_control) {
+ case FLOW_MODE_NONE:
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);