misc/72183: em driver em_poll doesn't start send if pending packets
Mark Gooderum
mark at verniernetworks.com
Wed Sep 29 14:10:23 PDT 2004
>Number: 72183
>Category: misc
>Synopsis: em driver em_poll doesn't start send if pending packets
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Sep 29 21:10:22 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator: Mark Gooderum
>Release: 5.3 Beta 4
>Organization:
Vernier Networks, Inc.
>Environment:
FreeBSD 172.20.1.199 5.3-BETA4 FreeBSD 5.3-BETA4 #6: Tue Sep 28 21:35:19 PDT 2004 root at eagle.jumpadmin.net:/usr/build/ambit2/freebsd5/sys/i386/compile/VNISMP i386
>Description:
The em driver has a reversed bit of logic in em_intr() - it will only restart transmission if the queue is empty, not if it is full. em_poll DTRT. Under high enough loads you can wedge a particular instance of an em interface although an ifconfig down/up will clear the condition. The bug is still present in Beta 6.
>How-To-Repeat:
Blast a _lot_ of packets at the system with very little local activity. We flushed this problem doing GigE<->GigE throughput tests with an Ixia. Once the queue is full the interface will wedge on transmit because ifq_handoff() will never tickled if_start/em_start and em_intr() will incorrectly not call em_start_locked(). Downing/uping the interface will recover because the queue will be flushed - switching to polled will too as em_poll() DTRT.
If there is enough local activity the local sends will tickled em_start often enough to keep the queue from filling. It's hard to reproduce the lockup without a piece of gear like an Ixia or Smartbits but the flaw in th elogic is obvious.
>Fix:
The following patch has fixed the problem for us:
--- /tmp/tmp.44554.0 Wed Sep 29 15:52:32 2004
+++ /data/work/mark/5.3B4A1.i386/usr/build/ambit2/freebsd5/sys/dev/em/if_em.c Wed Sep 29 15:51:31 2004
@@ -986,11 +986,11 @@
em_clean_transmit_interrupts(adapter);
}
loop_cnt--;
}
- if (ifp->if_flags & IFF_RUNNING && IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ if (ifp->if_flags & IFF_RUNNING && !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
em_start_locked(ifp);
EM_UNLOCK(adapter);
return;
}
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list