vmxnet3: use DMA memory barriers where required
[ Upstream commit f3002c1374fb2367c9d8dbb28852791ef90d2bac ] The gen bits must be read first from (resp. written last to) DMA memory. The proper way to enforce this on Linux is to call dma_rmb() (resp. dma_wmb()). Signed-off-by: Regis Duchesne <hpreg@vmware.com> Acked-by: Ronak Doshi <doshir@vmware.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
779fd38b60
commit
aab3292261
@ -369,6 +369,11 @@ vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq,
|
|||||||
|
|
||||||
gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
|
gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
|
||||||
while (VMXNET3_TCD_GET_GEN(&gdesc->tcd) == tq->comp_ring.gen) {
|
while (VMXNET3_TCD_GET_GEN(&gdesc->tcd) == tq->comp_ring.gen) {
|
||||||
|
/* Prevent any &gdesc->tcd field from being (speculatively)
|
||||||
|
* read before (&gdesc->tcd)->gen is read.
|
||||||
|
*/
|
||||||
|
dma_rmb();
|
||||||
|
|
||||||
completed += vmxnet3_unmap_pkt(VMXNET3_TCD_GET_TXIDX(
|
completed += vmxnet3_unmap_pkt(VMXNET3_TCD_GET_TXIDX(
|
||||||
&gdesc->tcd), tq, adapter->pdev,
|
&gdesc->tcd), tq, adapter->pdev,
|
||||||
adapter);
|
adapter);
|
||||||
@ -1099,6 +1104,11 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
|
|||||||
gdesc->txd.tci = skb_vlan_tag_get(skb);
|
gdesc->txd.tci = skb_vlan_tag_get(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure that the write to (&gdesc->txd)->gen will be observed after
|
||||||
|
* all other writes to &gdesc->txd.
|
||||||
|
*/
|
||||||
|
dma_wmb();
|
||||||
|
|
||||||
/* finally flips the GEN bit of the SOP desc. */
|
/* finally flips the GEN bit of the SOP desc. */
|
||||||
gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^
|
gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^
|
||||||
VMXNET3_TXD_GEN);
|
VMXNET3_TXD_GEN);
|
||||||
@ -1286,6 +1296,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
|
|||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prevent any rcd field from being (speculatively) read before
|
||||||
|
* rcd->gen is read.
|
||||||
|
*/
|
||||||
|
dma_rmb();
|
||||||
|
|
||||||
BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2 &&
|
BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2 &&
|
||||||
rcd->rqID != rq->dataRingQid);
|
rcd->rqID != rq->dataRingQid);
|
||||||
idx = rcd->rxdIdx;
|
idx = rcd->rxdIdx;
|
||||||
@ -1515,6 +1531,12 @@ rcd_done:
|
|||||||
ring->next2comp = idx;
|
ring->next2comp = idx;
|
||||||
num_to_alloc = vmxnet3_cmd_ring_desc_avail(ring);
|
num_to_alloc = vmxnet3_cmd_ring_desc_avail(ring);
|
||||||
ring = rq->rx_ring + ring_idx;
|
ring = rq->rx_ring + ring_idx;
|
||||||
|
|
||||||
|
/* Ensure that the writes to rxd->gen bits will be observed
|
||||||
|
* after all other writes to rxd objects.
|
||||||
|
*/
|
||||||
|
dma_wmb();
|
||||||
|
|
||||||
while (num_to_alloc) {
|
while (num_to_alloc) {
|
||||||
vmxnet3_getRxDesc(rxd, &ring->base[ring->next2fill].rxd,
|
vmxnet3_getRxDesc(rxd, &ring->base[ring->next2fill].rxd,
|
||||||
&rxCmdDesc);
|
&rxCmdDesc);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user