]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/staging/intel_sst/intel_sst_app_interface.c
Merge branch 'drm-intel-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ickle...
[linux-beck.git] / drivers / staging / intel_sst / intel_sst_app_interface.c
index 8390aa793b7bbf153664764eb4331e9111d105d4..991440015e9263e415a9449eb9fa7f34dae07f41 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/uaccess.h>
 #include <linux/firmware.h>
 #include <linux/ioctl.h>
-#include <linux/smp_lock.h>
 #ifdef CONFIG_MRST_RAR_HANDLER
 #include <linux/rar_register.h>
 #include "../../../drivers/staging/memrar/memrar.h"
@@ -244,12 +243,12 @@ static int intel_sst_mmap_play_capture(u32 str_id,
        int retval, i;
        struct stream_info *stream;
        struct snd_sst_mmap_buff_entry *buf_entry;
+       struct snd_sst_mmap_buff_entry *tmp_buf;
 
        pr_debug("sst:called for str_id %d\n", str_id);
        retval = sst_validate_strid(str_id);
        if (retval)
                return -EINVAL;
-       BUG_ON(!mmap_buf);
 
        stream = &sst_drv_ctx->streams[str_id];
        if (stream->mmapped != true)
@@ -262,14 +261,24 @@ static int intel_sst_mmap_play_capture(u32 str_id,
        stream->curr_bytes = 0;
        stream->cumm_bytes = 0;
 
+       tmp_buf = kcalloc(mmap_buf->entries, sizeof(*tmp_buf), GFP_KERNEL);
+       if (!tmp_buf)
+               return -ENOMEM;
+       if (copy_from_user(tmp_buf, (void __user *)mmap_buf->buff,
+                       mmap_buf->entries * sizeof(*tmp_buf))) {
+               retval = -EFAULT;
+               goto out_free;
+       }
+
        pr_debug("sst:new buffers count %d status %d\n",
                        mmap_buf->entries, stream->status);
-       buf_entry = mmap_buf->buff;
+       buf_entry = tmp_buf;
        for (i = 0; i < mmap_buf->entries; i++) {
-               BUG_ON(!buf_entry);
                bufs = kzalloc(sizeof(*bufs), GFP_KERNEL);
-               if (!bufs)
-                       return -ENOMEM;
+               if (!bufs) {
+                       retval = -ENOMEM;
+                       goto out_free;
+               }
                bufs->size = buf_entry->size;
                bufs->offset = buf_entry->offset;
                bufs->addr = sst_drv_ctx->mmap_mem;
@@ -293,13 +302,15 @@ static int intel_sst_mmap_play_capture(u32 str_id,
                        if (sst_play_frame(str_id) < 0) {
                                pr_warn("sst: play frames fail\n");
                                mutex_unlock(&stream->lock);
-                               return -EIO;
+                               retval = -EIO;
+                               goto out_free;
                        }
                } else if (stream->ops == STREAM_OPS_CAPTURE) {
                        if (sst_capture_frame(str_id) < 0) {
                                pr_warn("sst: capture frame fail\n");
                                mutex_unlock(&stream->lock);
-                               return -EIO;
+                               retval = -EIO;
+                               goto out_free;
                        }
                }
        }
@@ -314,6 +325,9 @@ static int intel_sst_mmap_play_capture(u32 str_id,
        if (retval >= 0)
                retval = stream->cumm_bytes;
        pr_debug("sst:end of play/rec ioctl bytes = %d!!\n", retval);
+
+out_free:
+       kfree(tmp_buf);
        return retval;
 }
 
@@ -377,7 +391,7 @@ static int snd_sst_fill_kernel_list(struct stream_info *stream,
 {
        struct sst_stream_bufs *stream_bufs;
        unsigned long index, mmap_len;
-       unsigned char *bufp;
+       unsigned char __user *bufp;
        unsigned long size, copied_size;
        int retval = 0, add_to_list = 0;
        static int sent_offset;
@@ -512,9 +526,7 @@ static int snd_sst_copy_userbuf_capture(struct stream_info *stream,
                        /* copy to user */
                        list_for_each_entry_safe(entry, _entry,
                                                copy_to_list, node) {
-                               if (copy_to_user((void *)
-                                            iovec[entry->iov_index].iov_base +
-                                            entry->iov_offset,
+                               if (copy_to_user(iovec[entry->iov_index].iov_base + entry->iov_offset,
                                             kbufs->addr + entry->offset,
                                             entry->size)) {
                                        /* Clean up the list and return error */
@@ -590,7 +602,7 @@ static int intel_sst_read_write(unsigned int str_id, char __user *buf,
                        buf, (int) count, (int) stream->status);
 
        stream->buf_type = SST_BUF_USER_STATIC;
-       iovec.iov_base = (void *)buf;
+       iovec.iov_base = buf;
        iovec.iov_len  = count;
        nr_segs = 1;
 
@@ -863,7 +875,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
                                data->str_id = retval;
                                str_info = &sst_drv_ctx->streams[retval];
                                str_info->src = SST_DRV;
-                               dest = (char *)arg + offsetof(struct snd_sst_params, stream_id);
+                               dest = (char __user *)arg + offsetof(struct snd_sst_params, stream_id);
                                retval = copy_to_user(dest, &retval, sizeof(__u32));
                                if (retval)
                                        retval = -EFAULT;
@@ -932,7 +944,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
                pr_debug("sst: id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n",
                                get_vol.stream_id, get_vol.volume,
                                get_vol.ramp_duration, get_vol.ramp_type);
-               if (copy_to_user((struct snd_sst_vol *)arg,
+               if (copy_to_user((struct snd_sst_vol __user *)arg,
                                &get_vol, sizeof(get_vol))) {
                        retval = -EFAULT;
                        break;
@@ -972,7 +984,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
                        retval = -EIO;
                        break;
                }
-               if (copy_to_user((struct snd_sst_get_stream_params *)arg,
+               if (copy_to_user((struct snd_sst_get_stream_params __user *)arg,
                                        &get_params, sizeof(get_params))) {
                        retval = -EFAULT;
                        break;
@@ -1017,8 +1029,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
                        break;
                }
                memcpy_fromio(&tstamp,
-                       ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
-                       +(str_id * sizeof(tstamp))),
+                       sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
                        sizeof(tstamp));
                time = tstamp.samples_rendered;
                freq = (unsigned long long) tstamp.sampling_frequency;
@@ -1105,62 +1116,83 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
        }
 
        case _IOC_NR(SNDRV_SST_STREAM_DECODE): {
-               struct snd_sst_dbufs *param =
-                               (struct snd_sst_dbufs *)arg, dbufs_local;
-               int i;
+               struct snd_sst_dbufs param;
+               struct snd_sst_dbufs dbufs_local;
                struct snd_sst_buffs ibufs, obufs;
-               struct snd_sst_buff_entry ibuf_temp[param->ibufs->entries],
-                               obuf_temp[param->obufs->entries];
+               struct snd_sst_buff_entry *ibuf_tmp, *obuf_tmp;
+               char __user *dest;
 
                pr_debug("sst: SNDRV_SST_STREAM_DECODE recived\n");
                if (minor != STREAM_MODULE) {
                        retval = -EBADRQC;
                        break;
                }
-               if (!param) {
-                       retval = -EINVAL;
+               if (copy_from_user(&param, (void __user *)arg,
+                               sizeof(param))) {
+                       retval = -EFAULT;
                        break;
                }
 
-               dbufs_local.input_bytes_consumed = param->input_bytes_consumed;
+               dbufs_local.input_bytes_consumed = param.input_bytes_consumed;
                dbufs_local.output_bytes_produced =
-                                       param->output_bytes_produced;
-               dbufs_local.ibufs = &ibufs;
-               dbufs_local.obufs = &obufs;
-               dbufs_local.ibufs->entries = param->ibufs->entries;
-               dbufs_local.ibufs->type = param->ibufs->type;
-               dbufs_local.obufs->entries = param->obufs->entries;
-               dbufs_local.obufs->type = param->obufs->type;
-
-               dbufs_local.ibufs->buff_entry = ibuf_temp;
-               for (i = 0; i < dbufs_local.ibufs->entries; i++) {
-                       ibuf_temp[i].buffer =
-                               param->ibufs->buff_entry[i].buffer;
-                       ibuf_temp[i].size =
-                               param->ibufs->buff_entry[i].size;
+                                       param.output_bytes_produced;
+
+               if (copy_from_user(&ibufs, (void __user *)param.ibufs, sizeof(ibufs))) {
+                       retval = -EFAULT;
+                       break;
                }
-               dbufs_local.obufs->buff_entry = obuf_temp;
-               for (i = 0; i < dbufs_local.obufs->entries; i++) {
-                       obuf_temp[i].buffer =
-                               param->obufs->buff_entry[i].buffer;
-                       obuf_temp[i].size =
-                               param->obufs->buff_entry[i].size;
+               if (copy_from_user(&obufs, (void __user *)param.obufs, sizeof(obufs))) {
+                       retval = -EFAULT;
+                       break;
                }
+
+               ibuf_tmp = kcalloc(ibufs.entries, sizeof(*ibuf_tmp), GFP_KERNEL);
+               obuf_tmp = kcalloc(obufs.entries, sizeof(*obuf_tmp), GFP_KERNEL);
+               if (!ibuf_tmp || !obuf_tmp) {
+                       retval = -ENOMEM;
+                       goto free_iobufs;
+               }
+
+               if (copy_from_user(ibuf_tmp, (void __user *)ibufs.buff_entry,
+                               ibufs.entries * sizeof(*ibuf_tmp))) {
+                       retval = -EFAULT;
+                       goto free_iobufs;
+               }
+               ibufs.buff_entry = ibuf_tmp;
+               dbufs_local.ibufs = &ibufs;
+
+               if (copy_from_user(obuf_tmp, (void __user *)obufs.buff_entry,
+                               obufs.entries * sizeof(*obuf_tmp))) {
+                       retval = -EFAULT;
+                       goto free_iobufs;
+               }
+               obufs.buff_entry = obuf_tmp;
+               dbufs_local.obufs = &obufs;
+
                retval = sst_decode(str_id, &dbufs_local);
-               if (retval)
-                       retval =  -EAGAIN;
-               if (copy_to_user(&param->input_bytes_consumed,
+               if (retval) {
+                       retval = -EAGAIN;
+                       goto free_iobufs;
+               }
+
+               dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
+               if (copy_to_user(dest,
                                &dbufs_local.input_bytes_consumed,
                                sizeof(unsigned long long))) {
-                       retval =  -EFAULT;
-                       break;
+                       retval = -EFAULT;
+                       goto free_iobufs;
                }
-               if (copy_to_user(&param->output_bytes_produced,
+
+               dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
+               if (copy_to_user(dest,
                                &dbufs_local.output_bytes_produced,
                                sizeof(unsigned long long))) {
-                       retval =  -EFAULT;
-                       break;
+                       retval = -EFAULT;
+                       goto free_iobufs;
                }
+free_iobufs:
+               kfree(ibuf_tmp);
+               kfree(obuf_tmp);
                break;
        }
 
@@ -1174,7 +1206,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
                break;
 
        case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): {
-               unsigned long long *bytes = (unsigned long long *)arg;
+               unsigned long long __user *bytes = (unsigned long long __user *)arg;
                struct snd_sst_tstamp tstamp = {0};
 
                pr_debug("sst: STREAM_BYTES_DECODED recieved!\n");
@@ -1183,8 +1215,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
                        break;
                }
                memcpy_fromio(&tstamp,
-                       ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
-                       +(str_id * sizeof(tstamp))),
+                       sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
                        sizeof(tstamp));
                if (copy_to_user(bytes, &tstamp.bytes_processed,
                                sizeof(*bytes)))
@@ -1207,7 +1238,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
                        kfree(fw_info);
                        break;
                }
-               if (copy_to_user((struct snd_sst_dbufs *)arg,
+               if (copy_to_user((struct snd_sst_dbufs __user *)arg,
                                fw_info, sizeof(*fw_info))) {
                        kfree(fw_info);
                        retval = -EFAULT;