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 swiotlb24 option (which extends this bounce buffer to 8192 x 2KB). With swiotlb92 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); }