Commit 181bbf73 authored by Martyn Welch's avatar Martyn Welch Committed by Jiri Slaby

VME: Stop using memcpy_[to|from]io() due to unwanted behaviour

commit a2a720e1 upstream.

The ca91cx42 and tsi148 VME bridges use the width of reads and writes on the
PCI bus in part to control the width of the cycles on the VME bus. It is
important that we can control the width of cycles on the VME bus as some VME
hardware requires cycles of a specific width. The memcpy_toio() and
memcpy_fromio() functions do not provide sufficient control, so instead loop
using ioread functions.
Reported-by: default avatarMichael Kenney <mfkenney@gmail.com>
Signed-off-by: default avatarMartyn Welch <martyn.welch@ge.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
parent ff286b46
...@@ -869,14 +869,13 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image, ...@@ -869,14 +869,13 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image,
spin_lock(&image->lock); spin_lock(&image->lock);
/* The following code handles VME address alignment problem /* The following code handles VME address alignment. We cannot use
* in order to assure the maximal data width cycle. * memcpy_xxx here because it may cut data transfers in to 8-bit
* We cannot use memcpy_xxx directly here because it * cycles when D16 or D32 cycles are required on the VME bus.
* may cut data transfer in 8-bits cycles, thus making * On the other hand, the bridge itself assures that the maximum data
* D16 cycle impossible. * cycle configured for the transfer is used and splits it
* From the other hand, the bridge itself assures that * automatically for non-aligned addresses, so we don't want the
* maximal configured data cycle is used and splits it * overhead of needlessly forcing small transfers for the entire cycle.
* automatically for non-aligned addresses.
*/ */
if ((uintptr_t)addr & 0x1) { if ((uintptr_t)addr & 0x1) {
*(u8 *)buf = ioread8(addr); *(u8 *)buf = ioread8(addr);
...@@ -896,9 +895,9 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image, ...@@ -896,9 +895,9 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image,
} }
count32 = (count - done) & ~0x3; count32 = (count - done) & ~0x3;
if (count32 > 0) { while (done < count32) {
memcpy_fromio(buf + done, addr + done, (unsigned int)count); *(u32 *)(buf + done) = ioread32(addr + done);
done += count32; done += 4;
} }
if ((count - done) & 0x2) { if ((count - done) & 0x2) {
...@@ -930,7 +929,7 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image, ...@@ -930,7 +929,7 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image,
spin_lock(&image->lock); spin_lock(&image->lock);
/* Here we apply for the same strategy we do in master_read /* Here we apply for the same strategy we do in master_read
* function in order to assure D16 cycle when required. * function in order to assure the correct cycles.
*/ */
if ((uintptr_t)addr & 0x1) { if ((uintptr_t)addr & 0x1) {
iowrite8(*(u8 *)buf, addr); iowrite8(*(u8 *)buf, addr);
...@@ -950,9 +949,9 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image, ...@@ -950,9 +949,9 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image,
} }
count32 = (count - done) & ~0x3; count32 = (count - done) & ~0x3;
if (count32 > 0) { while (done < count32) {
memcpy_toio(addr + done, buf + done, count32); iowrite32(*(u32 *)(buf + done), addr + done);
done += count32; done += 4;
} }
if ((count - done) & 0x2) { if ((count - done) & 0x2) {
......
...@@ -1282,8 +1282,8 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, ...@@ -1282,8 +1282,8 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
spin_lock(&image->lock); spin_lock(&image->lock);
/* The following code handles VME address alignment. We cannot use /* The following code handles VME address alignment. We cannot use
* memcpy_xxx directly here because it may cut small data transfers in * memcpy_xxx here because it may cut data transfers in to 8-bit
* to 8-bit cycles, thus making D16 cycle impossible. * cycles when D16 or D32 cycles are required on the VME bus.
* On the other hand, the bridge itself assures that the maximum data * On the other hand, the bridge itself assures that the maximum data
* cycle configured for the transfer is used and splits it * cycle configured for the transfer is used and splits it
* automatically for non-aligned addresses, so we don't want the * automatically for non-aligned addresses, so we don't want the
...@@ -1307,9 +1307,9 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, ...@@ -1307,9 +1307,9 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
} }
count32 = (count - done) & ~0x3; count32 = (count - done) & ~0x3;
if (count32 > 0) { while (done < count32) {
memcpy_fromio(buf + done, addr + done, count32); *(u32 *)(buf + done) = ioread32(addr + done);
done += count32; done += 4;
} }
if ((count - done) & 0x2) { if ((count - done) & 0x2) {
...@@ -1369,7 +1369,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, ...@@ -1369,7 +1369,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
spin_lock(&image->lock); spin_lock(&image->lock);
/* Here we apply for the same strategy we do in master_read /* Here we apply for the same strategy we do in master_read
* function in order to assure D16 cycle when required. * function in order to assure the correct cycles.
*/ */
if ((uintptr_t)addr & 0x1) { if ((uintptr_t)addr & 0x1) {
iowrite8(*(u8 *)buf, addr); iowrite8(*(u8 *)buf, addr);
...@@ -1389,9 +1389,9 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, ...@@ -1389,9 +1389,9 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
} }
count32 = (count - done) & ~0x3; count32 = (count - done) & ~0x3;
if (count32 > 0) { while (done < count32) {
memcpy_toio(addr + done, buf + done, count32); iowrite32(*(u32 *)(buf + done), addr + done);
done += count32; done += 4;
} }
if ((count - done) & 0x2) { if ((count - done) & 0x2) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment