vme: stop DMA transfer on interruption
authorDmitry Kalinkin <dmitry.kalinkin@gmail.com>
Thu, 28 May 2015 12:07:01 +0000 (15:07 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 13 Jun 2015 00:26:57 +0000 (17:26 -0700)
Signed-off-by: Dmitry Kalinkin <dmitry.kalinkin@gmail.com>
Cc: Igor Alekseev <igor.alekseev@itep.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/vme/bridges/vme_ca91cx42.c
drivers/vme/bridges/vme_tsi148.c

index 18078ec..e9bd657 100644 (file)
@@ -1192,7 +1192,7 @@ static int ca91cx42_dma_list_exec(struct vme_dma_list *list)
 {
        struct vme_dma_resource *ctrlr;
        struct ca91cx42_dma_entry *entry;
-       int retval = 0;
+       int retval;
        dma_addr_t bus_addr;
        u32 val;
        struct device *dev;
@@ -1245,8 +1245,18 @@ static int ca91cx42_dma_list_exec(struct vme_dma_list *list)
 
        iowrite32(val, bridge->base + DGCS);
 
-       wait_event_interruptible(bridge->dma_queue,
-               ca91cx42_dma_busy(ctrlr->parent));
+       retval = wait_event_interruptible(bridge->dma_queue,
+                                         ca91cx42_dma_busy(ctrlr->parent));
+
+       if (retval) {
+               val = ioread32(bridge->base + DGCS);
+               iowrite32(val | CA91CX42_DGCS_STOP_REQ, bridge->base + DGCS);
+               /* Wait for the operation to abort */
+               wait_event(bridge->dma_queue,
+                          ca91cx42_dma_busy(ctrlr->parent));
+               retval = -EINTR;
+               goto exit;
+       }
 
        /*
         * Read status register, this register is valid until we kick off a
@@ -1261,6 +1271,7 @@ static int ca91cx42_dma_list_exec(struct vme_dma_list *list)
                val = ioread32(bridge->base + DCTL);
        }
 
+exit:
        /* Remove list from running list */
        mutex_lock(&ctrlr->mtx);
        list_del(&list->list);
index 6562348..fb1e7ad 100644 (file)
@@ -1892,7 +1892,7 @@ static int tsi148_dma_busy(struct vme_bridge *tsi148_bridge, int channel)
 static int tsi148_dma_list_exec(struct vme_dma_list *list)
 {
        struct vme_dma_resource *ctrlr;
-       int channel, retval = 0;
+       int channel, retval;
        struct tsi148_dma_entry *entry;
        u32 bus_addr_high, bus_addr_low;
        u32 val, dctlreg = 0;
@@ -1942,9 +1942,19 @@ static int tsi148_dma_list_exec(struct vme_dma_list *list)
        iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, bridge->base +
                TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
 
-       wait_event_interruptible(bridge->dma_queue[channel],
+       retval = wait_event_interruptible(bridge->dma_queue[channel],
                tsi148_dma_busy(ctrlr->parent, channel));
 
+       if (retval) {
+               iowrite32be(dctlreg | TSI148_LCSR_DCTL_ABT, bridge->base +
+                       TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
+               /* Wait for the operation to abort */
+               wait_event(bridge->dma_queue[channel],
+                          tsi148_dma_busy(ctrlr->parent, channel));
+               retval = -EINTR;
+               goto exit;
+       }
+
        /*
         * Read status register, this register is valid until we kick off a
         * new transfer.
@@ -1957,6 +1967,7 @@ static int tsi148_dma_list_exec(struct vme_dma_list *list)
                retval = -EIO;
        }
 
+exit:
        /* Remove list from running list */
        mutex_lock(&ctrlr->mtx);
        list_del(&list->list);