• Anton Vorontsov's avatar
    gianfar: Fix TX ring processing on SMP machines · 0eddba52
    Anton Vorontsov authored
    Starting with commit a3bc1f11 ("gianfar: Revive SKB
    recycling") gianfar driver sooner or later stops transmitting any
    packets on SMP machines.
    
    start_xmit() prepares new skb for transmitting, generally it does
    three things:
    
    1. sets up all BDs (marks them ready to send), except the first one.
    2. stores skb into tx_queue->tx_skbuff so that clean_tx_ring()
       would cleanup it later.
    3. sets up the first BD, i.e. marks it ready.
    
    Here is what clean_tx_ring() does:
    
    1. reads skbs from tx_queue->tx_skbuff
    2. checks if the *last* BD is ready. If it's still ready [to send]
       then it it isn't transmitted, so clean_tx_ring() returns.
       Otherwise it actually cleanups BDs. All is OK.
    
    Now, if there is just one BD, code flow:
    
    - start_xmit(): stores skb into tx_skbuff. Note that the first BD
      (which is also the last one) isn't marked as ready, yet.
    - clean_tx_ring(): sees that skb is not null, *and* its lstatus
      says that it is NOT ready (like if BD was sent), so it cleans
      it up (bad!)
    - start_xmit(): marks BD as ready [to send], but it's too late.
    
    We can fix this simply by reordering lstatus/tx_skbuff writes.
    Reported-by: default avatarMartyn Welch <martyn.welch@ge.com>
    Bisected-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
    Signed-off-by: default avatarAnton Vorontsov <avorontsov@ru.mvista.com>
    Tested-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
    Tested-by: default avatarMartyn Welch <martyn.welch@ge.com>
    Cc: Sandeep Gopalpet <Sandeep.Kumar@freescale.com>
    Cc: Stable <stable@vger.kernel.org> [2.6.33]
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    0eddba52
gianfar.c 80.5 KB