From: Pat Gefre <pfg@sgi.com>

pci dma cleanup



---

 25-akpm/arch/ia64/sn/io/machvec/pci_dma.c |   77 ++++++++++++------------------
 1 files changed, 33 insertions(+), 44 deletions(-)

diff -puN arch/ia64/sn/io/machvec/pci_dma.c~sn56 arch/ia64/sn/io/machvec/pci_dma.c
--- 25/arch/ia64/sn/io/machvec/pci_dma.c~sn56	Thu Jan  8 15:25:24 2004
+++ 25-akpm/arch/ia64/sn/io/machvec/pci_dma.c	Thu Jan  8 15:25:24 2004
@@ -124,11 +124,6 @@ sn_pci_alloc_consistent(struct pci_dev *
 	unsigned long phys_addr;
 	pcibr_dmamap_t dma_map = 0;
 
-	*dma_handle = 0;
-
-	if (hwdev->dma_mask < 0xffffffffUL)
-		return NULL;
-
 	/*
 	 * Get hwgraph vertex for the device
 	 */
@@ -136,51 +131,48 @@ sn_pci_alloc_consistent(struct pci_dev *
 	vhdl = device_sysdata->vhdl;
 
 	/*
-	 * Allocate the memory.  FIXME: if we're allocating for
-	 * two devices on the same bus, we should at least try to
-	 * allocate memory in the same 2 GB window to avoid using
-	 * ATEs for the translation.  See the comment above about the
-	 * 32 bit requirement for this function.
+	 * Allocate the memory.
+	 * FIXME: We should be doing alloc_pages_node for the node closest
+	 *        to the PCI device.
 	 */
-	if(!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size))))
+	if (!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size))))
 		return NULL;
 
 	/* physical addr. of the memory we just got */
 	phys_addr = __pa(cpuaddr);
 
 	/*
-	 * This will try to use a Direct Map register to do the
-	 * 32 bit DMA mapping, but it may not succeed if another
-	 * device on the same bus is already mapped with different
-	 * attributes or to a different memory region.
-	 */
-	*dma_handle = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size,
-							PCIIO_DMA_CMD);
-
-        /*
-	 * If this device is in PCI-X mode, the system would have
-	 * automatically allocated a 64Bits DMA Address.  Error out if the 
-	 * device cannot support DAC.
-	 */
-	if (*dma_handle > hwdev->consistent_dma_mask) {
-		free_pages((unsigned long) cpuaddr, get_order(size));
-		return NULL;
+	 * 64 bit address translations should never fail.
+	 * 32 bit translations can fail if there are insufficient mapping
+	 *   resources and the direct map is already wired to a different
+	 *   2GB range.
+	 * 32 bit translations can also return a > 32 bit address, because
+	 *   pcibr_dmatrans_addr ignores a missing PCIIO_DMA_A64 flag on
+	 *   PCI-X buses.
+	 */
+	if (hwdev->consistent_dma_mask == ~0UL)
+		*dma_handle = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size,
+					  PCIIO_DMA_CMD | PCIIO_DMA_A64);
+	else {
+		dma_map = pcibr_dmamap_alloc(vhdl, NULL, size, PCIIO_DMA_CMD);
+		if (dma_map) {
+			*dma_handle = (dma_addr_t)
+				pcibr_dmamap_addr(dma_map, phys_addr, size);
+			dma_map->bd_dma_addr = *dma_handle;
+		}
+		else {
+			*dma_handle = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size,
+						  PCIIO_DMA_CMD);
+		}
 	}
 
-	/*
-	 * It is a 32 bit card and we cannot do direct mapping,
-	 * so we try to use an ATE.
-	 */
-	if (!(*dma_handle)) {
-		dma_map = pcibr_dmamap_alloc(vhdl, NULL, size, PCIIO_DMA_CMD);
-		if (!dma_map) {
-			printk(KERN_ERR "sn_pci_alloc_consistent: Unable to "
-			       "allocate anymore 32 bit page map entries.\n");
-			return 0;
+	if (!*dma_handle || *dma_handle > hwdev->consistent_dma_mask) {
+		if (dma_map) {
+			pcibr_dmamap_done(dma_map);
+			pcibr_dmamap_free(dma_map);
 		}
-		*dma_handle = (dma_addr_t) pcibr_dmamap_addr(dma_map,phys_addr,
-							     size);
-		dma_map->bd_dma_addr = *dma_handle;
+		free_pages((unsigned long) cpuaddr, get_order(size));
+		return NULL;
 	}
 
         return cpuaddr;
@@ -213,7 +205,6 @@ sn_pci_free_consistent(struct pci_dev *h
 	if (dma_map) {
 		pcibr_dmamap_done(dma_map);
 		pcibr_dmamap_free(dma_map);
-		dma_map->bd_dma_addr = 0;
 	}
 	free_pages((unsigned long) vaddr, get_order(size));
 }
@@ -338,7 +329,6 @@ sn_pci_unmap_sg(struct pci_dev *hwdev, s
         		if (dma_map) {
                 		pcibr_dmamap_done(dma_map);
                 		pcibr_dmamap_free(dma_map);
-                		dma_map->bd_dma_addr = 0;
 			}
         	}
 
@@ -359,7 +349,7 @@ sn_pci_unmap_sg(struct pci_dev *hwdev, s
  * the IA64 machvec code.
  *
  * We map this to the one step pcibr_dmamap_trans interface rather than
- * the two step pciio_dmamap_alloc/pciio_dmamap_addr because we have
+ * the two step pcibr_dmamap_alloc/pcibr_dmamap_addr because we have
  * no way of saving the dmamap handle from the alloc to later free
  * (which is pretty much unacceptable).
  *
@@ -464,7 +454,6 @@ sn_pci_unmap_single(struct pci_dev *hwde
 	if (dma_map) {
 		pcibr_dmamap_done(dma_map);
 		pcibr_dmamap_free(dma_map);
-		dma_map->bd_dma_addr = 0;
 	}
 }
 

_