mirror of
git://git.openwrt.org/openwrt/openwrt.git
synced 2024-12-24 07:33:04 +00:00
92 lines
2.9 KiB
Diff
92 lines
2.9 KiB
Diff
|
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;
|
||
|
}
|