* [PATCH,try2 1/3] ep93xx_eth: fix RX/TXstatus ring full handling
@ 2006-10-30 18:52 Lennert Buytenhek
2006-11-01 1:21 ` Jeff Garzik
0 siblings, 1 reply; 2+ messages in thread
From: Lennert Buytenhek @ 2006-10-30 18:52 UTC (permalink / raw)
To: jeff; +Cc: netdev, Ray Lehtiniemi, Herbert Valerio Riedel
Ray Lehtiniemi reported that an incoming UDP packet flood can lock up
the ep93xx ethernet driver. Herbert Valerio Riedel noted that due to
the way ep93xx_eth manages the RX/TXstatus rings, it cannot distinguish
a full ring from an empty one, and correctly suggested that this was
likely to be causing this lockup to occur.
Instead of looking at the hardware's RX/TXstatus ring write pointers
to determine when to stop reading from those rings, we should just check
every individual RX/TXstatus descriptor's valid bit instead, since there
is no other way to distinguish an empty ring from a full ring, and if
there is a descriptor waiting, we take the hit of reading the descriptor
from memory anyway.
Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Index: linux-2.6.19-rc3/drivers/net/arm/ep93xx_eth.c
===================================================================
--- linux-2.6.19-rc3.orig/drivers/net/arm/ep93xx_eth.c
+++ linux-2.6.19-rc3/drivers/net/arm/ep93xx_eth.c
@@ -193,12 +193,9 @@ static struct net_device_stats *ep93xx_g
static int ep93xx_rx(struct net_device *dev, int *budget)
{
struct ep93xx_priv *ep = netdev_priv(dev);
- int tail_offset;
int rx_done;
int processed;
- tail_offset = rdl(ep, REG_RXSTSQCURADD) - ep->descs_dma_addr;
-
rx_done = 0;
processed = 0;
while (*budget > 0) {
@@ -211,28 +208,23 @@ static int ep93xx_rx(struct net_device *
entry = ep->rx_pointer;
rstat = ep->descs->rstat + entry;
- if ((void *)rstat - (void *)ep->descs == tail_offset) {
+
+ rstat0 = rstat->rstat0;
+ rstat1 = rstat->rstat1;
+ if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP)) {
rx_done = 1;
break;
}
- rstat0 = rstat->rstat0;
- rstat1 = rstat->rstat1;
rstat->rstat0 = 0;
rstat->rstat1 = 0;
- if (!(rstat0 & RSTAT0_RFP))
- printk(KERN_CRIT "ep93xx_rx: buffer not done "
- " %.8x %.8x\n", rstat0, rstat1);
if (!(rstat0 & RSTAT0_EOF))
printk(KERN_CRIT "ep93xx_rx: not end-of-frame "
" %.8x %.8x\n", rstat0, rstat1);
if (!(rstat0 & RSTAT0_EOB))
printk(KERN_CRIT "ep93xx_rx: not end-of-buffer "
" %.8x %.8x\n", rstat0, rstat1);
- if (!(rstat1 & RSTAT1_RFP))
- printk(KERN_CRIT "ep93xx_rx: buffer1 not done "
- " %.8x %.8x\n", rstat0, rstat1);
if ((rstat1 & RSTAT1_BUFFER_INDEX) >> 16 != entry)
printk(KERN_CRIT "ep93xx_rx: entry mismatch "
" %.8x %.8x\n", rstat0, rstat1);
@@ -301,13 +293,8 @@ err:
static int ep93xx_have_more_rx(struct ep93xx_priv *ep)
{
- struct ep93xx_rstat *rstat;
- int tail_offset;
-
- rstat = ep->descs->rstat + ep->rx_pointer;
- tail_offset = rdl(ep, REG_RXSTSQCURADD) - ep->descs_dma_addr;
-
- return !((void *)rstat - (void *)ep->descs == tail_offset);
+ struct ep93xx_rstat *rstat = ep->descs->rstat + ep->rx_pointer;
+ return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP));
}
static int ep93xx_poll(struct net_device *dev, int *budget)
@@ -379,10 +366,8 @@ static int ep93xx_xmit(struct sk_buff *s
static void ep93xx_tx_complete(struct net_device *dev)
{
struct ep93xx_priv *ep = netdev_priv(dev);
- int tail_offset;
int wake;
- tail_offset = rdl(ep, REG_TXSTSQCURADD) - ep->descs_dma_addr;
wake = 0;
spin_lock(&ep->tx_pending_lock);
@@ -393,15 +378,13 @@ static void ep93xx_tx_complete(struct ne
entry = ep->tx_clean_pointer;
tstat = ep->descs->tstat + entry;
- if ((void *)tstat - (void *)ep->descs == tail_offset)
- break;
tstat0 = tstat->tstat0;
+ if (!(tstat0 & TSTAT0_TXFP))
+ break;
+
tstat->tstat0 = 0;
- if (!(tstat0 & TSTAT0_TXFP))
- printk(KERN_CRIT "ep93xx_tx_complete: buffer not done "
- " %.8x\n", tstat0);
if (tstat0 & TSTAT0_FA)
printk(KERN_CRIT "ep93xx_tx_complete: frame aborted "
" %.8x\n", tstat0);
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH,try2 1/3] ep93xx_eth: fix RX/TXstatus ring full handling
2006-10-30 18:52 [PATCH,try2 1/3] ep93xx_eth: fix RX/TXstatus ring full handling Lennert Buytenhek
@ 2006-11-01 1:21 ` Jeff Garzik
0 siblings, 0 replies; 2+ messages in thread
From: Jeff Garzik @ 2006-11-01 1:21 UTC (permalink / raw)
To: Lennert Buytenhek; +Cc: netdev, Ray Lehtiniemi, Herbert Valerio Riedel
Lennert Buytenhek wrote:
> Ray Lehtiniemi reported that an incoming UDP packet flood can lock up
> the ep93xx ethernet driver. Herbert Valerio Riedel noted that due to
> the way ep93xx_eth manages the RX/TXstatus rings, it cannot distinguish
> a full ring from an empty one, and correctly suggested that this was
> likely to be causing this lockup to occur.
>
> Instead of looking at the hardware's RX/TXstatus ring write pointers
> to determine when to stop reading from those rings, we should just check
> every individual RX/TXstatus descriptor's valid bit instead, since there
> is no other way to distinguish an empty ring from a full ring, and if
> there is a descriptor waiting, we take the hit of reading the descriptor
> from memory anyway.
>
> Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
applied 1-3
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-11-01 1:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-30 18:52 [PATCH,try2 1/3] ep93xx_eth: fix RX/TXstatus ring full handling Lennert Buytenhek
2006-11-01 1:21 ` Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).