misc: tegra-profiler: allocate memory on demand
Igor Nabirushkin [Wed, 31 Jul 2013 11:17:47 +0000 (15:17 +0400)]
Tegra Profiler misc driver:
allocate memory on demand from the user space, not on boot

Bug 1312406

Change-Id: Idc5e8365e38b7faca236e011d9e665f53ac992e6
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/256309
(cherry picked from commit 65234ad36d4c8eeef7753643d6cb2cf0c7f77976)
Reviewed-on: http://git-master/r/268513
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Tested-by: Maxim Morin <mmorin@nvidia.com>
Reviewed-by: Bo Yan <byan@nvidia.com>

drivers/misc/tegra-profiler/comm.c
drivers/misc/tegra-profiler/comm.h
drivers/misc/tegra-profiler/version.h
include/linux/tegra_profiler.h

index 36bfa67..e7a21ea 100644 (file)
@@ -29,8 +29,6 @@
 #include "comm.h"
 #include "version.h"
 
-#define QUADD_SIZE_RB_BUFFER   (0x100000 * 8)  /* 8 MB */
-
 struct quadd_comm_ctx comm_ctx;
 
 static inline void *rb_alloc(unsigned long size)
@@ -60,9 +58,9 @@ static int rb_init(struct quadd_ring_buffer *rb, size_t size)
        rb->buf = (char *) rb_alloc(rb->size);
        if (!rb->buf) {
                pr_err("Ring buffer alloc error\n");
-               return 1;
+               return -ENOMEM;
        }
-       pr_debug("data buffer size: %u\n", (unsigned int)rb->size);
+       pr_info("rb: data buffer size: %u\n", (unsigned int)rb->size);
 
        rb_reset(rb);
 
@@ -444,7 +442,7 @@ device_ioctl(struct file *file,
             unsigned long ioctl_param)
 {
        int err;
-       struct quadd_parameters user_params;
+       struct quadd_parameters *user_params;
        struct quadd_comm_cap cap;
        struct quadd_module_state state;
        struct quadd_module_version versions;
@@ -470,28 +468,44 @@ device_ioctl(struct file *file,
                        return -EBUSY;
                }
 
-               if (copy_from_user(&user_params, (void __user *)ioctl_param,
+               user_params = vmalloc(sizeof(*user_params));
+               if (!user_params)
+                       return -ENOMEM;
+
+               if (copy_from_user(user_params, (void __user *)ioctl_param,
                                   sizeof(struct quadd_parameters))) {
                        pr_err("setup failed\n");
+                       vfree(user_params);
                        mutex_unlock(&comm_ctx.io_mutex);
                        return -EFAULT;
                }
 
-               err = comm_ctx.control->set_parameters(&user_params,
+               err = comm_ctx.control->set_parameters(user_params,
                                                       &comm_ctx.debug_app_uid);
                if (err) {
                        pr_err("error: setup failed\n");
+                       vfree(user_params);
                        mutex_unlock(&comm_ctx.io_mutex);
                        return err;
                }
                comm_ctx.params_ok = 1;
-               comm_ctx.process_pid = user_params.pids[0];
+               comm_ctx.process_pid = user_params->pids[0];
+
+               if (user_params->reserved[QUADD_PARAM_IDX_SIZE_OF_RB] == 0) {
+                       pr_err("error: too old version of daemon\n");
+                       vfree(user_params);
+                       mutex_unlock(&comm_ctx.io_mutex);
+                       return -EINVAL;
+               }
+               comm_ctx.rb_size = user_params->reserved[0];
 
                pr_info("setup success: freq/mafreq: %u/%u, backtrace: %d, pid: %d\n",
-                       user_params.freq,
-                       user_params.ma_freq,
-                       user_params.backtrace,
-                       user_params.pids[0]);
+                       user_params->freq,
+                       user_params->ma_freq,
+                       user_params->backtrace,
+                       user_params->pids[0]);
+
+               vfree(user_params);
                break;
 
        case IOCTL_GET_CAP:
@@ -522,11 +536,11 @@ device_ioctl(struct file *file,
        case IOCTL_GET_STATE:
                comm_ctx.control->get_state(&state);
 
-               state.buffer_size = QUADD_SIZE_RB_BUFFER;
+               state.buffer_size = comm_ctx.rb_size;
 
                spin_lock_irqsave(&rb->lock, flags);
                state.buffer_fill_size =
-                       QUADD_SIZE_RB_BUFFER - rb_get_free_space(rb);
+                       comm_ctx.rb_size - rb_get_free_space(rb);
                spin_unlock_irqrestore(&rb->lock, flags);
 
                if (copy_to_user((void __user *)ioctl_param, &state,
@@ -546,6 +560,14 @@ device_ioctl(struct file *file,
                                return -EFAULT;
                        }
 
+                       err = rb_init(rb, comm_ctx.rb_size);
+                       if (err) {
+                               pr_err("error: rb_init failed\n");
+                               atomic_set(&comm_ctx.active, 0);
+                               mutex_unlock(&comm_ctx.io_mutex);
+                               return err;
+                       }
+
                        if (comm_ctx.control->start()) {
                                pr_err("error: start failed\n");
                                atomic_set(&comm_ctx.active, 0);
@@ -559,6 +581,7 @@ device_ioctl(struct file *file,
        case IOCTL_STOP:
                if (atomic_cmpxchg(&comm_ctx.active, 1, 0)) {
                        comm_ctx.control->stop();
+                       rb_deinit(&comm_ctx.rb);
                        pr_info("Stop profiling success\n");
                }
                break;
@@ -596,7 +619,6 @@ static int comm_init(void)
 {
        int res;
        struct miscdevice *misc_dev;
-       struct quadd_ring_buffer *rb = &comm_ctx.rb;
 
        misc_dev = kzalloc(sizeof(*misc_dev), GFP_KERNEL);
        if (!misc_dev) {
@@ -622,12 +644,6 @@ static int comm_init(void)
        comm_ctx.process_pid = 0;
        comm_ctx.nr_users = 0;
 
-       if (rb_init(rb, QUADD_SIZE_RB_BUFFER)) {
-               free_ctx();
-               unregister();
-               return -ENOMEM;
-       }
-
        return 0;
 }
 
index da8e918..e3c7e28 100644 (file)
@@ -53,7 +53,9 @@ struct quadd_comm_data_interface {
 
 struct quadd_comm_ctx {
        struct quadd_comm_control_interface *control;
+
        struct quadd_ring_buffer rb;
+       size_t rb_size;
 
        atomic_t active;
 
index b5cf277..6bfd1a3 100644 (file)
  *
  */
 
+
 #ifndef __QUADD_VERSION_H
 #define __QUADD_VERSION_H
 
-#define QUADD_MODULE_VERSION           "1.23"
-#define QUADD_MODULE_BRANCH            "Dev"
+#define QUADD_MODULE_VERSION           "1.25"
+#define QUADD_MODULE_BRANCH            "Blackrock2"
 
 #endif /* __QUADD_VERSION_H */
index 609a78f..e8f17ad 100644 (file)
@@ -20,7 +20,9 @@
 #include <linux/ioctl.h>
 
 #define QUADD_SAMPLES_VERSION  16
-#define QUADD_IO_VERSION       4
+#define QUADD_IO_VERSION       5
+
+#define QUADD_IO_VERSION_DYNAMIC_RB    5
 
 #define QUADD_MAX_COUNTERS     32
 #define QUADD_MAX_PROCESS      64
@@ -227,6 +229,10 @@ struct quadd_record_data {
 
 #define QUADD_MAX_PACKAGE_NAME 320
 
+enum {
+       QUADD_PARAM_IDX_SIZE_OF_RB = 0,
+};
+
 struct quadd_parameters {
        u32 freq;
        u32 ma_freq;