brcm2708: update to latest patches from RPi Foundation
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.19 / 950-0289-video-bcm2708_fb-Add-compat_ioctl-support.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0289-video-bcm2708_fb-Add-compat_ioctl-support.patch b/target/linux/brcm2708/patches-4.19/950-0289-video-bcm2708_fb-Add-compat_ioctl-support.patch
new file mode 100644 (file)
index 0000000..eb53480
--- /dev/null
@@ -0,0 +1,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)