Messages in this thread Patch in this message | | | Date | Thu, 16 Aug 2001 05:28:47 -0700 (PDT) | Subject | kill alt_address (Re: [patch] zero-bounce highmem I/O) | From | "David S. Miller" <> |
| |
From: Jens Axboe <axboe@suse.de> Date: Thu, 16 Aug 2001 13:51:50 +0200
On Wed, Aug 15 2001, David S. Miller wrote: > As promised. I actually got bored during the build and tried to Looks good! And works here too, even... ->
Ok, here is my current patch, it kills off alt_address as well as provide the new PCI dma interfaces.
I have no way to test the alt_address stuff here locally, and I'd be happy if someone would give it a go. All I guarentee is that it builds here on my machines :-)
--- ./arch/alpha/kernel/pci_iommu.c.~1~ Sun Aug 12 23:50:25 2001 +++ ./arch/alpha/kernel/pci_iommu.c Wed Aug 15 03:04:24 2001 @@ -636,7 +636,7 @@ supported properly. */ int -pci_dma_supported(struct pci_dev *pdev, dma_addr_t mask) +pci_dma_supported(struct pci_dev *pdev, u64 mask) { struct pci_controller *hose; struct pci_iommu_arena *arena; --- ./arch/sparc64/kernel/pci_iommu.c.~1~ Wed May 23 17:57:03 2001 +++ ./arch/sparc64/kernel/pci_iommu.c Wed Aug 15 06:40:54 2001 @@ -356,6 +356,20 @@ return 0; } +dma64_addr_t pci64_map_page(struct pci_dev *pdev, + struct page *page, unsigned long offset, + size_t sz, int direction) +{ + if (!(pdev->dma_flags & PCI_DMA_FLAG_HUGE_MAPS)) { + return (dma64_addr_t) + pci_map_single(pdev, + page_address(page) + offset, + sz, direction); + } + + return PCI64_ADDR_BASE + (__pa(page_address(page)) + offset); +} + /* Unmap a single streaming mode DMA translation. */ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) { @@ -378,7 +392,8 @@ ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU if (iopte_val(*base) == IOPTE_INVALID) - printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n", bus_addr, sz, __builtin_return_address(0)); + printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n", + bus_addr, sz, __builtin_return_address(0)); #endif bus_addr &= PAGE_MASK; @@ -423,18 +438,38 @@ spin_unlock_irqrestore(&iommu->lock, flags); } -static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, unsigned long iopte_protection) +void pci64_unmap_page(struct pci_dev *pdev, dma64_addr_t bus_addr, + size_t sz, int direction) +{ + if (!(pdev->dma_flags & PCI_DMA_FLAG_HUGE_MAPS)) { + if ((bus_addr >> 32) != (dma64_addr_t) 0) + BUG(); + + return pci_unmap_single(pdev, (dma_addr_t) bus_addr, + sz, direction); + } + + /* If doing real DAC, there is nothing to do. */ +} + +#define SG_ENT_PHYS_ADDRESS(SG) \ + ((SG)->address ? \ + __pa((SG)->address) : \ + (__pa(page_address((SG)->page)) + (SG)->offset)) + +static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, + int nused, unsigned long iopte_protection) { struct scatterlist *dma_sg = sg; int i; for (i = 0; i < nused; i++) { unsigned long pteval = ~0UL; - u32 dma_npages; + u64 dma_npages; - dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) + - dma_sg->dvma_length + - ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT; + dma_npages = ((dma_sg->dma_address & (PAGE_SIZE - 1UL)) + + dma_sg->dma_length + + ((PAGE_SIZE - 1UL))) >> PAGE_SHIFT; do { unsigned long offset; signed int len; @@ -447,7 +482,7 @@ for (;;) { unsigned long tmp; - tmp = (unsigned long) __pa(sg->address); + tmp = SG_ENT_PHYS_ADDRESS(sg); len = sg->length; if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) { pteval = tmp & PAGE_MASK; @@ -480,9 +515,9 @@ * detect a page crossing event. */ while ((pteval << (64 - PAGE_SHIFT)) != 0UL && - pteval == __pa(sg->address) && + (pteval == SG_ENT_PHYS_ADDRESS(sg)) && ((pteval ^ - (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { + (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { pteval += sg->length; sg++; } @@ -505,14 +540,19 @@ struct pci_strbuf *strbuf; unsigned long flags, ctx, npages, iopte_protection; iopte_t *base; - u32 dma_base; + u64 dma_base; struct scatterlist *sgtmp; int used; /* Fast path single entry scatterlists. */ if (nelems == 1) { - sglist->dvma_address = pci_map_single(pdev, sglist->address, sglist->length, direction); - sglist->dvma_length = sglist->length; + sglist->dma_address = (dma64_addr_t) + pci_map_single(pdev, + (sglist->address ? + sglist->address : + (page_address(sglist->page) + sglist->offset)), + sglist->length, direction); + sglist->dma_length = sglist->length; return 1; } @@ -540,8 +580,8 @@ used = nelems; sgtmp = sglist; - while (used && sgtmp->dvma_length) { - sgtmp->dvma_address += dma_base; + while (used && sgtmp->dma_length) { + sgtmp->dma_address += dma_base; sgtmp++; used--; } @@ -574,6 +614,23 @@ return 0; } +int pci64_map_sg(struct pci_dev *pdev, struct scatterlist *sg, + int nelems, int direction) +{ + if ((pdev->dma_flags & PCI_DMA_FLAG_HUGE_MAPS) != 0) { + int i; + + for (i = 0; i < nelems; i++) { + sg[i].dma_address = + PCI64_ADDR_BASE + SG_ENT_PHYS_ADDRESS(&sg[i]); + sg[i].dma_length = sg[i].length; + } + return nelems; + } + + return pci_map_sg(pdev, sg, nelems, direction); +} + /* Unmap a set of streaming mode DMA translations. */ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { @@ -582,7 +639,7 @@ struct pci_strbuf *strbuf; iopte_t *base; unsigned long flags, ctx, i, npages; - u32 bus_addr; + u64 bus_addr; if (direction == PCI_DMA_NONE) BUG(); @@ -591,20 +648,21 @@ iommu = pcp->pbm->iommu; strbuf = &pcp->pbm->stc; - bus_addr = sglist->dvma_address & PAGE_MASK; + bus_addr = sglist->dma_address & PAGE_MASK; for (i = 1; i < nelems; i++) - if (sglist[i].dvma_length == 0) + if (sglist[i].dma_length == 0) break; i--; - npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT; + npages = (PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> PAGE_SHIFT; base = iommu->page_table + ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU if (iopte_val(*base) == IOPTE_INVALID) - printk("pci_unmap_sg called on non-mapped region %08x,%d from %016lx\n", sglist->dvma_address, nelems, __builtin_return_address(0)); + printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", + sglist->dma_address, nelems, __builtin_return_address(0)); #endif spin_lock_irqsave(&iommu->lock, flags); @@ -616,7 +674,7 @@ /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) { - u32 vaddr = bus_addr; + u32 vaddr = (u32) bus_addr; PCI_STC_FLUSHFLAG_INIT(strbuf); if (strbuf->strbuf_ctxflush && @@ -648,6 +706,15 @@ spin_unlock_irqrestore(&iommu->lock, flags); } +void pci64_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, + int nelems, int direction) +{ + if (!(pdev->dma_flags & PCI_DMA_FLAG_HUGE_MAPS)) + return pci_unmap_sg(pdev, sglist, nelems, direction); + + /* If doing real DAC, there is nothing to do. */ +} + /* Make physical memory consistent for a single * streaming mode DMA translation after a transfer. */ @@ -709,6 +776,20 @@ spin_unlock_irqrestore(&iommu->lock, flags); } +void pci64_dma_sync_single(struct pci_dev *pdev, dma64_addr_t bus_addr, + size_t sz, int direction) +{ + if (!(pdev->dma_flags & PCI_DMA_FLAG_HUGE_MAPS)) { + if ((bus_addr >> 32) != (dma64_addr_t) 0) + BUG(); + + return pci_dma_sync_single(pdev, (dma_addr_t) bus_addr, + sz, direction); + } + + /* If doing real DAC, there is nothing to do. */ +} + /* Make physical memory consistent for a set of streaming * mode DMA translations after a transfer. */ @@ -735,7 +816,7 @@ iopte_t *iopte; iopte = iommu->page_table + - ((sglist[0].dvma_address - iommu->page_table_map_base) >> PAGE_SHIFT); + ((sglist[0].dma_address - iommu->page_table_map_base) >> PAGE_SHIFT); ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; } @@ -752,15 +833,15 @@ } while (((long)pci_iommu_read(matchreg)) < 0L); } else { unsigned long i, npages; - u32 bus_addr; + u64 bus_addr; - bus_addr = sglist[0].dvma_address & PAGE_MASK; + bus_addr = sglist[0].dma_address & PAGE_MASK; for(i = 1; i < nelems; i++) - if (!sglist[i].dvma_length) + if (!sglist[i].dma_length) break; i--; - npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT; + npages = (PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> PAGE_SHIFT; for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, bus_addr); } @@ -774,10 +855,19 @@ spin_unlock_irqrestore(&iommu->lock, flags); } -int pci_dma_supported(struct pci_dev *pdev, dma_addr_t device_mask) +void pci64_dma_sync_sg(struct pci_dev *pdev, struct scatterlist *sglist, + int nelems, int direction) +{ + if (!(pdev->dma_flags & PCI_DMA_FLAG_HUGE_MAPS)) + return pci_dma_sync_sg(pdev, sglist, nelems, direction); + + /* If doing real DAC, there is nothing to do. */ +} + +int pci_dma_supported(struct pci_dev *pdev, u64 device_mask) { struct pcidev_cookie *pcp = pdev->sysdata; - u32 dma_addr_mask; + u64 dma_addr_mask; if (pdev == NULL) { dma_addr_mask = 0xffffffff; --- ./arch/sparc64/kernel/iommu_common.c.~1~ Tue Nov 28 08:33:08 2000 +++ ./arch/sparc64/kernel/iommu_common.c Wed Aug 15 05:13:34 2001 @@ -12,7 +12,7 @@ */ #ifdef VERIFY_SG -int verify_lengths(struct scatterlist *sg, int nents, int npages) +static int verify_lengths(struct scatterlist *sg, int nents, int npages) { int sg_len, dma_len; int i, pgcount; @@ -22,8 +22,8 @@ sg_len += sg[i].length; dma_len = 0; - for (i = 0; i < nents && sg[i].dvma_length; i++) - dma_len += sg[i].dvma_length; + for (i = 0; i < nents && sg[i].dma_length; i++) + dma_len += sg[i].dma_length; if (sg_len != dma_len) { printk("verify_lengths: Error, different, sg[%d] dma[%d]\n", @@ -32,13 +32,13 @@ } pgcount = 0; - for (i = 0; i < nents && sg[i].dvma_length; i++) { + for (i = 0; i < nents && sg[i].dma_length; i++) { unsigned long start, end; - start = sg[i].dvma_address; + start = sg[i].dma_address; start = start & PAGE_MASK; - end = sg[i].dvma_address + sg[i].dvma_length; + end = sg[i].dma_address + sg[i].dma_length; end = (end + (PAGE_SIZE - 1)) & PAGE_MASK; pgcount += ((end - start) >> PAGE_SHIFT); @@ -55,15 +55,16 @@ return 0; } -int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte) +static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte) { struct scatterlist *sg = *__sg; iopte_t *iopte = *__iopte; - u32 dlen = dma_sg->dvma_length; - u32 daddr = dma_sg->dvma_address; + u32 dlen = dma_sg->dma_length; + u32 daddr; unsigned int sglen; unsigned long sgaddr; + daddr = dma_sg->dma_address; sglen = sg->length; sgaddr = (unsigned long) sg->address; while (dlen > 0) { @@ -136,7 +137,7 @@ return nents; } -int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte) +static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte) { struct scatterlist *dma_sg = sg; struct scatterlist *orig_dma_sg = dma_sg; @@ -147,7 +148,7 @@ if (nents <= 0) break; dma_sg++; - if (dma_sg->dvma_length == 0) + if (dma_sg->dma_length == 0) break; } @@ -174,14 +175,15 @@ verify_maps(sg, nents, iopte) < 0) { int i; - printk("verify_sglist: Crap, messed up mappings, dumping, iodma at %08x.\n", - (u32) (sg->dvma_address & PAGE_MASK)); + printk("verify_sglist: Crap, messed up mappings, dumping, iodma at "); + printk("%016lx.\n", sg->dma_address & PAGE_MASK); + for (i = 0; i < nents; i++) { printk("sg(%d): address(%p) length(%x) " - "dma_address[%08x] dma_length[%08x]\n", + "dma_address[%016lx] dma_length[%08x]\n", i, sg[i].address, sg[i].length, - sg[i].dvma_address, sg[i].dvma_length); + sg[i].dma_address, sg[i].dma_length); } } @@ -189,30 +191,23 @@ } #endif -/* Two addresses are "virtually contiguous" if and only if: - * 1) They are equal, or... - * 2) They are both on a page boundry - */ -#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \ - (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL) - unsigned long prepare_sg(struct scatterlist *sg, int nents) { struct scatterlist *dma_sg = sg; unsigned long prev; - u32 dent_addr, dent_len; + u64 dent_addr, dent_len; prev = (unsigned long) sg->address; prev += (unsigned long) (dent_len = sg->length); - dent_addr = (u32) ((unsigned long)sg->address & (PAGE_SIZE - 1UL)); + dent_addr = (u64) ((unsigned long)sg->address & (PAGE_SIZE - 1UL)); while (--nents) { unsigned long addr; sg++; addr = (unsigned long) sg->address; if (! VCONTIG(prev, addr)) { - dma_sg->dvma_address = dent_addr; - dma_sg->dvma_length = dent_len; + dma_sg->dma_address = dent_addr; + dma_sg->dma_length = dent_len; dma_sg++; dent_addr = ((dent_addr + @@ -225,8 +220,8 @@ dent_len += sg->length; prev = addr + sg->length; } - dma_sg->dvma_address = dent_addr; - dma_sg->dvma_length = dent_len; + dma_sg->dma_address = dent_addr; + dma_sg->dma_length = dent_len; return ((unsigned long) dent_addr + (unsigned long) dent_len + --- ./arch/sparc64/kernel/sbus.c.~1~ Wed May 23 17:57:03 2001 +++ ./arch/sparc64/kernel/sbus.c Wed Aug 15 06:41:43 2001 @@ -376,6 +376,11 @@ spin_unlock_irqrestore(&iommu->lock, flags); } +#define SG_ENT_PHYS_ADDRESS(SG) \ + ((SG)->address ? \ + __pa((SG)->address) : \ + (__pa(page_address((SG)->page)) + (SG)->offset)) + static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, unsigned long iopte_bits) { struct scatterlist *dma_sg = sg; @@ -383,11 +388,11 @@ for (i = 0; i < nused; i++) { unsigned long pteval = ~0UL; - u32 dma_npages; + u64 dma_npages; - dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) + - dma_sg->dvma_length + - ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT; + dma_npages = ((dma_sg->dma_address & (PAGE_SIZE - 1UL)) + + dma_sg->dma_length + + ((PAGE_SIZE - 1UL))) >> PAGE_SHIFT; do { unsigned long offset; signed int len; @@ -400,7 +405,7 @@ for (;;) { unsigned long tmp; - tmp = (unsigned long) __pa(sg->address); + tmp = (unsigned long) SG_ENT_PHYS_ADDRESS(sg); len = sg->length; if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) { pteval = tmp & PAGE_MASK; @@ -433,9 +438,9 @@ * detect a page crossing event. */ while ((pteval << (64 - PAGE_SHIFT)) != 0UL && - pteval == __pa(sg->address) && + (pteval == SG_ENT_PHYS_ADDRESS(sg)) && ((pteval ^ - (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { + (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { pteval += sg->length; sg++; } @@ -461,8 +466,13 @@ /* Fast path single entry scatterlists. */ if (nents == 1) { - sg->dvma_address = sbus_map_single(sdev, sg->address, sg->length, dir); - sg->dvma_length = sg->length; + sg->dma_address = (dma64_addr_t) + sbus_map_single(sdev, + (sg->address ? + sg->address : + (page_address(sg->page) + sg->offset)), + sg->length, dir); + sg->dma_length = sg->length; return 1; } @@ -478,8 +488,8 @@ sgtmp = sg; used = nents; - while (used && sgtmp->dvma_length) { - sgtmp->dvma_address += dma_base; + while (used && sgtmp->dma_length) { + sgtmp->dma_address += dma_base; sgtmp++; used--; } @@ -507,22 +517,22 @@ { unsigned long size, flags; struct sbus_iommu *iommu; - u32 dvma_base; + u64 dvma_base; int i; /* Fast path single entry scatterlists. */ if (nents == 1) { - sbus_unmap_single(sdev, sg->dvma_address, sg->dvma_length, direction); + sbus_unmap_single(sdev, sg->dma_address, sg->dma_length, direction); return; } - dvma_base = sg[0].dvma_address & PAGE_MASK; + dvma_base = sg[0].dma_address & PAGE_MASK; for (i = 0; i < nents; i++) { - if (sg[i].dvma_length == 0) + if (sg[i].dma_length == 0) break; } i--; - size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - dvma_base; + size = PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - dvma_base; iommu = sdev->bus->iommu; spin_lock_irqsave(&iommu->lock, flags); @@ -547,16 +557,16 @@ { struct sbus_iommu *iommu = sdev->bus->iommu; unsigned long flags, size; - u32 base; + u64 base; int i; - base = sg[0].dvma_address & PAGE_MASK; + base = sg[0].dma_address & PAGE_MASK; for (i = 0; i < nents; i++) { - if (sg[i].dvma_length == 0) + if (sg[i].dma_length == 0) break; } i--; - size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - base; + size = PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; spin_lock_irqsave(&iommu->lock, flags); strbuf_flush(iommu, base, size >> PAGE_SHIFT); --- ./arch/sparc64/kernel/iommu_common.h.~1~ Mon Aug 13 11:04:26 2001 +++ ./arch/sparc64/kernel/iommu_common.h Wed Aug 15 07:00:20 2001 @@ -18,10 +18,7 @@ #undef VERIFY_SG #ifdef VERIFY_SG -int verify_lengths(struct scatterlist *sg, int nents, int npages); -int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte); -int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte); -void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages); +extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages); #endif /* Two addresses are "virtually contiguous" if and only if: @@ -31,4 +28,4 @@ #define VCONTIG(__X, __Y) (((__X) == (__Y)) || \ (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL) -unsigned long prepare_sg(struct scatterlist *sg, int nents); +extern unsigned long prepare_sg(struct scatterlist *sg, int nents); --- ./arch/sparc64/kernel/sparc64_ksyms.c.~1~ Mon Jun 4 20:39:50 2001 +++ ./arch/sparc64/kernel/sparc64_ksyms.c Wed Aug 15 06:23:37 2001 @@ -216,10 +216,16 @@ EXPORT_SYMBOL(pci_free_consistent); EXPORT_SYMBOL(pci_map_single); EXPORT_SYMBOL(pci_unmap_single); +EXPORT_SYMBOL(pci64_map_page); +EXPORT_SYMBOL(pci64_unmap_page); EXPORT_SYMBOL(pci_map_sg); EXPORT_SYMBOL(pci_unmap_sg); +EXPORT_SYMBOL(pci64_map_sg); +EXPORT_SYMBOL(pci64_unmap_sg); EXPORT_SYMBOL(pci_dma_sync_single); +EXPORT_SYMBOL(pci64_dma_sync_single); EXPORT_SYMBOL(pci_dma_sync_sg); +EXPORT_SYMBOL(pci64_dma_sync_sg); EXPORT_SYMBOL(pci_dma_supported); #endif --- ./arch/ia64/sn/io/pci_dma.c.~1~ Fri Apr 13 22:44:54 2001 +++ ./arch/ia64/sn/io/pci_dma.c Thu Aug 16 04:50:22 2001 @@ -182,7 +182,7 @@ } /* - * On sn1 we use the alt_address entry of the scatterlist to store + * On sn1 we use the orig_address entry of the scatterlist to store * the physical address corresponding to the given virtual address */ int --- ./arch/parisc/kernel/ccio-dma.c.~1~ Sun Feb 11 23:53:07 2001 +++ ./arch/parisc/kernel/ccio-dma.c Wed Aug 15 03:07:31 2001 @@ -638,7 +638,7 @@ } -static int ccio_dma_supported( struct pci_dev *dev, dma_addr_t mask) +static int ccio_dma_supported( struct pci_dev *dev, u64 mask) { if (dev == NULL) { printk(MODULE_NAME ": EISA/ISA/et al not supported\n"); --- ./arch/parisc/kernel/pci-dma.c.~1~ Sun Feb 11 23:53:07 2001 +++ ./arch/parisc/kernel/pci-dma.c Wed Aug 15 03:07:50 2001 @@ -77,7 +77,7 @@ static inline void dump_resmap(void) {;} #endif -static int pa11_dma_supported( struct pci_dev *dev, dma_addr_t mask) +static int pa11_dma_supported( struct pci_dev *dev, u64 mask) { return 1; } --- ./arch/parisc/kernel/ccio-rm-dma.c.~1~ Wed Dec 6 05:30:33 2000 +++ ./arch/parisc/kernel/ccio-rm-dma.c Wed Aug 15 03:07:42 2001 @@ -93,7 +93,7 @@ } -static int ccio_dma_supported( struct pci_dev *dev, dma_addr_t mask) +static int ccio_dma_supported( struct pci_dev *dev, u64 mask) { if (dev == NULL) { printk(MODULE_NAME ": EISA/ISA/et al not supported\n"); --- ./arch/parisc/kernel/sba_iommu.c.~1~ Sun Feb 11 23:53:07 2001 +++ ./arch/parisc/kernel/sba_iommu.c Wed Aug 15 03:07:56 2001 @@ -779,7 +779,7 @@ } static int -sba_dma_supported( struct pci_dev *dev, dma_addr_t mask) +sba_dma_supported( struct pci_dev *dev, u64 mask) { if (dev == NULL) { printk(MODULE_NAME ": EISA/ISA/et al not supported\n"); --- ./drivers/net/acenic.c.~1~ Mon Aug 13 09:55:44 2001 +++ ./drivers/net/acenic.c Wed Aug 15 02:33:22 2001 @@ -202,6 +202,7 @@ #define pci_free_consistent(cookie, size, ptr, dma_ptr) kfree(ptr) #define pci_map_single(cookie, address, size, dir) virt_to_bus(address) #define pci_unmap_single(cookie, address, size, dir) +#define pci_set_dma_mask(dev, mask) do { } while (0) #endif #if (LINUX_VERSION_CODE < 0x02032b) @@ -258,11 +259,6 @@ #define ace_mark_net_bh() {do{} while(0);} #define ace_if_down(dev) {do{} while(0);} #endif - -#ifndef pci_set_dma_mask -#define pci_set_dma_mask(dev, mask) dev->dma_mask = mask; -#endif - #if (LINUX_VERSION_CODE >= 0x02031b) #define NEW_NETINIT --- ./drivers/pci/pci.c.~1~ Mon Aug 13 22:05:39 2001 +++ ./drivers/pci/pci.c Wed Aug 15 06:22:34 2001 @@ -832,7 +832,7 @@ } int -pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) +pci_set_dma_mask(struct pci_dev *dev, u64 mask) { if(! pci_dma_supported(dev, mask)) return -EIO; @@ -842,6 +842,12 @@ return 0; } +void +pci_change_dma_flag(struct pci_dev *dev, unsigned int on, unsigned int off) +{ + dev->dma_flags |= on; + dev->dma_flags &= ~off; +} /* * Translate the low bits of the PCI base @@ -1954,6 +1960,7 @@ EXPORT_SYMBOL(pci_find_subsys); EXPORT_SYMBOL(pci_set_master); EXPORT_SYMBOL(pci_set_dma_mask); +EXPORT_SYMBOL(pci_change_dma_flag); EXPORT_SYMBOL(pci_assign_resource); EXPORT_SYMBOL(pci_register_driver); EXPORT_SYMBOL(pci_unregister_driver); --- ./drivers/scsi/sr.c.~1~ Thu Jul 5 22:11:52 2001 +++ ./drivers/scsi/sr.c Thu Aug 16 04:59:37 2001 @@ -265,6 +265,7 @@ struct scatterlist *sg, *old_sg = NULL; int i, fsize, bsize, sg_ent, sg_count; char *front, *back; + void **bbpnt, **old_bbpnt = NULL; back = front = NULL; sg_ent = SCpnt->use_sg; @@ -292,17 +293,25 @@ * extend or allocate new scatter-gather table */ sg_count = SCpnt->use_sg; - if (sg_count) + if (sg_count) { old_sg = (struct scatterlist *) SCpnt->request_buffer; - else { + old_bbpnt = SCpnt->bounce_buffers; + } else { sg_count = 1; sg_ent++; } - i = ((sg_ent * sizeof(struct scatterlist)) + 511) & ~511; + /* Get space for scatterlist and bounce buffer array. */ + i = sg_ent * sizeof(struct scatterlist); + i += sg_ent * sizeof(void *); + i = (i + 511) & ~511; + if ((sg = scsi_malloc(i)) == NULL) goto no_mem; + bbpnt = (void **) + ((char *)sg + (sg_ent * sizeof(struct scatterlist))); + /* * no more failing memory allocs possible, we can safely assign * SCpnt values now @@ -313,13 +322,15 @@ i = 0; if (fsize) { - sg[0].address = sg[0].alt_address = front; + sg[0].address = bbpnt[0] = front; sg[0].length = fsize; i++; } if (old_sg) { memcpy(sg + i, old_sg, SCpnt->use_sg * sizeof(struct scatterlist)); - scsi_free(old_sg, ((SCpnt->use_sg * sizeof(struct scatterlist)) + 511) & ~511); + memcpy(bbpnt + i, old_bbpnt, SCpnt->use_sg * sizeof(void *)); + scsi_free(old_sg, (((SCpnt->use_sg * sizeof(struct scatterlist)) + + (SCpnt->use_sg * sizeof(void *))) + 511) & ~511); } else { sg[i].address = SCpnt->request_buffer; sg[i].length = SCpnt->request_bufflen; @@ -327,11 +338,12 @@ SCpnt->request_bufflen += (fsize + bsize); SCpnt->request_buffer = sg; + SCpnt->bounce_buffers = bbpnt; SCpnt->use_sg += i; if (bsize) { sg[SCpnt->use_sg].address = back; - sg[SCpnt->use_sg].alt_address = back; + bbpnt[SCpnt->use_sg] = back; sg[SCpnt->use_sg].length = bsize; SCpnt->use_sg++; } --- ./drivers/scsi/sym53c8xx.c.~1~ Thu Jul 5 22:11:53 2001 +++ ./drivers/scsi/sym53c8xx.c Wed Aug 15 02:34:39 2001 @@ -13101,7 +13101,7 @@ (int) (PciDeviceFn(pdev) & 7)); #ifdef SCSI_NCR_DYNAMIC_DMA_MAPPING - if (pci_set_dma_mask(pdev, (dma_addr_t) (0xffffffffUL))) { + if (pci_set_dma_mask(pdev, 0xffffffff)) { printk(KERN_WARNING NAME53C8XX "32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n"); return -1; --- ./drivers/scsi/sym53c8xx_comm.h.~1~ Tue Aug 14 21:43:17 2001 +++ ./drivers/scsi/sym53c8xx_comm.h Wed Aug 15 03:05:23 2001 @@ -2186,7 +2186,7 @@ (int) (PciDeviceFn(pdev) & 7)); #ifdef SCSI_NCR_DYNAMIC_DMA_MAPPING - if (!pci_dma_supported(pdev, (dma_addr_t) (0xffffffffUL))) { + if (!pci_dma_supported(pdev, 0xffffffff)) { printk(KERN_WARNING NAME53C8XX "32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n"); return -1; --- ./drivers/scsi/aha1542.c.~1~ Tue May 1 18:50:05 2001 +++ ./drivers/scsi/aha1542.c Thu Aug 16 04:21:56 2001 @@ -67,12 +67,10 @@ int nseg, int badseg) { - printk(KERN_CRIT "sgpnt[%d:%d] addr %p/0x%lx alt %p/0x%lx length %d\n", + printk(KERN_CRIT "sgpnt[%d:%d] addr %p/0x%lx length %d\n", badseg, nseg, sgpnt[badseg].address, SCSI_PA(sgpnt[badseg].address), - sgpnt[badseg].alt_address, - sgpnt[badseg].alt_address ? SCSI_PA(sgpnt[badseg].alt_address) : 0, sgpnt[badseg].length); /* @@ -716,7 +714,7 @@ unsigned char *ptr; printk(KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n", SCpnt->use_sg, i); for (i = 0; i < SCpnt->use_sg; i++) { - printk(KERN_CRIT "%d: %x %x %d\n", i, (unsigned int) sgpnt[i].address, (unsigned int) sgpnt[i].alt_address, + printk(KERN_CRIT "%d: %p %d\n", i, sgpnt[i].address, sgpnt[i].length); }; printk(KERN_CRIT "cptr %x: ", (unsigned int) cptr); --- ./drivers/scsi/osst.c.~1~ Mon Jul 23 05:12:27 2001 +++ ./drivers/scsi/osst.c Thu Aug 16 04:22:30 2001 @@ -4933,7 +4933,6 @@ tb->sg[0].address = (unsigned char *)__get_free_pages(priority, order); if (tb->sg[0].address != NULL) { - tb->sg[0].alt_address = NULL; tb->sg[0].length = b_size; break; } @@ -4969,7 +4968,6 @@ tb = NULL; break; } - tb->sg[segs].alt_address = NULL; tb->sg[segs].length = b_size; got += b_size; segs++; @@ -5043,7 +5041,6 @@ normalize_buffer(STbuffer); return FALSE; } - STbuffer->sg[segs].alt_address = NULL; STbuffer->sg[segs].length = b_size; STbuffer->sg_segs += 1; got += b_size; --- ./drivers/scsi/scsi_debug.c.~1~ Tue Nov 28 08:33:08 2000 +++ ./drivers/scsi/scsi_debug.c Thu Aug 16 04:23:40 2001 @@ -154,10 +154,7 @@ if (SCpnt->use_sg) { sgpnt = (struct scatterlist *) SCpnt->buffer; for (i = 0; i < SCpnt->use_sg; i++) { - lpnt = (int *) sgpnt[i].alt_address; - printk(":%p %p %d\n", sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length); - if (lpnt) - printk(" (Alt %x) ", lpnt[15]); + printk(":%p %d\n", sgpnt[i].address, sgpnt[i].length); }; } else { printk("nosg: %p %p %d\n", SCpnt->request.buffer, SCpnt->buffer, @@ -175,12 +172,6 @@ printk("\n"); if (flag == 0) return; - lpnt = (unsigned int *) sgpnt[0].alt_address; - for (i = 0; i < sizeof(Scsi_Cmnd) / 4 + 1; i++) { - if ((i & 7) == 0) - printk("\n"); - printk("%x ", *lpnt++); - }; #if 0 printk("\n"); lpnt = (unsigned int *) sgpnt[0].address; --- ./drivers/scsi/scsi.h.~1~ Wed Aug 15 06:48:23 2001 +++ ./drivers/scsi/scsi.h Thu Aug 16 04:41:17 2001 @@ -745,7 +745,8 @@ unsigned request_bufflen; /* Actual request size */ struct timer_list eh_timeout; /* Used to time out the command. */ - void *request_buffer; /* Actual requested buffer */ + void *request_buffer; /* Actual requested buffer */ + void **bounce_buffers; /* Array of bounce buffers when using scatter-gather */ /* These elements define the operation we ultimately want to perform */ unsigned char data_cmnd[MAX_COMMAND_SIZE]; --- ./drivers/scsi/scsi_merge.c.~1~ Thu Jul 5 22:11:52 2001 +++ ./drivers/scsi/scsi_merge.c Thu Aug 16 04:58:34 2001 @@ -120,9 +120,11 @@ { int jj; struct scatterlist *sgpnt; + void **bbpnt; int consumed = 0; sgpnt = (struct scatterlist *) SCpnt->request_buffer; + bbpnt = SCpnt->bounce_buffers; /* * Now print out a bunch of stats. First, start with the request @@ -136,15 +138,13 @@ */ for(jj=0; jj < SCpnt->use_sg; jj++) { - printk("[%d]\tlen:%d\taddr:%p\talt:%p\n", + printk("[%d]\tlen:%d\taddr:%p\tbounce:%p\n", jj, sgpnt[jj].length, sgpnt[jj].address, - sgpnt[jj].alt_address); - if( sgpnt[jj].alt_address != NULL ) - { - consumed = (sgpnt[jj].length >> 9); - } + (bbpnt ? bbpnt[jj] : NULL)); + if (bbpnt && bbpnt[jj]) + consumed += sgpnt[jj].length; } printk("Total %d sectors consumed\n", consumed); panic("DMA pool exhausted"); @@ -807,6 +807,7 @@ int sectors; struct scatterlist * sgpnt; int this_count; + void ** bbpnt; /* * FIXME(eric) - don't inline this - it doesn't depend on the @@ -861,10 +862,19 @@ /* * Allocate the actual scatter-gather table itself. - * scsi_malloc can only allocate in chunks of 512 bytes */ - SCpnt->sglist_len = (SCpnt->use_sg - * sizeof(struct scatterlist) + 511) & ~511; + SCpnt->sglist_len = (SCpnt->use_sg * sizeof(struct scatterlist)); + + /* If we could potentially require ISA bounce buffers, allocate + * space for this array here. + */ + if (dma_host) + SCpnt->sglist_len += (SCpnt->use_sg * sizeof(void *)); + + /* scsi_malloc can only allocate in chunks of 512 bytes so + * round it up. + */ + SCpnt->sglist_len = (SCpnt->sglist_len + 511) & ~511; sgpnt = (struct scatterlist *) scsi_malloc(SCpnt->sglist_len); @@ -889,6 +899,14 @@ SCpnt->request_bufflen = 0; bhprev = NULL; + if (dma_host) + bbpnt = (void **) ((char *)sgpnt + + (SCpnt->use_sg * sizeof(struct scatterlist))); + else + bbpnt = NULL; + + SCpnt->bounce_buffers = bbpnt; + for (count = 0, bh = SCpnt->request.bh; bh; bh = bh->b_reqnext) { if (use_clustering && bhprev != NULL) { @@ -956,7 +974,7 @@ if( scsi_dma_free_sectors - sectors <= 10 ) { /* * If this would nearly drain the DMA - * pool, mpty, then let's stop here. + * pool empty, then let's stop here. * Don't make this request any larger. * This is kind of a safety valve that * we use - we could get screwed later @@ -970,7 +988,7 @@ break; } - sgpnt[i].alt_address = sgpnt[i].address; + bbpnt[i] = sgpnt[i].address; sgpnt[i].address = (char *) scsi_malloc(sgpnt[i].length); /* @@ -987,7 +1005,7 @@ break; } if (SCpnt->request.cmd == WRITE) { - memcpy(sgpnt[i].address, sgpnt[i].alt_address, + memcpy(sgpnt[i].address, bbpnt[i], sgpnt[i].length); } } --- ./drivers/scsi/scsi_lib.c.~1~ Sun Aug 12 23:50:32 2001 +++ ./drivers/scsi/scsi_lib.c Thu Aug 16 04:41:34 2001 @@ -496,13 +496,16 @@ */ if (SCpnt->use_sg) { struct scatterlist *sgpnt; + void **bbpnt; int i; sgpnt = (struct scatterlist *) SCpnt->request_buffer; + bbpnt = SCpnt->bounce_buffers; - for (i = 0; i < SCpnt->use_sg; i++) { - if (sgpnt[i].alt_address) { - scsi_free(sgpnt[i].address, sgpnt[i].length); + if (bbpnt) { + for (i = 0; i < SCpnt->use_sg; i++) { + if (bbpnt[i]) + scsi_free(sgpnt[i].address, sgpnt[i].length); } } scsi_free(SCpnt->request_buffer, SCpnt->sglist_len); @@ -568,18 +571,22 @@ */ if (SCpnt->use_sg) { struct scatterlist *sgpnt; + void **bbpnt; int i; sgpnt = (struct scatterlist *) SCpnt->buffer; + bbpnt = SCpnt->bounce_buffers; - for (i = 0; i < SCpnt->use_sg; i++) { - if (sgpnt[i].alt_address) { - if (SCpnt->request.cmd == READ) { - memcpy(sgpnt[i].alt_address, - sgpnt[i].address, - sgpnt[i].length); + if (bbpnt) { + for (i = 0; i < SCpnt->use_sg; i++) { + if (bbpnt[i]) { + if (SCpnt->request.cmd == READ) { + memcpy(bbpnt[i], + sgpnt[i].address, + sgpnt[i].length); + } + scsi_free(sgpnt[i].address, sgpnt[i].length); } - scsi_free(sgpnt[i].address, sgpnt[i].length); } } scsi_free(SCpnt->buffer, SCpnt->sglist_len); --- ./drivers/scsi/st.c.~1~ Sun Aug 12 23:50:32 2001 +++ ./drivers/scsi/st.c Thu Aug 16 04:48:18 2001 @@ -3222,7 +3222,6 @@ tb->sg[0].address = (unsigned char *) __get_free_pages(priority, order); if (tb->sg[0].address != NULL) { - tb->sg[0].alt_address = NULL; tb->sg[0].length = b_size; break; } @@ -3258,7 +3257,6 @@ tb = NULL; break; } - tb->sg[segs].alt_address = NULL; tb->sg[segs].length = b_size; got += b_size; segs++; @@ -3332,7 +3330,6 @@ normalize_buffer(STbuffer); return FALSE; } - STbuffer->sg[segs].alt_address = NULL; STbuffer->sg[segs].length = b_size; STbuffer->sg_segs += 1; got += b_size; --- ./drivers/scsi/qlogicfc.c.~1~ Sun Aug 12 23:50:32 2001 +++ ./drivers/scsi/qlogicfc.c Wed Aug 15 06:53:38 2001 @@ -65,7 +65,7 @@ #if 1 /* Once pci64_ DMA mapping interface is in, kill this. */ -typedef dma_addr_t dma64_addr_t; +#define dma64_addr_t dma_addr_t #define pci64_alloc_consistent(d,s,p) pci_alloc_consistent((d),(s),(p)) #define pci64_free_consistent(d,s,c,a) pci_free_consistent((d),(s),(c),(a)) #define pci64_map_single(d,c,s,dir) pci_map_single((d),(c),(s),(dir)) @@ -80,6 +80,7 @@ #define pci64_dma_lo32(a) (a) #endif /* BITS_PER_LONG */ #define pci64_dma_build(hi,lo) (lo) +#undef sg_dma64_address #define sg_dma64_address(s) sg_dma_address(s) #define sg_dma64_len(s) sg_dma_len(s) #if BITS_PER_LONG > 32 --- ./include/asm-alpha/pci.h.~1~ Wed May 23 17:57:18 2001 +++ ./include/asm-alpha/pci.h Wed Aug 15 03:05:38 2001 @@ -144,7 +144,7 @@ only drive the low 24-bits during PCI bus mastering, then you would pass 0x00ffffff as the mask to this function. */ -extern int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask); +extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask); /* Return the index of the PCI controller for device PDEV. */ extern int pci_controller_num(struct pci_dev *pdev); --- ./include/asm-alpha/scatterlist.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-alpha/scatterlist.h Thu Aug 16 04:50:38 2001 @@ -5,8 +5,6 @@ struct scatterlist { char *address; /* Source/target vaddr. */ - char *alt_address; /* Location of actual if address is a - dma indirect buffer, else NULL. */ dma_addr_t dma_address; unsigned int length; unsigned int dma_length; --- ./include/asm-arm/pci.h.~1~ Sun Aug 12 23:50:35 2001 +++ ./include/asm-arm/pci.h Wed Aug 15 03:05:45 2001 @@ -152,7 +152,7 @@ * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -static inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) { return 1; } --- ./include/asm-arm/scatterlist.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-arm/scatterlist.h Thu Aug 16 04:50:52 2001 @@ -5,7 +5,6 @@ struct scatterlist { char *address; /* virtual address */ - char *alt_address; /* indirect dma address, or NULL */ dma_addr_t dma_address; /* dma address */ unsigned int length; /* length */ }; --- ./include/asm-i386/pci.h.~1~ Fri Jul 27 02:21:22 2001 +++ ./include/asm-i386/pci.h Wed Aug 15 06:47:07 2001 @@ -55,6 +55,9 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle); +/* This is always fine. */ +#define pci_dac_cycles_ok(pci_dev) (1) + /* Map a single buffer of the indicated size for DMA in streaming mode. * The 32-bit bus address to use is returned. * @@ -84,6 +87,46 @@ /* Nothing to do */ } +/* + * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical + * to pci_map_single, but takes a struct page instead of a virtual address + */ +static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page, + unsigned long offset, size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + + return (page - mem_map) * PAGE_SIZE + offset; +} + +static inline void pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + /* Nothing to do */ +} + +/* 64-bit variants */ +static inline dma64_addr_t pci64_map_page(struct pci_dev *hwdev, struct page *page, + unsigned long offset, size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + + return (((dma64_addr_t) (page - mem_map)) * + ((dma64_addr_t) PAGE_SIZE)) + (dma64_addr_t) offset; +} + +static inline void pci64_unmap_page(struct pci_dev *hwdev, dma64_addr_t dma_address, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + /* Nothing to do */ +} + /* Map a set of buffers described by scatterlist in streaming * mode for DMA. This is the scather-gather version of the * above pci_map_single interface. Here the scatter gather list @@ -102,8 +145,26 @@ static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) { + int i; + if (direction == PCI_DMA_NONE) BUG(); + + /* + * temporary 2.4 hack + */ + for (i = 0; i < nents; i++ ) { + if (sg[i].address && sg[i].page) + BUG(); + else if (!sg[i].address && !sg[i].page) + BUG(); + + if (sg[i].address) + sg[i].dma_address = virt_to_bus(sg[i].address); + else + sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset; + } + return nents; } @@ -119,6 +180,9 @@ /* Nothing to do */ } +#define pci64_map_sg pci_map_sg +#define pci64_unmap_sg pci_unmap_sg + /* Make physical memory consistent for a single * streaming mode DMA translation after a transfer. * @@ -152,12 +216,15 @@ /* Nothing to do */ } +#define pci64_dma_sync_single pci_dma_sync_single +#define pci64_dma_sync_sg pci_dma_sync_sg + /* Return whether the given PCI device DMA address mask can * be supported properly. For example, if your device can * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -static inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) { /* * we fall back to GFP_DMA when the mask isn't all 1s, @@ -173,10 +240,10 @@ /* These macros should be used after a pci_map_sg call has been done * to get bus addresses of each of the SG entries and their lengths. * You should only work with the number of sg entries pci_map_sg - * returns, or alternatively stop on the first sg_dma_len(sg) which - * is 0. + * returns. */ -#define sg_dma_address(sg) (virt_to_bus((sg)->address)) +#define sg_dma_address(sg) ((dma_addr_t) ((sg)->dma_address)) +#define sg_dma64_address(sg) ((sg)->dma_address) #define sg_dma_len(sg) ((sg)->length) /* Return the index of the PCI controller for device. */ --- ./include/asm-i386/scatterlist.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-i386/scatterlist.h Thu Aug 16 04:51:00 2001 @@ -2,9 +2,12 @@ #define _I386_SCATTERLIST_H struct scatterlist { - char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ + char * address; /* Location data is to be transferred to, NULL for + * highmem page */ + struct page * page; /* Location for highmem page, if any */ + unsigned int offset;/* for highmem, page offset */ + + dma64_addr_t dma_address; unsigned int length; }; --- ./include/asm-i386/types.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-i386/types.h Wed Aug 15 06:32:48 2001 @@ -27,6 +27,8 @@ */ #ifdef __KERNEL__ +#include <linux/config.h> + typedef signed char s8; typedef unsigned char u8; @@ -44,6 +46,11 @@ /* Dma addresses are 32-bits wide. */ typedef u32 dma_addr_t; +#ifdef CONFIG_HIGHMEM +typedef u64 dma64_addr_t; +#else +typedef u32 dma64_addr_t; +#endif #endif /* __KERNEL__ */ --- ./include/asm-m68k/scatterlist.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-m68k/scatterlist.h Thu Aug 16 04:51:09 2001 @@ -3,8 +3,6 @@ struct scatterlist { char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ unsigned int length; unsigned long dvma_address; }; --- ./include/asm-mips/pci.h.~1~ Tue Jul 3 18:14:13 2001 +++ ./include/asm-mips/pci.h Wed Aug 15 03:06:03 2001 @@ -206,7 +206,7 @@ * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +extern inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) { /* * we fall back to GFP_DMA when the mask isn't all 1s, --- ./include/asm-mips/scatterlist.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-mips/scatterlist.h Thu Aug 16 04:51:17 2001 @@ -3,8 +3,6 @@ struct scatterlist { char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ unsigned int length; __u32 dvma_address; --- ./include/asm-ppc/pci.h.~1~ Wed May 23 17:57:21 2001 +++ ./include/asm-ppc/pci.h Wed Aug 15 03:06:10 2001 @@ -108,7 +108,7 @@ * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +extern inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) { return 1; } --- ./include/asm-ppc/scatterlist.h.~1~ Wed May 23 17:57:21 2001 +++ ./include/asm-ppc/scatterlist.h Thu Aug 16 04:51:23 2001 @@ -9,8 +9,6 @@ struct scatterlist { char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ unsigned int length; }; --- ./include/asm-sparc/pci.h.~1~ Sat May 12 03:47:41 2001 +++ ./include/asm-sparc/pci.h Wed Aug 15 03:06:17 2001 @@ -108,7 +108,7 @@ * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +extern inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) { return 1; } --- ./include/asm-sparc/scatterlist.h.~1~ Thu Dec 14 14:52:04 2000 +++ ./include/asm-sparc/scatterlist.h Thu Aug 16 04:51:30 2001 @@ -6,8 +6,6 @@ struct scatterlist { char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ unsigned int length; __u32 dvma_address; /* A place to hang host-specific addresses at. */ --- ./include/asm-sparc64/types.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-sparc64/types.h Wed Aug 15 02:13:44 2001 @@ -45,9 +45,10 @@ #define BITS_PER_LONG 64 -/* Dma addresses are 32-bits wide for now. */ +/* Dma addresses come in 32-bit and 64-bit flavours. */ typedef u32 dma_addr_t; +typedef u64 dma64_addr_t; #endif /* __KERNEL__ */ --- ./include/asm-sparc64/pci.h.~1~ Tue Aug 14 21:31:07 2001 +++ ./include/asm-sparc64/pci.h Wed Aug 15 06:43:53 2001 @@ -28,6 +28,15 @@ /* Dynamic DMA mapping stuff. */ +/* PCI 64-bit addressing works for all slots on all controller + * types on sparc64. However, it requires that the device + * can drive enough of the 64 bits. + */ +#define PCI64_ADDR_BASE 0x3fff000000000000 +#define PCI64_REQUIRED_MASK (~(dma64_addr_t)0) +#define pci_dac_cycles_ok(pci_dev) \ + (((pci_dev)->dma_mask & PCI64_REQUIRED_MASK) == PCI64_REQUIRED_MASK) + #include <asm/scatterlist.h> struct pci_dev; @@ -64,6 +73,20 @@ */ extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction); +/* No highmem on sparc64, plus we have an IOMMU, so mapping pages is easy. */ +#define pci_map_page(dev, page, off, size, dir) \ + pci_map_single(dev, (page_address(page) + (off)), size, dir) +#define pci_unmap_page(dev,addr,sz,dir) pci_unmap_single(dev,addr,sz,dir) + +/* The 64-bit cases might have to do something interesting if + * PCI_DMA_FLAG_HUGE_MAPS is set in hwdev->dma_flags. + */ +extern dma64_addr_t pci64_map_page(struct pci_dev *hwdev, + struct page *page, unsigned long offset, + size_t size, int direction); +extern void pci64_unmap_page(struct pci_dev *hwdev, dma64_addr_t dma_addr, + size_t size, int direction); + /* Map a set of buffers described by scatterlist in streaming * mode for DMA. This is the scather-gather version of the * above pci_map_single interface. Here the scatter gather list @@ -79,13 +102,19 @@ * Device ownership issues as mentioned above for pci_map_single are * the same here. */ -extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction); +extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction); +extern int pci64_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction); /* Unmap a set of streaming mode DMA translations. * Again, cpu read rules concerning calls here are the same as for * pci_unmap_single() above. */ -extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents, int direction); +extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nhwents, int direction); +extern void pci64_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nhwents, int direction); /* Make physical memory consistent for a single * streaming mode DMA translation after a transfer. @@ -96,7 +125,10 @@ * next point you give the PCI dma address back to the card, the * device again owns the buffer. */ -extern void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction); +extern void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, + size_t size, int direction); +extern void pci64_dma_sync_single(struct pci_dev *hwdev, dma64_addr_t dma_handle, + size_t size, int direction); /* Make physical memory consistent for a set of streaming * mode DMA translations after a transfer. @@ -105,13 +137,14 @@ * same rules and usage. */ extern void pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction); +extern void pci64_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction); /* Return whether the given PCI device DMA address mask can * be supported properly. For example, if your device can * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -extern int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask); +extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask); /* Return the index of the PCI controller for device PDEV. */ --- ./include/asm-sparc64/scatterlist.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-sparc64/scatterlist.h Thu Aug 16 04:51:36 2001 @@ -5,17 +5,24 @@ #include <asm/page.h> struct scatterlist { - char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ - unsigned int length; + /* This will disappear in 2.5.x */ + char *address; - __u32 dvma_address; /* A place to hang host-specific addresses at. */ - __u32 dvma_length; + /* These two are only valid if ADDRESS member of this + * struct is NULL. + */ + struct page *page; + unsigned int offset; + + unsigned int length; + + dma64_addr_t dma_address; + __u32 dma_length; }; -#define sg_dma_address(sg) ((sg)->dvma_address) -#define sg_dma_len(sg) ((sg)->dvma_length) +#define sg_dma_address(sg) ((dma_addr_t) ((sg)->dma_address)) +#define sg_dma64_address(sg) ((sg)->dma_address) +#define sg_dma_len(sg) ((sg)->dma_length) #define ISA_DMA_THRESHOLD (~0UL) --- ./include/linux/pci.h.~1~ Tue Aug 14 21:31:11 2001 +++ ./include/linux/pci.h Wed Aug 15 06:43:53 2001 @@ -314,6 +314,12 @@ #define PCI_DMA_FROMDEVICE 2 #define PCI_DMA_NONE 3 +/* These are the boolean attributes stored in pci_dev->dma_flags. */ +#define PCI_DMA_FLAG_HUGE_MAPS 0x00000001 /* Device may hold an enormous number + * of mappings at once? + */ +#define PCI_DMA_FLAG_ARCHMASK 0xf0000000 /* Reserved for arch-specific flags */ + #define DEVICE_COUNT_COMPATIBLE 4 #define DEVICE_COUNT_IRQ 2 #define DEVICE_COUNT_DMA 2 @@ -353,11 +359,12 @@ struct pci_driver *driver; /* which driver has allocated this device */ void *driver_data; /* data private to the driver */ - dma_addr_t dma_mask; /* Mask of the bits of bus address this + u64 dma_mask; /* Mask of the bits of bus address this device implements. Normally this is 0xffffffff. You only need to change this if your device has broken DMA or supports 64-bit transfers. */ + unsigned int dma_flags; /* See PCI_DMA_FLAG_* above */ u32 current_state; /* Current operating state. In ACPI-speak, this is D0-D3, D0 being fully functional, @@ -559,7 +566,8 @@ int pci_enable_device(struct pci_dev *dev); void pci_disable_device(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev); -int pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask); +int pci_set_dma_mask(struct pci_dev *dev, u64 mask); +void pci_change_dma_flag(struct pci_dev *dev, unsigned int on, unsigned int off); int pci_assign_resource(struct pci_dev *dev, int i); /* Power management related routines */ @@ -641,7 +649,8 @@ static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } static inline void pci_disable_device(struct pci_dev *dev) { } static inline int pci_module_init(struct pci_driver *drv) { return -ENODEV; } -static inline int pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) { return -EIO; } +static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } +static inline void pci_change_dma_flag(struct pci_dev *dev, unsigned int on, unsigned int off) { } static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;} static inline int pci_register_driver(struct pci_driver *drv) { return 0;} static inline void pci_unregister_driver(struct pci_driver *drv) { } --- ./include/asm-sh/pci.h.~1~ Fri Jun 29 14:26:55 2001 +++ ./include/asm-sh/pci.h Wed Aug 15 03:06:33 2001 @@ -167,7 +167,7 @@ * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +extern inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) { return 1; } --- ./include/asm-sh/scatterlist.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-sh/scatterlist.h Thu Aug 16 04:51:43 2001 @@ -3,8 +3,6 @@ struct scatterlist { char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ unsigned int length; }; --- ./include/asm-s390/scatterlist.h.~1~ Fri Feb 16 21:04:19 2001 +++ ./include/asm-s390/scatterlist.h Thu Aug 16 04:51:50 2001 @@ -3,8 +3,6 @@ struct scatterlist { char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ unsigned int length; }; --- ./include/asm-ia64/pci.h.~1~ Sat May 12 03:47:41 2001 +++ ./include/asm-ia64/pci.h Wed Aug 15 03:06:42 2001 @@ -52,7 +52,7 @@ * you would pass 0x00ffffff as the mask to this function. */ static inline int -pci_dma_supported (struct pci_dev *hwdev, dma_addr_t mask) +pci_dma_supported (struct pci_dev *hwdev, u64 mask) { return 1; } --- ./include/asm-ia64/scatterlist.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-ia64/scatterlist.h Thu Aug 16 04:52:17 2001 @@ -8,11 +8,6 @@ struct scatterlist { char *address; /* location data is to be transferred to */ - /* - * Location of actual buffer if ADDRESS points to a DMA - * indirection buffer, NULL otherwise: - */ - char *alt_address; char *orig_address; /* Save away the original buffer address (used by pci-dma.c) */ unsigned int length; /* buffer length */ }; --- ./include/asm-mips64/pci.h.~1~ Thu Jul 5 16:52:48 2001 +++ ./include/asm-mips64/pci.h Wed Aug 15 03:06:49 2001 @@ -195,7 +195,7 @@ #endif } -extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +extern inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) { /* * we fall back to GFP_DMA when the mask isn't all 1s, --- ./include/asm-mips64/scatterlist.h.~1~ Tue Nov 28 08:33:08 2000 +++ ./include/asm-mips64/scatterlist.h Thu Aug 16 04:52:23 2001 @@ -3,8 +3,6 @@ struct scatterlist { char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ unsigned int length; __u32 dvma_address; --- ./include/asm-parisc/pci.h.~1~ Sat May 12 03:47:41 2001 +++ ./include/asm-parisc/pci.h Wed Aug 15 03:07:07 2001 @@ -113,7 +113,7 @@ ** See Documentation/DMA-mapping.txt */ struct pci_dma_ops { - int (*dma_supported)(struct pci_dev *dev, dma_addr_t mask); + int (*dma_supported)(struct pci_dev *dev, u64 mask); void *(*alloc_consistent)(struct pci_dev *dev, size_t size, dma_addr_t *iova); void (*free_consistent)(struct pci_dev *dev, size_t size, void *vaddr, dma_addr_t iova); dma_addr_t (*map_single)(struct pci_dev *dev, void *addr, size_t size, int direction); --- ./include/asm-parisc/scatterlist.h.~1~ Wed Dec 6 05:30:34 2000 +++ ./include/asm-parisc/scatterlist.h Thu Aug 16 04:52:28 2001 @@ -3,8 +3,6 @@ struct scatterlist { char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ unsigned int length; /* an IOVA can be 64-bits on some PA-Risc platforms. */ --- ./include/asm-s390x/scatterlist.h.~1~ Fri Feb 16 21:04:20 2001 +++ ./include/asm-s390x/scatterlist.h Thu Aug 16 04:52:35 2001 @@ -3,8 +3,6 @@ struct scatterlist { char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ unsigned int length; }; --- ./net/ipv6/mcast.c.~1~ Wed Apr 25 13:46:34 2001 +++ ./net/ipv6/mcast.c Wed Aug 15 00:36:31 2001 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque <roque@di.fc.ul.pt> * - * $Id: mcast.c,v 1.37 2001/04/25 20:46:34 davem Exp $ + * $Id: mcast.c,v 1.38 2001/08/15 07:36:31 davem Exp $ * * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c * @@ -90,7 +90,6 @@ mc_lst->next = NULL; memcpy(&mc_lst->addr, addr, sizeof(struct in6_addr)); - mc_lst->ifindex = ifindex; if (ifindex == 0) { struct rt6_info *rt; @@ -107,6 +106,8 @@ sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); return -ENODEV; } + + mc_lst->ifindex = dev->ifindex; /* * now add/increase the group membership on the device - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |