diff options
author | Álvaro Fernández Rojas <noltari@gmail.com> | 2021-08-21 10:54:34 +0200 |
---|---|---|
committer | Álvaro Fernández Rojas <noltari@gmail.com> | 2021-08-21 19:07:07 +0200 |
commit | 8299d1f057439f94c6a4412e2e5c5082b82a30c9 (patch) | |
tree | 1bf678d61f11f7394493be464c7876e496f7faed /target/linux/bcm27xx/patches-5.10/950-0043-fbdev-add-FBIOCOPYAREA-ioctl.patch | |
parent | 33b6885975ce376ff075362b7f0890326043111b (diff) | |
download | upstream-8299d1f057439f94c6a4412e2e5c5082b82a30c9.tar.gz upstream-8299d1f057439f94c6a4412e2e5c5082b82a30c9.tar.bz2 upstream-8299d1f057439f94c6a4412e2e5c5082b82a30c9.zip |
bcm27xx: add kernel 5.10 support
Rebased RPi foundation patches on linux 5.10.59, removed applied and reverted
patches, wireless patches and defconfig patches.
bcm2708: boot tested on RPi B+ v1.2
bcm2709: boot tested on RPi 4B v1.1 4G
bcm2711: boot tested on RPi 4B v1.1 4G
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/bcm27xx/patches-5.10/950-0043-fbdev-add-FBIOCOPYAREA-ioctl.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.10/950-0043-fbdev-add-FBIOCOPYAREA-ioctl.patch | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.10/950-0043-fbdev-add-FBIOCOPYAREA-ioctl.patch b/target/linux/bcm27xx/patches-5.10/950-0043-fbdev-add-FBIOCOPYAREA-ioctl.patch new file mode 100644 index 0000000000..75e3aea2d7 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.10/950-0043-fbdev-add-FBIOCOPYAREA-ioctl.patch @@ -0,0 +1,337 @@ +From 6005247285065235845f233077bbeedb19a484c7 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 + +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 | 170 ++++++++++++++++++++++++++++++- + drivers/video/fbdev/core/fbmem.c | 35 +++++++ + include/uapi/linux/fb.h | 12 +++ + 3 files changed, 213 insertions(+), 4 deletions(-) + +--- a/drivers/video/fbdev/bcm2708_fb.c ++++ b/drivers/video/fbdev/bcm2708_fb.c +@@ -32,8 +32,10 @@ + #include <linux/printk.h> + #include <linux/console.h> + #include <linux/debugfs.h> ++#include <linux/uaccess.h> + #include <linux/io.h> + #include <linux/dma-mapping.h> ++#include <linux/cred.h> + #include <soc/bcm2835/raspberrypi-firmware.h> + #include <linux/mutex.h> + +@@ -184,9 +186,6 @@ static int bcm2708_fb_debugfs_init(struc + + fb->debugfs_subdir = debugfs_create_dir(buf, fb->debugfs_dir); + +- debugfs_create_regset32("stats", 0444, fb->debugfs_dir, +- &fb->stats.regset); +- + if (!fb->debugfs_subdir) { + dev_warn(fb->fb.dev, "%s: could not create debugfs entry %u\n", + __func__, fb->display_settings.display_num); +@@ -603,7 +602,110 @@ 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) ++{ ++ struct bcm2708_fb_dev *fbdev = fb->fbdev; ++ struct bcm2708_dma_cb *cb = fbdev->cb_base; ++ int burst_size = (fbdev->dma_chan == 0) ? 8 : 2; ++ ++ 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; ++ ++ // Not sure what to do if this gets a signal whilst waiting ++ if (mutex_lock_interruptible(&fbdev->dma_mutex)) ++ return; ++ ++ if (size < dma_busy_wait_threshold) { ++ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle); ++ bcm_dma_wait_idle(fbdev->dma_chan_base); ++ } else { ++ void __iomem *local_dma_chan = fbdev->dma_chan_base; ++ ++ cb->info |= BCM2708_DMA_INT_EN; ++ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle); ++ while (bcm_dma_is_busy(local_dma_chan)) { ++ wait_event_interruptible(fbdev->dma_waitq, ++ !bcm_dma_is_busy(local_dma_chan)); ++ } ++ fbdev->dma_stats.dma_irqs++; ++ } ++ fbdev->dma_stats.dma_copies++; ++ ++ mutex_unlock(&fbdev->dma_mutex); ++} ++ ++/* 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, 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; ++ } ++ ++ 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) { ++ 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(%zd)\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); ++ 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); ++ 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) + { +@@ -619,6 +721,21 @@ static int bcm2708_ioctl(struct fb_info + RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC, + &dummy, sizeof(dummy)); + break; ++ ++ case FBIODMACOPY: ++ { ++ 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; +@@ -629,6 +746,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(¶m32, (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, ¶m); ++ 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) + { +@@ -821,6 +980,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) +--- a/drivers/video/fbdev/core/fbmem.c ++++ b/drivers/video/fbdev/core/fbmem.c +@@ -1079,6 +1079,30 @@ 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; ++ lock_fb_info(info); ++ 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) + { +@@ -1087,6 +1111,7 @@ static long do_fb_ioctl(struct fb_info * + struct fb_fix_screeninfo fix; + struct fb_cmap cmap_from; + struct fb_cmap_user cmap; ++ struct fb_copyarea copy; + void __user *argp = (void __user *)arg; + long ret = 0; + +@@ -1162,6 +1187,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: + lock_fb_info(info); + fb = info->fbops; +@@ -1307,6 +1341,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); + fallthrough; + 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 */ +@@ -348,6 +354,12 @@ struct fb_copyarea { + __u32 sy; + }; + ++struct fb_dmacopy { ++ void *dst; ++ __u32 src; ++ __u32 length; ++}; ++ + struct fb_fillrect { + __u32 dx; /* screen-relative */ + __u32 dy; |