• Don Fry's avatar
    [PATCH] 2.6.3 pcnet32.c transmit hang fix · 5f0ccf26
    Don Fry authored
    The transmit routine will stop interrupting and hang, causing the
    tx_timeout routine to attempt to restart the device when the 32-bit
    cur_tx counter wraps below dirty_tx.  If the device had called
    netif_stop_queue it will never call netif_wake_queue in the interrupt
    routine (at least on an IA32 system) due to 32-bit wrap around arithmetic.
    
    On my IA32 system 'dirty_tx > lp->cur_tx - TX_RING_SIZE + 2' would
    always evaluate to false when dirty and cur_tx were less than 15,
    preventing netif_wake_queue to be called.
    
    By starting dirty_tx and cur_tx at 0xfffffff0 (to reduce test time) I
    found that once cur_tx wrapped to zero, that transmitted buffers would
    never be unmapped or freed because 'while (dirty_tx < lp->cur_tx) {'
    was not true.  cur_tx would keep incrementing (in start_xmit) but dirty_tx
    would not (in pcnet32_interrupt), thus leaking skb's and pci map entries.
    On PPC machines, the system would quickly run out of pci maps.
    
    Fix tested on PPC and IA32.
    5f0ccf26
pcnet32.c 54.6 KB