diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.19/950-0058-fbdev-add-FBIOCOPYAREA-ioctl.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.19/950-0058-fbdev-add-FBIOCOPYAREA-ioctl.patch | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/target/linux/brcm2708/patches-4.19/950-0058-fbdev-add-FBIOCOPYAREA-ioctl.patch b/target/linux/brcm2708/patches-4.19/950-0058-fbdev-add-FBIOCOPYAREA-ioctl.patch deleted file mode 100644 index 16c15d59f2..0000000000 --- a/target/linux/brcm2708/patches-4.19/950-0058-fbdev-add-FBIOCOPYAREA-ioctl.patch +++ /dev/null @@ -1,265 +0,0 @@ -From 5269119dadfc6874aec51fed4468c73f1b0187a2 Mon Sep 17 00:00:00 2001 -From: Siarhei Siamashka <siarhei.siamashka@gmail.com> -Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH] fbdev: add FBIOCOPYAREA ioctl - -Based on the patch authored by Ali Gholami Rudi at - https://lkml.org/lkml/2009/7/13/153 - -Provide an ioctl for userspace applications, but only if this operation -is hardware accelerated (otherwide it does not make any sense). - -Signed-off-by: Siarhei Siamashka <siarhei.siamashka@gmail.com> - -bcm2708_fb: Add ioctl for reading gpu memory through dma ---- - drivers/video/fbdev/bcm2708_fb.c | 119 ++++++++++++++++++++++++++++++- - drivers/video/fbdev/core/fbmem.c | 36 ++++++++++ - include/uapi/linux/fb.h | 12 ++++ - 3 files changed, 166 insertions(+), 1 deletion(-) - ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -31,8 +31,10 @@ - #include <linux/console.h> - #include <linux/debugfs.h> - #include <asm/sizes.h> -+#include <linux/uaccess.h> - #include <linux/io.h> - #include <linux/dma-mapping.h> -+#include <linux/cred.h> - #include <soc/bcm2835/raspberrypi-firmware.h> - - //#define BCM2708_FB_DEBUG -@@ -95,6 +97,7 @@ struct bcm2708_fb { - wait_queue_head_t dma_waitq; - struct bcm2708_fb_stats stats; - unsigned long fb_bus_address; -+ struct { u32 base, length; } gpu; - }; - - #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb) -@@ -439,7 +442,118 @@ static int bcm2708_fb_pan_display(struct - return result; - } - --static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) -+static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, -+ int size) -+{ -+ int burst_size = (fb->dma_chan == 0) ? 8 : 2; -+ struct bcm2708_dma_cb *cb = fb->cb_base; -+ -+ cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH | -+ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH | -+ BCM2708_DMA_D_INC; -+ cb->dst = dst; -+ cb->src = src; -+ cb->length = size; -+ cb->stride = 0; -+ cb->pad[0] = 0; -+ cb->pad[1] = 0; -+ cb->next = 0; -+ -+ if (size < dma_busy_wait_threshold) { -+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); -+ bcm_dma_wait_idle(fb->dma_chan_base); -+ } else { -+ void __iomem *dma_chan = fb->dma_chan_base; -+ -+ cb->info |= BCM2708_DMA_INT_EN; -+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); -+ while (bcm_dma_is_busy(dma_chan)) { -+ wait_event_interruptible( -+ fb->dma_waitq, -+ !bcm_dma_is_busy(dma_chan)); -+ } -+ fb->stats.dma_irqs++; -+ } -+ fb->stats.dma_copies++; -+} -+ -+/* address with no aliases */ -+#define INTALIAS_NORMAL(x) ((x)&~0xc0000000) -+/* 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) -+{ -+ struct fb_dmacopy ioparam; -+ size_t size = PAGE_SIZE; -+ u32 *buf = NULL; -+ dma_addr_t bus_addr; -+ long rc = 0; -+ size_t offset; -+ -+ /* restrict this to root user */ -+ if (!uid_eq(current_euid(), GLOBAL_ROOT_UID)) { -+ rc = -EFAULT; -+ 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) { -+ 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) { -+ pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__, -+ INTALIAS_NORMAL(ioparam.src), fb->gpu.base, -+ fb->gpu.base + fb->gpu.length); -+ return -EFAULT; -+ } -+ -+ buf = dma_alloc_coherent(fb->fb.device, PAGE_ALIGN(size), &bus_addr, -+ GFP_ATOMIC); -+ if (!buf) { -+ pr_err("[%s]: failed to dma_alloc_coherent(%d)\n", -+ __func__, size); -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ 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; -+ -+ dma_memcpy(fb, bus_addr, -+ INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size); -+ if (copy_to_user(q, buf, s) != 0) { -+ pr_err("[%s]: failed to copy-to-user\n", -+ __func__); -+ rc = -EFAULT; -+ goto out; -+ } -+ } -+out: -+ if (buf) -+ dma_free_coherent(fb->fb.device, PAGE_ALIGN(size), buf, -+ bus_addr); -+ return rc; -+} -+ -+static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, -+ unsigned long arg) - { - struct bcm2708_fb *fb = to_bcm2708(info); - u32 dummy = 0; -@@ -451,6 +565,9 @@ static int bcm2708_ioctl(struct fb_info - RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC, - &dummy, sizeof(dummy)); - break; -+ case FBIODMACOPY: -+ ret = vc_mem_copy(fb, arg); -+ break; - default: - dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd); - return -ENOTTY; ---- a/drivers/video/fbdev/core/fbmem.c -+++ b/drivers/video/fbdev/core/fbmem.c -@@ -1081,6 +1081,31 @@ fb_blank(struct fb_info *info, int blank - } - EXPORT_SYMBOL(fb_blank); - -+static int fb_copyarea_user(struct fb_info *info, -+ struct fb_copyarea *copy) -+{ -+ int ret = 0; -+ if (!lock_fb_info(info)) -+ return -ENODEV; -+ if (copy->dx >= info->var.xres || -+ copy->sx >= info->var.xres || -+ copy->width > info->var.xres || -+ copy->dy >= info->var.yres || -+ copy->sy >= info->var.yres || -+ copy->height > info->var.yres || -+ copy->dx + copy->width > info->var.xres || -+ copy->sx + copy->width > info->var.xres || -+ copy->dy + copy->height > info->var.yres || -+ copy->sy + copy->height > info->var.yres) { -+ ret = -EINVAL; -+ goto out; -+ } -+ info->fbops->fb_copyarea(info, copy); -+out: -+ unlock_fb_info(info); -+ return ret; -+} -+ - static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) - { -@@ -1091,6 +1116,7 @@ static long do_fb_ioctl(struct fb_info * - struct fb_cmap cmap_from; - struct fb_cmap_user cmap; - struct fb_event event; -+ struct fb_copyarea copy; - void __user *argp = (void __user *)arg; - long ret = 0; - -@@ -1208,6 +1234,15 @@ static long do_fb_ioctl(struct fb_info * - unlock_fb_info(info); - console_unlock(); - break; -+ case FBIOCOPYAREA: -+ if (info->flags & FBINFO_HWACCEL_COPYAREA) { -+ /* only provide this ioctl if it is accelerated */ -+ if (copy_from_user(©, argp, sizeof(copy))) -+ return -EFAULT; -+ ret = fb_copyarea_user(info, ©); -+ break; -+ } -+ /* fall through */ - default: - if (!lock_fb_info(info)) - return -ENODEV; -@@ -1353,6 +1388,7 @@ static long fb_compat_ioctl(struct file - case FBIOPAN_DISPLAY: - case FBIOGET_CON2FBMAP: - case FBIOPUT_CON2FBMAP: -+ case FBIOCOPYAREA: - arg = (unsigned long) compat_ptr(arg); - /* fall through */ - case FBIOBLANK: ---- a/include/uapi/linux/fb.h -+++ b/include/uapi/linux/fb.h -@@ -35,6 +35,12 @@ - #define FBIOPUT_MODEINFO 0x4617 - #define FBIOGET_DISPINFO 0x4618 - #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) -+/* -+ * HACK: use 'z' in order not to clash with any other ioctl numbers which might -+ * be concurrently added to the mainline kernel -+ */ -+#define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea) -+#define FBIODMACOPY _IOW('z', 0x22, struct fb_dmacopy) - - #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ - #define FB_TYPE_PLANES 1 /* Non interleaved planes */ -@@ -347,6 +353,12 @@ struct fb_copyarea { - __u32 sy; - }; - -+struct fb_dmacopy { -+ void *dst; -+ __u32 src; -+ __u32 length; -+}; -+ - struct fb_fillrect { - __u32 dx; /* screen-relative */ - __u32 dy; |