Commit f47c11ee authored by David S. Miller's avatar David S. Miller

[TG3]: Eliminate all hw IRQ handler spinlocks.

Move all driver spinlocks to be taken at sw IRQ
context only.

This fixes the skb_copy() we were doing with hw
IRQs disabled (which is illegal and triggers a
BUG() with HIGHMEM enabled).  It also simplifies
the locking all over the driver tremendously.

We accomplish this feat by creating a special
sequence to synchronize with the hw IRQ handler
using a binary state and synchronize_irq().
This idea is from Herbert Xu.

Thanks to Michael Chan for helping to track down
all of the race conditions in initial versions
of this code.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cd024c8b
This diff is collapsed.
...@@ -2006,17 +2006,31 @@ struct tg3_ethtool_stats { ...@@ -2006,17 +2006,31 @@ struct tg3_ethtool_stats {
struct tg3 { struct tg3 {
/* begin "general, frequently-used members" cacheline section */ /* begin "general, frequently-used members" cacheline section */
/* If the IRQ handler (which runs lockless) needs to be
* quiesced, the following bitmask state is used. The
* SYNC flag is set by non-IRQ context code to initiate
* the quiescence.
*
* When the IRQ handler notices that SYNC is set, it
* disables interrupts and returns.
*
* When all outstanding IRQ handlers have returned after
* the SYNC flag has been set, the setter can be assured
* that interrupts will no longer get run.
*
* In this way all SMP driver locks are never acquired
* in hw IRQ context, only sw IRQ context or lower.
*/
unsigned int irq_sync;
/* SMP locking strategy: /* SMP locking strategy:
* *
* lock: Held during all operations except TX packet * lock: Held during all operations except TX packet
* processing. * processing.
* *
* tx_lock: Held during tg3_start_xmit{,_4gbug} and tg3_tx * tx_lock: Held during tg3_start_xmit and tg3_tx
* *
* If you want to shut up all asynchronous processing you must * Both of these locks are to be held with BH safety.
* acquire both locks, 'lock' taken before 'tx_lock'. IRQs must
* be disabled to take 'lock' but only softirq disabling is
* necessary for acquisition of 'tx_lock'.
*/ */
spinlock_t lock; spinlock_t lock;
spinlock_t indirect_lock; spinlock_t indirect_lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment