In the case of multi-threaded OACTIVE, why not just do this: upon queue completion:
* lock; * do queue completion; * if any frames were completed, clear queue busy; * if (queue busy == clear && OACTIVE) clear OACTIVE; * run queue completion; * unlock. upon queue transmit: * lock; * queue frame; * if (fail) - mark queue as busy; * if (all busy) - set OACTIVE. * unlock The stack will stop sending you frames whilst OACTIVE Is set, but will continue sending them when you clear it. If you just clear OACTIVE when _a_ queue is clear then you'll get frames queued via start/transmit when queues are busy, but what you won't do is starve them all until all queues have free slots. Ie, you don't mind clearing it, then getting a frame and immediately finding you're busy. Once you've done that, any further issues are likely either concurrency with accessing the tx/rx descriptor rings (per-queue), or the interrupt handling races. Ie, you disable interrupts, handle the tx queue completion, -then- re-enable interrupts and clear masks. Maybe that logic in igb_enable_intr() is to blame? Ie, que_mask / link_mask, is that before or after the queue has been handled? If it's called after the queue is handled, and que_mask / link_mask is 0, but the queue is full, you'll never pick up the next interrupt as there won't be one? 2c, Adrian _______________________________________________ freebsd-net@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-net To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"