diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-02 02:36:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-02 02:36:47 +0000 |
commit | 8624512aa908741ba2795200133eae0d7f4557ea (patch) | |
tree | d5d3036fccf2604f4c98dedc11e8adb929d6b52e /arch/alpha/kernel/pci_iommu.c | |
parent | 7b8f5d6f1d45d9f9de1d26e7d3c32aa5af11b488 (diff) |
Merge with 2.3.48.
Diffstat (limited to 'arch/alpha/kernel/pci_iommu.c')
-rw-r--r-- | arch/alpha/kernel/pci_iommu.c | 53 |
1 files changed, 49 insertions, 4 deletions
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index 72ce8bcb6..f5a9bd990 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -133,6 +133,9 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size, int direction) unsigned long paddr; dma_addr_t ret; + if (direction == PCI_DMA_NONE) + BUG(); + paddr = virt_to_phys(cpu_addr); /* First check to see if we can use the direct map window. */ @@ -186,12 +189,15 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size, int direction) wrote there. */ void -pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size, int direction) +pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size, + int direction) { struct pci_controler *hose = pdev ? pdev->sysdata : pci_isa_hose; struct pci_iommu_arena *arena; long dma_ofs, npages; + if (direction == PCI_DMA_NONE) + BUG(); if (dma_addr >= __direct_map_base && dma_addr < __direct_map_base + __direct_map_size) { @@ -247,7 +253,8 @@ pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp) } memset(cpu_addr, 0, size); - *dma_addrp = pci_map_single(pdev, cpu_addr, size, PCI_DMA_BIDIRECTIONAL); + *dma_addrp = pci_map_single(pdev, cpu_addr, size, + PCI_DMA_BIDIRECTIONAL); if (*dma_addrp == 0) { free_pages((unsigned long)cpu_addr, order); return NULL; @@ -424,13 +431,17 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end, } int -pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direction) +pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, + int direction) { struct scatterlist *start, *end, *out; struct pci_controler *hose; struct pci_iommu_arena *arena; dma_addr_t max_dma; + if (direction == PCI_DMA_NONE) + BUG(); + /* Fast path single entry scatterlists. */ if (nents == 1) { sg->dma_length = sg->length; @@ -499,7 +510,8 @@ error: above. */ void -pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direction) +pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, + int direction) { struct pci_controler *hose; struct pci_iommu_arena *arena; @@ -507,6 +519,9 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direct dma_addr_t max_dma; dma_addr_t fstart, fend; + if (direction == PCI_DMA_NONE) + BUG(); + if (! alpha_mv.mv_pci_tbi) return; @@ -555,3 +570,33 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direct DBGA("pci_unmap_sg: %d entries\n", nents - (end - sg)); } + +/* Return whether the given PCI device DMA address mask can be + supported properly. */ + +int +pci_dma_supported(struct pci_dev *pdev, dma_addr_t mask) +{ + struct pci_controler *hose; + struct pci_iommu_arena *arena; + + /* If there exists a direct map, and the mask fits either + MAX_DMA_ADDRESS defined such that GFP_DMA does something + useful, or the total system memory as shifted by the + map base. */ + if (__direct_map_size != 0 + && (__direct_map_base + MAX_DMA_ADDRESS-IDENT_ADDR-1 <= mask + || __direct_map_base + (max_low_pfn<<PAGE_SHIFT)-1 <= mask)) + return 1; + + /* Check that we have a scatter-gather arena that fits. */ + hose = pdev ? pdev->sysdata : pci_isa_hose; + arena = hose->sg_isa; + if (arena && arena->dma_base + arena->size <= mask) + return 1; + arena = hose->sg_pci; + if (arena && arena->dma_base + arena->size <= mask) + return 1; + + return 0; +} |