kill alt_address (Re: [patch] zero-bounce highmem I/O)

From: David S. Miller (davem@redhat.com)
Date: Thu Aug 16 2001 - 07:28:47 EST


   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/



This archive was generated by hypermail 2b29 : Thu Aug 23 2001 - 21:00:15 EST