[Linux-ia64] SW IO TLB buffer management in kernel test10

From: Hirofumi Fujita <h-fujita_at_ebina.hitachi.co.jp>
Date: 2000-11-15 19:15:52
Hi,

there seems to be a problem on buffer management of SW IO TLB.
The contents of io_tlb_list[] become broken.

This happens when a machine has more then 2GB memory,
and CD-ROM or SCSI (>4GB addressing is disabled) are accessed.

But there may be another bug ?

I applied the attached patch and kernel panic when mke2fs /dev/sda4.
(QLogic BIOS setting: >4GB addressing is disabled)
Kernel panic: __pci_map_single: could not allocate software IO TLB (16384 bytes)
At this time, io_tlb_list[] are almost 0.

Same with swiotlb=1024 option (which extends this bounce buffer to
8192 x 2KB).

With swiotlb=8192 option, mke2fs successes,
but 60% of io_tlb_list[] remain 0 after mke2fs finished.
This is because pci_unmap is not called correctly ?

Hirofumi Fujita
Hitachi, Ltd.

--- linux-2.4.0-test10-ia64-001101/arch/ia64/kernel/pci-dma.c.org	Mon Nov 13 12:05:13 2000
+++ linux-2.4.0-test10-ia64-001101/arch/ia64/kernel/pci-dma.c	Wed Nov 15 16:19:12 2000
@@ -109,7 +109,8 @@
 {
 	unsigned long flags;
 	char *dma_addr;
-	unsigned int i, nslots, stride, index, wrap;
+	unsigned int nslots, stride, index, wrap;
+	int i;
 
 	/*
 	 * For mappings greater than a page size, we limit the stride (and hence alignment)
@@ -133,7 +134,7 @@
 		wrap = index = ALIGN(io_tlb_index, stride);
 
 		if (index >= io_tlb_nslabs) 
-			index = 0;
+			wrap = index = 0;
 
 		do {
 			/*
@@ -142,8 +143,11 @@
 			 * entries as '0' indicating unavailable.
 			 */
 			if (io_tlb_list[index] >= nslots) {
+				int count = 0;
 				for (i = index; i < index + nslots; i++)
 					io_tlb_list[i] = 0;
+				for (i = index - 1; (i >= 0) && io_tlb_list[i]; i--)
+					io_tlb_list[i] = ++count;
 				dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
 
 				/*
@@ -210,14 +214,10 @@
 		int count = ((index + nslots) < io_tlb_nslabs ? io_tlb_list[index + nslots] : 0);
 		/*
 		 * Step 1: return the slots to the free list, merging the slots with superceeding slots
-		 */
-		for (i = index + nslots - 1; i >= index; i--)
-			io_tlb_list[i] = ++count;
-		/*
 		 * Step 2: merge the returned slots with the preceeding slots, if available (non zero)
 		 */
-		for (i = index - 1; (i >= 0) && io_tlb_list[i]; i--)
-			io_tlb_list[i] += io_tlb_list[index];
+		for (i = index + nslots - 1; (i >= 0) && io_tlb_list[i]; i--)
+			io_tlb_list[i] = ++count;
 	}
 	spin_unlock_irqrestore(&io_tlb_lock, flags);
 }
Received on Wed Nov 15 00:17:34 2000

This archive was generated by hypermail 2.1.8 : 2005-08-02 09:20:00 EST