summaryrefslogtreecommitdiffstats
path: root/arch/s390/pci
diff options
context:
space:
mode:
authorNiklas Schnelle <schnelle@linux.ibm.com>2023-11-28 16:22:49 +0100
committerAlexander Gordeev <agordeev@linux.ibm.com>2024-01-11 18:22:58 +0100
commit80df7d6af7f6d229b34cf237b2cc9024c07111cd (patch)
treefdc236d23e01eaa0f7efd56203aad489269e545b /arch/s390/pci
parent0130a0d3a61889060e912a533e996201c4d9a2e5 (diff)
downloadlinux-80df7d6af7f6d229b34cf237b2cc9024c07111cd.tar.gz
linux-80df7d6af7f6d229b34cf237b2cc9024c07111cd.tar.bz2
linux-80df7d6af7f6d229b34cf237b2cc9024c07111cd.zip
s390/pci: fix max size calculation in zpci_memcpy_toio()
The zpci_get_max_write_size() helper is used to determine the maximum size a PCI store or load can use at a given __iomem address. For the PCI block store the following restrictions apply: 1. The dst + len must not cross a 4K boundary in the (pseudo-)MMIO space 2. len must not exceed ZPCI_MAX_WRITE_SIZE 3. len must be a multiple of 8 bytes 4. The src address must be double word (8 byte) aligned 5. The dst address must be double word (8 byte) aligned Otherwise only a normal PCI store which takes its src value from a register can be used. For these PCI store restriction 1 still applies. Similarly 1 also applies to PCI loads. It turns out zpci_max_write_size() instead implements stricter conditions which prevents PCI block stores from being used where they can and should be used. In particular instead of conditions 4 and 5 it wrongly enforces both dst and src to be size aligned. This indirectly covers condition 1 but also prevents many legal PCI block stores. On top of the functional shortcomings the zpci_get_max_write_size() is misnamed as it is used for both read and write size calculations. Rename it to zpci_get_max_io_size() and implement the listed conditions explicitly. Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Fixes: cd24834130ac ("s390/pci: base support") Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> [agordeev@linux.ibm.com replaced spaces with tabs] Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Diffstat (limited to 'arch/s390/pci')
-rw-r--r--arch/s390/pci/pci_mmio.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/arch/s390/pci/pci_mmio.c b/arch/s390/pci/pci_mmio.c
index 588089332931..a90499c087f0 100644
--- a/arch/s390/pci/pci_mmio.c
+++ b/arch/s390/pci/pci_mmio.c
@@ -97,9 +97,9 @@ static inline int __memcpy_toio_inuser(void __iomem *dst,
return -EINVAL;
while (n > 0) {
- size = zpci_get_max_write_size((u64 __force) dst,
- (u64 __force) src, n,
- ZPCI_MAX_WRITE_SIZE);
+ size = zpci_get_max_io_size((u64 __force) dst,
+ (u64 __force) src, n,
+ ZPCI_MAX_WRITE_SIZE);
if (size > 8) /* main path */
rc = __pcistb_mio_inuser(dst, src, size, &status);
else
@@ -242,9 +242,9 @@ static inline int __memcpy_fromio_inuser(void __user *dst,
u8 status;
while (n > 0) {
- size = zpci_get_max_write_size((u64 __force) src,
- (u64 __force) dst, n,
- ZPCI_MAX_READ_SIZE);
+ size = zpci_get_max_io_size((u64 __force) src,
+ (u64 __force) dst, n,
+ ZPCI_MAX_READ_SIZE);
rc = __pcilg_mio_inuser(dst, src, size, &status);
if (rc)
break;