in kernel/pci_iommu.c [713:787]
static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
unsigned long attrs)
{
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
unsigned long flags;
struct pci_controller *hose;
struct pci_iommu_arena *arena;
struct scatterlist *end;
dma_addr_t max_dma;
dma_addr_t fbeg, fend;
BUG_ON(dir == PCI_DMA_NONE);
if (! alpha_mv.mv_pci_tbi)
return;
hose = pdev ? pdev->sysdata : pci_isa_hose;
max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
arena = hose->sg_pci;
if (!arena || arena->dma_base + arena->size - 1 > max_dma)
arena = hose->sg_isa;
fbeg = -1, fend = 0;
spin_lock_irqsave(&arena->lock, flags);
for (end = sg + nents; sg < end; ++sg) {
dma_addr_t addr;
size_t size;
long npages, ofs;
dma_addr_t tend;
addr = sg->dma_address;
size = sg->dma_length;
if (!size)
break;
if (addr > 0xffffffff) {
/* It's a DAC address -- nothing to do. */
DBGA(" (%ld) DAC [%llx,%zx]\n",
sg - end + nents, addr, size);
continue;
}
if (addr >= __direct_map_base
&& addr < __direct_map_base + __direct_map_size) {
/* Nothing to do. */
DBGA(" (%ld) direct [%llx,%zx]\n",
sg - end + nents, addr, size);
continue;
}
DBGA(" (%ld) sg [%llx,%zx]\n",
sg - end + nents, addr, size);
npages = iommu_num_pages(addr, size, PAGE_SIZE);
ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
iommu_arena_free(arena, ofs, npages);
tend = addr + size - 1;
if (fbeg > addr) fbeg = addr;
if (fend < tend) fend = tend;
}
/* If we're freeing ptes above the `next_entry' pointer (they
may have snuck back into the TLB since the last wrap flush),
we need to flush the TLB before reallocating the latter. */
if ((fend - arena->dma_base) >> PAGE_SHIFT >= arena->next_entry)
alpha_mv.mv_pci_tbi(hose, fbeg, fend);
spin_unlock_irqrestore(&arena->lock, flags);
DBGA("pci_unmap_sg: %ld entries\n", nents - (end - sg));
}