Subject: 2.4 pci_dma_sync_sg fix

From: Atsushi Nemoto <[email-masked]>
Date: Thu, 01 Jul 2004 22:21:20 +0900 (JST)

pci_dma_sync_sg in 2.4 tree seems broken.  pci_map_sg were fixed a
while ago.  Please fix pci_dma_sync_sg also.

Here is a patch.

Index: pci.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pci.h,v
retrieving revision 1.24.2.16
diff -u -r1.24.2.16 pci.h
--- pci.h	17 Nov 2003 01:07:45 -0000	1.24.2.16
+++ pci.h	1 Jul 2004 13:10:48 -0000
@@ -270,20 +270,28 @@
  */
 static inline void pci_dma_sync_sg(struct pci_dev *hwdev,
 				   struct scatterlist *sg,
-				   int nelems, int direction)
+				   int nents, int direction)
 {
-#ifdef CONFIG_NONCOHERENT_IO
 	int i;
-#endif
 
 	if (direction == PCI_DMA_NONE)
 		out_of_line_bug();
 
-	/* Make sure that gcc doesn't leave the empty loop body.  */
-#ifdef CONFIG_NONCOHERENT_IO
-	for (i = 0; i < nelems; i++, sg++)
-		dma_cache_wback_inv((unsigned long)sg->address, sg->length);
-#endif
+	for (i = 0; i < nents; i++, sg++) {
+		if (sg->address && sg->page)
+			out_of_line_bug();
+		else if (!sg->address && !sg->page)
+			out_of_line_bug();
+
+		if (sg->address) {
+			dma_cache_wback_inv((unsigned long)sg->address,
+			                    sg->length);
+		} else {
+			dma_cache_wback_inv((unsigned long)
+				(page_address(sg->page) + sg->offset),
+				sg->length);
+		}
+	}
 }
 
 /*
---
Atsushi Nemoto

---

From: Ralf Baechle <[email-masked]>
Date: Thu, 1 Jul 2004 15:22:40 +0200

> while ago.  Please fix pci_dma_sync_sg also.

Leave the #ifdef stuff there - or otherwise gcc might optimize this into
empty loops ...

  Ralf

---

From: Atsushi Nemoto <[email-masked]>
Date: Thu, 01 Jul 2004 22:45:35 +0900 (JST)

>>>>> On Thu, 1 Jul 2004 15:22:40 +0200, Ralf Baechle <[email-masked]> said:

ralf> Leave the #ifdef stuff there - or otherwise gcc might optimize
ralf> this into empty loops ...

The loop contains paranoid out_of_line_bug, so it never be optimized
to empty.

---
Atsushi Nemoto

---

From: Ralf Baechle <[email-masked]>
Date: Thu, 1 Jul 2004 15:59:19 +0200

> The loop contains paranoid out_of_line_bug, so it never be optimized

Indeed and I think that's a bit of overkill.  I've never seen these
assertions catch any bugs - and 2.4 isn't exactly new anymore.  Anyway,
even if the loop was empty gcc would not eleminate it.

  Ralf

---

From: Atsushi Nemoto <[email-masked]>
Date: Sat, 03 Jul 2004 21:44:11 +0900 (JST)

>>>>> On Thu, 1 Jul 2004 15:59:19 +0200, Ralf Baechle <[email-masked]> said:

>> The loop contains paranoid out_of_line_bug, so it never be
>> optimized to empty.

ralf> Indeed and I think that's a bit of overkill.  I've never seen
ralf> these assertions catch any bugs - and 2.4 isn't exactly new
ralf> anymore.  Anyway, even if the loop was empty gcc would not
ralf> eleminate it.

Then how about this?

Index: pci.h
+++ pci.h	3 Jul 2004 12:30:36 -0000
@@ -281,8 +281,16 @@
 
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 #ifdef CONFIG_NONCOHERENT_IO
-	for (i = 0; i < nelems; i++, sg++)
-		dma_cache_wback_inv((unsigned long)sg->address, sg->length);
+	for (i = 0; i < nelems; i++, sg++) {
+		if (sg->address) {
+			dma_cache_wback_inv((unsigned long)sg->address,
+			                    sg->length);
+		} else {
+			dma_cache_wback_inv((unsigned long)
+				(page_address(sg->page) + sg->offset),
+				sg->length);
+		}
+	}
 #endif
 }