diff options
Diffstat (limited to 'drivers/vme')
-rw-r--r-- | drivers/vme/bridges/Kconfig | 2 | ||||
-rw-r--r-- | drivers/vme/bridges/vme_ca91cx42.c | 18 | ||||
-rw-r--r-- | drivers/vme/bridges/vme_ca91cx42.h | 2 | ||||
-rw-r--r-- | drivers/vme/bridges/vme_tsi148.c | 42 | ||||
-rw-r--r-- | drivers/vme/vme.c | 11 |
5 files changed, 49 insertions, 26 deletions
diff --git a/drivers/vme/bridges/Kconfig b/drivers/vme/bridges/Kconfig index 9331064e0..f6d854584 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 18078ecbf..f692efcf6 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 d46b12dc3..d54119e59 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 895c2a319..fb1e7ad27 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 6bab2c4ed..56708915e 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 |