aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/realtek
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@redhat.com>2014-12-11 18:02:17 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-11 21:15:06 -0500
commita0750138704a63834bac065c24d227c08768a019 (patch)
tree3d766919775414c5e8a9737995aa1d0eef9f7829 /drivers/net/ethernet/realtek
parent1077fa36f23e259858caf6f269a47393a5aff523 (diff)
r8169: Use dma_rmb() and dma_wmb() for DescOwn checks
The r8169 use a pair of wmb() calls when setting up the descriptor rings. The first is to synchronize the descriptor data with the descriptor status, and the second is to synchronize the descriptor status with the use of the MMIO doorbell to notify the device that descriptors are ready. This can come at a heavy price on some systems, and is not really necessary on systems such as x86 as a simple barrier() would suffice to order store/store accesses. As such we can replace the first memory barrier with dma_wmb() to reduce the cost for these accesses. In addition the r8169 uses a rmb() to prevent compiler optimization in the cleanup paths, however by moving the barrier down a few lines and replacing it with a dma_rmb() we should be able to use it to guarantee descriptor accesses do not occur until the device has updated the DescOwn bit from its end. One last change I made is to move the update of cur_tx in the xmit path to after the wmb. This way we can guarantee the device and all CPUs should see the DescOwn update before they see the cur_tx value update. Cc: Realtek linux nic maintainers <nic_swsd@realtek.com> Cc: Francois Romieu <romieu@fr.zoreil.com> Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/realtek')
-rw-r--r--drivers/net/ethernet/realtek/r8169.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 3dad7e884952..088136b37ebe 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -6605,6 +6605,9 @@ static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
6605{ 6605{
6606 u32 eor = le32_to_cpu(desc->opts1) & RingEnd; 6606 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
6607 6607
6608 /* Force memory writes to complete before releasing descriptor */
6609 dma_wmb();
6610
6608 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); 6611 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
6609} 6612}
6610 6613
@@ -6612,7 +6615,6 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
6612 u32 rx_buf_sz) 6615 u32 rx_buf_sz)
6613{ 6616{
6614 desc->addr = cpu_to_le64(mapping); 6617 desc->addr = cpu_to_le64(mapping);
6615 wmb();
6616 rtl8169_mark_to_asic(desc, rx_buf_sz); 6618 rtl8169_mark_to_asic(desc, rx_buf_sz);
6617} 6619}
6618 6620
@@ -7073,16 +7075,18 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
7073 7075
7074 skb_tx_timestamp(skb); 7076 skb_tx_timestamp(skb);
7075 7077
7076 wmb(); 7078 /* Force memory writes to complete before releasing descriptor */
7079 dma_wmb();
7077 7080
7078 /* Anti gcc 2.95.3 bugware (sic) */ 7081 /* Anti gcc 2.95.3 bugware (sic) */
7079 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); 7082 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
7080 txd->opts1 = cpu_to_le32(status); 7083 txd->opts1 = cpu_to_le32(status);
7081 7084
7082 tp->cur_tx += frags + 1; 7085 /* Force all memory writes to complete before notifying device */
7083
7084 wmb(); 7086 wmb();
7085 7087
7088 tp->cur_tx += frags + 1;
7089
7086 RTL_W8(TxPoll, NPQ); 7090 RTL_W8(TxPoll, NPQ);
7087 7091
7088 mmiowb(); 7092 mmiowb();
@@ -7181,11 +7185,16 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
7181 struct ring_info *tx_skb = tp->tx_skb + entry; 7185 struct ring_info *tx_skb = tp->tx_skb + entry;
7182 u32 status; 7186 u32 status;
7183 7187
7184 rmb();
7185 status = le32_to_cpu(tp->TxDescArray[entry].opts1); 7188 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
7186 if (status & DescOwn) 7189 if (status & DescOwn)
7187 break; 7190 break;
7188 7191
7192 /* This barrier is needed to keep us from reading
7193 * any other fields out of the Tx descriptor until
7194 * we know the status of DescOwn
7195 */
7196 dma_rmb();
7197
7189 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, 7198 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
7190 tp->TxDescArray + entry); 7199 tp->TxDescArray + entry);
7191 if (status & LastFrag) { 7200 if (status & LastFrag) {
@@ -7280,11 +7289,16 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget
7280 struct RxDesc *desc = tp->RxDescArray + entry; 7289 struct RxDesc *desc = tp->RxDescArray + entry;
7281 u32 status; 7290 u32 status;
7282 7291
7283 rmb();
7284 status = le32_to_cpu(desc->opts1) & tp->opts1_mask; 7292 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
7285
7286 if (status & DescOwn) 7293 if (status & DescOwn)
7287 break; 7294 break;
7295
7296 /* This barrier is needed to keep us from reading
7297 * any other fields out of the Rx descriptor until
7298 * we know the status of DescOwn
7299 */
7300 dma_rmb();
7301
7288 if (unlikely(status & RxRES)) { 7302 if (unlikely(status & RxRES)) {
7289 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", 7303 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
7290 status); 7304 status);
@@ -7346,7 +7360,6 @@ process_pkt:
7346 } 7360 }
7347release_descriptor: 7361release_descriptor:
7348 desc->opts2 = 0; 7362 desc->opts2 = 0;
7349 wmb();
7350 rtl8169_mark_to_asic(desc, rx_buf_sz); 7363 rtl8169_mark_to_asic(desc, rx_buf_sz);
7351 } 7364 }
7352 7365