Skip to content

Commit

Permalink
sky2: status ring race fix
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stephen Hemminger authored and Jeff Garzik committed Nov 10, 2007
1 parent ac93a39 commit ab5adec
Showing 1 changed file with 9 additions and 3 deletions.
12 changes: 9 additions & 3 deletions drivers/net/sky2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit ab5adec

Please sign in to comment.