qede: Utilize xmit_more
authorManish Chopra <manish.chopra@qlogic.com>
Thu, 30 Jun 2016 06:35:20 +0000 (02:35 -0400)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 Jul 2016 09:40:53 +0000 (05:40 -0400)
This patch uses xmit_more optimization to reduce
number of TX doorbells write per packet.

Signed-off-by: Manish <manish.chopra@qlogic.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qede/qede_main.c

index 9bc4c9f1a6c206f15167ffb7e595dda64b717133..ea2df1460ea40b1806801bce62f075d133ca676a 100644 (file)
@@ -485,6 +485,24 @@ static bool qede_pkt_req_lin(struct qede_dev *edev, struct sk_buff *skb,
 }
 #endif
 
+static inline void qede_update_tx_producer(struct qede_tx_queue *txq)
+{
+       /* wmb makes sure that the BDs data is updated before updating the
+        * producer, otherwise FW may read old data from the BDs.
+        */
+       wmb();
+       barrier();
+       writel(txq->tx_db.raw, txq->doorbell_addr);
+
+       /* mmiowb is needed to synchronize doorbell writes from more than one
+        * processor. It guarantees that the write arrives to the device before
+        * the queue lock is released and another start_xmit is called (possibly
+        * on another CPU). Without this barrier, the next doorbell can bypass
+        * this doorbell. This is applicable to IA64/Altix systems.
+        */
+       mmiowb();
+}
+
 /* Main transmit function */
 static
 netdev_tx_t qede_start_xmit(struct sk_buff *skb,
@@ -543,6 +561,7 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb,
        if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
                DP_NOTICE(edev, "SKB mapping failed\n");
                qede_free_failed_tx_pkt(edev, txq, first_bd, 0, false);
+               qede_update_tx_producer(txq);
                return NETDEV_TX_OK;
        }
        nbd++;
@@ -657,6 +676,7 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb,
                if (rc) {
                        qede_free_failed_tx_pkt(edev, txq, first_bd, nbd,
                                                data_split);
+                       qede_update_tx_producer(txq);
                        return NETDEV_TX_OK;
                }
 
@@ -681,6 +701,7 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb,
                if (rc) {
                        qede_free_failed_tx_pkt(edev, txq, first_bd, nbd,
                                                data_split);
+                       qede_update_tx_producer(txq);
                        return NETDEV_TX_OK;
                }
        }
@@ -701,20 +722,8 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb,
        txq->tx_db.data.bd_prod =
                cpu_to_le16(qed_chain_get_prod_idx(&txq->tx_pbl));
 
-       /* wmb makes sure that the BDs data is updated before updating the
-        * producer, otherwise FW may read old data from the BDs.
-        */
-       wmb();
-       barrier();
-       writel(txq->tx_db.raw, txq->doorbell_addr);
-
-       /* mmiowb is needed to synchronize doorbell writes from more than one
-        * processor. It guarantees that the write arrives to the device before
-        * the queue lock is released and another start_xmit is called (possibly
-        * on another CPU). Without this barrier, the next doorbell can bypass
-        * this doorbell. This is applicable to IA64/Altix systems.
-        */
-       mmiowb();
+       if (!skb->xmit_more || netif_tx_queue_stopped(netdev_txq))
+               qede_update_tx_producer(txq);
 
        if (unlikely(qed_chain_get_elem_left(&txq->tx_pbl)
                      < (MAX_SKB_FRAGS + 1))) {