net: qlge: Eliminate duplicate barriers on weakly-ordered archs
authorSinan Kaya <okaya@codeaurora.org>
Sun, 25 Mar 2018 14:39:19 +0000 (10:39 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 26 Mar 2018 16:47:56 +0000 (12:47 -0400)
Code includes wmb() followed by writel(). writel() already has a barrier on
some architectures like arm64.

This ends up CPU observing two barriers back to back before executing the
register write.

Create a new wrapper function with relaxed write operator. Use the new
wrapper when a write is following a wmb().

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qlge/qlge.h
drivers/net/ethernet/qlogic/qlge/qlge_main.c

index 84ac50f..3e71b65 100644 (file)
@@ -2185,6 +2185,22 @@ static inline void ql_write_db_reg(u32 val, void __iomem *addr)
 }
 
 /*
+ * Doorbell Registers:
+ * Doorbell registers are virtual registers in the PCI memory space.
+ * The space is allocated by the chip during PCI initialization.  The
+ * device driver finds the doorbell address in BAR 3 in PCI config space.
+ * The registers are used to control outbound and inbound queues. For
+ * example, the producer index for an outbound queue.  Each queue uses
+ * 1 4k chunk of memory.  The lower half of the space is for outbound
+ * queues. The upper half is for inbound queues.
+ * Caller has to guarantee ordering.
+ */
+static inline void ql_write_db_reg_relaxed(u32 val, void __iomem *addr)
+{
+       writel_relaxed(val, addr);
+}
+
+/*
  * Shadow Registers:
  * Outbound queues have a consumer index that is maintained by the chip.
  * Inbound queues have a producer index that is maintained by the chip.
index 50038d9..8293c20 100644 (file)
@@ -2700,7 +2700,8 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev)
                tx_ring->prod_idx = 0;
        wmb();
 
-       ql_write_db_reg(tx_ring->prod_idx, tx_ring->prod_idx_db_reg);
+       ql_write_db_reg_relaxed(tx_ring->prod_idx, tx_ring->prod_idx_db_reg);
+       mmiowb();
        netif_printk(qdev, tx_queued, KERN_DEBUG, qdev->ndev,
                     "tx queued, slot %d, len %d\n",
                     tx_ring->prod_idx, skb->len);