in kernel/pci_iommu.c [349:406]
static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
unsigned long attrs)
{
unsigned long flags;
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
struct pci_iommu_arena *arena;
long dma_ofs, npages;
BUG_ON(dir == PCI_DMA_NONE);
if (dma_addr >= __direct_map_base
&& dma_addr < __direct_map_base + __direct_map_size) {
/* Nothing to do. */
DBGA2("pci_unmap_single: direct [%llx,%zx] from %ps\n",
dma_addr, size, __builtin_return_address(0));
return;
}
if (dma_addr > 0xffffffff) {
DBGA2("pci64_unmap_single: DAC [%llx,%zx] from %ps\n",
dma_addr, size, __builtin_return_address(0));
return;
}
arena = hose->sg_pci;
if (!arena || dma_addr < arena->dma_base)
arena = hose->sg_isa;
dma_ofs = (dma_addr - arena->dma_base) >> PAGE_SHIFT;
if (dma_ofs * PAGE_SIZE >= arena->size) {
printk(KERN_ERR "Bogus pci_unmap_single: dma_addr %llx "
" base %llx size %x\n",
dma_addr, arena->dma_base, arena->size);
return;
BUG();
}
npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
spin_lock_irqsave(&arena->lock, flags);
iommu_arena_free(arena, dma_ofs, npages);
/* 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 (dma_ofs >= arena->next_entry)
alpha_mv.mv_pci_tbi(hose, dma_addr, dma_addr + size - 1);
spin_unlock_irqrestore(&arena->lock, flags);
DBGA2("pci_unmap_single: sg [%llx,%zx] np %ld from %ps\n",
dma_addr, size, npages, __builtin_return_address(0));
}