aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0517-bcm2835_smi_dev-Fix-handling-of-word-odd-lengths.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0517-bcm2835_smi_dev-Fix-handling-of-word-odd-lengths.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.15/950-0517-bcm2835_smi_dev-Fix-handling-of-word-odd-lengths.patch91
1 files changed, 91 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0517-bcm2835_smi_dev-Fix-handling-of-word-odd-lengths.patch b/target/linux/bcm27xx/patches-5.15/950-0517-bcm2835_smi_dev-Fix-handling-of-word-odd-lengths.patch
new file mode 100644
index 0000000000..b0055dfcf8
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.15/950-0517-bcm2835_smi_dev-Fix-handling-of-word-odd-lengths.patch
@@ -0,0 +1,91 @@
+From 0922abd923ec50f6cc41ded24485bd22c719c7bd Mon Sep 17 00:00:00 2001
+From: madimario <madimario@users.noreply.github.com>
+Date: Tue, 28 Sep 2021 04:20:06 -0400
+Subject: [PATCH] bcm2835_smi_dev: Fix handling of word-odd lengths
+
+The read and write functions did not use the correct pointer offset
+when dealing with an odd number of bytes after a DMA transfer. Also,
+only handle the remaining odd bytes if the DMA transfer completed
+successfully.
+
+Submitted-by: @madimario (GitHub)
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/char/broadcom/bcm2835_smi_dev.c | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+--- a/drivers/char/broadcom/bcm2835_smi_dev.c
++++ b/drivers/char/broadcom/bcm2835_smi_dev.c
+@@ -191,6 +191,7 @@ bcm2835_read_file(struct file *f, char _
+ size_t count, loff_t *offs)
+ {
+ int odd_bytes;
++ size_t count_check;
+
+ dev_dbg(inst->dev, "User reading %zu bytes from SMI.", count);
+ /* We don't want to DMA a number of bytes % 4 != 0 (32 bit FIFO) */
+@@ -199,6 +200,7 @@ bcm2835_read_file(struct file *f, char _
+ else
+ odd_bytes = count;
+ count -= odd_bytes;
++ count_check = count;
+ if (count) {
+ struct bcm2835_smi_bounce_info *bounce;
+
+@@ -209,15 +211,16 @@ bcm2835_read_file(struct file *f, char _
+ count = dma_bounce_user(DMA_DEV_TO_MEM, user_ptr,
+ count, bounce);
+ }
+- if (odd_bytes) {
++ if (odd_bytes && (count == count_check)) {
+ /* Read from FIFO directly if not using DMA */
+ uint8_t buf[DMA_THRESHOLD_BYTES];
++ unsigned long bytes_not_transferred;
+
+ bcm2835_smi_read_buf(smi_inst, buf, odd_bytes);
+- if (copy_to_user(user_ptr, buf, odd_bytes))
++ bytes_not_transferred = copy_to_user(user_ptr + count, buf, odd_bytes);
++ if (bytes_not_transferred)
+ dev_err(inst->dev, "copy_to_user() failed.");
+- count += odd_bytes;
+-
++ count += odd_bytes - bytes_not_transferred;
+ }
+ return count;
+ }
+@@ -227,6 +230,7 @@ bcm2835_write_file(struct file *f, const
+ size_t count, loff_t *offs)
+ {
+ int odd_bytes;
++ size_t count_check;
+
+ dev_dbg(inst->dev, "User writing %zu bytes to SMI.", count);
+ if (count > DMA_THRESHOLD_BYTES)
+@@ -234,6 +238,7 @@ bcm2835_write_file(struct file *f, const
+ else
+ odd_bytes = count;
+ count -= odd_bytes;
++ count_check = count;
+ if (count) {
+ struct bcm2835_smi_bounce_info *bounce;
+
+@@ -245,14 +250,16 @@ bcm2835_write_file(struct file *f, const
+ (char __user *)user_ptr,
+ count, bounce);
+ }
+- if (odd_bytes) {
++ if (odd_bytes && (count == count_check)) {
+ uint8_t buf[DMA_THRESHOLD_BYTES];
++ unsigned long bytes_not_transferred;
+
+- if (copy_from_user(buf, user_ptr, odd_bytes))
++ bytes_not_transferred = copy_from_user(buf, user_ptr + count, odd_bytes);
++ if (bytes_not_transferred)
+ dev_err(inst->dev, "copy_from_user() failed.");
+ else
+ bcm2835_smi_write_buf(smi_inst, buf, odd_bytes);
+- count += odd_bytes;
++ count += odd_bytes - bytes_not_transferred;
+ }
+ return count;
+ }