Staging: VME: Convert TSI148 to use dma_map_single
authorMartyn Welch <martyn.welch@ge.com>
Thu, 22 Mar 2012 13:27:29 +0000 (13:27 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Apr 2012 17:37:06 +0000 (10:37 -0700)
The DMA functionality fails to work on some Intel based platforms. Some
recent Intel platforms have an IOMMU. Transferring the DMA descriptors,
which were mapped using virt_to_phys(), failed. This patch updates the
driver to use dma_map_single().

Signed-off-by: Martyn Welch <martyn.welch@ge.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/vme/bridges/vme_tsi148.c
drivers/staging/vme/bridges/vme_tsi148.h

index f50582169b244caf21d0b9aede30b125b951b142..cd3c821eb0a60efbf78f2782a56b80e623828c09 100644 (file)
@@ -1614,7 +1614,6 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
        struct vme_dma_pattern *pattern_attr;
        struct vme_dma_pci *pci_attr;
        struct vme_dma_vme *vme_attr;
-       dma_addr_t desc_ptr;
        int retval = 0;
        struct vme_bridge *tsi148_bridge;
 
@@ -1739,9 +1738,12 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
                prev = list_entry(entry->list.prev, struct tsi148_dma_entry,
                        list);
                /* We need the bus address for the pointer */
-               desc_ptr = virt_to_bus(&entry->descriptor);
-               reg_split(desc_ptr, &prev->descriptor.dnlau,
-                       &prev->descriptor.dnlal);
+               entry->dma_handle = dma_map_single(tsi148_bridge->parent,
+                       &entry->descriptor,
+                       sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE);
+
+               reg_split((unsigned long long)entry->dma_handle,
+                       &prev->descriptor.dnlau, &prev->descriptor.dnlal);
        }
 
        return 0;
@@ -1784,7 +1786,6 @@ static int tsi148_dma_list_exec(struct vme_dma_list *list)
        struct vme_dma_resource *ctrlr;
        int channel, retval = 0;
        struct tsi148_dma_entry *entry;
-       dma_addr_t bus_addr;
        u32 bus_addr_high, bus_addr_low;
        u32 val, dctlreg = 0;
        struct vme_bridge *tsi148_bridge;
@@ -1817,11 +1818,13 @@ static int tsi148_dma_list_exec(struct vme_dma_list *list)
        entry = list_first_entry(&list->entries, struct tsi148_dma_entry,
                list);
 
-       bus_addr = virt_to_bus(&entry->descriptor);
+       entry->dma_handle = dma_map_single(tsi148_bridge->parent,
+               &entry->descriptor,
+               sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE);
 
        mutex_unlock(&ctrlr->mtx);
 
-       reg_split(bus_addr, &bus_addr_high, &bus_addr_low);
+       reg_split(entry->dma_handle, &bus_addr_high, &bus_addr_low);
 
        iowrite32be(bus_addr_high, bridge->base +
                TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU);
@@ -1864,10 +1867,15 @@ static int tsi148_dma_list_empty(struct vme_dma_list *list)
        struct list_head *pos, *temp;
        struct tsi148_dma_entry *entry;
 
+       struct vme_bridge *tsi148_bridge = list->parent->parent;
+
        /* detach and free each entry */
        list_for_each_safe(pos, temp, &list->entries) {
                list_del(pos);
                entry = list_entry(pos, struct tsi148_dma_entry, list);
+
+               dma_unmap_single(tsi148_bridge->parent, entry->dma_handle,
+                       sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE);
                kfree(entry);
        }
 
index a3ac2fe988168d6d0e21ebf0f6992c57c6dcb34f..00b116087d73556d4dce0f0d68ef9e591920ad0e 100644 (file)
@@ -75,6 +75,7 @@ struct tsi148_dma_entry {
         */
        struct tsi148_dma_descriptor descriptor;
        struct list_head list;
+       dma_addr_t dma_handle;
 };
 
 /*