|
@@ -6605,6 +6605,9 @@ static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
|
|
|
{
|
|
|
u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
|
|
|
|
|
|
+ /* Force memory writes to complete before releasing descriptor */
|
|
|
+ dma_wmb();
|
|
|
+
|
|
|
desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
|
|
|
}
|
|
|
|
|
@@ -6612,7 +6615,6 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
|
|
|
u32 rx_buf_sz)
|
|
|
{
|
|
|
desc->addr = cpu_to_le64(mapping);
|
|
|
- wmb();
|
|
|
rtl8169_mark_to_asic(desc, rx_buf_sz);
|
|
|
}
|
|
|
|
|
@@ -7073,16 +7075,18 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
|
|
|
|
|
|
skb_tx_timestamp(skb);
|
|
|
|
|
|
- wmb();
|
|
|
+ /* Force memory writes to complete before releasing descriptor */
|
|
|
+ dma_wmb();
|
|
|
|
|
|
/* Anti gcc 2.95.3 bugware (sic) */
|
|
|
status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
|
|
|
txd->opts1 = cpu_to_le32(status);
|
|
|
|
|
|
- tp->cur_tx += frags + 1;
|
|
|
-
|
|
|
+ /* Force all memory writes to complete before notifying device */
|
|
|
wmb();
|
|
|
|
|
|
+ tp->cur_tx += frags + 1;
|
|
|
+
|
|
|
RTL_W8(TxPoll, NPQ);
|
|
|
|
|
|
mmiowb();
|
|
@@ -7181,11 +7185,16 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
|
|
|
struct ring_info *tx_skb = tp->tx_skb + entry;
|
|
|
u32 status;
|
|
|
|
|
|
- rmb();
|
|
|
status = le32_to_cpu(tp->TxDescArray[entry].opts1);
|
|
|
if (status & DescOwn)
|
|
|
break;
|
|
|
|
|
|
+ /* This barrier is needed to keep us from reading
|
|
|
+ * any other fields out of the Tx descriptor until
|
|
|
+ * we know the status of DescOwn
|
|
|
+ */
|
|
|
+ dma_rmb();
|
|
|
+
|
|
|
rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
|
|
|
tp->TxDescArray + entry);
|
|
|
if (status & LastFrag) {
|
|
@@ -7280,11 +7289,16 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget
|
|
|
struct RxDesc *desc = tp->RxDescArray + entry;
|
|
|
u32 status;
|
|
|
|
|
|
- rmb();
|
|
|
status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
|
|
|
-
|
|
|
if (status & DescOwn)
|
|
|
break;
|
|
|
+
|
|
|
+ /* This barrier is needed to keep us from reading
|
|
|
+ * any other fields out of the Rx descriptor until
|
|
|
+ * we know the status of DescOwn
|
|
|
+ */
|
|
|
+ dma_rmb();
|
|
|
+
|
|
|
if (unlikely(status & RxRES)) {
|
|
|
netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
|
|
|
status);
|
|
@@ -7346,7 +7360,6 @@ process_pkt:
|
|
|
}
|
|
|
release_descriptor:
|
|
|
desc->opts2 = 0;
|
|
|
- wmb();
|
|
|
rtl8169_mark_to_asic(desc, rx_buf_sz);
|
|
|
}
|
|
|
|