The attached patch is based on tg3.c as found in 2.4.20-rc3 or the latest Linus 2.5.x kernel, and originates from two motivations: * When net drivers move TX completion from interrupt to dev->poll(), this allows the rethinking of some traditional locking, namely eliminating a lock in dev->start_xmit() that most drivers implement these days. * Specific to the tg3 implementation, spin-lock-irq is held during NIC hardware halt and re-initialization (and a few other operations). In general a goal is to change this; the driver may wind up holding interrupts disabled for longer than prudence dictates. The attached patch does not address this issue directly, but it does begin to lay the groundwork for my upcoming solution :) I mention "NAPI" in the subject because other NAPI drivers may wish to re-examine their locking as well, and this patch could serve as a basis for discussion. Overall, I believe the attached patch (after testing/debugging/review) will make the tg3 driver faster due to less locking in dev->start_xmit, and more friendly system interaction because interrupts are being disabled->enabled less frequently by this driver. Here is a function-by-function description of changes, which gives one a better idea of the locking changes that may be a found in a driver: all functions: s/spin_lock_irq/spin_lock_irqsave/ to be more conservative and "obviously safe" all functions: locking ordering now reversed: dev->xmit_lock obtained before tp->lock. tg3_set_power_state: Do not call tg3_halt(), the one case where this code path is hit, the caller has already called tg3_halt() tg3_poll: hold dev->xmit_lock when checking for TX work, and running TX completion cycle. tp->tx_lock GC'd. tg3_tx_timeout: net stack already holds dev->xmit_lock. tx_lock GC'd. tg3_{4gbug}_start_xmit: net stack already holds dev->xmit_lock, no other locks needed (whee!), so: tp->lock GC'd. tg3_change_mtu: get dev->xmit_lock instead of tp->tx_lock. wrap locking in netif_start_queue ... netif_wake_queue. tg3_timer: get xmit_lock instead of tx_lock. wrap NIC reset in netif_start_queue ... netif_wake_queue. tg3_open: no need for tx locking, just move netif_start_queue down to the bottom of the function. tg3_close: s/tp->tx_lock/dev->xmit_lock/ tg3_get_regs: likewise tg3_ethtool_ioctl: likewise, plus netif_{start,wake}_queue wrap around NIC reset tg3_vlan_rx_register: remove TX lock tg3_vlan_rx_kill_vid: remove TX lock tg3_suspend: s/tp->tx_lock/dev->xmit_lock/, netif_{start,wake}_queue wrap tg3_resume: likewise Th-th-th-th-that's all, folks! Questions/comments/flames requested.