123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955 |
- /*
- * linux/arch/alpha/kernel/pci_iommu.c
- */
- #include <linux/kernel.h>
- #include <linux/mm.h>
- #include <linux/pci.h>
- #include <linux/gfp.h>
- #include <linux/bootmem.h>
- #include <linux/export.h>
- #include <linux/scatterlist.h>
- #include <linux/log2.h>
- #include <linux/dma-mapping.h>
- #include <linux/iommu-helper.h>
- #include <asm/io.h>
- #include <asm/hwrpb.h>
- #include "proto.h"
- #include "pci_impl.h"
- #define DEBUG_ALLOC 0
- #if DEBUG_ALLOC > 0
- # define DBGA(args...) printk(KERN_DEBUG args)
- #else
- # define DBGA(args...)
- #endif
- #if DEBUG_ALLOC > 1
- # define DBGA2(args...) printk(KERN_DEBUG args)
- #else
- # define DBGA2(args...)
- #endif
- #define DEBUG_NODIRECT 0
- #define ISA_DMA_MASK 0x00ffffff
- static inline unsigned long
- mk_iommu_pte(unsigned long paddr)
- {
- return (paddr >> (PAGE_SHIFT-1)) | 1;
- }
- /* Return the minimum of MAX or the first power of two larger
- than main memory. */
- unsigned long
- size_for_memory(unsigned long max)
- {
- unsigned long mem = max_low_pfn << PAGE_SHIFT;
- if (mem < max)
- max = roundup_pow_of_two(mem);
- return max;
- }
- struct pci_iommu_arena * __init
- iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base,
- unsigned long window_size, unsigned long align)
- {
- unsigned long mem_size;
- struct pci_iommu_arena *arena;
- mem_size = window_size / (PAGE_SIZE / sizeof(unsigned long));
- /* Note that the TLB lookup logic uses bitwise concatenation,
- not addition, so the required arena alignment is based on
- the size of the window. Retain the align parameter so that
- particular systems can over-align the arena. */
- if (align < mem_size)
- align = mem_size;
- #ifdef CONFIG_DISCONTIGMEM
- arena = alloc_bootmem_node(NODE_DATA(nid), sizeof(*arena));
- if (!NODE_DATA(nid) || !arena) {
- printk("%s: couldn't allocate arena from node %d\n"
- " falling back to system-wide allocation\n",
- __func__, nid);
- arena = alloc_bootmem(sizeof(*arena));
- }
- arena->ptes = __alloc_bootmem_node(NODE_DATA(nid), mem_size, align, 0);
- if (!NODE_DATA(nid) || !arena->ptes) {
- printk("%s: couldn't allocate arena ptes from node %d\n"
- " falling back to system-wide allocation\n",
- __func__, nid);
- arena->ptes = __alloc_bootmem(mem_size, align, 0);
- }
- #else /* CONFIG_DISCONTIGMEM */
- arena = alloc_bootmem(sizeof(*arena));
- arena->ptes = __alloc_bootmem(mem_size, align, 0);
- #endif /* CONFIG_DISCONTIGMEM */
- spin_lock_init(&arena->lock);
- arena->hose = hose;
- arena->dma_base = base;
- arena->size = window_size;
- arena->next_entry = 0;
- /* Align allocations to a multiple of a page size. Not needed
- unless there are chip bugs. */
- arena->align_entry = 1;
- return arena;
- }
- struct pci_iommu_arena * __init
- iommu_arena_new(struct pci_controller *hose, dma_addr_t base,
- unsigned long window_size, unsigned long align)
- {
- return iommu_arena_new_node(0, hose, base, window_size, align);
- }
- /* Must be called with the arena lock held */
- static long
- iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
- long n, long mask)
- {
- unsigned long *ptes;
- long i, p, nent;
- int pass = 0;
- unsigned long base;
- unsigned long boundary_size;
- base = arena->dma_base >> PAGE_SHIFT;
- if (dev) {
- boundary_size = dma_get_seg_boundary(dev) + 1;
- boundary_size >>= PAGE_SHIFT;
- } else {
- boundary_size = 1UL << (32 - PAGE_SHIFT);
- }
- /* Search forward for the first mask-aligned sequence of N free ptes */
- ptes = arena->ptes;
- nent = arena->size >> PAGE_SHIFT;
- p = ALIGN(arena->next_entry, mask + 1);
- i = 0;
- again:
- while (i < n && p+i < nent) {
- if (!i && iommu_is_span_boundary(p, n, base, boundary_size)) {
- p = ALIGN(p + 1, mask + 1);
- goto again;
- }
- if (ptes[p+i])
- p = ALIGN(p + i + 1, mask + 1), i = 0;
- else
- i = i + 1;
- }
- if (i < n) {
- if (pass < 1) {
- /*
- * Reached the end. Flush the TLB and restart
- * the search from the beginning.
- */
- alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
- pass++;
- p = 0;
- i = 0;
- goto again;
- } else
- return -1;
- }
- /* Success. It's the responsibility of the caller to mark them
- in use before releasing the lock */
- return p;
- }
- static long
- iommu_arena_alloc(struct device *dev, struct pci_iommu_arena *arena, long n,
- unsigned int align)
- {
- unsigned long flags;
- unsigned long *ptes;
- long i, p, mask;
- spin_lock_irqsave(&arena->lock, flags);
- /* Search for N empty ptes */
- ptes = arena->ptes;
- mask = max(align, arena->align_entry) - 1;
- p = iommu_arena_find_pages(dev, arena, n, mask);
- if (p < 0) {
- spin_unlock_irqrestore(&arena->lock, flags);
- return -1;
- }
- /* Success. Mark them all in use, ie not zero and invalid
- for the iommu tlb that could load them from under us.
- The chip specific bits will fill this in with something
- kosher when we return. */
- for (i = 0; i < n; ++i)
- ptes[p+i] = IOMMU_INVALID_PTE;
- arena->next_entry = p + n;
- spin_unlock_irqrestore(&arena->lock, flags);
- return p;
- }
- static void
- iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
- {
- unsigned long *p;
- long i;
- p = arena->ptes + ofs;
- for (i = 0; i < n; ++i)
- p[i] = 0;
- }
- /*
- * True if the machine supports DAC addressing, and DEV can
- * make use of it given MASK.
- */
- static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
- {
- dma_addr_t dac_offset = alpha_mv.pci_dac_offset;
- int ok = 1;
- /* If this is not set, the machine doesn't support DAC at all. */
- if (dac_offset == 0)
- ok = 0;
- /* The device has to be able to address our DAC bit. */
- if ((dac_offset & dev->dma_mask) != dac_offset)
- ok = 0;
- /* If both conditions above are met, we are fine. */
- DBGA("pci_dac_dma_supported %s from %pf\n",
- ok ? "yes" : "no", __builtin_return_address(0));
- return ok;
- }
- /* Map a single buffer of the indicated size for PCI DMA in streaming
- mode. The 32-bit PCI bus mastering address to use is returned.
- Once the device is given the dma address, the device owns this memory
- until either pci_unmap_single or pci_dma_sync_single is performed. */
- static dma_addr_t
- pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
- int dac_allowed)
- {
- struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
- dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
- struct pci_iommu_arena *arena;
- long npages, dma_ofs, i;
- unsigned long paddr;
- dma_addr_t ret;
- unsigned int align = 0;
- struct device *dev = pdev ? &pdev->dev : NULL;
- paddr = __pa(cpu_addr);
- #if !DEBUG_NODIRECT
- /* First check to see if we can use the direct map window. */
- if (paddr + size + __direct_map_base - 1 <= max_dma
- && paddr + size <= __direct_map_size) {
- ret = paddr + __direct_map_base;
- DBGA2("pci_map_single: [%p,%zx] -> direct %llx from %pf\n",
- cpu_addr, size, ret, __builtin_return_address(0));
- return ret;
- }
- #endif
- /* Next, use DAC if selected earlier. */
- if (dac_allowed) {
- ret = paddr + alpha_mv.pci_dac_offset;
- DBGA2("pci_map_single: [%p,%zx] -> DAC %llx from %pf\n",
- cpu_addr, size, ret, __builtin_return_address(0));
- return ret;
- }
- /* If the machine doesn't define a pci_tbi routine, we have to
- assume it doesn't support sg mapping, and, since we tried to
- use direct_map above, it now must be considered an error. */
- if (! alpha_mv.mv_pci_tbi) {
- printk_once(KERN_WARNING "pci_map_single: no HW sg\n");
- return 0;
- }
- arena = hose->sg_pci;
- if (!arena || arena->dma_base + arena->size - 1 > max_dma)
- arena = hose->sg_isa;
- npages = iommu_num_pages(paddr, size, PAGE_SIZE);
- /* Force allocation to 64KB boundary for ISA bridges. */
- if (pdev && pdev == isa_bridge)
- align = 8;
- dma_ofs = iommu_arena_alloc(dev, arena, npages, align);
- if (dma_ofs < 0) {
- printk(KERN_WARNING "pci_map_single failed: "
- "could not allocate dma page tables\n");
- return 0;
- }
- paddr &= PAGE_MASK;
- for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
- arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr);
- ret = arena->dma_base + dma_ofs * PAGE_SIZE;
- ret += (unsigned long)cpu_addr & ~PAGE_MASK;
- DBGA2("pci_map_single: [%p,%zx] np %ld -> sg %llx from %pf\n",
- cpu_addr, size, npages, ret, __builtin_return_address(0));
- return ret;
- }
- /* Helper for generic DMA-mapping functions. */
- static struct pci_dev *alpha_gendev_to_pci(struct device *dev)
- {
- if (dev && dev_is_pci(dev))
- return to_pci_dev(dev);
- /* Assume that non-PCI devices asking for DMA are either ISA or EISA,
- BUG() otherwise. */
- BUG_ON(!isa_bridge);
- /* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA
- bridge is bus master then). */
- if (!dev || !dev->dma_mask || !*dev->dma_mask)
- return isa_bridge;
- /* For EISA bus masters, return isa_bridge (it might have smaller
- dma_mask due to wiring limitations). */
- if (*dev->dma_mask >= isa_bridge->dma_mask)
- return isa_bridge;
- /* This assumes ISA bus master with dma_mask 0xffffff. */
- return NULL;
- }
- static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
- unsigned long attrs)
- {
- struct pci_dev *pdev = alpha_gendev_to_pci(dev);
- int dac_allowed;
- BUG_ON(dir == PCI_DMA_NONE);
- dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
- return pci_map_single_1(pdev, (char *)page_address(page) + offset,
- size, dac_allowed);
- }
- /* Unmap a single streaming mode DMA translation. The DMA_ADDR and
- SIZE must match what was provided for in a previous pci_map_single
- call. All other usages are undefined. After this call, reads by
- the cpu to the buffer are guaranteed to see whatever the device
- wrote there. */
- 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 %pf\n",
- dma_addr, size, __builtin_return_address(0));
- return;
- }
- if (dma_addr > 0xffffffff) {
- DBGA2("pci64_unmap_single: DAC [%llx,%zx] from %pf\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 %pf\n",
- dma_addr, size, npages, __builtin_return_address(0));
- }
- /* Allocate and map kernel buffer using consistent mode DMA for PCI
- device. Returns non-NULL cpu-view pointer to the buffer if
- successful and sets *DMA_ADDRP to the pci side dma address as well,
- else DMA_ADDRP is undefined. */
- static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addrp, gfp_t gfp,
- unsigned long attrs)
- {
- struct pci_dev *pdev = alpha_gendev_to_pci(dev);
- void *cpu_addr;
- long order = get_order(size);
- gfp &= ~GFP_DMA;
- try_again:
- cpu_addr = (void *)__get_free_pages(gfp, order);
- if (! cpu_addr) {
- printk(KERN_INFO "pci_alloc_consistent: "
- "get_free_pages failed from %pf\n",
- __builtin_return_address(0));
- /* ??? Really atomic allocation? Otherwise we could play
- with vmalloc and sg if we can't find contiguous memory. */
- return NULL;
- }
- memset(cpu_addr, 0, size);
- *dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0);
- if (*dma_addrp == 0) {
- free_pages((unsigned long)cpu_addr, order);
- if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA))
- return NULL;
- /* The address doesn't fit required mask and we
- do not have iommu. Try again with GFP_DMA. */
- gfp |= GFP_DMA;
- goto try_again;
- }
- DBGA2("pci_alloc_consistent: %zx -> [%p,%llx] from %pf\n",
- size, cpu_addr, *dma_addrp, __builtin_return_address(0));
- return cpu_addr;
- }
- /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must
- be values that were returned from pci_alloc_consistent. SIZE must
- be the same as what as passed into pci_alloc_consistent.
- References to the memory and mappings associated with CPU_ADDR or
- DMA_ADDR past this call are illegal. */
- static void alpha_pci_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_addr,
- unsigned long attrs)
- {
- struct pci_dev *pdev = alpha_gendev_to_pci(dev);
- pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
- free_pages((unsigned long)cpu_addr, get_order(size));
- DBGA2("pci_free_consistent: [%llx,%zx] from %pf\n",
- dma_addr, size, __builtin_return_address(0));
- }
- /* Classify the elements of the scatterlist. Write dma_address
- of each element with:
- 0 : Followers all physically adjacent.
- 1 : Followers all virtually adjacent.
- -1 : Not leader, physically adjacent to previous.
- -2 : Not leader, virtually adjacent to previous.
- Write dma_length of each leader with the combined lengths of
- the mergable followers. */
- #define SG_ENT_VIRT_ADDRESS(SG) (sg_virt((SG)))
- #define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
- static void
- sg_classify(struct device *dev, struct scatterlist *sg, struct scatterlist *end,
- int virt_ok)
- {
- unsigned long next_paddr;
- struct scatterlist *leader;
- long leader_flag, leader_length;
- unsigned int max_seg_size;
- leader = sg;
- leader_flag = 0;
- leader_length = leader->length;
- next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length;
- /* we will not marge sg without device. */
- max_seg_size = dev ? dma_get_max_seg_size(dev) : 0;
- for (++sg; sg < end; ++sg) {
- unsigned long addr, len;
- addr = SG_ENT_PHYS_ADDRESS(sg);
- len = sg->length;
- if (leader_length + len > max_seg_size)
- goto new_segment;
- if (next_paddr == addr) {
- sg->dma_address = -1;
- leader_length += len;
- } else if (((next_paddr | addr) & ~PAGE_MASK) == 0 && virt_ok) {
- sg->dma_address = -2;
- leader_flag = 1;
- leader_length += len;
- } else {
- new_segment:
- leader->dma_address = leader_flag;
- leader->dma_length = leader_length;
- leader = sg;
- leader_flag = 0;
- leader_length = len;
- }
- next_paddr = addr + len;
- }
- leader->dma_address = leader_flag;
- leader->dma_length = leader_length;
- }
- /* Given a scatterlist leader, choose an allocation method and fill
- in the blanks. */
- static int
- sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
- struct scatterlist *out, struct pci_iommu_arena *arena,
- dma_addr_t max_dma, int dac_allowed)
- {
- unsigned long paddr = SG_ENT_PHYS_ADDRESS(leader);
- long size = leader->dma_length;
- struct scatterlist *sg;
- unsigned long *ptes;
- long npages, dma_ofs, i;
- #if !DEBUG_NODIRECT
- /* If everything is physically contiguous, and the addresses
- fall into the direct-map window, use it. */
- if (leader->dma_address == 0
- && paddr + size + __direct_map_base - 1 <= max_dma
- && paddr + size <= __direct_map_size) {
- out->dma_address = paddr + __direct_map_base;
- out->dma_length = size;
- DBGA(" sg_fill: [%p,%lx] -> direct %llx\n",
- __va(paddr), size, out->dma_address);
- return 0;
- }
- #endif
- /* If physically contiguous and DAC is available, use it. */
- if (leader->dma_address == 0 && dac_allowed) {
- out->dma_address = paddr + alpha_mv.pci_dac_offset;
- out->dma_length = size;
- DBGA(" sg_fill: [%p,%lx] -> DAC %llx\n",
- __va(paddr), size, out->dma_address);
- return 0;
- }
- /* Otherwise, we'll use the iommu to make the pages virtually
- contiguous. */
- paddr &= ~PAGE_MASK;
- npages = iommu_num_pages(paddr, size, PAGE_SIZE);
- dma_ofs = iommu_arena_alloc(dev, arena, npages, 0);
- if (dma_ofs < 0) {
- /* If we attempted a direct map above but failed, die. */
- if (leader->dma_address == 0)
- return -1;
- /* Otherwise, break up the remaining virtually contiguous
- hunks into individual direct maps and retry. */
- sg_classify(dev, leader, end, 0);
- return sg_fill(dev, leader, end, out, arena, max_dma, dac_allowed);
- }
- out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
- out->dma_length = size;
- DBGA(" sg_fill: [%p,%lx] -> sg %llx np %ld\n",
- __va(paddr), size, out->dma_address, npages);
- /* All virtually contiguous. We need to find the length of each
- physically contiguous subsegment to fill in the ptes. */
- ptes = &arena->ptes[dma_ofs];
- sg = leader;
- do {
- #if DEBUG_ALLOC > 0
- struct scatterlist *last_sg = sg;
- #endif
- size = sg->length;
- paddr = SG_ENT_PHYS_ADDRESS(sg);
- while (sg+1 < end && (int) sg[1].dma_address == -1) {
- size += sg[1].length;
- sg++;
- }
- npages = iommu_num_pages(paddr, size, PAGE_SIZE);
- paddr &= PAGE_MASK;
- for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
- *ptes++ = mk_iommu_pte(paddr);
- #if DEBUG_ALLOC > 0
- DBGA(" (%ld) [%p,%x] np %ld\n",
- last_sg - leader, SG_ENT_VIRT_ADDRESS(last_sg),
- last_sg->length, npages);
- while (++last_sg <= sg) {
- DBGA(" (%ld) [%p,%x] cont\n",
- last_sg - leader, SG_ENT_VIRT_ADDRESS(last_sg),
- last_sg->length);
- }
- #endif
- } while (++sg < end && (int) sg->dma_address < 0);
- return 1;
- }
- static int alpha_pci_map_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);
- struct scatterlist *start, *end, *out;
- struct pci_controller *hose;
- struct pci_iommu_arena *arena;
- dma_addr_t max_dma;
- int dac_allowed;
- BUG_ON(dir == PCI_DMA_NONE);
- dac_allowed = dev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
- /* Fast path single entry scatterlists. */
- if (nents == 1) {
- sg->dma_length = sg->length;
- sg->dma_address
- = pci_map_single_1(pdev, SG_ENT_VIRT_ADDRESS(sg),
- sg->length, dac_allowed);
- return sg->dma_address != 0;
- }
- start = sg;
- end = sg + nents;
- /* First, prepare information about the entries. */
- sg_classify(dev, sg, end, alpha_mv.mv_pci_tbi != 0);
- /* Second, figure out where we're going to map things. */
- if (alpha_mv.mv_pci_tbi) {
- 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;
- } else {
- max_dma = -1;
- arena = NULL;
- hose = NULL;
- }
- /* Third, iterate over the scatterlist leaders and allocate
- dma space as needed. */
- for (out = sg; sg < end; ++sg) {
- if ((int) sg->dma_address < 0)
- continue;
- if (sg_fill(dev, sg, end, out, arena, max_dma, dac_allowed) < 0)
- goto error;
- out++;
- }
- /* Mark the end of the list for pci_unmap_sg. */
- if (out < end)
- out->dma_length = 0;
- if (out - start == 0)
- printk(KERN_WARNING "pci_map_sg failed: no entries?\n");
- DBGA("pci_map_sg: %ld entries\n", out - start);
- return out - start;
- error:
- printk(KERN_WARNING "pci_map_sg failed: "
- "could not allocate dma page tables\n");
- /* Some allocation failed while mapping the scatterlist
- entries. Unmap them now. */
- if (out > start)
- pci_unmap_sg(pdev, start, out - start, dir);
- return 0;
- }
- /* Unmap a set of streaming mode DMA translations. Again, cpu read
- rules concerning calls here are the same as for pci_unmap_single()
- above. */
- 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));
- }
- /* Return whether the given PCI device DMA address mask can be
- supported properly. */
- static int alpha_pci_supported(struct device *dev, u64 mask)
- {
- struct pci_dev *pdev = alpha_gendev_to_pci(dev);
- struct pci_controller *hose;
- struct pci_iommu_arena *arena;
- /* If there exists a direct map, and the mask fits either
- the entire direct mapped space or the total system memory as
- shifted by the map base */
- if (__direct_map_size != 0
- && (__direct_map_base + __direct_map_size - 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 - 1 <= mask)
- return 1;
- arena = hose->sg_pci;
- if (arena && arena->dma_base + arena->size - 1 <= mask)
- return 1;
- /* As last resort try ZONE_DMA. */
- if (!__direct_map_base && MAX_DMA_ADDRESS - IDENT_ADDR - 1 <= mask)
- return 1;
- return 0;
- }
- /*
- * AGP GART extensions to the IOMMU
- */
- int
- iommu_reserve(struct pci_iommu_arena *arena, long pg_count, long align_mask)
- {
- unsigned long flags;
- unsigned long *ptes;
- long i, p;
- if (!arena) return -EINVAL;
- spin_lock_irqsave(&arena->lock, flags);
- /* Search for N empty ptes. */
- ptes = arena->ptes;
- p = iommu_arena_find_pages(NULL, arena, pg_count, align_mask);
- if (p < 0) {
- spin_unlock_irqrestore(&arena->lock, flags);
- return -1;
- }
- /* Success. Mark them all reserved (ie not zero and invalid)
- for the iommu tlb that could load them from under us.
- They will be filled in with valid bits by _bind() */
- for (i = 0; i < pg_count; ++i)
- ptes[p+i] = IOMMU_RESERVED_PTE;
- arena->next_entry = p + pg_count;
- spin_unlock_irqrestore(&arena->lock, flags);
- return p;
- }
- int
- iommu_release(struct pci_iommu_arena *arena, long pg_start, long pg_count)
- {
- unsigned long *ptes;
- long i;
- if (!arena) return -EINVAL;
- ptes = arena->ptes;
- /* Make sure they're all reserved first... */
- for(i = pg_start; i < pg_start + pg_count; i++)
- if (ptes[i] != IOMMU_RESERVED_PTE)
- return -EBUSY;
- iommu_arena_free(arena, pg_start, pg_count);
- return 0;
- }
- int
- iommu_bind(struct pci_iommu_arena *arena, long pg_start, long pg_count,
- struct page **pages)
- {
- unsigned long flags;
- unsigned long *ptes;
- long i, j;
- if (!arena) return -EINVAL;
-
- spin_lock_irqsave(&arena->lock, flags);
- ptes = arena->ptes;
- for(j = pg_start; j < pg_start + pg_count; j++) {
- if (ptes[j] != IOMMU_RESERVED_PTE) {
- spin_unlock_irqrestore(&arena->lock, flags);
- return -EBUSY;
- }
- }
-
- for(i = 0, j = pg_start; i < pg_count; i++, j++)
- ptes[j] = mk_iommu_pte(page_to_phys(pages[i]));
- spin_unlock_irqrestore(&arena->lock, flags);
- return 0;
- }
- int
- iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)
- {
- unsigned long *p;
- long i;
- if (!arena) return -EINVAL;
- p = arena->ptes + pg_start;
- for(i = 0; i < pg_count; i++)
- p[i] = IOMMU_RESERVED_PTE;
- return 0;
- }
- static int alpha_pci_mapping_error(struct device *dev, dma_addr_t dma_addr)
- {
- return dma_addr == 0;
- }
- struct dma_map_ops alpha_pci_ops = {
- .alloc = alpha_pci_alloc_coherent,
- .free = alpha_pci_free_coherent,
- .map_page = alpha_pci_map_page,
- .unmap_page = alpha_pci_unmap_page,
- .map_sg = alpha_pci_map_sg,
- .unmap_sg = alpha_pci_unmap_sg,
- .mapping_error = alpha_pci_mapping_error,
- .dma_supported = alpha_pci_supported,
- };
- struct dma_map_ops *dma_ops = &alpha_pci_ops;
- EXPORT_SYMBOL(dma_ops);
|