bcm27xx: add support for linux v5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.15 / 950-0517-bcm2835_smi_dev-Fix-handling-of-word-odd-lengths.patch
1 From 0922abd923ec50f6cc41ded24485bd22c719c7bd Mon Sep 17 00:00:00 2001
2 From: madimario <madimario@users.noreply.github.com>
3 Date: Tue, 28 Sep 2021 04:20:06 -0400
4 Subject: [PATCH] bcm2835_smi_dev: Fix handling of word-odd lengths
5
6 The read and write functions did not use the correct pointer offset
7 when dealing with an odd number of bytes after a DMA transfer. Also,
8 only handle the remaining odd bytes if the DMA transfer completed
9 successfully.
10
11 Submitted-by: @madimario (GitHub)
12 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
13 ---
14 drivers/char/broadcom/bcm2835_smi_dev.c | 21 ++++++++++++++-------
15 1 file changed, 14 insertions(+), 7 deletions(-)
16
17 --- a/drivers/char/broadcom/bcm2835_smi_dev.c
18 +++ b/drivers/char/broadcom/bcm2835_smi_dev.c
19 @@ -191,6 +191,7 @@ bcm2835_read_file(struct file *f, char _
20 size_t count, loff_t *offs)
21 {
22 int odd_bytes;
23 + size_t count_check;
24
25 dev_dbg(inst->dev, "User reading %zu bytes from SMI.", count);
26 /* We don't want to DMA a number of bytes % 4 != 0 (32 bit FIFO) */
27 @@ -199,6 +200,7 @@ bcm2835_read_file(struct file *f, char _
28 else
29 odd_bytes = count;
30 count -= odd_bytes;
31 + count_check = count;
32 if (count) {
33 struct bcm2835_smi_bounce_info *bounce;
34
35 @@ -209,15 +211,16 @@ bcm2835_read_file(struct file *f, char _
36 count = dma_bounce_user(DMA_DEV_TO_MEM, user_ptr,
37 count, bounce);
38 }
39 - if (odd_bytes) {
40 + if (odd_bytes && (count == count_check)) {
41 /* Read from FIFO directly if not using DMA */
42 uint8_t buf[DMA_THRESHOLD_BYTES];
43 + unsigned long bytes_not_transferred;
44
45 bcm2835_smi_read_buf(smi_inst, buf, odd_bytes);
46 - if (copy_to_user(user_ptr, buf, odd_bytes))
47 + bytes_not_transferred = copy_to_user(user_ptr + count, buf, odd_bytes);
48 + if (bytes_not_transferred)
49 dev_err(inst->dev, "copy_to_user() failed.");
50 - count += odd_bytes;
51 -
52 + count += odd_bytes - bytes_not_transferred;
53 }
54 return count;
55 }
56 @@ -227,6 +230,7 @@ bcm2835_write_file(struct file *f, const
57 size_t count, loff_t *offs)
58 {
59 int odd_bytes;
60 + size_t count_check;
61
62 dev_dbg(inst->dev, "User writing %zu bytes to SMI.", count);
63 if (count > DMA_THRESHOLD_BYTES)
64 @@ -234,6 +238,7 @@ bcm2835_write_file(struct file *f, const
65 else
66 odd_bytes = count;
67 count -= odd_bytes;
68 + count_check = count;
69 if (count) {
70 struct bcm2835_smi_bounce_info *bounce;
71
72 @@ -245,14 +250,16 @@ bcm2835_write_file(struct file *f, const
73 (char __user *)user_ptr,
74 count, bounce);
75 }
76 - if (odd_bytes) {
77 + if (odd_bytes && (count == count_check)) {
78 uint8_t buf[DMA_THRESHOLD_BYTES];
79 + unsigned long bytes_not_transferred;
80
81 - if (copy_from_user(buf, user_ptr, odd_bytes))
82 + bytes_not_transferred = copy_from_user(buf, user_ptr + count, odd_bytes);
83 + if (bytes_not_transferred)
84 dev_err(inst->dev, "copy_from_user() failed.");
85 else
86 bcm2835_smi_write_buf(smi_inst, buf, odd_bytes);
87 - count += odd_bytes;
88 + count += odd_bytes - bytes_not_transferred;
89 }
90 return count;
91 }