]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: dc: fix structs for 64-bit
authorJon Mayo <jmayo@nvidia.com>
Wed, 5 Mar 2014 19:15:40 +0000 (11:15 -0800)
committerJon Mayo <jmayo@nvidia.com>
Fri, 7 Mar 2014 21:04:11 +0000 (13:04 -0800)
Add compat ioctls and clean up data structures where it would be
simplier to break the old 64-bit APIs for a new one that works.

Some user space binaries will have to be rebuilt after this patch, but
those binaries were almost certainly already broken as the driver wasn't
doing the right thing.

adds 32-bit compat version of:
TEGRA_DC_EXT_CONTROL_GET_OUTPUT_EDID
TEGRA_DC_EXT_FLIP2
TEGRA_DC_EXT_SET_PROPOSED_BW
TEGRA_DC_EXT_SET_LUT
TEGRA_DC_EXT_GET_FEATURES

updates struct tegra_dc_ext_flip_windowattr to be the same size in both
environments. This allows these ioctls to work:
TEGRA_DC_EXT_FLIP
TEGRA_DC_EXT_FLIP3

Bug 1466416

Change-Id: I17b8ba1b1fc5ace659b7db99dd252c03e96273e8
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/378129
Reviewed-by: Automatic_Commit_Validation_User
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_config.c
drivers/video/tegra/dc/dc_config.h
drivers/video/tegra/dc/ext/control.c
drivers/video/tegra/dc/ext/dev.c
include/video/tegra_dc_ext.h

index 284826312331f79aa0a76c7ef5342b086442b029..0f1c638076c55e74081098feeab66467e0c53be4 100644 (file)
@@ -822,8 +822,8 @@ static int dbg_dc_event_inject_show(struct seq_file *s, void *unused)
        return 0;
 }
 
-static int dbg_dc_event_inject_write(struct file *file, const char __user *addr,
-       size_t len, loff_t *pos)
+static ssize_t dbg_dc_event_inject_write(struct file *file,
+       const char __user *addr, size_t len, loff_t *pos)
 {
        struct seq_file *m = file->private_data; /* single_open() initialized */
        struct tegra_dc *dc = m ? m->private : NULL;
index cff664b4d3d52bbdfd1a299317386cac8c67e07a..bf2107dd039ba50f845fff077f2b2e22fe751e97 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/dc_config.c
  *
- * Copyright (c) 2012-2013, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION, All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -414,7 +414,7 @@ int tegra_dc_get_feature(struct tegra_dc_feature *feature, int win_idx,
        return -EINVAL;
 }
 
-long *tegra_dc_parse_feature(struct tegra_dc *dc, int win_idx, int operation)
+u32 *tegra_dc_parse_feature(struct tegra_dc *dc, int win_idx, int operation)
 {
        int idx;
        struct tegra_dc_feature_entry *entry;
@@ -464,7 +464,7 @@ long *tegra_dc_parse_feature(struct tegra_dc *dc, int win_idx, int operation)
 int tegra_dc_feature_has_scaling(struct tegra_dc *dc, int win_idx)
 {
        int i;
-       long *addr = tegra_dc_parse_feature(dc, win_idx, HAS_SCALE);
+       u32 *addr = tegra_dc_parse_feature(dc, win_idx, HAS_SCALE);
 
        if (WARN_ONCE(!addr, "window does not exist"))
                return 0;
@@ -477,7 +477,7 @@ int tegra_dc_feature_has_scaling(struct tegra_dc *dc, int win_idx)
 
 int tegra_dc_feature_has_tiling(struct tegra_dc *dc, int win_idx)
 {
-       long *addr = tegra_dc_parse_feature(dc, win_idx, HAS_TILED);
+       u32 *addr = tegra_dc_parse_feature(dc, win_idx, HAS_TILED);
 
        if (WARN_ONCE(!addr, "window does not exist"))
                return 0;
@@ -487,7 +487,7 @@ int tegra_dc_feature_has_tiling(struct tegra_dc *dc, int win_idx)
 
 int tegra_dc_feature_has_blocklinear(struct tegra_dc *dc, int win_idx)
 {
-       long *addr = tegra_dc_parse_feature(dc, win_idx, HAS_BLOCKLINEAR);
+       u32 *addr = tegra_dc_parse_feature(dc, win_idx, HAS_BLOCKLINEAR);
 
        if (WARN_ONCE(!addr, "window does not exist"))
                return 0;
@@ -497,7 +497,7 @@ int tegra_dc_feature_has_blocklinear(struct tegra_dc *dc, int win_idx)
 
 int tegra_dc_feature_has_interlace(struct tegra_dc *dc, int win_idx)
 {
-       long *addr = tegra_dc_parse_feature(dc, win_idx, HAS_INTERLACE);
+       u32 *addr = tegra_dc_parse_feature(dc, win_idx, HAS_INTERLACE);
 
        if (WARN_ONCE(!addr, "window does not exist"))
                return 0;
@@ -507,7 +507,7 @@ int tegra_dc_feature_has_interlace(struct tegra_dc *dc, int win_idx)
 
 int tegra_dc_feature_has_filter(struct tegra_dc *dc, int win_idx, int operation)
 {
-       long *addr = tegra_dc_parse_feature(dc, win_idx, operation);
+       u32 *addr = tegra_dc_parse_feature(dc, win_idx, operation);
 
        if (WARN_ONCE(!addr, "window does not exist"))
                return 0;
@@ -520,7 +520,7 @@ int tegra_dc_feature_has_filter(struct tegra_dc *dc, int win_idx, int operation)
 
 int tegra_dc_feature_is_gen2_blender(struct tegra_dc *dc, int win_idx)
 {
-       long *addr = tegra_dc_parse_feature(dc, win_idx, HAS_GEN2_BLEND);
+       u32 *addr = tegra_dc_parse_feature(dc, win_idx, HAS_GEN2_BLEND);
 
        if (WARN_ONCE(!addr, "window does not exist"))
                return 0;
index d836fa4c2a4bbc18197eb6b4bbb07d36cc755962..9c12e52595c56391241d627547682e0466b6aec6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/dc_config.c
  *
- * Copyright (c) 2010-2013, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2010-2014, NVIDIA CORPORATION, All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -167,7 +167,7 @@ enum tegra_dc_feature_option {
 struct tegra_dc_feature_entry {
        u32 window_index;
        u32 option;
-       long arg[ENTRY_SIZE];
+       u32 arg[ENTRY_SIZE];
 };
 
 struct tegra_dc_feature {
@@ -182,7 +182,7 @@ int tegra_dc_feature_has_interlace(struct tegra_dc *dc, int win_idx);
 int tegra_dc_feature_has_filter(struct tegra_dc *dc, int win_idx, int operation);
 int tegra_dc_feature_is_gen2_blender(struct tegra_dc *dc, int win_idx);
 
-long *tegra_dc_parse_feature(struct tegra_dc *dc, int win_idx, int operation);
+u32 *tegra_dc_parse_feature(struct tegra_dc *dc, int win_idx, int operation);
 void tegra_dc_feature_register(struct tegra_dc *dc);
 
 static inline bool win_use_v_filter(struct tegra_dc *dc,
index b73f7980a19c1a3491d8c6daf16cf40e121a061c..d0d0f100095d07ee5ab8bf3ad2250c2c0b3aab75 100644 (file)
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
 
 #include "tegra_dc_ext_priv.h"
 
+#ifdef CONFIG_COMPAT
+struct tegra_dc_ext_control_output_edid32 {
+       __u32 handle;
+       __u32 size;
+       __u32 data;     /* void *data; */
+};
+
+#define TEGRA_DC_EXT_CONTROL_GET_OUTPUT_EDID32 \
+       _IOWR('C', 0x02, struct tegra_dc_ext_control_output_edid32)
+#endif
+
 static struct tegra_dc_ext_control g_control;
 
 int tegra_dc_ext_process_hotplug(int output)
@@ -185,6 +199,33 @@ static long tegra_dc_ext_control_ioctl(struct file *filp, unsigned int cmd,
 
                return ret;
        }
+#ifdef CONFIG_COMPAT
+       case TEGRA_DC_EXT_CONTROL_GET_OUTPUT_EDID32:
+       {
+               struct tegra_dc_ext_control_output_edid32 args;
+               struct tegra_dc_ext_control_output_edid tmp;
+               int ret;
+
+               if (copy_from_user(&args, user_arg, sizeof(args)))
+                       return -EFAULT;
+
+               /* translate 32-bit version to 64-bit */
+               tmp.handle = args.handle;
+               tmp.size = args.size;
+               tmp.data = compat_ptr(args.data);
+
+               ret = get_output_edid(&tmp);
+
+               /* convert it back to 32-bit version, tmp.data not modified */
+               args.handle = tmp.handle;
+               args.size = tmp.size;
+
+               if (copy_to_user(user_arg, &args, sizeof(args)))
+                       return -EFAULT;
+
+               return ret;
+       }
+#endif
        case TEGRA_DC_EXT_CONTROL_GET_OUTPUT_EDID:
        {
                struct tegra_dc_ext_control_output_edid args;
index 381d75039562748789e041da403f839c2aadf986..a7b260520d299211c49790a3c1e4c0cf88cf83ec 100644 (file)
 #include "../../../staging/android/sync.h"
 #endif
 
+#ifdef CONFIG_COMPAT
+/* compat versions that happen to be the same size as the uapi version. */
+
+struct tegra_dc_ext_lut32 {
+       __u32 win_index;        /* window index to set lut for */
+       __u32 flags;            /* Flag bitmask, see TEGRA_DC_EXT_LUT_FLAGS_* */
+       __u32 start;            /* start index to update lut from */
+       __u32 len;              /* number of valid lut entries */
+       __u32 r;                /* array of 16-bit red values, 0 to reset */
+       __u32 g;                /* array of 16-bit green values, 0 to reset */
+       __u32 b;                /* array of 16-bit blue values, 0 to reset */
+};
+
+#define TEGRA_DC_EXT_SET_LUT32 \
+               _IOW('D', 0x0A, struct tegra_dc_ext_lut32)
+
+struct tegra_dc_ext_feature32 {
+       __u32 length;
+       __u32 entries;          /* pointer to array of 32-bit entries */
+};
+
+#define TEGRA_DC_EXT_GET_FEATURES32 \
+               _IOW('D', 0x0B, struct tegra_dc_ext_feature32)
+
+struct tegra_dc_ext_flip_2_32 {
+       __u32 win;              /* struct tegra_dc_ext_flip_windowattr* */
+       __u8 win_num;
+       __u8 reserved1;         /* unused - must be 0 */
+       __u16 reserved2;        /* unused - must be 0 */
+       __u32 post_syncpt_id;
+       __u32 post_syncpt_val;
+       __u16 dirty_rect[4]; /* x,y,w,h for partial screen update. 0 ignores */
+};
+
+#define TEGRA_DC_EXT_FLIP2_32 \
+               _IOWR('D', 0x0E, struct tegra_dc_ext_flip_2_32)
+
+#define TEGRA_DC_EXT_SET_PROPOSED_BW32 \
+               _IOR('D', 0x13, struct tegra_dc_ext_flip_2_32)
+
+#endif
+
 int tegra_dc_ext_devno;
 struct class *tegra_dc_ext_class;
 static int head_count;
@@ -70,6 +112,16 @@ struct tegra_dc_ext_flip_data {
        int act_window_num;
 };
 
+static inline s64 tegra_timespec_to_ns(const struct tegra_timespec *ts)
+{
+       return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
+}
+
+static inline int test_bit_u32(int nr, const u32 *addr)
+{
+       return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
+}
+
 int tegra_dc_ext_get_num_outputs(void)
 {
        /* TODO: decouple output count from head count */
@@ -169,7 +221,7 @@ void tegra_dc_ext_disable(struct tegra_dc_ext *ext)
 int tegra_dc_ext_check_windowattr(struct tegra_dc_ext *ext,
                                                struct tegra_dc_win *win)
 {
-       long *addr;
+       u32 *addr;
        struct tegra_dc *dc = ext->dc;
 
        addr = tegra_dc_parse_feature(dc, win->idx, GET_WIN_FORMATS);
@@ -180,7 +232,7 @@ int tegra_dc_ext_check_windowattr(struct tegra_dc_ext *ext,
                goto fail;
        }
        /* Check the window format */
-       if (!test_bit(win->fmt, addr)) {
+       if (!test_bit_u32(win->fmt, addr)) {
                dev_err(&dc->ndev->dev,
                        "Color format of window %d is invalid.\n", win->idx);
                goto fail;
@@ -342,7 +394,7 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
                return err;
 
        if (tegra_platform_is_silicon()) {
-               timestamp_ns = timespec_to_ns(&flip_win->attr.timestamp);
+               timestamp_ns = tegra_timespec_to_ns(&flip_win->attr.timestamp);
 
                if (timestamp_ns) {
                        /* XXX: Should timestamping be overridden by "no_vsync"
@@ -437,11 +489,11 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
                                        dev_err(&win->dc->ndev->dev,
                                                        "work queue did NOT dequeue head!!!");
                                else
-                                       head_timestamp =
-                                               timespec_to_ns(&flip_win->attr.timestamp);
+                                       head_timestamp = tegra_timespec_to_ns(
+                                               &flip_win->attr.timestamp);
                        } else {
-                               s64 timestamp =
-                                       timespec_to_ns(&temp->win[i].attr.timestamp);
+                               s64 timestamp = tegra_timespec_to_ns(
+                                       &temp->win[i].attr.timestamp);
 
                                skip_flip = !tegra_dc_does_vsync_separate(ext->dc,
                                                timestamp, head_timestamp);
@@ -637,7 +689,8 @@ static int tegra_dc_ext_pin_windows(struct tegra_dc_ext_user *user,
                int index = wins[i].index;
 
                memcpy(&flip_win->attr, &wins[i], sizeof(flip_win->attr));
-               if (has_timestamp && timespec_to_ns(&flip_win->attr.timestamp))
+               if (has_timestamp && tegra_timespec_to_ns(
+                       &flip_win->attr.timestamp))
                        *has_timestamp = true;
 
                if (index < 0 || !test_bit(index, &dc->valid_windows))
@@ -1107,6 +1160,41 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
                return ret;
        }
 
+#ifdef CONFIG_COMPAT
+       case TEGRA_DC_EXT_FLIP2_32:
+       {
+               int ret;
+               int win_num;
+               struct tegra_dc_ext_flip_2_32 args;
+               struct tegra_dc_ext_flip_windowattr *win;
+
+               if (copy_from_user(&args, user_arg, sizeof(args)))
+                       return -EFAULT;
+
+               win_num = args.win_num;
+               win = kzalloc(sizeof(*win) * win_num, GFP_KERNEL);
+
+               if (copy_from_user(win, compat_ptr(args.win),
+                       sizeof(*win) * win_num)) {
+                       kfree(win);
+                       return -EFAULT;
+               }
+
+               ret = tegra_dc_ext_flip(user, win, win_num,
+                       &args.post_syncpt_id, &args.post_syncpt_val, NULL);
+
+               if (copy_to_user(compat_ptr(args.win), win,
+                       sizeof(*win) * win_num) ||
+                       copy_to_user(user_arg, &args, sizeof(args))) {
+                       kfree(win);
+                       return -EFAULT;
+               }
+
+               kfree(win);
+               return ret;
+       }
+
+#endif
        case TEGRA_DC_EXT_FLIP2:
        {
                int ret;
@@ -1171,6 +1259,33 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
                return ret;
        }
 #ifdef CONFIG_TEGRA_ISOMGR
+#ifdef CONFIG_COMPAT
+       case TEGRA_DC_EXT_SET_PROPOSED_BW32:
+       {
+               int ret;
+               int win_num;
+               struct tegra_dc_ext_flip_2_32 args;
+               struct tegra_dc_ext_flip_windowattr *win;
+
+               if (copy_from_user(&args, user_arg, sizeof(args)))
+                       return -EFAULT;
+
+               win_num = args.win_num;
+               win = kzalloc(sizeof(*win) * win_num, GFP_KERNEL);
+
+               if (copy_from_user(win, compat_ptr(args.win),
+                               sizeof(*win) * win_num)) {
+                       kfree(win);
+                       return -EFAULT;
+               }
+
+               ret = tegra_dc_ext_negotiate_bw(user, win, win_num);
+
+               kfree(win);
+
+               return ret;
+       }
+#endif
        case TEGRA_DC_EXT_SET_PROPOSED_BW:
        {
                int ret;
@@ -1184,8 +1299,7 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
                win_num = args.win_num;
                win = kzalloc(sizeof(*win) * win_num, GFP_KERNEL);
 
-               if (copy_from_user(win, (void *)(uintptr_t)args.win, 
-                               sizeof(*win) * win_num)) {
+               if (copy_from_user(win, args.win, sizeof(*win) * win_num)) {
                        kfree(win);
                        return -EFAULT;
                }
@@ -1273,6 +1387,27 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
                return ret;
        }
 
+#ifdef CONFIG_COMPAT
+       case TEGRA_DC_EXT_SET_LUT32:
+       {
+               struct tegra_dc_ext_lut32 args;
+               struct tegra_dc_ext_lut tmp;
+
+               if (copy_from_user(&args, user_arg, sizeof(args)))
+                       return -EFAULT;
+
+               /* translate 32-bit version to 64-bit */
+               tmp.win_index = args.win_index;
+               tmp.flags = args.flags;
+               tmp.start = args.start;
+               tmp.len = args.len;
+               tmp.r = compat_ptr(args.r);
+               tmp.g = compat_ptr(args.g);
+               tmp.b = compat_ptr(args.b);
+
+               return tegra_dc_ext_set_lut(user, &tmp);
+       }
+#endif
        case TEGRA_DC_EXT_SET_LUT:
        {
                struct tegra_dc_ext_lut args;
@@ -1283,6 +1418,31 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
                return tegra_dc_ext_set_lut(user, &args);
        }
 
+#ifdef CONFIG_COMPAT
+       case TEGRA_DC_EXT_GET_FEATURES32:
+       {
+               struct tegra_dc_ext_feature32 args;
+               struct tegra_dc_ext_feature tmp;
+               int ret;
+
+               if (copy_from_user(&args, user_arg, sizeof(args)))
+                       return -EFAULT;
+
+               /* convert 32-bit to 64-bit version */
+               tmp.length = args.length;
+               tmp.entries = compat_ptr(args.entries);
+
+               ret = tegra_dc_ext_get_feature(user, &tmp);
+
+               /* convert back to 32-bit version, tmp.entries not modified */
+               args.length = tmp.length;
+
+               if (copy_to_user(user_arg, &args, sizeof(args)))
+                       return -EFAULT;
+
+               return ret;
+       }
+#endif
        case TEGRA_DC_EXT_GET_FEATURES:
        {
                struct tegra_dc_ext_feature args;
@@ -1463,7 +1623,7 @@ static const struct file_operations tegra_dc_devops = {
        .release =              tegra_dc_release,
        .unlocked_ioctl =       tegra_dc_ioctl,
 #ifdef CONFIG_COMPAT
-       .compat_ioctl = tegra_dc_ioctl,
+       .compat_ioctl =         tegra_dc_ioctl,
 #endif
 };
 
index 5b2eebde9915d35d2eec09712bcdb0383a2d2c01..72e6329b02e7292ababdf28ce356cc48768455a0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013, NVIDIA Corporation. All rights reserved.
+ * Copyright (C) 2011-2014, NVIDIA Corporation. All rights reserved.
  *
  * Author: Robert Morell <rmorell@nvidia.com>
  * Some code based on fbdev extensions written by:
 #define TEGRA_DC_EXT_FLIP_FLAG_SCAN_COLUMN     (1 << 6)
 #define TEGRA_DC_EXT_FLIP_FLAG_INTERLACE       (1 << 7)
 
+struct tegra_timespec {
+       __s32   tv_sec; /* seconds */
+       __s32   tv_nsec; /* nanoseconds */
+};
+
 struct tegra_dc_ext_flip_windowattr {
        __s32   index;
        __u32   buff_id;
@@ -117,13 +122,13 @@ struct tegra_dc_ext_flip_windowattr {
        __u32   out_h;
        __u32   z;
        __u32   swap_interval;
-       struct timespec timestamp;
+       struct tegra_timespec timestamp;
        union {
                struct {
                        __u32 pre_syncpt_id;
                        __u32 pre_syncpt_val;
                };
-               int pre_syncpt_fd;
+               __s32 pre_syncpt_fd;
        };
        /* These two are optional; if zero, U and V are taken from buff_id */
        __u32   buff_id_u;
@@ -159,11 +164,11 @@ struct tegra_dc_ext_flip_2 {
 };
 
 struct tegra_dc_ext_flip_3 {
-       __u64 win; /* window attributes stored as __u64 for portability. */
+       __u64 win; /* pointer: struct tegra_dc_ext_flip_windowattr* */
        __u8 win_num;
        __u8 reserved1; /* unused - must be 0 */
        __u16 reserved2; /* unused - must be 0 */
-       int post_syncpt_fd;
+       __s32 post_syncpt_fd;
        __u16 dirty_rect[4]; /* x,y,w,h for partial screen update. 0 ignores */
 };
 
@@ -400,9 +405,11 @@ struct tegra_dc_ext_feature {
 #define TEGRA_DC_EXT_GET_CUSTOM_CMU \
        _IOR('D', 0x10, struct tegra_dc_ext_cmu)
 
+/* obsolete - do not use */
 #define TEGRA_DC_EXT_SET_CURSOR_IMAGE_LOW_LATENCY \
        _IOW('D', 0x11, struct tegra_dc_ext_cursor_image)
 
+/* obsolete - do not use */
 #define TEGRA_DC_EXT_SET_CURSOR_LOW_LATENCY \
        _IOW('D', 0x12, struct tegra_dc_ext_cursor_image)
 
@@ -458,7 +465,7 @@ struct tegra_dc_ext_control_output_edid {
 
 struct tegra_dc_ext_event {
        __u32   type;
-       ssize_t data_size;
+       __u32   data_size;
        char    data[0];
 };