Michal Kubecek ec8941
From: Benjamin Poirier <bpoirier@suse.com>
Michal Kubecek ec8941
Date: Tue, 7 May 2019 14:43:18 +0900
Michal Kubecek ec8941
Subject: qlge: Fix dma_sync_single calls
Michal Kubecek ec8941
Patch-mainline: Not yet, submitted v1, will submit v2 after v5.4-rc1
Michal Kubecek ec8941
References: bsc#1106061
Michal Kubecek ec8941
Michal Kubecek ec8941
Using the unmap addr elsewhere than unmap calls is a misuse of the dma api.
Michal Kubecek ec8941
In prevision of this fix, qlge kept two copies of the dma address around ;)
Michal Kubecek ec8941
Michal Kubecek ec8941
Fixes: c4e84bde1d59 ("qlge: New Qlogic 10Gb Ethernet Driver.")
Michal Kubecek ec8941
Fixes: 7c734359d350 ("qlge: Size RX buffers based on MTU.")
Michal Kubecek ec8941
Fixes: 2c9a266afefe ("qlge: Fix receive packets drop.")
Michal Kubecek ec8941
Signed-off-by: Benjamin Poirier <bpoirier@suse.com>
Michal Kubecek ec8941
---
Michal Kubecek ec8941
 drivers/net/ethernet/qlogic/qlge/qlge.h      |    5 --
Michal Kubecek ec8941
 drivers/net/ethernet/qlogic/qlge/qlge_main.c |   54 ++++++++++-----------------
Michal Kubecek ec8941
 2 files changed, 22 insertions(+), 37 deletions(-)
Michal Kubecek ec8941
Michal Kubecek ec8941
--- a/drivers/net/ethernet/qlogic/qlge/qlge.h
Michal Kubecek ec8941
+++ b/drivers/net/ethernet/qlogic/qlge/qlge.h
Michal Kubecek ec8941
@@ -1410,12 +1410,9 @@ struct qlge_bq_desc {
Michal Kubecek ec8941
 		struct sk_buff *skb;
Michal Kubecek ec8941
 	} p;
Michal Kubecek ec8941
 	dma_addr_t dma_addr;
Michal Kubecek ec8941
-	/* address in ring where the buffer address (dma_addr) is written for
Michal Kubecek ec8941
-	 * the device
Michal Kubecek ec8941
-	 */
Michal Kubecek ec8941
+	/* address in ring where the buffer address is written for the device */
Michal Kubecek ec8941
 	__le64 *buf_ptr;
Michal Kubecek ec8941
 	u32 index;
Michal Kubecek ec8941
-	DEFINE_DMA_UNMAP_ADDR(mapaddr);
Michal Kubecek ec8941
 };
Michal Kubecek ec8941
 
Michal Kubecek ec8941
 /* buffer queue */
Michal Kubecek ec8941
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
Michal Kubecek ec8941
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
Michal Kubecek ec8941
@@ -995,15 +995,13 @@ static struct qlge_bq_desc *ql_get_curr_
Michal Kubecek ec8941
 {
Michal Kubecek ec8941
 	struct qlge_bq_desc *lbq_desc = qlge_get_curr_buf(&rx_ring->lbq);
Michal Kubecek ec8941
 
Michal Kubecek ec8941
-	pci_dma_sync_single_for_cpu(qdev->pdev,
Michal Kubecek ec8941
-				    dma_unmap_addr(lbq_desc, mapaddr),
Michal Kubecek ec8941
+	pci_dma_sync_single_for_cpu(qdev->pdev, lbq_desc->dma_addr,
Michal Kubecek ec8941
 				    qdev->lbq_buf_size, PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 
Michal Kubecek ec8941
 	if ((lbq_desc->p.pg_chunk.offset + qdev->lbq_buf_size) ==
Michal Kubecek ec8941
 	    ql_lbq_block_size(qdev)) {
Michal Kubecek ec8941
 		/* last chunk of the master page */
Michal Kubecek ec8941
-		pci_unmap_page(qdev->pdev, lbq_desc->dma_addr -
Michal Kubecek ec8941
-			       lbq_desc->p.pg_chunk.offset,
Michal Kubecek ec8941
+		pci_unmap_page(qdev->pdev, lbq_desc->dma_addr,
Michal Kubecek ec8941
 			       ql_lbq_block_size(qdev), PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 	}
Michal Kubecek ec8941
 
Michal Kubecek ec8941
@@ -1031,7 +1029,7 @@ static const char * const bq_type_name[]
Michal Kubecek ec8941
 	[QLGE_LB] = "lbq",
Michal Kubecek ec8941
 };
Michal Kubecek ec8941
 
Michal Kubecek ec8941
-/* return size of allocated buffer (may be 0) or negative error */
Michal Kubecek ec8941
+/* return 0 or negative error */
Michal Kubecek ec8941
 static int qlge_refill_sb(struct rx_ring *rx_ring,
Michal Kubecek ec8941
 			  struct qlge_bq_desc *sbq_desc)
Michal Kubecek ec8941
 {
Michal Kubecek ec8941
@@ -1058,12 +1056,13 @@ static int qlge_refill_sb(struct rx_ring
Michal Kubecek ec8941
 		dev_kfree_skb_any(skb);
Michal Kubecek ec8941
 		return -EIO;
Michal Kubecek ec8941
 	}
Michal Kubecek ec8941
+	*sbq_desc->buf_ptr = cpu_to_le64(sbq_desc->dma_addr);
Michal Kubecek ec8941
 
Michal Kubecek ec8941
 	sbq_desc->p.skb = skb;
Michal Kubecek ec8941
-	return SMALL_BUFFER_SIZE;
Michal Kubecek ec8941
+	return 0;
Michal Kubecek ec8941
 }
Michal Kubecek ec8941
 
Michal Kubecek ec8941
-/* return size of allocated buffer or negative error */
Michal Kubecek ec8941
+/* return 0 or negative error */
Michal Kubecek ec8941
 static int qlge_refill_lb(struct rx_ring *rx_ring,
Michal Kubecek ec8941
 			  struct qlge_bq_desc *lbq_desc)
Michal Kubecek ec8941
 {
Michal Kubecek ec8941
@@ -1094,7 +1093,9 @@ static int qlge_refill_lb(struct rx_ring
Michal Kubecek ec8941
 	}
Michal Kubecek ec8941
 
Michal Kubecek ec8941
 	lbq_desc->p.pg_chunk = *master_chunk;
Michal Kubecek ec8941
-	lbq_desc->dma_addr = rx_ring->chunk_dma_addr + master_chunk->offset;
Michal Kubecek ec8941
+	lbq_desc->dma_addr = rx_ring->chunk_dma_addr;
Michal Kubecek ec8941
+	*lbq_desc->buf_ptr = cpu_to_le64(lbq_desc->dma_addr +
Michal Kubecek ec8941
+					 lbq_desc->p.pg_chunk.offset);
Michal Kubecek ec8941
 
Michal Kubecek ec8941
 	/* Adjust the master page chunk for next
Michal Kubecek ec8941
 	 * buffer get.
Michal Kubecek ec8941
@@ -1107,7 +1108,7 @@ static int qlge_refill_lb(struct rx_ring
Michal Kubecek ec8941
 		get_page(master_chunk->page);
Michal Kubecek ec8941
 	}
Michal Kubecek ec8941
 
Michal Kubecek ec8941
-	return qdev->lbq_buf_size;
Michal Kubecek ec8941
+	return 0;
Michal Kubecek ec8941
 }
Michal Kubecek ec8941
 
Michal Kubecek ec8941
 static void qlge_refill_bq(struct qlge_bq *bq)
Michal Kubecek ec8941
@@ -1138,13 +1139,7 @@ static void qlge_refill_bq(struct qlge_b
Michal Kubecek ec8941
 				retval = qlge_refill_sb(rx_ring, bq_desc);
Michal Kubecek ec8941
 			else
Michal Kubecek ec8941
 				retval = qlge_refill_lb(rx_ring, bq_desc);
Michal Kubecek ec8941
-
Michal Kubecek ec8941
-			if (retval > 0) {
Michal Kubecek ec8941
-				dma_unmap_addr_set(bq_desc, mapaddr,
Michal Kubecek ec8941
-						   bq_desc->dma_addr);
Michal Kubecek ec8941
-				*bq_desc->buf_ptr =
Michal Kubecek ec8941
-					cpu_to_le64(bq_desc->dma_addr);
Michal Kubecek ec8941
-			} else if (retval < 0) {
Michal Kubecek ec8941
+			if (retval < 0) {
Michal Kubecek ec8941
 				bq->clean_idx = clean_idx;
Michal Kubecek ec8941
 				netif_err(qdev, ifup, qdev->ndev,
Michal Kubecek ec8941
 					  "ring %u %s: Could not get a page chunk, i=%d, clean_idx =%d .\n",
Michal Kubecek ec8941
@@ -1567,8 +1562,7 @@ static void ql_process_mac_rx_skb(struct
Michal Kubecek ec8941
 	}
Michal Kubecek ec8941
 	skb_reserve(new_skb, NET_IP_ALIGN);
Michal Kubecek ec8941
 
Michal Kubecek ec8941
-	pci_dma_sync_single_for_cpu(qdev->pdev,
Michal Kubecek ec8941
-				    dma_unmap_addr(sbq_desc, mapaddr),
Michal Kubecek ec8941
+	pci_dma_sync_single_for_cpu(qdev->pdev, sbq_desc->dma_addr,
Michal Kubecek ec8941
 				    SMALL_BUF_MAP_SIZE, PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 
Michal Kubecek ec8941
 	skb_put_data(new_skb, skb->data, length);
Michal Kubecek ec8941
@@ -1690,9 +1684,8 @@ static struct sk_buff *ql_build_rx_skb(s
Michal Kubecek ec8941
 		 * Headers fit nicely into a small buffer.
Michal Kubecek ec8941
 		 */
Michal Kubecek ec8941
 		sbq_desc = qlge_get_curr_buf(&rx_ring->sbq);
Michal Kubecek ec8941
-		pci_unmap_single(qdev->pdev,
Michal Kubecek ec8941
-				dma_unmap_addr(sbq_desc, mapaddr),
Michal Kubecek ec8941
-				SMALL_BUF_MAP_SIZE, PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
+		pci_unmap_single(qdev->pdev, sbq_desc->dma_addr,
Michal Kubecek ec8941
+				 SMALL_BUF_MAP_SIZE, PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 		skb = sbq_desc->p.skb;
Michal Kubecek ec8941
 		ql_realign_skb(skb, hdr_len);
Michal Kubecek ec8941
 		skb_put(skb, hdr_len);
Michal Kubecek ec8941
@@ -1722,8 +1715,7 @@ static struct sk_buff *ql_build_rx_skb(s
Michal Kubecek ec8941
 			 */
Michal Kubecek ec8941
 			sbq_desc = qlge_get_curr_buf(&rx_ring->sbq);
Michal Kubecek ec8941
 			pci_dma_sync_single_for_cpu(qdev->pdev,
Michal Kubecek ec8941
-						    dma_unmap_addr(sbq_desc,
Michal Kubecek ec8941
-								   mapaddr),
Michal Kubecek ec8941
+						    sbq_desc->dma_addr,
Michal Kubecek ec8941
 						    SMALL_BUF_MAP_SIZE,
Michal Kubecek ec8941
 						    PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 			skb_put_data(skb, sbq_desc->p.skb->data, length);
Michal Kubecek ec8941
@@ -1735,8 +1727,7 @@ static struct sk_buff *ql_build_rx_skb(s
Michal Kubecek ec8941
 			skb = sbq_desc->p.skb;
Michal Kubecek ec8941
 			ql_realign_skb(skb, length);
Michal Kubecek ec8941
 			skb_put(skb, length);
Michal Kubecek ec8941
-			pci_unmap_single(qdev->pdev,
Michal Kubecek ec8941
-					 dma_unmap_addr(sbq_desc, mapaddr),
Michal Kubecek ec8941
+			pci_unmap_single(qdev->pdev, sbq_desc->dma_addr,
Michal Kubecek ec8941
 					 SMALL_BUF_MAP_SIZE,
Michal Kubecek ec8941
 					 PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 			sbq_desc->p.skb = NULL;
Michal Kubecek ec8941
@@ -1774,8 +1765,7 @@ static struct sk_buff *ql_build_rx_skb(s
Michal Kubecek ec8941
 					     "No skb available, drop the packet.\n");
Michal Kubecek ec8941
 				return NULL;
Michal Kubecek ec8941
 			}
Michal Kubecek ec8941
-			pci_unmap_page(qdev->pdev,
Michal Kubecek ec8941
-				       dma_unmap_addr(lbq_desc, mapaddr),
Michal Kubecek ec8941
+			pci_unmap_page(qdev->pdev, lbq_desc->dma_addr,
Michal Kubecek ec8941
 				       qdev->lbq_buf_size,
Michal Kubecek ec8941
 				       PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 			skb_reserve(skb, NET_IP_ALIGN);
Michal Kubecek ec8941
@@ -1808,8 +1798,7 @@ static struct sk_buff *ql_build_rx_skb(s
Michal Kubecek ec8941
 		 */
Michal Kubecek ec8941
 		int size, i = 0;
Michal Kubecek ec8941
 		sbq_desc = qlge_get_curr_buf(&rx_ring->sbq);
Michal Kubecek ec8941
-		pci_unmap_single(qdev->pdev,
Michal Kubecek ec8941
-				 dma_unmap_addr(sbq_desc, mapaddr),
Michal Kubecek ec8941
+		pci_unmap_single(qdev->pdev, sbq_desc->dma_addr,
Michal Kubecek ec8941
 				 SMALL_BUF_MAP_SIZE, PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 		if (!(ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS)) {
Michal Kubecek ec8941
 			/*
Michal Kubecek ec8941
@@ -2735,8 +2724,8 @@ static void ql_free_lbq_buffers(struct q
Michal Kubecek ec8941
 		struct qlge_bq_desc *lbq_desc = &rx_ring->lbq.queue[curr_idx];
Michal Kubecek ec8941
 
Michal Kubecek ec8941
 		if (lbq_desc->p.pg_chunk.offset == last_offset)
Michal Kubecek ec8941
-			pci_unmap_page(qdev->pdev, lbq_desc->dma_addr -
Michal Kubecek ec8941
-				       last_offset, ql_lbq_block_size(qdev),
Michal Kubecek ec8941
+			pci_unmap_page(qdev->pdev, lbq_desc->dma_addr,
Michal Kubecek ec8941
+				       ql_lbq_block_size(qdev),
Michal Kubecek ec8941
 				       PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 
Michal Kubecek ec8941
 		put_page(lbq_desc->p.pg_chunk.page);
Michal Kubecek ec8941
@@ -2767,8 +2756,7 @@ static void ql_free_sbq_buffers(struct q
Michal Kubecek ec8941
 			return;
Michal Kubecek ec8941
 		}
Michal Kubecek ec8941
 		if (sbq_desc->p.skb) {
Michal Kubecek ec8941
-			pci_unmap_single(qdev->pdev,
Michal Kubecek ec8941
-					 dma_unmap_addr(sbq_desc, mapaddr),
Michal Kubecek ec8941
+			pci_unmap_single(qdev->pdev, sbq_desc->dma_addr,
Michal Kubecek ec8941
 					 SMALL_BUF_MAP_SIZE,
Michal Kubecek ec8941
 					 PCI_DMA_FROMDEVICE);
Michal Kubecek ec8941
 			dev_kfree_skb(sbq_desc->p.skb);