Commit 94b16634 authored by Finn Thain's avatar Finn Thain Committed by David S. Miller

net/sonic: Improve receive descriptor status flag check

After sonic_tx_timeout() calls sonic_init(), it can happen that
sonic_rx() will subsequently encounter a receive descriptor with no
flags set. Remove the comment that says that this can't happen.

When giving a receive descriptor to the SONIC, clear the descriptor
status field. That way, any rx descriptor with flags set can only be
a newly received packet.

Don't process a descriptor without the LPKT bit set. The buffer is
still in use by the SONIC.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Tested-by: default avatarStan Johnson <userm57@yahoo.com>
Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eaabfd19
...@@ -434,7 +434,6 @@ static int index_from_addr(struct sonic_local *lp, dma_addr_t addr, ...@@ -434,7 +434,6 @@ static int index_from_addr(struct sonic_local *lp, dma_addr_t addr,
static void sonic_rx(struct net_device *dev) static void sonic_rx(struct net_device *dev)
{ {
struct sonic_local *lp = netdev_priv(dev); struct sonic_local *lp = netdev_priv(dev);
int status;
int entry = lp->cur_rx; int entry = lp->cur_rx;
int prev_entry = lp->eol_rx; int prev_entry = lp->eol_rx;
...@@ -445,9 +444,10 @@ static void sonic_rx(struct net_device *dev) ...@@ -445,9 +444,10 @@ static void sonic_rx(struct net_device *dev)
u16 bufadr_l; u16 bufadr_l;
u16 bufadr_h; u16 bufadr_h;
int pkt_len; int pkt_len;
u16 status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
status = sonic_rda_get(dev, entry, SONIC_RD_STATUS); /* If the RD has LPKT set, the chip has finished with the RB */
if (status & SONIC_RCR_PRX) { if ((status & SONIC_RCR_PRX) && (status & SONIC_RCR_LPKT)) {
u32 addr = (sonic_rda_get(dev, entry, u32 addr = (sonic_rda_get(dev, entry,
SONIC_RD_PKTPTR_H) << 16) | SONIC_RD_PKTPTR_H) << 16) |
sonic_rda_get(dev, entry, SONIC_RD_PKTPTR_L); sonic_rda_get(dev, entry, SONIC_RD_PKTPTR_L);
...@@ -495,10 +495,6 @@ static void sonic_rx(struct net_device *dev) ...@@ -495,10 +495,6 @@ static void sonic_rx(struct net_device *dev)
bufadr_h = (unsigned long)new_laddr >> 16; bufadr_h = (unsigned long)new_laddr >> 16;
sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l); sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l);
sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h); sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h);
} else {
/* This should only happen, if we enable accepting broken packets. */
}
if (status & SONIC_RCR_LPKT) {
/* /*
* this was the last packet out of the current receive buffer * this was the last packet out of the current receive buffer
* give the buffer back to the SONIC * give the buffer back to the SONIC
...@@ -511,12 +507,11 @@ static void sonic_rx(struct net_device *dev) ...@@ -511,12 +507,11 @@ static void sonic_rx(struct net_device *dev)
__func__); __func__);
SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); /* clear the flag */ SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); /* clear the flag */
} }
} else }
printk(KERN_ERR "%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",
dev->name);
/* /*
* give back the descriptor * give back the descriptor
*/ */
sonic_rda_put(dev, entry, SONIC_RD_STATUS, 0);
sonic_rda_put(dev, entry, SONIC_RD_IN_USE, 1); sonic_rda_put(dev, entry, SONIC_RD_IN_USE, 1);
prev_entry = entry; prev_entry = entry;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment