aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-4.19/950-0287-video-bcm2708_fb-Add-compat_ioctl-support.patch
blob: eb53480080b870386f7c9dfdfebb49279950a7bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
From b5bd7b621f6ab2f29e9f18ec2a2720d702b9727c Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Fri, 25 Jan 2019 17:12:54 +0000
Subject: [PATCH] video: bcm2708_fb: Add compat_ioctl support.

When using a 64 bit kernel with 32 bit userspace we need
compat ioctl handling for FBIODMACOPY as one of the
parameters is a pointer.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
---
 drivers/video/fbdev/bcm2708_fb.c | 87 ++++++++++++++++++++++++--------
 1 file changed, 66 insertions(+), 21 deletions(-)

--- a/drivers/video/fbdev/bcm2708_fb.c
+++ b/drivers/video/fbdev/bcm2708_fb.c
@@ -482,9 +482,8 @@ static void dma_memcpy(struct bcm2708_fb
 /* cache coherent but non-allocating in L1 and L2 */
 #define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
 
-static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
+static long vc_mem_copy(struct bcm2708_fb *fb, struct fb_dmacopy *ioparam)
 {
-	struct fb_dmacopy ioparam;
 	size_t size = PAGE_SIZE;
 	u32 *buf = NULL;
 	dma_addr_t bus_addr;
@@ -497,26 +496,16 @@ static long vc_mem_copy(struct bcm2708_f
 		goto out;
 	}
 
-	/* Get the parameter data.
-	 */
-	if (copy_from_user
-	    (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
-		pr_err("[%s]: failed to copy-from-user\n",
-				__func__);
-		rc = -EFAULT;
-		goto out;
-	}
-
-	if (fb->gpu.base == 0 || fb->gpu.length == 0) {
+	if (!fb->gpu.base || !fb->gpu.length) {
 		pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
 			__func__, fb->gpu.base, fb->gpu.length);
 		return -EFAULT;
 	}
 
-	if (INTALIAS_NORMAL(ioparam.src) < fb->gpu.base ||
-		INTALIAS_NORMAL(ioparam.src) >= fb->gpu.base + fb->gpu.length) {
+	if (INTALIAS_NORMAL(ioparam->src) < fb->gpu.base ||
+	    INTALIAS_NORMAL(ioparam->src) >= fb->gpu.base + fb->gpu.length) {
 		pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
-			INTALIAS_NORMAL(ioparam.src), fb->gpu.base,
+			INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
 			fb->gpu.base + fb->gpu.length);
 		return -EFAULT;
 	}
@@ -530,11 +519,11 @@ static long vc_mem_copy(struct bcm2708_f
 		goto out;
 	}
 
-	for (offset = 0; offset < ioparam.length; offset += size) {
-		size_t remaining = ioparam.length - offset;
+	for (offset = 0; offset < ioparam->length; offset += size) {
+		size_t remaining = ioparam->length - offset;
 		size_t s = min(size, remaining);
-		unsigned char *p = (unsigned char *)ioparam.src + offset;
-		unsigned char *q = (unsigned char *)ioparam.dst + offset;
+		u8 *p = (u8 *)((uintptr_t)ioparam->src + offset);
+		u8 *q = (u8 *)ioparam->dst + offset;
 
 		dma_memcpy(fb, bus_addr,
 			   INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
@@ -566,8 +555,19 @@ static int bcm2708_ioctl(struct fb_info
 					    &dummy, sizeof(dummy));
 		break;
 	case FBIODMACOPY:
-		ret = vc_mem_copy(fb, arg);
+	{
+		struct fb_dmacopy ioparam;
+		/* Get the parameter data.
+		 */
+		if (copy_from_user
+		    (&ioparam, (void *)arg, sizeof(ioparam))) {
+			pr_err("[%s]: failed to copy-from-user\n", __func__);
+			ret = -EFAULT;
+			break;
+		}
+		ret = vc_mem_copy(fb, &ioparam);
 		break;
+	}
 	default:
 		dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd);
 		return -ENOTTY;
@@ -578,6 +578,48 @@ static int bcm2708_ioctl(struct fb_info
 
 	return ret;
 }
+
+#ifdef CONFIG_COMPAT
+struct fb_dmacopy32 {
+	compat_uptr_t dst;
+	__u32 src;
+	__u32 length;
+};
+
+#define FBIODMACOPY32		_IOW('z', 0x22, struct fb_dmacopy32)
+
+static int bcm2708_compat_ioctl(struct fb_info *info, unsigned int cmd,
+				unsigned long arg)
+{
+	struct bcm2708_fb *fb = to_bcm2708(info);
+	int ret;
+
+	switch (cmd) {
+	case FBIODMACOPY32:
+	{
+		struct fb_dmacopy32 param32;
+		struct fb_dmacopy param;
+		/* Get the parameter data.
+		 */
+		if (copy_from_user(&param32, (void *)arg, sizeof(param32))) {
+			pr_err("[%s]: failed to copy-from-user\n", __func__);
+			ret = -EFAULT;
+			break;
+		}
+		param.dst = compat_ptr(param32.dst);
+		param.src = param32.src;
+		param.length = param32.length;
+		ret = vc_mem_copy(fb, &param);
+		break;
+	}
+	default:
+		ret = bcm2708_ioctl(info, cmd, arg);
+		break;
+	}
+	return ret;
+}
+#endif
+
 static void bcm2708_fb_fillrect(struct fb_info *info,
 				const struct fb_fillrect *rect)
 {
@@ -768,6 +810,9 @@ static struct fb_ops bcm2708_fb_ops = {
 	.fb_imageblit = bcm2708_fb_imageblit,
 	.fb_pan_display = bcm2708_fb_pan_display,
 	.fb_ioctl = bcm2708_ioctl,
+#ifdef CONFIG_COMPAT
+	.fb_compat_ioctl = bcm2708_compat_ioctl,
+#endif
 };
 
 static int bcm2708_fb_register(struct bcm2708_fb *fb)