Here is a better patch, after I mulled it over on the trip to Atlanta. It is based on the premise, derived from the chip documentation, that 1) intr-mbox-0 register usage is used to indicate to the NIC that the driver is "in interrupt handler". 2) (intr-mbox-0 = 1) == pci-inta-mask + pci-inta-clear + stuff 3) the docs seem to be saying "just use intr-mbox-0 and ignore pci-inta-mask" Based on these three observations, the attached patch updates tg3 for the following changes: 1) Mask ints in tg3_interrupt and unmask in tg3_poll. We not only eliminate several MMIO writes/reads, but we also eliminate all usage of functions tg3_[un]mask_ints(), which bit-bangs the MISC_HOST_CTRL_MASK_PCI_INT bit in the TG3PCI_MISC_HOST_CTRL register. 2) If tg3_main_interrupt_work() returns no-work-exists, we [obviously must] unmask ints in tg3_interrupt. But this is an unlikely case. 3) Simply call netif_rx_schedule(dev) in tg3_interrupt_main_work(). This was a change previously discussed. Eliminates the "poll already scheduled" message which was often actually a bogus message. 4) Because of #2, tg3_interrupt_main_work returns boolean 'work_exists' now. 5) There are some Bugzilla bug reports for tg3 1.2, where NMI watchdog triggers in tg3_timer. I did s/spin_lock_irq/spin_lock_irqsave/ in tg3_poll for safety, because we might be locking against a timer not only an interrupt handler. And just for general paranoia and safety as an "obviously more safe" change. Comments/feedback/corrections/flames requested :)