diff options
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.patch | 91 |
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; + } |