summaryrefslogtreecommitdiff
path: root/drivers/vme
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vme')
-rw-r--r--drivers/vme/bridges/Kconfig2
-rw-r--r--drivers/vme/bridges/vme_ca91cx42.c18
-rw-r--r--drivers/vme/bridges/vme_ca91cx42.h2
-rw-r--r--drivers/vme/bridges/vme_tsi148.c42
-rw-r--r--drivers/vme/vme.c11
5 files changed, 49 insertions, 26 deletions
diff --git a/drivers/vme/bridges/Kconfig b/drivers/vme/bridges/Kconfig
index 9331064e0476..f6d854584906 100644
--- a/drivers/vme/bridges/Kconfig
+++ b/drivers/vme/bridges/Kconfig
@@ -9,7 +9,7 @@ config VME_CA91CX42
config VME_TSI148
tristate "Tempe"
- depends on VIRT_TO_BUS
+ depends on HAS_DMA
help
If you say Y here you get support for the Tundra TSI148 VME bridge
chip.
diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c
index 18078ecbfcc6..f692efcf683f 100644
--- a/drivers/vme/bridges/vme_ca91cx42.c
+++ b/drivers/vme/bridges/vme_ca91cx42.c
@@ -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
@@ -1259,8 +1269,10 @@ static int ca91cx42_dma_list_exec(struct vme_dma_list *list)
dev_err(dev, "ca91c042: DMA Error. DGCS=%08X\n", val);
val = ioread32(bridge->base + DCTL);
+ retval = -EIO;
}
+exit:
/* Remove list from running list */
mutex_lock(&ctrlr->mtx);
list_del(&list->list);
diff --git a/drivers/vme/bridges/vme_ca91cx42.h b/drivers/vme/bridges/vme_ca91cx42.h
index d46b12dc3b82..d54119e59d55 100644
--- a/drivers/vme/bridges/vme_ca91cx42.h
+++ b/drivers/vme/bridges/vme_ca91cx42.h
@@ -547,7 +547,7 @@ static const int CA91CX42_LINT_LM[] = { CA91CX42_LINT_LM0, CA91CX42_LINT_LM1,
#define CA91CX42_LM_CTL_DATA (1<<22)
#define CA91CX42_LM_CTL_SUPR (1<<21)
#define CA91CX42_LM_CTL_NPRIV (1<<20)
-#define CA91CX42_LM_CTL_AS_M (5<<16)
+#define CA91CX42_LM_CTL_AS_M (7<<16)
#define CA91CX42_LM_CTL_AS_A16 0
#define CA91CX42_LM_CTL_AS_A24 (1<<16)
#define CA91CX42_LM_CTL_AS_A32 (1<<17)
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c
index 895c2a31918d..fb1e7ad272ec 100644
--- a/drivers/vme/bridges/vme_tsi148.c
+++ b/drivers/vme/bridges/vme_tsi148.c
@@ -1833,24 +1833,29 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
/* Add to list */
list_add_tail(&entry->list, &list->entries);
+ entry->dma_handle = dma_map_single(tsi148_bridge->parent,
+ &entry->descriptor,
+ sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE);
+ if (dma_mapping_error(tsi148_bridge->parent, entry->dma_handle)) {
+ dev_err(tsi148_bridge->parent, "DMA mapping error\n");
+ retval = -EINVAL;
+ goto err_dma;
+ }
+
/* Fill out previous descriptors "Next Address" */
if (entry->list.prev != &list->entries) {
- prev = list_entry(entry->list.prev, struct tsi148_dma_entry,
- list);
- /* We need the bus address for the pointer */
- 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, &address_high,
&address_low);
- entry->descriptor.dnlau = cpu_to_be32(address_high);
- entry->descriptor.dnlal = cpu_to_be32(address_low);
+ prev = list_entry(entry->list.prev, struct tsi148_dma_entry,
+ list);
+ prev->descriptor.dnlau = cpu_to_be32(address_high);
+ prev->descriptor.dnlal = cpu_to_be32(address_low);
}
return 0;
+err_dma:
err_dest:
err_source:
err_align:
@@ -1887,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;
@@ -1921,10 +1926,6 @@ static int tsi148_dma_list_exec(struct vme_dma_list *list)
entry = list_first_entry(&list->entries, struct tsi148_dma_entry,
list);
- 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(entry->dma_handle, &bus_addr_high, &bus_addr_low);
@@ -1941,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.
@@ -1956,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);
diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c
index 6bab2c4ed77c..56708915ebbe 100644
--- a/drivers/vme/vme.c
+++ b/drivers/vme/vme.c
@@ -177,8 +177,8 @@ size_t vme_get_size(struct vme_resource *resource)
}
EXPORT_SYMBOL(vme_get_size);
-static int vme_check_window(u32 aspace, unsigned long long vme_base,
- unsigned long long size)
+int vme_check_window(u32 aspace, unsigned long long vme_base,
+ unsigned long long size)
{
int retval = 0;
@@ -199,10 +199,8 @@ static int vme_check_window(u32 aspace, unsigned long long vme_base,
retval = -EFAULT;
break;
case VME_A64:
- /*
- * Any value held in an unsigned long long can be used as the
- * base
- */
+ if ((size != 0) && (vme_base > U64_MAX + 1 - size))
+ retval = -EFAULT;
break;
case VME_CRCSR:
if (((vme_base + size) > VME_CRCSR_MAX) ||
@@ -223,6 +221,7 @@ static int vme_check_window(u32 aspace, unsigned long long vme_base,
return retval;
}
+EXPORT_SYMBOL(vme_check_window);
/*
* Request a slave image with specific attributes, return some unique