diff options
author | Benjamin Poirier <bpoirier@suse.com> | 2016-11-07 17:57:56 +0800 |
---|---|---|
committer | Jiri Slaby <jslaby@suse.cz> | 2017-01-27 17:14:54 +0100 |
commit | 32dacf499429803e502361a3a778cbbd691d368b (patch) | |
tree | 3d4333635863a1f2d1c641944778483ce3afc471 | |
parent | e4f13c5f27d6bfb2fea565d346273b0c74023ae6 (diff) | |
download | linux-stable-32dacf499429803e502361a3a778cbbd691d368b.tar.gz linux-stable-32dacf499429803e502361a3a778cbbd691d368b.tar.bz2 linux-stable-32dacf499429803e502361a3a778cbbd691d368b.zip |
bna: Add synchronization for tx ring.
commit d667f78514c656a6a8bf0b3d6134a7fe5cd4d317 upstream.
We received two reports of BUG_ON in bnad_txcmpl_process() where
hw_consumer_index appeared to be ahead of producer_index. Out of order
write/read of these variables could explain these reports.
bnad_start_xmit(), as a producer of tx descriptors, has a few memory
barriers sprinkled around writes to producer_index and the device's
doorbell but they're not paired with anything in bnad_txcmpl_process(), a
consumer.
Since we are synchronizing with a device, we must use mandatory barriers,
not smp_*. Also, I didn't see the purpose of the last smp_mb() in
bnad_start_xmit().
Signed-off-by: Benjamin Poirier <bpoirier@suse.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bnad.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index 45ce6e2214b3..2deabae1d66e 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -193,6 +193,7 @@ bnad_txcmpl_process(struct bnad *bnad, struct bna_tcb *tcb) return 0; hw_cons = *(tcb->hw_consumer_index); + rmb(); cons = tcb->consumer_index; q_depth = tcb->q_depth; @@ -2906,13 +2907,12 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) BNA_QE_INDX_INC(prod, q_depth); tcb->producer_index = prod; - smp_mb(); + wmb(); if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) return NETDEV_TX_OK; bna_txq_prod_indx_doorbell(tcb); - smp_mb(); return NETDEV_TX_OK; } |