Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ab5adecb2d02f3688719dfb5936a82833fcc3955
Commit:     ab5adecb2d02f3688719dfb5936a82833fcc3955
Parent:     ac93a3946b676025fa55356180e8321639744b31
Author:     Stephen Hemminger <[EMAIL PROTECTED]>
AuthorDate: Mon Nov 5 15:52:09 2007 -0800
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Sat Nov 10 04:25:08 2007 -0500

    sky2: status ring race fix
    
    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 <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/net/sky2.c |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 4f41a94..706884a 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -2247,20 +2247,26 @@ static int sky2_status_intr(struct sky2_hw *hw, int 
to_do, u16 idx)
        do {
                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);
@@ -2353,7 +2359,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int 
to_do, u16 idx)
                default:
                        if (net_ratelimit())
                                printk(KERN_WARNING PFX
-                                      "unknown status opcode 0x%x\n", 
le->opcode);
+                                      "unknown status opcode 0x%x\n", opcode);
                }
        } while (hw->st_idx != idx);
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to