From a2a720e15f59be60c7ae1c58b5b4ac1003dd5078 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Thu, 6 Feb 2014 13:35:36 +0000 Subject: VME: Stop using memcpy_[to|from]io() due to unwanted behaviour 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: Michael Kenney Signed-off-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/vme/bridges/vme_tsi148.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/vme/bridges/vme_tsi148.c') diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 16830d8b777..21ac513486f 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -1276,8 +1276,8 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, spin_lock(&image->lock); /* The following code handles VME address alignment. We cannot use - * memcpy_xxx directly here because it may cut small data transfers in - * to 8-bit cycles, thus making D16 cycle impossible. + * memcpy_xxx here because it may cut data transfers in to 8-bit + * cycles when D16 or D32 cycles are required on the VME bus. * On the other hand, the bridge itself assures that the maximum data * cycle configured for the transfer is used and splits it * automatically for non-aligned addresses, so we don't want the @@ -1301,9 +1301,9 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, } count32 = (count - done) & ~0x3; - if (count32 > 0) { - memcpy_fromio(buf + done, addr + done, count32); - done += count32; + while (done < count32) { + *(u32 *)(buf + done) = ioread32(addr + done); + done += 4; } if ((count - done) & 0x2) { @@ -1363,7 +1363,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, spin_lock(&image->lock); /* 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) { iowrite8(*(u8 *)buf, addr); @@ -1383,9 +1383,9 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, } count32 = (count - done) & ~0x3; - if (count32 > 0) { - memcpy_toio(addr + done, buf + done, count32); - done += count32; + while (done < count32) { + iowrite32(*(u32 *)(buf + done), addr + done); + done += 4; } if ((count - done) & 0x2) { -- cgit v1.2.3-70-g09d2 From 098ced8fefe4a4e4240fa47b1ed9b00d65b6cd21 Mon Sep 17 00:00:00 2001 From: Joe Schultz Date: Thu, 3 Apr 2014 14:47:55 -0500 Subject: vme_tsi148: Fix typo in tsi148_slave_get() This patch corrects a typo where "vme_base" was used instead of "*vme_base". The typo resulted in an incorrect value being returned to userspace (via vme_user). It also removes the following compile warning on some platforms: warning: cast from pointer to integer of different size [asierra: commit title/log rewording] Signed-off-by: Joe Schultz Signed-off-by: Aaron Sierra Signed-off-by: Greg Kroah-Hartman --- drivers/vme/bridges/vme_tsi148.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/vme/bridges/vme_tsi148.c') diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 06990c6a1a6..6b03be71500 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -741,7 +741,7 @@ static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled, reg_join(vme_bound_high, vme_bound_low, &vme_bound); reg_join(pci_offset_high, pci_offset_low, &pci_offset); - *pci_base = (dma_addr_t)vme_base + pci_offset; + *pci_base = (dma_addr_t)(*vme_base + pci_offset); *enabled = 0; *aspace = 0; -- cgit v1.2.3-70-g09d2 From 226572b110ab6083cb8c1d6afb191166b4178179 Mon Sep 17 00:00:00 2001 From: Joe Schultz Date: Thu, 3 Apr 2014 14:48:16 -0500 Subject: vme_tsi148: Fix PCI address mapping assumption Previously, tsi148_master_set() assumed the address contained in its PCI bus resource represented the actual PCI bus address. This is a fine assumption on some platforms. However, on platforms that don't use a 1:1 (CPU:PCI) mapping this results in the tsi148 driver configuring an invalid master window translation. This patch updates the vme_tsi148 driver to first convert the address contained in the PCI bus resource into a PCI bus address before using it. [asierra: account for pcibios_resource_to_bus() prototype change] Signed-off-by: Joe Schultz Signed-off-by: Aaron Sierra Signed-off-by: Greg Kroah-Hartman --- drivers/vme/bridges/vme_tsi148.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/vme/bridges/vme_tsi148.c') diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 6b03be71500..e64e4208de2 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -910,11 +910,15 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled, unsigned long long pci_bound, vme_offset, pci_base; struct vme_bridge *tsi148_bridge; struct tsi148_driver *bridge; + struct pci_bus_region region; + struct pci_dev *pdev; tsi148_bridge = image->parent; bridge = tsi148_bridge->driver_priv; + pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + /* Verify input data */ if (vme_base & 0xFFFF) { dev_err(tsi148_bridge->parent, "Invalid VME Window " @@ -949,7 +953,9 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled, pci_bound = 0; vme_offset = 0; } else { - pci_base = (unsigned long long)image->bus_resource.start; + pcibios_resource_to_bus(pdev->bus, ®ion, + &image->bus_resource); + pci_base = region.start; /* * Bound address is a valid address for the window, adjust -- cgit v1.2.3-70-g09d2 From 177581faf2a5aa71898d223bc47dbc882eeb1488 Mon Sep 17 00:00:00 2001 From: Aaron Sierra Date: Thu, 3 Apr 2014 14:48:27 -0500 Subject: vme_tsi148: Utilize to_pci_dev() macro Save some characters by using to_pci_dev() instead of container_of(). Signed-off-by: Aaron Sierra Signed-off-by: Greg Kroah-Hartman --- drivers/vme/bridges/vme_tsi148.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/vme/bridges/vme_tsi148.c') diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index e64e4208de2..61e706c0e00 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -320,7 +320,7 @@ static int tsi148_irq_init(struct vme_bridge *tsi148_bridge) struct pci_dev *pdev; struct tsi148_driver *bridge; - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + pdev = to_pci_dev(tsi148_bridge->parent); bridge = tsi148_bridge->driver_priv; @@ -433,9 +433,7 @@ static void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level, iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); if (sync != 0) { - pdev = container_of(tsi148_bridge->parent, - struct pci_dev, dev); - + pdev = to_pci_dev(tsi148_bridge->parent); synchronize_irq(pdev->irq); } } else { @@ -814,7 +812,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image, tsi148_bridge = image->parent; - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + pdev = to_pci_dev(tsi148_bridge->parent); existing_size = (unsigned long long)(image->bus_resource.end - image->bus_resource.start); @@ -917,7 +915,7 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled, bridge = tsi148_bridge->driver_priv; - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + pdev = to_pci_dev(tsi148_bridge->parent); /* Verify input data */ if (vme_base & 0xFFFF) { @@ -2238,7 +2236,7 @@ static void *tsi148_alloc_consistent(struct device *parent, size_t size, struct pci_dev *pdev; /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); + pdev = to_pci_dev(parent); return pci_alloc_consistent(pdev, size, dma); } @@ -2249,7 +2247,7 @@ static void tsi148_free_consistent(struct device *parent, size_t size, struct pci_dev *pdev; /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); + pdev = to_pci_dev(parent); pci_free_consistent(pdev, size, vaddr, dma); } -- cgit v1.2.3-70-g09d2