diff options
| author | Rygebin <kaankulahli2@gmail.com> | 2017-06-03 15:18:12 +0000 |
|---|---|---|
| committer | Rygebin <kaankulahli2@gmail.com> | 2017-06-04 19:10:34 +0000 |
| commit | 115fb818e75092bdd65276eb0cd92c7294ea6524 (patch) | |
| tree | 17f17d217045deac85db82208fd581a5b5f7d3d7 | |
| parent | 97bb9b1ba8eebead4901c050ea6d251deb3b98d7 (diff) | |
| parent | 2f6fa6bb65962fdce2415150afd04af88559b9d4 (diff) | |
Merge branch 'android-msm-shamrock-3.10-nougat-mr1-release' of https://github.com/android/kernel_msm into cm-14.1
77 files changed, 1430 insertions, 1849 deletions
diff --git a/arch/arm/configs/msm8952-perf_defconfig b/arch/arm/configs/msm8952-perf_defconfig index 68032acab88..3e74e12a6c1 100644 --- a/arch/arm/configs/msm8952-perf_defconfig +++ b/arch/arm/configs/msm8952-perf_defconfig @@ -57,7 +57,6 @@ CONFIG_AEABI=y CONFIG_BALANCE_ANON_FILE_RECLAIM=y CONFIG_HIGHMEM=y CONFIG_ENABLE_VMALLOC_SAVING=y -CONFIG_CP_ACCESS=y CONFIG_AUTO_ZRELADDR=y CONFIG_ARM_DECOMPRESSOR_LIMIT=0x3200000 CONFIG_SCHED_FREQ_INPUT=y diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 97c02d299a3..797a42d86b4 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2015,2017, The Linux Foundation. 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 version 2 and @@ -457,9 +457,9 @@ static int overlap_ptr_cmp(const void *a, const void *b) return st == 0 ? ed : st; } -static void context_build_overlap(struct smq_invoke_ctx *ctx) +static int context_build_overlap(struct smq_invoke_ctx *ctx) { - int i; + int err = 0, i; remote_arg_t *lpra = ctx->lpra; int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); @@ -468,6 +468,11 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) for (i = 0; i < nbufs; ++i) { ctx->overs[i].start = (uintptr_t)lpra[i].buf.pv; ctx->overs[i].end = ctx->overs[i].start + lpra[i].buf.len; + if (lpra[i].buf.len) { + VERIFY(err, ctx->overs[i].end > ctx->overs[i].start); + if (err) + goto bail; + } ctx->overs[i].raix = i; ctx->overps[i] = &ctx->overs[i]; } @@ -493,6 +498,8 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) max = *ctx->overps[i]; } } +bail: + return err; } #define K_COPY_FROM_USER(err, kernel, dst, src, size) \ @@ -557,8 +564,11 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, goto bail; } ctx->sc = invoke->sc; - if (bufs) - context_build_overlap(ctx); + if (bufs) { + VERIFY(err, 0 == context_build_overlap(ctx)); + if (err) + goto bail; + } ctx->retval = -1; ctx->pid = current->pid; ctx->tgid = current->tgid; diff --git a/drivers/crypto/msm/ota_crypto.c b/drivers/crypto/msm/ota_crypto.c index 9fc548d73e6..d9e3395fec5 100644 --- a/drivers/crypto/msm/ota_crypto.c +++ b/drivers/crypto/msm/ota_crypto.c @@ -880,8 +880,8 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, int len; len = _disp_stats(); - - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); return rc; diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index c4334c9d05d..bbdde2206c7 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -1279,7 +1279,8 @@ go_proc: CRYPTO_CONFIG_REG)); /* issue go to crypto */ if (use_hw_key == false) { - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); } else { QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), @@ -1461,7 +1462,8 @@ static int _ce_setup_aead_direct(struct qce_device *pce_dev, CRYPTO_CONFIG_REG)); /* issue go to crypto */ - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); /* * Ensure previous instructions (setting the GO register) @@ -1781,7 +1783,8 @@ static int _ce_setup_cipher_direct(struct qce_device *pce_dev, CRYPTO_CONFIG_REG)); /* issue go to crypto */ if (use_hw_key == false) { - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); } else { QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), @@ -1869,7 +1872,8 @@ static int _ce_f9_setup_direct(struct qce_device *pce_dev, QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + CRYPTO_CONFIG_REG)); /* write go */ - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); /* * Ensure previous instructions (setting the GO register) @@ -1946,7 +1950,8 @@ static int _ce_f8_setup_direct(struct qce_device *pce_dev, QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + CRYPTO_CONFIG_REG)); /* write go */ - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); /* * Ensure previous instructions (setting the GO register) @@ -3024,8 +3029,8 @@ static int _setup_cipher_aes_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3137,8 +3142,8 @@ static int _setup_cipher_des_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3315,8 +3320,8 @@ static int _setup_auth_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3530,8 +3535,8 @@ static int _setup_aead_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3662,8 +3667,8 @@ static int _setup_aead_ccm_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3747,8 +3752,8 @@ static int _setup_f8_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3828,8 +3833,8 @@ static int _setup_f9_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -4425,6 +4430,12 @@ int qce_aead_req(void *handle, struct qce_req *q_req) else q_req->cryptlen = areq->cryptlen - authsize; + if ((q_req->cryptlen > UINT_MAX - areq->assoclen) || + (q_req->cryptlen + areq->assoclen > UINT_MAX - ivsize)) { + pr_err("Integer overflow on total aead req length.\n"); + return -EINVAL; + } + totallen = q_req->cryptlen + areq->assoclen + ivsize; if (pce_dev->support_cmd_dscr) { diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index 0bc47fbf1a9..1bfbe7c1fa3 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1472,6 +1472,15 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, pr_err("%s: Invalid byte offset\n", __func__); goto error; } + total = req->byteoffset; + for (i = 0; i < req->entries; i++) { + if (total > U32_MAX - req->vbuf.src[i].len) { + pr_err("%s:Integer overflow on total src len\n", + __func__); + goto error; + } + total += req->vbuf.src[i].len; + } } if (req->data_len < req->byteoffset) { @@ -1507,7 +1516,7 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, } } /* Check for sum of all dst length is equal to data_len */ - for (i = 0; i < req->entries; i++) { + for (i = 0, total = 0; i < req->entries; i++) { if (req->vbuf.dst[i].len >= U32_MAX - total) { pr_err("%s: Integer overflow on total req dst vbuf length\n", __func__); @@ -2075,9 +2084,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, len = _disp_stats(qcedev); - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); - return rc; } diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index 1c5a18fa4c3..64e8f466a68 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -5147,9 +5147,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, len = _disp_stats(qcrypto); - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); - return rc; } diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c index ada68b69b9e..430292d3e24 100644 --- a/drivers/input/touchscreen/gt9xx/goodix_tool.c +++ b/drivers/input/touchscreen/gt9xx/goodix_tool.c @@ -1,7 +1,7 @@ /* drivers/input/touchscreen/goodix_tool.c * * 2010 - 2012 Goodix Technology. - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, The Linux Foundation. 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 @@ -311,6 +311,7 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, size_t count, loff_t *ppos) { s32 ret = 0; + u8 *dataptr = NULL; mutex_lock(&lock); ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH); @@ -469,6 +470,11 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, ret = CMD_HEAD_LENGTH; exit: + dataptr = cmd_head.data; + memset(&cmd_head, 0, sizeof(cmd_head)); + cmd_head.wr = 0xFF; + cmd_head.data = dataptr; + mutex_unlock(&lock); return ret; } diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c index 392238f20be..bda73cb85d6 100644 --- a/drivers/leds/leds-qpnp-flash.c +++ b/drivers/leds/leds-qpnp-flash.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. 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 version 2 and @@ -213,10 +213,13 @@ struct flash_led_platform_data { }; struct qpnp_flash_led_buffer { - size_t rpos; - size_t wpos; - size_t len; - char data[0]; + struct mutex debugfs_lock; /* Prevent thread concurrency */ + size_t rpos; + size_t wpos; + size_t len; + struct qpnp_flash_led *led; + u32 buffer_cnt; + char data[0]; }; /* @@ -233,10 +236,8 @@ struct qpnp_flash_led { struct workqueue_struct *ordered_workq; struct qpnp_vadc_chip *vadc_dev; struct mutex flash_led_lock; - struct qpnp_flash_led_buffer *log; struct dentry *dbgfs_root; int num_leds; - u32 buffer_cnt; u16 base; u16 current_addr; u16 current2_addr; @@ -266,10 +267,11 @@ static int flash_led_dbgfs_file_open(struct qpnp_flash_led *led, log->rpos = 0; log->wpos = 0; log->len = logbufsize - sizeof(*log); - led->log = log; + mutex_init(&log->debugfs_lock); + log->led = led; - led->buffer_cnt = 1; - file->private_data = led; + log->buffer_cnt = 1; + file->private_data = log; return 0; } @@ -282,24 +284,30 @@ static int flash_led_dfs_open(struct inode *inode, struct file *file) static int flash_led_dfs_close(struct inode *inode, struct file *file) { - struct qpnp_flash_led *led = file->private_data; + struct qpnp_flash_led_buffer *log = file->private_data; - if (led && led->log) { + if (log) { file->private_data = NULL; - kfree(led->log); + mutex_destroy(&log->debugfs_lock); + kfree(log); } return 0; } +#define MIN_BUFFER_WRITE_LEN 20 static int print_to_log(struct qpnp_flash_led_buffer *log, const char *fmt, ...) { va_list args; int cnt; - char *log_buf = &log->data[log->wpos]; + char *log_buf; size_t size = log->len - log->wpos; + if (size < MIN_BUFFER_WRITE_LEN) + return 0; /* not enough buffer left */ + + log_buf = &log->data[log->wpos]; va_start(args, fmt); cnt = vscnprintf(log_buf, size, fmt, args); va_end(args); @@ -310,15 +318,23 @@ static int print_to_log(struct qpnp_flash_led_buffer *log, static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) { - struct qpnp_flash_led *led = fp->private_data; - struct qpnp_flash_led_buffer *log = led->log; + struct qpnp_flash_led_buffer *log = fp->private_data; + struct qpnp_flash_led *led; u8 val; - int rc; + int rc = 0; size_t len; size_t ret; - if (log->rpos >= log->wpos && led->buffer_cnt == 0) - return 0; + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + + mutex_lock(&log->debugfs_lock); + if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || + ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) + goto unlock_mutex; rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid, INT_LATCHED_STS(led->base), &val, 1); @@ -326,17 +342,17 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, dev_err(&led->spmi_dev->dev, "Unable to read from address %x, rc(%d)\n", INT_LATCHED_STS(led->base), rc); - return -EINVAL; + goto unlock_mutex; } - led->buffer_cnt--; + log->buffer_cnt--; rc = print_to_log(log, "0x%05X ", INT_LATCHED_STS(led->base)); if (rc == 0) - return rc; + goto unlock_mutex; rc = print_to_log(log, "0x%02X ", val); if (rc == 0) - return rc; + goto unlock_mutex; if (log->wpos > 0 && log->data[log->wpos - 1] == ' ') log->data[log->wpos - 1] = '\n'; @@ -346,36 +362,49 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, ret = copy_to_user(buf, &log->data[log->rpos], len); if (ret) { pr_err("error copy register value to user\n"); - return -EFAULT; + rc = -EFAULT; + goto unlock_mutex; } len -= ret; *ppos += len; log->rpos += len; - return len; + rc = len; + +unlock_mutex: + mutex_unlock(&log->debugfs_lock); + return rc; } static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) { - struct qpnp_flash_led *led = fp->private_data; - struct qpnp_flash_led_buffer *log = led->log; - int rc; + struct qpnp_flash_led_buffer *log = fp->private_data; + struct qpnp_flash_led *led; + int rc = 0; size_t len; size_t ret; - if (log->rpos >= log->wpos && led->buffer_cnt == 0) - return 0; + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + + mutex_lock(&log->debugfs_lock); + if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || + ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) + goto unlock_mutex; - led->buffer_cnt--; + log->buffer_cnt--; rc = print_to_log(log, "0x%05X ", FLASH_LED_FAULT_STATUS(led->base)); if (rc == 0) - return rc; + goto unlock_mutex; rc = print_to_log(log, "0x%02X ", led->fault_reg); if (rc == 0) - return rc; + goto unlock_mutex; if (log->wpos > 0 && log->data[log->wpos - 1] == ' ') log->data[log->wpos - 1] = '\n'; @@ -385,14 +414,19 @@ static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, ret = copy_to_user(buf, &log->data[log->rpos], len); if (ret) { pr_err("error copy register value to user\n"); - return -EFAULT; + rc = -EFAULT; + goto unlock_mutex; } len -= ret; *ppos += len; log->rpos += len; - return len; + rc = len; + +unlock_mutex: + mutex_unlock(&log->debugfs_lock); + return rc; } static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, @@ -404,10 +438,22 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, int data; size_t ret = 0; - struct qpnp_flash_led *led = file->private_data; - char *kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + struct qpnp_flash_led_buffer *log = file->private_data; + struct qpnp_flash_led *led; + char *kbuf; + + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + + mutex_lock(&log->debugfs_lock); + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } ret = copy_from_user(kbuf, buf, count); if (!ret) { @@ -436,6 +482,8 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, free_buf: kfree(kbuf); +unlock_mutex: + mutex_unlock(&log->debugfs_lock); return ret; } @@ -447,11 +495,22 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, int cnt = 0; int data; size_t ret = 0; + struct qpnp_flash_led_buffer *log = file->private_data; + struct qpnp_flash_led *led; + char *kbuf; - struct qpnp_flash_led *led = file->private_data; - char *kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + + mutex_lock(&log->debugfs_lock); + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } ret = copy_from_user(kbuf, buf, count); if (ret == count) { @@ -479,6 +538,8 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, free_buf: kfree(kbuf); +unlock_mutex: + mutex_unlock(&log->debugfs_lock); return ret; } diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c index eee402593eb..94bc01712ac 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c @@ -1151,6 +1151,13 @@ static struct msm_cam_clk_info *msm_cci_get_clk(struct cci_device *cci_dev, struct msm_cci_clk_params_t *clk_params = NULL; enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; struct device_node *of_node = cci_dev->pdev->dev.of_node; + + if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) { + pr_err("%s:%d invalid i2c_freq_mode %d\n", + __func__, __LINE__, i2c_freq_mode); + return NULL; + } + clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; cci_clk_src = clk_params->cci_clk_src; diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c index 0022fc5275c..f70cd662fb6 100755 --- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c @@ -293,6 +293,16 @@ static int32_t msm_flash_i2c_init( flash_ctrl->power_info.power_down_setting_size = flash_ctrl->power_setting_array.size_down; + if ((flash_ctrl->power_info.power_setting_size > MAX_POWER_CONFIG) || + (flash_ctrl->power_info.power_down_setting_size > MAX_POWER_CONFIG)) { + pr_err("%s:%d invalid power setting size=%d size_down=%d\n", + __func__, __LINE__, + flash_ctrl->power_info.power_setting_size, + flash_ctrl->power_info.power_down_setting_size); + rc = -EINVAL; + goto msm_flash_i2c_init_fail; + } + rc = msm_camera_power_up(&flash_ctrl->power_info, flash_ctrl->flash_device_type, &flash_ctrl->flash_i2c_client); diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c index 29ed44ab3db..b6130709957 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c @@ -42,6 +42,7 @@ void msm_camera_io_w_mb(u32 data, void __iomem *addr) u32 msm_camera_io_r(void __iomem *addr) { uint32_t data = readl_relaxed(addr); + CDBG("%s: 0x%pK %08x\n", __func__, (addr), (data)); return data; } @@ -49,6 +50,7 @@ u32 msm_camera_io_r(void __iomem *addr) u32 msm_camera_io_r_mb(void __iomem *addr) { uint32_t data; + rmb(); data = readl_relaxed(addr); rmb(); @@ -73,6 +75,7 @@ void msm_camera_io_dump(void __iomem *addr, int size) int i; u32 *p = (u32 *) addr; u32 data; + CDBG("%s: %pK %d\n", __func__, addr, size); line_str[0] = '\0'; p_str = line_str; @@ -152,6 +155,7 @@ int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info, int i; int rc = 0; long clk_rate; + if (enable) { for (i = 0; i < num_clk; i++) { CDBG("%s enable %s\n", __func__, clk_info[i].clk_name); @@ -258,6 +262,12 @@ int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg, pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__); return -EINVAL; } + + if (cam_vreg == NULL) { + pr_err("%s:%d cam_vreg sequence invalid\n", __func__, __LINE__); + return -EINVAL; + } + if (!num_vreg_seq) num_vreg_seq = num_vreg; @@ -434,6 +444,7 @@ void msm_camera_bus_scale_cfg(uint32_t bus_perf_client, enum msm_bus_perf_setting perf_setting) { int rc = 0; + if (!bus_perf_client) { pr_err("%s: Bus Client NOT Registered!!!\n", __func__); return; diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index a2f4501c23c..f61d1d7ba76 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1939,6 +1939,9 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, if (!found) return -ENOENT; + if (ctrl->info.size < mapping->size) + return -EINVAL; + if (mutex_lock_interruptible(&chain->ctrl_mutex)) return -ERESTARTSYS; diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c index 3ad63abf5b2..fd35c264238 100644 --- a/drivers/mfd/wcd9xxx-slimslave.c +++ b/drivers/mfd/wcd9xxx-slimslave.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. 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 version 2 and @@ -62,6 +62,10 @@ int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la, goto err; } + if (!rx_num || rx_num > wcd9xxx->num_rx_port) { + pr_err("%s: invalid rx num %d\n", __func__, rx_num); + return -EINVAL; + } if (wcd9xxx->rx_chs) { wcd9xxx->num_rx_port = rx_num; for (i = 0; i < rx_num; i++) { @@ -84,6 +88,10 @@ int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la, wcd9xxx->num_rx_port); } + if (!tx_num || tx_num > wcd9xxx->num_tx_port) { + pr_err("%s: invalid tx num %d\n", __func__, tx_num); + return -EINVAL; + } if (wcd9xxx->tx_chs) { wcd9xxx->num_tx_port = tx_num; for (i = 0; i < tx_num; i++) { diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index ec3b5c2d8d2..166601e22db 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -17,7 +17,6 @@ #include "q6audio_common.h" #include "audio_utils_aio.h" #include <sound/msm-audio-effects-q6-v2.h> -#include <sound/msm-dts-eagle.h> #define MAX_CHANNELS_SUPPORTED 8 #define WAIT_TIMEDOUT_DURATION_SECS 1 @@ -29,6 +28,8 @@ struct q6audio_effects { struct audio_client *ac; struct msm_hwacc_effects_config config; + struct mutex lock; + atomic_t in_count; atomic_t out_count; @@ -51,31 +52,11 @@ static void audio_effects_init_pp(struct audio_client *ac) pr_err("%s: audio client null to init pp\n", __func__); return; } - switch (ac->topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_1); - if (ret < 0) - pr_err("%s: Send SoftVolume1 Param failed ret=%d\n", - __func__, ret); - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_2); - if (ret < 0) - pr_err("%s: Send SoftVolume2 Param failed ret=%d\n", - __func__, ret); - - msm_dts_eagle_init_master_module(ac); - - break; - default: - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_1); - if (ret < 0) - pr_err("%s: Send SoftVolume Param failed ret=%d\n", - __func__, ret); - break; - } + ret = q6asm_set_softvolume_v2(ac, &softvol, + SOFT_VOLUME_INSTANCE_1); + if (ret < 0) + pr_err("%s: Send SoftVolume Param failed ret=%d\n", + __func__, ret); } static void audio_effects_deinit_pp(struct audio_client *ac) @@ -84,13 +65,6 @@ static void audio_effects_deinit_pp(struct audio_client *ac) pr_err("%s: audio client null to deinit pp\n", __func__); return; } - switch (ac->topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - msm_dts_eagle_deinit_master_module(ac); - break; - default: - break; - } } static void audio_effects_event_handler(uint32_t opcode, uint32_t token, @@ -230,8 +204,11 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, uint32_t idx = 0; uint32_t size = 0; + mutex_lock(&effects->lock); + if (!effects->started) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } @@ -241,11 +218,13 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (!rc) { pr_err("%s: write wait_event_timeout\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } if (!atomic_read(&effects->out_count)) { pr_err("%s: pcm stopped out_count 0\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } @@ -254,6 +233,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (copy_from_user(bufptr, (void *)arg, effects->config.buf_cfg.output_len)) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } rc = q6asm_write(effects->ac, @@ -261,6 +241,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, 0, 0, NO_TIMESTAMP); if (rc < 0) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } atomic_dec(&effects->out_count); @@ -268,6 +249,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: AUDIO_EFFECTS_WRITE: Buffer dropped\n", __func__); } + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_READ: { @@ -400,33 +382,6 @@ static long audio_effects_set_pp_param(struct q6audio_effects *effects, &(effects->audio_effects.topo_switch_vol), (long *)&values[1], SOFT_VOLUME_INSTANCE_2); break; - case DTS_EAGLE_MODULE_ENABLE: - pr_debug("%s: DTS_EAGLE_MODULE_ENABLE\n", __func__); - if (msm_audio_effects_is_effmodule_supp_in_top( - effects_module, effects->ac->topology)) { - /* - * HPX->OFF: first disable HPX and then - * enable SA+ - * HPX->ON: first disable SA+ and then - * enable HPX - */ - bool hpx_state = (bool)values[1]; - if (hpx_state) - msm_audio_effects_enable_extn(effects->ac, - &(effects->audio_effects), - false); - msm_dts_eagle_enable_asm(effects->ac, - hpx_state, - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); - msm_dts_eagle_enable_asm(effects->ac, - hpx_state, - AUDPROC_MODULE_ID_DTS_HPX_POSTMIX); - if (!hpx_state) - msm_audio_effects_enable_extn(effects->ac, - &(effects->audio_effects), - true); - } - break; default: pr_err("%s: Invalid effects config module\n", __func__); rc = -EINVAL; @@ -464,6 +419,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, break; } case AUDIO_EFFECTS_SET_BUF_LEN: { + mutex_lock(&effects->lock); if (copy_from_user(&effects->config.buf_cfg, (void *)arg, sizeof(effects->config.buf_cfg))) { pr_err("%s: copy from user for AUDIO_EFFECTS_SET_BUF_LEN failed\n", @@ -473,6 +429,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, pr_debug("%s: write buf len: %d, read buf len: %d\n", __func__, effects->config.buf_cfg.output_len, effects->config.buf_cfg.input_len); + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_GET_BUF_AVAIL: { @@ -717,6 +674,7 @@ static int audio_effects_release(struct inode *inode, struct file *file) } q6asm_audio_client_free(effects->ac); + mutex_destroy(&effects->lock); kfree(effects); pr_debug("%s: close session success\n", __func__); @@ -747,6 +705,7 @@ static int audio_effects_open(struct inode *inode, struct file *file) init_waitqueue_head(&effects->read_wait); init_waitqueue_head(&effects->write_wait); + mutex_init(&effects->lock); effects->opened = 0; effects->started = 0; diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index b228952f554..79f5c7843fd 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -1,6 +1,6 @@ /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver * - * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, The Linux Foundation. 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 version 2 and @@ -78,6 +78,9 @@ /* Encrypt/Decrypt Data Integrity Partition (DIP) for MDTP */ #define SCM_MDTP_CIPHER_DIP 0x01 +/* Maximum Allowed Size (128K) of Data Integrity Partition (DIP) for MDTP */ +#define MAX_DIP 0x20000 + #define RPMB_SERVICE 0x2000 #define SSD_SERVICE 0x3000 @@ -116,6 +119,35 @@ static DEFINE_MUTEX(qsee_bw_mutex); static DEFINE_MUTEX(app_access_lock); static DEFINE_MUTEX(clk_access_lock); +struct sglist_info { + uint32_t indexAndFlags; + uint32_t sizeOrCount; +}; + +/* + * The 31th bit indicates only one or multiple physical address inside + * the request buffer. If it is set, the index locates a single physical addr + * inside the request buffer, and `sizeOrCount` is the size of the memory being + * shared at that physical address. + * Otherwise, the index locates an array of {start, len} pairs (a + * "scatter/gather list"), and `sizeOrCount` gives the number of entries in + * that array. + * + * The 30th bit indicates 64 or 32bit address; when it is set, physical addr + * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values. + * + * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer. + */ +#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \ + ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff))) + +#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD) + +#define FEATURE_ID_WHITELIST 15 /*whitelist feature id*/ + +#define MAKE_WHITELIST_VERSION(major, minor, patch) \ + (((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF)) + struct qseecom_registered_listener_list { struct list_head list; struct qseecom_register_listener_req svc; @@ -130,6 +162,8 @@ struct qseecom_registered_listener_list { bool listener_in_use; /* wq for thread blocked on this listener*/ wait_queue_head_t listener_block_app_wq; + struct sglist_info sglistinfo_ptr[MAX_ION_FD]; + uint32_t sglist_cnt; }; struct qseecom_registered_app_list { @@ -181,6 +215,7 @@ struct qseecom_control { uint32_t qseos_version; uint32_t qsee_version; struct device *pdev; + bool whitelist_support; bool commonlib_loaded; bool commonlib64_loaded; struct ion_handle *cmnlib_ion_handle; @@ -254,6 +289,9 @@ struct qseecom_dev_handle { bool perf_enabled; bool fast_load_enabled; enum qseecom_bandwidth_request_mode mode; + struct sglist_info sglistinfo_ptr[MAX_ION_FD]; + uint32_t sglist_cnt; + bool use_legacy_cmd; }; struct qseecom_key_id_usage_desc { @@ -513,6 +551,34 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, ret = scm_call2(smc_id, &desc); break; } + case QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST: { + struct qseecom_client_listener_data_irsp *req; + struct qseecom_client_listener_data_64bit_irsp *req_64; + + smc_id = + TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID; + desc.arginfo = + TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID; + if (qseecom.qsee_version < QSEE_VERSION_40) { + req = + (struct qseecom_client_listener_data_irsp *) + req_buf; + desc.args[0] = req->listener_id; + desc.args[1] = req->status; + desc.args[2] = req->sglistinfo_ptr; + desc.args[3] = req->sglistinfo_len; + } else { + req_64 = + (struct qseecom_client_listener_data_64bit_irsp *) + req_buf; + desc.args[0] = req_64->listener_id; + desc.args[1] = req_64->status; + desc.args[2] = req_64->sglistinfo_ptr; + desc.args[3] = req_64->sglistinfo_len; + } + ret = scm_call2(smc_id, &desc); + break; + } case QSEOS_LOAD_EXTERNAL_ELF_COMMAND: { struct qseecom_load_app_ireq *req; struct qseecom_load_app_64bit_ireq *req_64bit; @@ -568,6 +634,38 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, ret = scm_call2(smc_id, &desc); break; } + case QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST: { + struct qseecom_client_send_data_ireq *req; + struct qseecom_client_send_data_64bit_ireq *req_64bit; + + smc_id = TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID; + desc.arginfo = + TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID_PARAM_ID; + if (qseecom.qsee_version < QSEE_VERSION_40) { + req = (struct qseecom_client_send_data_ireq *) + req_buf; + desc.args[0] = req->app_id; + desc.args[1] = req->req_ptr; + desc.args[2] = req->req_len; + desc.args[3] = req->rsp_ptr; + desc.args[4] = req->rsp_len; + desc.args[5] = req->sglistinfo_ptr; + desc.args[6] = req->sglistinfo_len; + } else { + req_64bit = + (struct qseecom_client_send_data_64bit_ireq *) + req_buf; + desc.args[0] = req_64bit->app_id; + desc.args[1] = req_64bit->req_ptr; + desc.args[2] = req_64bit->req_len; + desc.args[3] = req_64bit->rsp_ptr; + desc.args[4] = req_64bit->rsp_len; + desc.args[5] = req_64bit->sglistinfo_ptr; + desc.args[6] = req_64bit->sglistinfo_len; + } + ret = scm_call2(smc_id, &desc); + break; + } case QSEOS_RPMB_PROVISION_KEY_COMMAND: { struct qseecom_client_send_service_ireq *req; req = (struct qseecom_client_send_service_ireq *) @@ -695,6 +793,36 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, ret = scm_call2(smc_id, &desc); break; } + case QSEOS_TEE_OPEN_SESSION_WHITELIST: { + struct qseecom_qteec_ireq *req; + struct qseecom_qteec_64bit_ireq *req_64bit; + + smc_id = TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID; + desc.arginfo = + TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID_PARAM_ID; + if (qseecom.qsee_version < QSEE_VERSION_40) { + req = (struct qseecom_qteec_ireq *)req_buf; + desc.args[0] = req->app_id; + desc.args[1] = req->req_ptr; + desc.args[2] = req->req_len; + desc.args[3] = req->resp_ptr; + desc.args[4] = req->resp_len; + desc.args[5] = req->sglistinfo_ptr; + desc.args[6] = req->sglistinfo_len; + } else { + req_64bit = (struct qseecom_qteec_64bit_ireq *) + req_buf; + desc.args[0] = req_64bit->app_id; + desc.args[1] = req_64bit->req_ptr; + desc.args[2] = req_64bit->req_len; + desc.args[3] = req_64bit->resp_ptr; + desc.args[4] = req_64bit->resp_len; + desc.args[5] = req_64bit->sglistinfo_ptr; + desc.args[6] = req_64bit->sglistinfo_len; + } + ret = scm_call2(smc_id, &desc); + break; + } case QSEOS_TEE_INVOKE_COMMAND: { struct qseecom_qteec_ireq *req; struct qseecom_qteec_64bit_ireq *req_64bit; @@ -719,6 +847,36 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, ret = scm_call2(smc_id, &desc); break; } + case QSEOS_TEE_INVOKE_COMMAND_WHITELIST: { + struct qseecom_qteec_ireq *req; + struct qseecom_qteec_64bit_ireq *req_64bit; + + smc_id = TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID; + desc.arginfo = + TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID_PARAM_ID; + if (qseecom.qsee_version < QSEE_VERSION_40) { + req = (struct qseecom_qteec_ireq *)req_buf; + desc.args[0] = req->app_id; + desc.args[1] = req->req_ptr; + desc.args[2] = req->req_len; + desc.args[3] = req->resp_ptr; + desc.args[4] = req->resp_len; + desc.args[5] = req->sglistinfo_ptr; + desc.args[6] = req->sglistinfo_len; + } else { + req_64bit = (struct qseecom_qteec_64bit_ireq *) + req_buf; + desc.args[0] = req_64bit->app_id; + desc.args[1] = req_64bit->req_ptr; + desc.args[2] = req_64bit->req_len; + desc.args[3] = req_64bit->resp_ptr; + desc.args[4] = req_64bit->resp_len; + desc.args[5] = req_64bit->sglistinfo_ptr; + desc.args[6] = req_64bit->sglistinfo_len; + } + ret = scm_call2(smc_id, &desc); + break; + } case QSEOS_TEE_CLOSE_SESSION: { struct qseecom_qteec_ireq *req; struct qseecom_qteec_64bit_ireq *req_64bit; @@ -946,7 +1104,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, return -EBUSY; } - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); if (!new_entry) { pr_err("kmalloc failed\n"); return -ENOMEM; @@ -1398,6 +1556,16 @@ static int __qseecom_qseos_fail_return_resp_tz(struct qseecom_dev_handle *data, return ret; } +static void __qseecom_clean_listener_sglistinfo( + struct qseecom_registered_listener_list *ptr_svc) +{ + if (ptr_svc->sglist_cnt) { + memset(ptr_svc->sglistinfo_ptr, 0, + SGLISTINFO_TABLE_SIZE); + ptr_svc->sglist_cnt = 0; + } +} + static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, struct qseecom_command_scm_resp *resp) { @@ -1406,9 +1574,14 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, uint32_t lstnr; unsigned long flags; struct qseecom_client_listener_data_irsp send_data_rsp; + struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit; struct qseecom_registered_listener_list *ptr_svc = NULL; sigset_t new_sigset; sigset_t old_sigset; + uint32_t status; + void *cmd_buf = NULL; + size_t cmd_len; + struct sglist_info *table = NULL; while (resp->result == QSEOS_RESULT_INCOMPLETE) { lstnr = resp->data; @@ -1420,6 +1593,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head, list) { if (ptr_svc->svc.listener_id == lstnr) { + ptr_svc->listener_in_use = true; ptr_svc->rcv_req_flag = 1; wake_up_interruptible(&ptr_svc->rcv_req_wq); break; @@ -1467,14 +1641,42 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", data->client.app_id, lstnr, ret); rc = -ENODEV; - send_data_rsp.status = QSEOS_RESULT_FAILURE; + status = QSEOS_RESULT_FAILURE; } else { - send_data_rsp.status = QSEOS_RESULT_SUCCESS; + status = QSEOS_RESULT_SUCCESS; } qseecom.send_resp_flag = 0; - send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; - send_data_rsp.listener_id = lstnr; + ptr_svc->send_resp_flag = 0; + table = ptr_svc->sglistinfo_ptr; + if (qseecom.qsee_version < QSEE_VERSION_40) { + send_data_rsp.listener_id = lstnr; + send_data_rsp.status = status; + send_data_rsp.sglistinfo_ptr = + (uint32_t)virt_to_phys(table); + send_data_rsp.sglistinfo_len = + SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp; + cmd_len = sizeof(send_data_rsp); + } else { + send_data_rsp_64bit.listener_id = lstnr; + send_data_rsp_64bit.status = status; + send_data_rsp_64bit.sglistinfo_ptr = + virt_to_phys(table); + send_data_rsp_64bit.sglistinfo_len = + SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp_64bit; + cmd_len = sizeof(send_data_rsp_64bit); + } + if (qseecom.whitelist_support == false) + *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND; + else + *(uint32_t *)cmd_buf = + QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; if (ptr_svc) msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, ptr_svc->sb_virt, ptr_svc->sb_length, @@ -1484,9 +1686,9 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, __qseecom_enable_clk(CLK_QSEE); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, - (const void *)&send_data_rsp, - sizeof(send_data_rsp), resp, - sizeof(*resp)); + cmd_buf, cmd_len, resp, sizeof(*resp)); + ptr_svc->listener_in_use = false; + __qseecom_clean_listener_sglistinfo(ptr_svc); if (ret) { pr_err("scm_call() failed with err: %d (app_id = %d)\n", ret, data->client.app_id); @@ -1519,9 +1721,14 @@ static int __qseecom_reentrancy_process_incomplete_cmd( uint32_t lstnr; unsigned long flags; struct qseecom_client_listener_data_irsp send_data_rsp; + struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit; struct qseecom_registered_listener_list *ptr_svc = NULL; sigset_t new_sigset; sigset_t old_sigset; + uint32_t status; + void *cmd_buf = NULL; + size_t cmd_len; + struct sglist_info *table = NULL; while (resp->result == QSEOS_RESULT_INCOMPLETE) { lstnr = resp->data; @@ -1585,13 +1792,38 @@ static int __qseecom_reentrancy_process_incomplete_cmd( pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", data->client.app_id, lstnr, ret); rc = -ENODEV; - send_data_rsp.status = QSEOS_RESULT_FAILURE; + status = QSEOS_RESULT_FAILURE; } else { - send_data_rsp.status = QSEOS_RESULT_SUCCESS; + status = QSEOS_RESULT_SUCCESS; } - - send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; - send_data_rsp.listener_id = lstnr; + table = ptr_svc->sglistinfo_ptr; + if (qseecom.qsee_version < QSEE_VERSION_40) { + send_data_rsp.listener_id = lstnr; + send_data_rsp.status = status; + send_data_rsp.sglistinfo_ptr = + (uint32_t)virt_to_phys(table); + send_data_rsp.sglistinfo_len = SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp; + cmd_len = sizeof(send_data_rsp); + } else { + send_data_rsp_64bit.listener_id = lstnr; + send_data_rsp_64bit.status = status; + send_data_rsp_64bit.sglistinfo_ptr = + virt_to_phys(table); + send_data_rsp_64bit.sglistinfo_len = + SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp_64bit; + cmd_len = sizeof(send_data_rsp_64bit); + } + if (qseecom.whitelist_support == false) + *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND; + else + *(uint32_t *)cmd_buf = + QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; if (ptr_svc) msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, ptr_svc->sb_virt, ptr_svc->sb_length, @@ -1601,11 +1833,9 @@ static int __qseecom_reentrancy_process_incomplete_cmd( __qseecom_enable_clk(CLK_QSEE); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, - (const void *)&send_data_rsp, - sizeof(send_data_rsp), resp, - sizeof(*resp)); - + cmd_buf, cmd_len, resp, sizeof(*resp)); ptr_svc->listener_in_use = false; + __qseecom_clean_listener_sglistinfo(ptr_svc); wake_up_interruptible(&ptr_svc->listener_block_app_wq); if (ret) { @@ -2134,11 +2364,6 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, return -EINVAL; } - if ((!req_ptr->cmd_req_buf) || (!req_ptr->resp_buf)) { - pr_err("Invalid req/resp buffer, exiting\n"); - return -EINVAL; - } - /* Clients need to ensure req_buf is at base offset of shared buffer */ if ((uintptr_t)req_ptr->cmd_req_buf != data_ptr->client.user_virt_sb_base) { @@ -2146,15 +2371,11 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, return -EINVAL; } - if (((uintptr_t)req_ptr->resp_buf < - data_ptr->client.user_virt_sb_base) || - ((uintptr_t)req_ptr->resp_buf >= - (data_ptr->client.user_virt_sb_base + - data_ptr->client.sb_length))){ - pr_err("response buffer address not within shared bufffer\n"); + if (data_ptr->client.sb_length < + sizeof(struct qseecom_rpmb_provision_key)) { + pr_err("shared buffer is too small to hold key type\n"); return -EINVAL; } - req_buf = data_ptr->client.sb_virt; send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id; @@ -2181,36 +2402,6 @@ int __qseecom_process_fsm_key_svc_cmd(struct qseecom_dev_handle *data_ptr, return -EINVAL; } - if (((uintptr_t)req_ptr->cmd_req_buf < - data_ptr->client.user_virt_sb_base) || - ((uintptr_t)req_ptr->cmd_req_buf >= - (data_ptr->client.user_virt_sb_base + - data_ptr->client.sb_length))) { - pr_err("cmd buffer address not within shared bufffer\n"); - return -EINVAL; - } - - if (((uintptr_t)req_ptr->resp_buf < - data_ptr->client.user_virt_sb_base) || - ((uintptr_t)req_ptr->resp_buf >= - (data_ptr->client.user_virt_sb_base + - data_ptr->client.sb_length))){ - pr_err("response buffer address not within shared bufffer\n"); - return -EINVAL; - } - - if ((req_ptr->cmd_req_len == 0) || (req_ptr->resp_len == 0) || - req_ptr->cmd_req_len > data_ptr->client.sb_length || - req_ptr->resp_len > data_ptr->client.sb_length) { - pr_err("cmd buffer length or response buffer length not valid\n"); - return -EINVAL; - } - - if (req_ptr->cmd_req_len > UINT_MAX - req_ptr->resp_len) { - pr_err("Integer overflow detected in req_len & rsp_len, exiting now\n"); - return -EINVAL; - } - reqd_len_sb_in = req_ptr->cmd_req_len + req_ptr->resp_len; if (reqd_len_sb_in > data_ptr->client.sb_length) { pr_err("Not enough memory to fit cmd_buf and resp_buf. "); @@ -2232,28 +2423,11 @@ int __qseecom_process_fsm_key_svc_cmd(struct qseecom_dev_handle *data_ptr, return ret; } -static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, - void __user *argp) +static int __validate_send_service_cmd_inputs(struct qseecom_dev_handle *data, + struct qseecom_send_svc_cmd_req *req) { - int ret = 0; - struct qseecom_client_send_service_ireq send_svc_ireq; - struct qseecom_client_send_fsm_key_req send_fsm_key_svc_ireq; - struct qseecom_command_scm_resp resp; - struct qseecom_send_svc_cmd_req req; - void *send_req_ptr; - size_t req_buf_size; - - /*struct qseecom_command_scm_resp resp;*/ - - if (copy_from_user(&req, - (void __user *)argp, - sizeof(req))) { - pr_err("copy_from_user failed\n"); - return -EFAULT; - } - - if ((req.resp_buf == NULL) || (req.cmd_req_buf == NULL)) { - pr_err("cmd buffer or response buffer is null\n"); + if (!req || !req->resp_buf || !req->cmd_req_buf) { + pr_err("req or cmd buffer or response buffer is null\n"); return -EINVAL; } @@ -2277,6 +2451,86 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, return -EINVAL; } + if (((uintptr_t)req->cmd_req_buf < + data->client.user_virt_sb_base) || + ((uintptr_t)req->cmd_req_buf >= + (data->client.user_virt_sb_base + data->client.sb_length))) { + pr_err("cmd buffer address not within shared bufffer\n"); + return -EINVAL; + } + if (((uintptr_t)req->resp_buf < + data->client.user_virt_sb_base) || + ((uintptr_t)req->resp_buf >= + (data->client.user_virt_sb_base + data->client.sb_length))) { + pr_err("response buffer address not within shared bufffer\n"); + return -EINVAL; + } + if ((req->cmd_req_len == 0) || (req->resp_len == 0) || + (req->cmd_req_len > data->client.sb_length) || + (req->resp_len > data->client.sb_length)) { + pr_err("cmd buf length or response buf length not valid\n"); + return -EINVAL; + } + if (req->cmd_req_len > UINT_MAX - req->resp_len) { + pr_err("Integer overflow detected in req_len & rsp_len\n"); + return -EINVAL; + } + + if ((req->cmd_req_len + req->resp_len) > data->client.sb_length) { + pr_debug("Not enough memory to fit cmd_buf.\n"); + pr_debug("resp_buf. Required: %u, Available: %zu\n", + (req->cmd_req_len + req->resp_len), + data->client.sb_length); + return -ENOMEM; + } + if ((uintptr_t)req->cmd_req_buf > (ULONG_MAX - req->cmd_req_len)) { + pr_err("Integer overflow in req_len & cmd_req_buf\n"); + return -EINVAL; + } + if ((uintptr_t)req->resp_buf > (ULONG_MAX - req->resp_len)) { + pr_err("Integer overflow in resp_len & resp_buf\n"); + return -EINVAL; + } + if (data->client.user_virt_sb_base > + (ULONG_MAX - data->client.sb_length)) { + pr_err("Integer overflow in user_virt_sb_base & sb_length\n"); + return -EINVAL; + } + if ((((uintptr_t)req->cmd_req_buf + req->cmd_req_len) > + ((uintptr_t)data->client.user_virt_sb_base + + data->client.sb_length)) || + (((uintptr_t)req->resp_buf + req->resp_len) > + ((uintptr_t)data->client.user_virt_sb_base + + data->client.sb_length))) { + pr_err("cmd buf or resp buf is out of shared buffer region\n"); + return -EINVAL; + } + return 0; +} + +static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, + void __user *argp) +{ + int ret = 0; + struct qseecom_client_send_service_ireq send_svc_ireq; + struct qseecom_client_send_fsm_key_req send_fsm_key_svc_ireq; + struct qseecom_command_scm_resp resp; + struct qseecom_send_svc_cmd_req req; + void *send_req_ptr; + size_t req_buf_size; + + /*struct qseecom_command_scm_resp resp;*/ + + if (copy_from_user(&req, + (void __user *)argp, + sizeof(req))) { + pr_err("copy_from_user failed\n"); + return -EFAULT; + } + + if (__validate_send_service_cmd_inputs(data, &req)) + return -EINVAL; + data->type = QSEECOM_SECURE_SERVICE; switch (req.cmd_id) { @@ -2528,8 +2782,8 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, { int ret = 0; u32 reqd_len_sb_in = 0; - struct qseecom_client_send_data_ireq send_data_req; - struct qseecom_client_send_data_64bit_ireq send_data_req_64bit; + struct qseecom_client_send_data_ireq send_data_req = {0}; + struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0}; struct qseecom_command_scm_resp resp; unsigned long flags; struct qseecom_registered_app_list *ptr_app; @@ -2537,6 +2791,7 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, int name_len = 0; void *cmd_buf = NULL; size_t cmd_len; + struct sglist_info *table = data->sglistinfo_ptr; reqd_len_sb_in = req->cmd_req_len + req->resp_len; /* find app_id & img_name from list */ @@ -2561,7 +2816,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, } if (qseecom.qsee_version < QSEE_VERSION_40) { - send_data_req.qsee_cmd_id = QSEOS_CLIENT_SEND_DATA_COMMAND; send_data_req.app_id = data->client.app_id; send_data_req.req_ptr = (uint32_t)(__qseecom_uvirt_to_kphys( data, (uintptr_t)req->cmd_req_buf)); @@ -2569,11 +2823,14 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, send_data_req.rsp_ptr = (uint32_t)(__qseecom_uvirt_to_kphys( data, (uintptr_t)req->resp_buf)); send_data_req.rsp_len = req->resp_len; + send_data_req.sglistinfo_ptr = + (uint32_t)virt_to_phys(table); + send_data_req.sglistinfo_len = SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); cmd_buf = (void *)&send_data_req; cmd_len = sizeof(struct qseecom_client_send_data_ireq); } else { - send_data_req_64bit.qsee_cmd_id = - QSEOS_CLIENT_SEND_DATA_COMMAND; send_data_req_64bit.app_id = data->client.app_id; send_data_req_64bit.req_ptr = __qseecom_uvirt_to_kphys(data, (uintptr_t)req->cmd_req_buf); @@ -2595,10 +2852,20 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, send_data_req_64bit.rsp_len); return -EFAULT; } + send_data_req_64bit.sglistinfo_ptr = + (uint64_t)virt_to_phys(table); + send_data_req_64bit.sglistinfo_len = SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); cmd_buf = (void *)&send_data_req_64bit; cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq); } + if (qseecom.whitelist_support == false || data->use_legacy_cmd == true) + *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND; + else + *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; + msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, reqd_len_sb_in, @@ -2699,6 +2966,8 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, struct qseecom_send_modfd_cmd_req *req = NULL; struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL; struct qseecom_registered_listener_list *this_lstnr = NULL; + uint32_t offset; + struct sg_table *sg_ptr; if ((data->type != QSEECOM_LISTENER_SERVICE) && (data->type != QSEECOM_CLIENT_APP)) @@ -2720,7 +2989,6 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, } for (i = 0; i < MAX_ION_FD; i++) { - struct sg_table *sg_ptr = NULL; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { ihandle = ion_import_dma_buf(qseecom.ion_clnt, @@ -2852,14 +3120,37 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, goto err; } } - if (cleanup) + + if (cleanup) { msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_INV_CACHES); - else + } else { msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); + if (data->type == QSEECOM_CLIENT_APP) { + offset = req->ifd_data[i].cmd_buf_offset; + data->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( + (sg_ptr->nents == 1), 0, offset); + data->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + data->sglist_cnt = i + 1; + } else { + offset = (lstnr_resp->ifd_data[i].cmd_buf_offset + + (uintptr_t)lstnr_resp->resp_buf_ptr - + (uintptr_t)this_lstnr->sb_virt); + this_lstnr->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( + (sg_ptr->nents == 1), 0, offset); + this_lstnr->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + this_lstnr->sglist_cnt = i + 1; + } + } /* Deallocate the handle */ if (!IS_ERR_OR_NULL(ihandle)) ion_free(qseecom.ion_clnt, ihandle); @@ -2883,6 +3174,8 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, struct qseecom_send_modfd_cmd_req *req = NULL; struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL; struct qseecom_registered_listener_list *this_lstnr = NULL; + uint32_t offset; + struct sg_table *sg_ptr; if ((data->type != QSEECOM_LISTENER_SERVICE) && (data->type != QSEECOM_CLIENT_APP)) @@ -2904,7 +3197,6 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, } for (i = 0; i < MAX_ION_FD; i++) { - struct sg_table *sg_ptr = NULL; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { ihandle = ion_import_dma_buf(qseecom.ion_clnt, @@ -2994,14 +3286,36 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, sg = sg_next(sg); } } - if (cleanup) + if (cleanup) { msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_INV_CACHES); - else + } else { msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); + if (data->type == QSEECOM_CLIENT_APP) { + offset = req->ifd_data[i].cmd_buf_offset; + data->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( + (sg_ptr->nents == 1), 1, offset); + data->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + data->sglist_cnt = i + 1; + } else { + offset = (lstnr_resp->ifd_data[i].cmd_buf_offset + + (uintptr_t)lstnr_resp->resp_buf_ptr - + (uintptr_t)this_lstnr->sb_virt); + this_lstnr->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( + (sg_ptr->nents == 1), 1, offset); + this_lstnr->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + this_lstnr->sglist_cnt = i + 1; + } + } /* Deallocate the handle */ if (!IS_ERR_OR_NULL(ihandle)) ion_free(qseecom.ion_clnt, ihandle); @@ -3195,7 +3509,7 @@ static bool __qseecom_is_fw_image_valid(const struct firmware *fw_entry) return true; } -static int __qseecom_get_fw_size(char *appname, uint32_t *fw_size, +static int __qseecom_get_fw_size(const char *appname, uint32_t *fw_size, uint32_t *app_arch) { int ret = -1; @@ -3233,14 +3547,21 @@ static int __qseecom_get_fw_size(char *appname, uint32_t *fw_size, } pr_debug("QSEE %s app, arch %u\n", appname, *app_arch); release_firmware(fw_entry); + fw_entry = NULL; for (i = 0; i < num_images; i++) { memset(fw_name, 0, sizeof(fw_name)); snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i); ret = request_firmware(&fw_entry, fw_name, qseecom.pdev); if (ret) goto err; + if (*fw_size > U32_MAX - fw_entry->size) { + pr_err("QSEE %s app file size overflow\n", appname); + ret = -EINVAL; + goto err; + } *fw_size += fw_entry->size; release_firmware(fw_entry); + fw_entry = NULL; } return ret; @@ -3251,8 +3572,9 @@ err: return ret; } -static int __qseecom_get_fw_data(char *appname, u8 *img_data, - struct qseecom_load_app_ireq *load_req) +static int __qseecom_get_fw_data(const char *appname, u8 *img_data, + uint32_t fw_size, + struct qseecom_load_app_ireq *load_req) { int ret = -1; int i = 0, rc = 0; @@ -3272,6 +3594,12 @@ static int __qseecom_get_fw_data(char *appname, u8 *img_data, } load_req->img_len = fw_entry->size; + if (load_req->img_len > fw_size) { + pr_err("app %s size %zu is larger than buf size %u\n", + appname, fw_entry->size, fw_size); + ret = -EINVAL; + goto err; + } memcpy(img_data_ptr, fw_entry->data, fw_entry->size); img_data_ptr = img_data_ptr + fw_entry->size; load_req->mdt_len = fw_entry->size; /*Get MDT LEN*/ @@ -3290,6 +3618,7 @@ static int __qseecom_get_fw_data(char *appname, u8 *img_data, goto err; } release_firmware(fw_entry); + fw_entry = NULL; for (i = 0; i < num_images; i++) { snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i); ret = request_firmware(&fw_entry, fw_name, qseecom.pdev); @@ -3297,10 +3626,17 @@ static int __qseecom_get_fw_data(char *appname, u8 *img_data, pr_err("Failed to locate blob %s\n", fw_name); goto err; } + if ((fw_entry->size > U32_MAX - load_req->img_len) || + (fw_entry->size + load_req->img_len > fw_size)) { + pr_err("Invalid file size for %s\n", fw_name); + ret = -EINVAL; + goto err; + } memcpy(img_data_ptr, fw_entry->data, fw_entry->size); img_data_ptr = img_data_ptr + fw_entry->size; load_req->img_len += fw_entry->size; release_firmware(fw_entry); + fw_entry = NULL; } return ret; err: @@ -3405,7 +3741,7 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname) if (ret) return ret; - ret = __qseecom_get_fw_data(appname, img_data, &load_req); + ret = __qseecom_get_fw_data(appname, img_data, fw_size, &load_req); if (ret) { ret = -EIO; goto exit_free_img_data; @@ -3526,7 +3862,7 @@ static int qseecom_load_commonlib_image(struct qseecom_dev_handle *data, if (ret) return -EIO; - ret = __qseecom_get_fw_data(cmnlib_name, img_data, &load_req); + ret = __qseecom_get_fw_data(cmnlib_name, img_data, fw_size, &load_req); if (ret) { ret = -EIO; goto exit_free_img_data; @@ -3894,8 +4230,11 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, } perf_enabled = true; } + if (!strcmp(data->client.app_name, "securemm")) + data->use_legacy_cmd = true; ret = __qseecom_send_cmd(data, &req); + data->use_legacy_cmd = false; if (qseecom.support_bus_scaling) __qseecom_add_bw_scale_down_timer( QSEECOM_SEND_CMD_CRYPTO_TIMEOUT); @@ -5295,7 +5634,8 @@ static int qseecom_mdtp_cipher_dip(void __user *argp) } if (req.in_buf == NULL || req.out_buf == NULL || - req.in_buf_size == 0 || req.out_buf_size == 0 || + req.in_buf_size == 0 || req.in_buf_size > MAX_DIP || + req.out_buf_size == 0 || req.out_buf_size > MAX_DIP || req.direction > 1) { pr_err("invalid parameters\n"); ret = -EINVAL; @@ -5575,14 +5915,23 @@ static int __qseecom_update_qteec_req_buf(struct qseecom_qteec_modfd_req *req, *update = (uint32_t)sg_dma_address(sg_ptr->sgl); } clean: - if (cleanup) + if (cleanup) { msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, sg->length, ION_IOC_INV_CACHES); - else + } else { msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, sg->length, ION_IOC_CLEAN_INV_CACHES); + data->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( + (sg_ptr->nents == 1), 0, + req->ifd_data[i].cmd_buf_offset); + data->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + data->sglist_cnt = i + 1; + } /* Deallocate the handle */ if (!IS_ERR_OR_NULL(ihandle)) ion_free(qseecom.ion_clnt, ihandle); @@ -5607,6 +5956,7 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, uint32_t reqd_len_sb_in = 0; void *cmd_buf = NULL; size_t cmd_len; + struct sglist_info *table = data->sglistinfo_ptr; ret = __qseecom_qteec_validate_msg(data, req); if (ret) @@ -5631,8 +5981,15 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, return -ENOENT; } + if ((cmd_id == QSEOS_TEE_OPEN_SESSION) || + (cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) { + ret = __qseecom_update_qteec_req_buf( + (struct qseecom_qteec_modfd_req *)req, data, false); + if (ret) + return ret; + } + if (qseecom.qsee_version < QSEE_VERSION_40) { - ireq.qsee_cmd_id = cmd_id; ireq.app_id = data->client.app_id; ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, (uintptr_t)req->req_ptr); @@ -5640,10 +5997,13 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, (uintptr_t)req->resp_ptr); ireq.resp_len = req->resp_len; + ireq.sglistinfo_ptr = (uint32_t)virt_to_phys(table); + ireq.sglistinfo_len = SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); cmd_buf = (void *)&ireq; cmd_len = sizeof(struct qseecom_qteec_ireq); } else { - ireq_64bit.qsee_cmd_id = cmd_id; ireq_64bit.app_id = data->client.app_id; ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, (uintptr_t)req->req_ptr); @@ -5663,17 +6023,19 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, ireq_64bit.resp_ptr, ireq_64bit.resp_len); return -EFAULT; } + ireq_64bit.sglistinfo_ptr = (uint64_t)virt_to_phys(table); + ireq_64bit.sglistinfo_len = SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); cmd_buf = (void *)&ireq_64bit; cmd_len = sizeof(struct qseecom_qteec_64bit_ireq); } + if (qseecom.whitelist_support == true + && cmd_id == QSEOS_TEE_OPEN_SESSION) + *(uint32_t *)cmd_buf = QSEOS_TEE_OPEN_SESSION_WHITELIST; + else + *(uint32_t *)cmd_buf = cmd_id; - if ((cmd_id == QSEOS_TEE_OPEN_SESSION) || - (cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) { - ret = __qseecom_update_qteec_req_buf( - (struct qseecom_qteec_modfd_req *)req, data, false); - if (ret) - return ret; - } reqd_len_sb_in = req->req_len + req->resp_len; msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, @@ -5771,6 +6133,9 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, uint32_t reqd_len_sb_in = 0; void *cmd_buf = NULL; size_t cmd_len; + struct sglist_info *table = data->sglistinfo_ptr; + void *req_ptr = NULL; + void *resp_ptr = NULL; ret = copy_from_user(&req, argp, sizeof(struct qseecom_qteec_modfd_req)); @@ -5782,6 +6147,8 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, (struct qseecom_qteec_req *)(&req)); if (ret) return ret; + req_ptr = req.req_ptr; + resp_ptr = req.resp_ptr; /* find app_id & img_name from list */ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); @@ -5802,45 +6169,56 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, return -ENOENT; } + /* validate offsets */ + for (i = 0; i < MAX_ION_FD; i++) { + if (req.ifd_data[i].fd) { + if (req.ifd_data[i].cmd_buf_offset >= req.req_len) + return -EINVAL; + } + } + req.req_ptr = (void *)__qseecom_uvirt_to_kvirt(data, + (uintptr_t)req.req_ptr); + req.resp_ptr = (void *)__qseecom_uvirt_to_kvirt(data, + (uintptr_t)req.resp_ptr); + ret = __qseecom_update_qteec_req_buf(&req, data, false); + if (ret) + return ret; + if (qseecom.qsee_version < QSEE_VERSION_40) { - ireq.qsee_cmd_id = QSEOS_TEE_INVOKE_COMMAND; ireq.app_id = data->client.app_id; ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req.req_ptr); + (uintptr_t)req_ptr); ireq.req_len = req.req_len; ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req.resp_ptr); + (uintptr_t)resp_ptr); ireq.resp_len = req.resp_len; cmd_buf = (void *)&ireq; cmd_len = sizeof(struct qseecom_qteec_ireq); + ireq.sglistinfo_ptr = (uint32_t)virt_to_phys(table); + ireq.sglistinfo_len = SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); } else { - ireq_64bit.qsee_cmd_id = QSEOS_TEE_INVOKE_COMMAND; ireq_64bit.app_id = data->client.app_id; ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req.req_ptr); + (uintptr_t)req_ptr); ireq_64bit.req_len = req.req_len; ireq_64bit.resp_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req.resp_ptr); + (uintptr_t)resp_ptr); ireq_64bit.resp_len = req.resp_len; cmd_buf = (void *)&ireq_64bit; cmd_len = sizeof(struct qseecom_qteec_64bit_ireq); + ireq_64bit.sglistinfo_ptr = (uint64_t)virt_to_phys(table); + ireq_64bit.sglistinfo_len = SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); } reqd_len_sb_in = req.req_len + req.resp_len; + if (qseecom.whitelist_support == true) + *(uint32_t *)cmd_buf = QSEOS_TEE_INVOKE_COMMAND_WHITELIST; + else + *(uint32_t *)cmd_buf = QSEOS_TEE_INVOKE_COMMAND; - /* validate offsets */ - for (i = 0; i < MAX_ION_FD; i++) { - if (req.ifd_data[i].fd) { - if (req.ifd_data[i].cmd_buf_offset >= req.req_len) - return -EINVAL; - } - } - req.req_ptr = (void *)__qseecom_uvirt_to_kvirt(data, - (uintptr_t)req.req_ptr); - req.resp_ptr = (void *)__qseecom_uvirt_to_kvirt(data, - (uintptr_t)req.resp_ptr); - ret = __qseecom_update_qteec_req_buf(&req, data, false); - if (ret) - return ret; msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, reqd_len_sb_in, @@ -5903,6 +6281,15 @@ static int qseecom_qteec_request_cancellation(struct qseecom_dev_handle *data, return ret; } +static void __qseecom_clean_data_sglistinfo(struct qseecom_dev_handle *data) +{ + if (data->sglist_cnt) { + memset(data->sglistinfo_ptr, 0, + SGLISTINFO_TABLE_SIZE); + data->sglist_cnt = 0; + } +} + long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) { int ret = 0; @@ -6082,6 +6469,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) mutex_unlock(&app_access_lock); if (ret) pr_err("failed qseecom_send_cmd: %d\n", ret); + __qseecom_clean_data_sglistinfo(data); break; } case QSEECOM_IOCTL_RECEIVE_REQ: { @@ -6455,6 +6843,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) wake_up_all(&data->abort_wq); if (ret) pr_err("failed qseecom_send_mod_resp: %d\n", ret); + __qseecom_clean_data_sglistinfo(data); break; } case QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ: { @@ -6479,6 +6868,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) mutex_unlock(&app_access_lock); if (ret) pr_err("failed open_session_cmd: %d\n", ret); + __qseecom_clean_data_sglistinfo(data); break; } case QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ: { @@ -6527,6 +6917,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) mutex_unlock(&app_access_lock); if (ret) pr_err("failed Invoke cmd: %d\n", ret); + __qseecom_clean_data_sglistinfo(data); break; } case QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ: { @@ -6578,7 +6969,6 @@ static int qseecom_open(struct inode *inode, struct file *file) data->mode = INACTIVE; init_waitqueue_head(&data->abort_wq); atomic_set(&data->ioctl_count, 0); - return ret; } @@ -6773,6 +7163,17 @@ static void __qseecom_deinit_clk(enum qseecom_ce_hw_instance ce) qclk->instance = CLK_INVALID; } +/* + * Check whitelist feature, and if TZ feature version is < 1.0.0, + * then whitelist feature is not supported. + */ +static int qseecom_check_whitelist_feature(void) +{ + int version = scm_get_feat_version(FEATURE_ID_WHITELIST); + + return version >= MAKE_WHITELIST_VERSION(1, 0, 0); +} + static int qseecom_probe(struct platform_device *pdev) { int rc; @@ -6804,6 +7205,7 @@ static int qseecom_probe(struct platform_device *pdev) qseecom.app_block_ref_cnt = 0; init_waitqueue_head(&qseecom.app_block_wq); + qseecom.whitelist_support = true; rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV); if (rc < 0) { @@ -7096,6 +7498,10 @@ static int qseecom_probe(struct platform_device *pdev) qseecom.qsee_perf_client = msm_bus_scale_register_client( qseecom_platform_support); + qseecom.whitelist_support = qseecom_check_whitelist_feature(); + pr_warn("qseecom.whitelist_support = %d\n", + qseecom.whitelist_support); + if (!qseecom.qsee_perf_client) pr_err("Unable to register bus client\n"); return 0; diff --git a/drivers/net/ethernet/msm/rndis_ipa.c b/drivers/net/ethernet/msm/rndis_ipa.c index 09b85fb32d4..c61e2a72040 100644 --- a/drivers/net/ethernet/msm/rndis_ipa.c +++ b/drivers/net/ethernet/msm/rndis_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015, 2017 The Linux Foundation. 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 version 2 and @@ -132,29 +132,6 @@ enum rndis_ipa_operation { RNDIS_IPA_DEBUG("Driver state: %s\n",\ rndis_ipa_state_string(ctx->state)); -/** - * struct rndis_loopback_pipe - hold all information needed for - * pipe loopback logic - */ -struct rndis_loopback_pipe { - struct sps_pipe *ipa_sps; - struct ipa_sps_params ipa_sps_connect; - struct ipa_connect_params ipa_connect_params; - - struct sps_pipe *dma_sps; - struct sps_connect dma_connect; - - struct sps_alloc_dma_chan dst_alloc; - struct sps_dma_chan ipa_sps_channel; - enum sps_mode mode; - u32 ipa_peer_bam_hdl; - u32 peer_pipe_index; - u32 ipa_drv_ep_hdl; - u32 ipa_pipe_index; - enum ipa_client_type ipa_client; - ipa_notify_cb ipa_callback; - struct ipa_ep_cfg *ipa_ep_cfg; -}; /** * struct rndis_ipa_dev - main driver context parameters @@ -169,13 +146,9 @@ struct rndis_loopback_pipe { * @rx_dump_enable: dump all Rx packets * @icmp_filter: allow all ICMP packet to pass through the filters * @rm_enable: flag that enable/disable Resource manager request prior to Tx - * @loopback_enable: flag that enable/disable USB stub loopback * @deaggregation_enable: enable/disable IPA HW deaggregation logic * @during_xmit_error: flags that indicate that the driver is in a middle * of error handling in Tx path - * @usb_to_ipa_loopback_pipe: usb to ipa (Rx) pipe representation for loopback - * @ipa_to_usb_loopback_pipe: ipa to usb (Tx) pipe representation for loopback - * @bam_dma_hdl: handle representing bam-dma, used for loopback logic * @directory: holds all debug flags used by the driver to allow cleanup * for driver unload * @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table @@ -205,12 +178,8 @@ struct rndis_ipa_dev { u32 rx_dump_enable; u32 icmp_filter; u32 rm_enable; - bool loopback_enable; u32 deaggregation_enable; u32 during_xmit_error; - struct rndis_loopback_pipe usb_to_ipa_loopback_pipe; - struct rndis_loopback_pipe ipa_to_usb_loopback_pipe; - u32 bam_dma_hdl; struct dentry *directory; uint32_t eth_ipv4_hdr_hdl; uint32_t eth_ipv6_hdr_hdl; @@ -274,31 +243,12 @@ static int resource_request(struct rndis_ipa_dev *rndis_ipa_ctx); static void resource_release(struct rndis_ipa_dev *rndis_ipa_ctx); static netdev_tx_t rndis_ipa_start_xmit(struct sk_buff *skb, struct net_device *net); -static int rndis_ipa_loopback_pipe_create( - struct rndis_ipa_dev *rndis_ipa_ctx, - struct rndis_loopback_pipe *loopback_pipe); -static void rndis_ipa_destroy_loopback_pipe( - struct rndis_loopback_pipe *loopback_pipe); -static int rndis_ipa_create_loopback(struct rndis_ipa_dev *rndis_ipa_ctx); -static void rndis_ipa_destroy_loopback(struct rndis_ipa_dev *rndis_ipa_ctx); -static int rndis_ipa_setup_loopback(bool enable, - struct rndis_ipa_dev *rndis_ipa_ctx); -static int rndis_ipa_debugfs_loopback_open(struct inode *inode, - struct file *file); static int rndis_ipa_debugfs_atomic_open(struct inode *inode, struct file *file); static int rndis_ipa_debugfs_aggr_open(struct inode *inode, struct file *file); static ssize_t rndis_ipa_debugfs_aggr_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos); -static ssize_t rndis_ipa_debugfs_loopback_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static ssize_t rndis_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static ssize_t rndis_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos); -static ssize_t rndis_ipa_debugfs_loopback_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos); static ssize_t rndis_ipa_debugfs_atomic_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos); static void rndis_ipa_dump_skb(struct sk_buff *skb); @@ -333,12 +283,6 @@ const struct file_operations rndis_ipa_debugfs_atomic_ops = { .read = rndis_ipa_debugfs_atomic_read, }; -const struct file_operations rndis_ipa_loopback_ops = { - .open = rndis_ipa_debugfs_loopback_open, - .read = rndis_ipa_debugfs_loopback_read, - .write = rndis_ipa_debugfs_loopback_write, -}; - const struct file_operations rndis_ipa_aggr_ops = { .open = rndis_ipa_debugfs_aggr_open, .write = rndis_ipa_debugfs_aggr_write, @@ -2188,14 +2132,6 @@ static int rndis_ipa_debugfs_init(struct rndis_ipa_dev *rndis_ipa_ctx) goto fail_file; } - file = debugfs_create_file("loopback_enable", flags_read_write, - rndis_ipa_ctx->directory, - rndis_ipa_ctx, &rndis_ipa_loopback_ops); - if (!file) { - RNDIS_IPA_ERROR("could not create outstanding file\n"); - goto fail_file; - } - file = debugfs_create_u8("state", flags_read_only, rndis_ipa_ctx->directory, (u8 *)&rndis_ipa_ctx->state); if (!file) { @@ -2351,59 +2287,6 @@ static ssize_t rndis_ipa_debugfs_aggr_write(struct file *file, return count; } -static int rndis_ipa_debugfs_loopback_open(struct inode *inode, - struct file *file) -{ - struct rndis_ipa_dev *rndis_ipa_ctx = inode->i_private; - file->private_data = rndis_ipa_ctx; - - return 0; -} - -static ssize_t rndis_ipa_debugfs_loopback_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos) -{ - int cnt; - struct rndis_ipa_dev *rndis_ipa_ctx = file->private_data; - - file->private_data = &rndis_ipa_ctx->loopback_enable; - - cnt = rndis_ipa_debugfs_enable_read(file, - ubuf, count, ppos); - - return cnt; -} - -static ssize_t rndis_ipa_debugfs_loopback_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - int retval; - int cnt; - struct rndis_ipa_dev *rndis_ipa_ctx = file->private_data; - bool old_state = rndis_ipa_ctx->loopback_enable; - - file->private_data = &rndis_ipa_ctx->loopback_enable; - - cnt = rndis_ipa_debugfs_enable_write(file, - buf, count, ppos); - - RNDIS_IPA_DEBUG("loopback_enable was set to:%d->%d\n", - old_state, rndis_ipa_ctx->loopback_enable); - - if (old_state == rndis_ipa_ctx->loopback_enable) { - RNDIS_IPA_ERROR("NOP - same state\n"); - return cnt; - } - - retval = rndis_ipa_setup_loopback( - rndis_ipa_ctx->loopback_enable, - rndis_ipa_ctx); - if (retval) - rndis_ipa_ctx->loopback_enable = old_state; - - return cnt; -} - static int rndis_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) { struct rndis_ipa_dev *rndis_ipa_ctx = inode->i_private; @@ -2434,319 +2317,6 @@ static ssize_t rndis_ipa_debugfs_atomic_read(struct file *file, return simple_read_from_buffer(ubuf, count, ppos, atomic_str, nbytes); } -static ssize_t rndis_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos) -{ - int nbytes; - int size = 0; - int ret; - loff_t pos; - u8 enable_str[sizeof(char)*3] = {0}; - bool *enable = file->private_data; - pos = *ppos; - nbytes = scnprintf(enable_str, sizeof(enable_str), "%d\n", *enable); - ret = simple_read_from_buffer(ubuf, count, ppos, enable_str, nbytes); - if (ret < 0) { - RNDIS_IPA_ERROR("simple_read_from_buffer problem\n"); - return ret; - } - size += ret; - count -= nbytes; - *ppos = pos + size; - return size; -} - -static ssize_t rndis_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - unsigned long missing; - char input; - bool *enable = file->private_data; - if (count != sizeof(input) + 1) { - RNDIS_IPA_ERROR("wrong input length(%zd)\n", count); - return -EINVAL; - } - if (!buf) { - RNDIS_IPA_ERROR("Bad argument\n"); - return -EINVAL; - } - missing = copy_from_user(&input, buf, 1); - if (missing) - return -EFAULT; - RNDIS_IPA_DEBUG("input received %c\n", input); - *enable = input - '0'; - RNDIS_IPA_DEBUG("value was set to %d\n", *enable); - return count; -} - -/** - * Connects IPA->BAMDMA - * This shall simulate the path from IPA to USB - * Allowing the driver TX path - */ -static int rndis_ipa_loopback_pipe_create( - struct rndis_ipa_dev *rndis_ipa_ctx, - struct rndis_loopback_pipe *loopback_pipe) -{ - int retval; - - RNDIS_IPA_LOG_ENTRY(); - - /* SPS pipe has two side handshake - * This is the first handshake of IPA->BAMDMA, - * This is the IPA side - */ - loopback_pipe->ipa_connect_params.client = loopback_pipe->ipa_client; - loopback_pipe->ipa_connect_params.client_bam_hdl = - rndis_ipa_ctx->bam_dma_hdl; - loopback_pipe->ipa_connect_params.client_ep_idx = - loopback_pipe->peer_pipe_index; - loopback_pipe->ipa_connect_params.desc_fifo_sz = BAM_DMA_DESC_FIFO_SIZE; - loopback_pipe->ipa_connect_params.data_fifo_sz = BAM_DMA_DATA_FIFO_SIZE; - loopback_pipe->ipa_connect_params.notify = loopback_pipe->ipa_callback; - loopback_pipe->ipa_connect_params.priv = rndis_ipa_ctx; - loopback_pipe->ipa_connect_params.ipa_ep_cfg = - *(loopback_pipe->ipa_ep_cfg); - - /* loopback_pipe->ipa_sps_connect is out param */ - retval = ipa_connect(&loopback_pipe->ipa_connect_params, - &loopback_pipe->ipa_sps_connect, - &loopback_pipe->ipa_drv_ep_hdl); - if (retval) { - RNDIS_IPA_ERROR("ipa_connect() fail (%d)", retval); - return retval; - } - RNDIS_IPA_DEBUG("ipa_connect() succeeded, ipa_drv_ep_hdl=%d", - loopback_pipe->ipa_drv_ep_hdl); - - /* SPS pipe has two side handshake - * This is the second handshake of IPA->BAMDMA, - * This is the BAMDMA side - */ - loopback_pipe->dma_sps = sps_alloc_endpoint(); - if (!loopback_pipe->dma_sps) { - RNDIS_IPA_ERROR("sps_alloc_endpoint() failed "); - retval = -ENOMEM; - goto fail_sps_alloc; - } - - retval = sps_get_config(loopback_pipe->dma_sps, - &loopback_pipe->dma_connect); - if (retval) { - RNDIS_IPA_ERROR("sps_get_config() failed (%d)", retval); - goto fail_get_cfg; - } - - /* Start setting the non IPA ep for SPS driver*/ - loopback_pipe->dma_connect.mode = loopback_pipe->mode; - - /* SPS_MODE_DEST: DMA end point is the dest (consumer) IPA->DMA */ - if (loopback_pipe->mode == SPS_MODE_DEST) { - - loopback_pipe->dma_connect.source = - loopback_pipe->ipa_sps_connect.ipa_bam_hdl; - loopback_pipe->dma_connect.src_pipe_index = - loopback_pipe->ipa_sps_connect.ipa_ep_idx; - loopback_pipe->dma_connect.destination = - rndis_ipa_ctx->bam_dma_hdl; - loopback_pipe->dma_connect.dest_pipe_index = - loopback_pipe->peer_pipe_index; - - /* SPS_MODE_SRC: DMA end point is the source (producer) DMA->IPA */ - } else { - - loopback_pipe->dma_connect.source = - rndis_ipa_ctx->bam_dma_hdl; - loopback_pipe->dma_connect.src_pipe_index = - loopback_pipe->peer_pipe_index; - loopback_pipe->dma_connect.destination = - loopback_pipe->ipa_sps_connect.ipa_bam_hdl; - loopback_pipe->dma_connect.dest_pipe_index = - loopback_pipe->ipa_sps_connect.ipa_ep_idx; - - } - - loopback_pipe->dma_connect.desc = loopback_pipe->ipa_sps_connect.desc; - loopback_pipe->dma_connect.data = loopback_pipe->ipa_sps_connect.data; - loopback_pipe->dma_connect.event_thresh = 0x10; - /* BAM-to-BAM */ - loopback_pipe->dma_connect.options = SPS_O_AUTO_ENABLE; - - RNDIS_IPA_DEBUG("doing sps_connect() with - "); - RNDIS_IPA_DEBUG("src bam_hdl:0x%lx, src_pipe#:%d", - loopback_pipe->dma_connect.source, - loopback_pipe->dma_connect.src_pipe_index); - RNDIS_IPA_DEBUG("dst bam_hdl:0x%lx, dst_pipe#:%d", - loopback_pipe->dma_connect.destination, - loopback_pipe->dma_connect.dest_pipe_index); - - retval = sps_connect(loopback_pipe->dma_sps, - &loopback_pipe->dma_connect); - if (retval) { - RNDIS_IPA_ERROR("sps_connect() fail for BAMDMA side (%d)", - retval); - goto fail_sps_connect; - } - - RNDIS_IPA_LOG_EXIT(); - - return 0; - -fail_sps_connect: -fail_get_cfg: - sps_free_endpoint(loopback_pipe->dma_sps); -fail_sps_alloc: - ipa_disconnect(loopback_pipe->ipa_drv_ep_hdl); - return retval; -} - -static void rndis_ipa_destroy_loopback_pipe( - struct rndis_loopback_pipe *loopback_pipe) -{ - sps_disconnect(loopback_pipe->dma_sps); - sps_free_endpoint(loopback_pipe->dma_sps); -} - -/** - * rndis_ipa_create_loopback() - create a BAM-DMA loopback - * in order to replace the USB core - */ -static int rndis_ipa_create_loopback(struct rndis_ipa_dev *rndis_ipa_ctx) -{ - /* The BAM handle should be use as - * source/destination in the sps_connect() - */ - int retval; - - RNDIS_IPA_LOG_ENTRY(); - - - retval = sps_ctrl_bam_dma_clk(true); - if (retval) { - RNDIS_IPA_ERROR("fail on enabling BAM-DMA clocks"); - return -ENODEV; - } - - /* Get BAM handle instead of USB handle */ - rndis_ipa_ctx->bam_dma_hdl = sps_dma_get_bam_handle(); - if (!rndis_ipa_ctx->bam_dma_hdl) { - RNDIS_IPA_ERROR("sps_dma_get_bam_handle() failed"); - return -ENODEV; - } - RNDIS_IPA_DEBUG("sps_dma_get_bam_handle() succeeded (0x%x)", - rndis_ipa_ctx->bam_dma_hdl); - - /* IPA<-BAMDMA, NetDev Rx path (BAMDMA is the USB stub) */ - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_client = - IPA_CLIENT_USB_PROD; - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.peer_pipe_index = - FROM_USB_TO_IPA_BAMDMA; - /*DMA EP mode*/ - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.mode = SPS_MODE_SRC; - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_ep_cfg = - &usb_to_ipa_ep_cfg_deaggr_en; - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_callback = - rndis_ipa_packet_receive_notify; - RNDIS_IPA_DEBUG("setting up IPA<-BAMDAM pipe (RNDIS_IPA RX path)"); - retval = rndis_ipa_loopback_pipe_create(rndis_ipa_ctx, - &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); - if (retval) { - RNDIS_IPA_ERROR("fail to close IPA->BAMDAM pipe"); - goto fail_to_usb; - } - RNDIS_IPA_DEBUG("IPA->BAMDAM pipe successfully connected (TX path)"); - - /* IPA->BAMDMA, NetDev Tx path (BAMDMA is the USB stub)*/ - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_client = - IPA_CLIENT_USB_CONS; - /*DMA EP mode*/ - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.mode = SPS_MODE_DEST; - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_ep_cfg = &ipa_to_usb_ep_cfg; - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.peer_pipe_index = - FROM_IPA_TO_USB_BAMDMA; - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_callback = - rndis_ipa_tx_complete_notify; - RNDIS_IPA_DEBUG("setting up IPA->BAMDAM pipe (RNDIS_IPA TX path)"); - retval = rndis_ipa_loopback_pipe_create(rndis_ipa_ctx, - &rndis_ipa_ctx->ipa_to_usb_loopback_pipe); - if (retval) { - RNDIS_IPA_ERROR("fail to close IPA<-BAMDAM pipe"); - goto fail_from_usb; - } - RNDIS_IPA_DEBUG("IPA<-BAMDAM pipe successfully connected(RX path)"); - - RNDIS_IPA_LOG_EXIT(); - - return 0; - -fail_from_usb: - rndis_ipa_destroy_loopback_pipe( - &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); -fail_to_usb: - - return retval; -} - -static void rndis_ipa_destroy_loopback(struct rndis_ipa_dev *rndis_ipa_ctx) -{ - rndis_ipa_destroy_loopback_pipe( - &rndis_ipa_ctx->ipa_to_usb_loopback_pipe); - rndis_ipa_destroy_loopback_pipe( - &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); - sps_dma_free_bam_handle(rndis_ipa_ctx->bam_dma_hdl); - if (sps_ctrl_bam_dma_clk(false)) - RNDIS_IPA_ERROR("fail to disable BAM-DMA clocks"); -} - -/** - * rndis_ipa_setup_loopback() - create/destroy a loopback on IPA HW - * (as USB pipes loopback) and notify RNDIS_IPA netdev for pipe connected - * @enable: flag that determines if the loopback should be created or destroyed - * @rndis_ipa_ctx: driver main context - * - * This function is the main loopback logic. - * It shall create/destory the loopback by using BAM-DMA and notify - * the netdev accordingly. - */ -static int rndis_ipa_setup_loopback(bool enable, - struct rndis_ipa_dev *rndis_ipa_ctx) -{ - int retval; - - if (!enable) { - rndis_ipa_destroy_loopback(rndis_ipa_ctx); - RNDIS_IPA_DEBUG("loopback destroy done"); - retval = rndis_ipa_pipe_disconnect_notify(rndis_ipa_ctx); - if (retval) { - RNDIS_IPA_ERROR("connect notify fail"); - return -ENODEV; - } - return 0; - } - - RNDIS_IPA_DEBUG("creating loopback (instead of USB core)"); - retval = rndis_ipa_create_loopback(rndis_ipa_ctx); - RNDIS_IPA_DEBUG("creating loopback- %s", (retval ? "FAIL" : "OK")); - if (retval) { - RNDIS_IPA_ERROR("Fail to connect loopback"); - return -ENODEV; - } - retval = rndis_ipa_pipe_connect_notify( - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_drv_ep_hdl, - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_drv_ep_hdl, - BAM_DMA_DATA_FIFO_SIZE, - 15, - BAM_DMA_DATA_FIFO_SIZE - rndis_ipa_ctx->net->mtu, - rndis_ipa_ctx); - if (retval) { - RNDIS_IPA_ERROR("connect notify fail"); - return -ENODEV; - } - - return 0; - -} - static int rndis_ipa_init_module(void) { pr_info("RNDIS_IPA module is loaded."); diff --git a/drivers/platform/msm/ipa/ipa_flt.c b/drivers/platform/msm/ipa/ipa_flt.c index 140986aab5f..b179737c318 100644 --- a/drivers/platform/msm/ipa/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_flt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. 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 version 2 and @@ -235,7 +235,7 @@ static int ipa_generate_flt_hw_rule(enum ipa_ip_type ip, * @ip: the ip address family type * @hdr_sz: header size * - * Returns: 0 on success, negative on failure + * Returns: size on success, negative on failure * * caller needs to hold any needed locks to ensure integrity * @@ -373,7 +373,12 @@ static int ipa_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, ((long)body & IPA_FLT_ENTRY_MEMORY_ALLIGNMENT)); } else { - WARN_ON(tbl->sz == 0); + if (tbl->sz == 0) { + IPAERR("tbl size is 0\n"); + WARN_ON(1); + goto proc_err; + } + /* allocate memory for the flt tbl */ flt_tbl_mem.size = tbl->sz; flt_tbl_mem.base = @@ -460,7 +465,12 @@ static int ipa_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, ((long)body & IPA_FLT_ENTRY_MEMORY_ALLIGNMENT)); } else { - WARN_ON(tbl->sz == 0); + if (tbl->sz == 0) { + IPAERR("tbl size is 0\n"); + WARN_ON(1); + goto proc_err; + } + /* allocate memory for the flt tbl */ flt_tbl_mem.size = tbl->sz; flt_tbl_mem.base = @@ -534,8 +544,15 @@ static int ipa_generate_flt_hw_tbl_v1_1(enum ipa_ip_type ip, u8 *hdr; u8 *body; u8 *base; + int res; + + res = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); + if (res < 0) { + IPAERR("ipa_get_flt_hw_tbl_size failed %d\n", res); + return res; + } - mem->size = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); + mem->size = res; mem->size = IPA_HW_TABLE_ALIGNMENT(mem->size); if (mem->size == 0) { @@ -720,6 +737,7 @@ static int ipa_generate_flt_hw_tbl_v2(enum ipa_ip_type ip, u32 *entr; u32 body_start_offset; u32 hdr_top; + int res; if (ip == IPA_IP_v4) body_start_offset = IPA_MEM_PART(apps_v4_flt_ofst) - @@ -756,7 +774,13 @@ static int ipa_generate_flt_hw_tbl_v2(enum ipa_ip_type ip, entr++; } - mem->size = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); + res = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); + if (res < 0) { + IPAERR("ipa_get_flt_hw_tbl_size failed %d\n", res); + goto body_err; + } + + mem->size = res; mem->size -= hdr_sz; mem->size = IPA_HW_TABLE_ALIGNMENT(mem->size); diff --git a/drivers/platform/msm/ipa/ipa_nat.c b/drivers/platform/msm/ipa/ipa_nat.c index b4ccf5f9946..12691fac466 100644 --- a/drivers/platform/msm/ipa/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_nat.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. 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 version 2 and @@ -25,6 +25,16 @@ #define IPA_NAT_SHARED_MEMORY 1 #define IPA_NAT_TEMP_MEM_SIZE 128 +enum nat_table_type { + IPA_NAT_BASE_TBL = 0, + IPA_NAT_EXPN_TBL = 1, + IPA_NAT_INDX_TBL = 2, + IPA_NAT_INDEX_EXPN_TBL = 3, +}; + +#define NAT_TABLE_ENTRY_SIZE_BYTE 32 +#define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4 + static int ipa_nat_vma_fault_remap( struct vm_area_struct *vma, struct vm_fault *vmf) { @@ -566,6 +576,71 @@ int ipa_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) goto bail; } + for (cnt = 0; cnt < dma->entries; cnt++) { + if (dma->dma[cnt].table_index >= 1) { + IPAERR("Invalid table index %d\n", + dma->dma[cnt].table_index); + ret = -EPERM; + goto bail; + } + + switch (dma->dma[cnt].base_addr) { + case IPA_NAT_BASE_TBL: + if (dma->dma[cnt].offset >= + (ipa_ctx->nat_mem.size_base_tables + 1) * + NAT_TABLE_ENTRY_SIZE_BYTE) { + IPAERR("Invalid offset %d\n", + dma->dma[cnt].offset); + ret = -EPERM; + goto bail; + } + + break; + + case IPA_NAT_EXPN_TBL: + if (dma->dma[cnt].offset >= + ipa_ctx->nat_mem.size_expansion_tables * + NAT_TABLE_ENTRY_SIZE_BYTE) { + IPAERR("Invalid offset %d\n", + dma->dma[cnt].offset); + ret = -EPERM; + goto bail; + } + + break; + + case IPA_NAT_INDX_TBL: + if (dma->dma[cnt].offset >= + (ipa_ctx->nat_mem.size_base_tables + 1) * + NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { + IPAERR("Invalid offset %d\n", + dma->dma[cnt].offset); + ret = -EPERM; + goto bail; + } + + break; + + case IPA_NAT_INDEX_EXPN_TBL: + if (dma->dma[cnt].offset >= + ipa_ctx->nat_mem.size_expansion_tables * + NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { + IPAERR("Invalid offset %d\n", + dma->dma[cnt].offset); + ret = -EPERM; + goto bail; + } + + break; + + default: + IPAERR("Invalid base_addr %d\n", + dma->dma[cnt].base_addr); + ret = -EPERM; + goto bail; + } + } + size = sizeof(struct ipa_desc) * NUM_OF_DESC; desc = kzalloc(size, GFP_KERNEL); if (desc == NULL) { diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c index 660f3fb014c..0476f519b24 100644 --- a/drivers/platform/msm/ipa/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_rt.c @@ -226,7 +226,7 @@ int __ipa_generate_rt_hw_rule_v2_6L(enum ipa_ip_type ip, * @hdr_sz: header size * @max_rt_idx: maximal index * - * Returns: 0 on success, negative on failure + * Returns: size on success, negative on failure * * caller needs to hold any needed locks to ensure integrity * @@ -355,7 +355,11 @@ static int ipa_generate_rt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, u8 *hdr, ((long)body & IPA_RT_ENTRY_MEMORY_ALLIGNMENT)); } else { - WARN_ON(tbl->sz == 0); + if (tbl->sz == 0) { + IPAERR("cannot generate 0 size table\n"); + goto proc_err; + } + /* allocate memory for the RT tbl */ rt_tbl_mem.size = tbl->sz; rt_tbl_mem.base = @@ -428,8 +432,15 @@ static int ipa_generate_rt_hw_tbl_v1_1(enum ipa_ip_type ip, u8 *base; int max_rt_idx; int i; + int res; - mem->size = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); + res = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); + if (res < 0) { + IPAERR("ipa_get_rt_hw_tbl_size failed %d\n", res); + goto error; + } + + mem->size = res; mem->size = (mem->size + IPA_RT_TABLE_MEMORY_ALLIGNMENT) & ~IPA_RT_TABLE_MEMORY_ALLIGNMENT; @@ -602,6 +613,7 @@ static int ipa_generate_rt_hw_tbl_v2(enum ipa_ip_type ip, int num_index; u32 body_start_offset; u32 apps_start_idx; + int res; if (ip == IPA_IP_v4) { num_index = IPA_MEM_PART(v4_apps_rt_index_hi) - @@ -631,7 +643,13 @@ static int ipa_generate_rt_hw_tbl_v2(enum ipa_ip_type ip, entr++; } - mem->size = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); + res = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); + if (res < 0) { + IPAERR("ipa_get_rt_hw_tbl_size failed %d\n", res); + goto base_err; + } + + mem->size = res; mem->size -= hdr_sz; mem->size = (mem->size + IPA_RT_TABLE_MEMORY_ALLIGNMENT) & ~IPA_RT_TABLE_MEMORY_ALLIGNMENT; diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c index 25e1f1ced3b..a83284e65c7 100755 --- a/drivers/power/qpnp-fg.c +++ b/drivers/power/qpnp-fg.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. 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 version 2 and @@ -525,6 +525,7 @@ struct fg_trans { struct fg_chip *chip; struct fg_log_buffer *log; /* log buffer */ u8 *data; /* fg data that is read */ + struct mutex memif_dfs_lock; /* Prevent thread concurrency */ }; struct fg_dbgfs { @@ -5259,6 +5260,7 @@ static int fg_memif_data_open(struct inode *inode, struct file *file) trans->addr = dbgfs_data.addr; trans->chip = dbgfs_data.chip; trans->offset = trans->addr; + mutex_init(&trans->memif_dfs_lock); file->private_data = trans; return 0; @@ -5270,6 +5272,7 @@ static int fg_memif_dfs_close(struct inode *inode, struct file *file) if (trans && trans->log && trans->data) { file->private_data = NULL; + mutex_destroy(&trans->memif_dfs_lock); kfree(trans->log); kfree(trans->data); kfree(trans); @@ -5427,10 +5430,13 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, size_t ret; size_t len; + mutex_lock(&trans->memif_dfs_lock); /* Is the the log buffer empty */ if (log->rpos >= log->wpos) { - if (get_log_data(trans) <= 0) - return 0; + if (get_log_data(trans) <= 0) { + len = 0; + goto unlock_mutex; + } } len = min(count, log->wpos - log->rpos); @@ -5438,7 +5444,8 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, ret = copy_to_user(buf, &log->data[log->rpos], len); if (ret == len) { pr_err("error copy sram register values to user\n"); - return -EFAULT; + len = -EFAULT; + goto unlock_mutex; } /* 'ret' is the number of bytes not copied */ @@ -5446,6 +5453,9 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, *ppos += len; log->rpos += len; + +unlock_mutex: + mutex_unlock(&trans->memif_dfs_lock); return len; } @@ -5466,14 +5476,20 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf, int cnt = 0; u8 *values; size_t ret = 0; + char *kbuf; + u32 offset; struct fg_trans *trans = file->private_data; - u32 offset = trans->offset; + + mutex_lock(&trans->memif_dfs_lock); + offset = trans->offset; /* Make a copy of the user data */ - char *kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } ret = copy_from_user(kbuf, buf, count); if (ret == count) { @@ -5512,6 +5528,8 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf, free_buf: kfree(kbuf); +unlock_mutex: + mutex_unlock(&trans->memif_dfs_lock); return ret; } diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c index aca73efdec6..5d04f48c12e 100644 --- a/drivers/slimbus/slim-msm-ngd.c +++ b/drivers/slimbus/slim-msm-ngd.c @@ -1447,11 +1447,13 @@ static void ngd_adsp_down(struct msm_slim_ctrl *dev) struct slim_controller *ctrl = &dev->ctrl; struct slim_device *sbdev; + mutex_lock(&dev->ssr_lock); ngd_slim_enable(dev, false); /* device up should be called again after SSR */ list_for_each_entry(sbdev, &ctrl->devs, dev_list) slim_report_absent(sbdev); SLIM_INFO(dev, "SLIM ADSP SSR (DOWN) done\n"); + mutex_unlock(&dev->ssr_lock); } static void ngd_adsp_up(struct work_struct *work) @@ -1460,7 +1462,9 @@ static void ngd_adsp_up(struct work_struct *work) container_of(work, struct msm_slim_qmi, ssr_up); struct msm_slim_ctrl *dev = container_of(qmi, struct msm_slim_ctrl, qmi); + mutex_lock(&dev->ssr_lock); ngd_slim_enable(dev, true); + mutex_unlock(&dev->ssr_lock); } static ssize_t show_mask(struct device *device, struct device_attribute *attr, @@ -1624,6 +1628,7 @@ static int ngd_slim_probe(struct platform_device *pdev) init_completion(&dev->reconf); init_completion(&dev->ctrl_up); mutex_init(&dev->tx_lock); + mutex_init(&dev->ssr_lock); spin_lock_init(&dev->tx_buf_lock); spin_lock_init(&dev->rx_lock); dev->ee = 1; diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h index dbb125dc9a6..0b4c4d33f79 100644 --- a/drivers/slimbus/slim-msm.h +++ b/drivers/slimbus/slim-msm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2016, The Linux Foundation. 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 version 2 and @@ -284,6 +284,7 @@ struct msm_slim_ctrl { struct clk *rclk; struct clk *hclk; struct mutex tx_lock; + struct mutex ssr_lock; spinlock_t tx_buf_lock; u8 pgdla; enum msm_slim_msgq use_rx_msgqs; diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c index 67c58d1e6d4..c54d9dda420 100644 --- a/drivers/soc/qcom/qdsp6v2/voice_svc.c +++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. 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 version 2 and @@ -42,6 +42,12 @@ struct voice_svc_prvt { struct list_head response_queue; wait_queue_head_t response_wait; spinlock_t response_lock; + /* + * This mutex ensures responses are processed in sequential order and + * that no two threads access and free the same response at the same + * time. + */ + struct mutex response_mutex_lock; }; struct apr_data { @@ -448,6 +454,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, goto done; } + mutex_lock(&prtd->response_mutex_lock); spin_lock_irqsave(&prtd->response_lock, spin_flags); if (list_empty(&prtd->response_queue)) { @@ -461,7 +468,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, pr_debug("%s: Read timeout\n", __func__); ret = -ETIMEDOUT; - goto done; + goto unlock; } else if (ret > 0 && !list_empty(&prtd->response_queue)) { pr_debug("%s: Interrupt recieved for response\n", __func__); @@ -469,7 +476,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, pr_debug("%s: Interrupted by SIGNAL %d\n", __func__, ret); - goto done; + goto unlock; } spin_lock_irqsave(&prtd->response_lock, spin_flags); @@ -488,7 +495,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, __func__, count, size); ret = -ENOMEM; - goto done; + goto unlock; } if (!access_ok(VERIFY_WRITE, arg, size)) { @@ -496,7 +503,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, __func__); ret = -EPERM; - goto done; + goto unlock; } ret = copy_to_user(arg, &resp->resp, @@ -506,7 +513,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, pr_err("%s: copy_to_user failed %d\n", __func__, ret); ret = -EPERM; - goto done; + goto unlock; } spin_lock_irqsave(&prtd->response_lock, spin_flags); @@ -520,6 +527,8 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, ret = count; +unlock: + mutex_unlock(&prtd->response_mutex_lock); done: return ret; } @@ -575,6 +584,7 @@ static int voice_svc_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&prtd->response_queue); init_waitqueue_head(&prtd->response_wait); spin_lock_init(&prtd->response_lock); + mutex_init(&prtd->response_mutex_lock); file->private_data = (void *)prtd; /* Current APR implementation doesn't support session based @@ -625,6 +635,7 @@ static int voice_svc_release(struct inode *inode, struct file *file) pr_err("%s: Failed to dereg MVM %d\n", __func__, ret); } + mutex_lock(&prtd->response_mutex_lock); spin_lock_irqsave(&prtd->response_lock, spin_flags); while (!list_empty(&prtd->response_queue)) { @@ -638,6 +649,9 @@ static int voice_svc_release(struct inode *inode, struct file *file) } spin_unlock_irqrestore(&prtd->response_lock, spin_flags); + mutex_unlock(&prtd->response_mutex_lock); + + mutex_destroy(&prtd->response_mutex_lock); kfree(file->private_data); file->private_data = NULL; diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c index 05da047c526..1ffda2eca13 100644 --- a/drivers/soc/qcom/scm.c +++ b/drivers/soc/qcom/scm.c @@ -46,9 +46,6 @@ static DEFINE_MUTEX(scm_lock); #define SMC_ATOMIC_MASK 0x80000000 #define IS_CALL_AVAIL_CMD 1 -#define SCM_BUF_LEN(__cmd_size, __resp_size) \ - (sizeof(struct scm_command) + sizeof(struct scm_response) + \ - __cmd_size + __resp_size) /** * struct scm_command - one SCM command buffer * @len: total available memory for command and response @@ -120,6 +117,21 @@ struct scm_response { #endif +/* Calculate size for buffer given cmd_size and resp_size. + * Returns 0 in case the result would overflow size_t. + */ +static size_t scm_get_buf_len(size_t cmd_size, size_t resp_size) +{ + size_t contents = cmd_size + resp_size; + size_t structs = sizeof(struct scm_command) + + sizeof(struct scm_response); + size_t buf_len = contents + structs; + + if (contents < cmd_size || buf_len < contents) + buf_len = 0; + return buf_len; +} + /** * scm_command_to_response() - Get a pointer to a scm_response * @cmd: command @@ -342,10 +354,9 @@ int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf, void *scm_buf, size_t scm_buf_len) { int ret; - size_t len = SCM_BUF_LEN(cmd_len, resp_len); + size_t len = scm_get_buf_len(cmd_len, resp_len); - if (cmd_len > scm_buf_len || resp_len > scm_buf_len || - len > scm_buf_len) + if (len == 0 || len > scm_buf_len) return -EINVAL; if (!IS_ALIGNED((unsigned long)scm_buf, PAGE_SIZE)) @@ -739,9 +750,9 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, { struct scm_command *cmd; int ret; - size_t len = SCM_BUF_LEN(cmd_len, resp_len); + size_t len = scm_get_buf_len(cmd_len, resp_len); - if (cmd_len > len || resp_len > len) + if (len == 0 || PAGE_ALIGN(len) < len) return -EINVAL; cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); diff --git a/drivers/spmi/spmi-dbgfs.c b/drivers/spmi/spmi-dbgfs.c index b0a354b59a5..2e0b0a9d584 100644 --- a/drivers/spmi/spmi-dbgfs.c +++ b/drivers/spmi/spmi-dbgfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. 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 version 2 and @@ -69,6 +69,7 @@ struct spmi_trans { u32 addr; /* 20-bit address: SID + PID + Register offset */ u32 offset; /* Offset of last read data */ bool raw_data; /* Set to true for raw data dump */ + struct mutex spmi_dfs_lock; /* Prevent thread concurrency */ struct spmi_controller *ctrl; struct spmi_log_buffer *log; /* log buffer */ }; @@ -168,6 +169,7 @@ static int spmi_dfs_open(struct spmi_ctrl_data *ctrl_data, struct file *file) trans->addr = ctrl_data->addr; trans->ctrl = ctrl_data->ctrl; trans->offset = trans->addr; + mutex_init(&trans->spmi_dfs_lock); file->private_data = trans; return 0; @@ -197,6 +199,7 @@ static int spmi_dfs_close(struct inode *inode, struct file *file) if (trans && trans->log) { file->private_data = NULL; + mutex_destroy(&trans->spmi_dfs_lock); kfree(trans->log); kfree(trans); } @@ -473,14 +476,21 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf, int cnt = 0; u8 *values; size_t ret = 0; - + u32 offset; + char *kbuf; struct spmi_trans *trans = file->private_data; - u32 offset = trans->offset; + + mutex_lock(&trans->spmi_dfs_lock); + + trans = file->private_data; + offset = trans->offset; /* Make a copy of the user data */ - char *kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } ret = copy_from_user(kbuf, buf, count); if (ret == count) { @@ -517,6 +527,8 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf, free_buf: kfree(kbuf); +unlock_mutex: + mutex_unlock(&trans->spmi_dfs_lock); return ret; } @@ -537,10 +549,13 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf, size_t ret; size_t len; + mutex_lock(&trans->spmi_dfs_lock); /* Is the the log buffer empty */ if (log->rpos >= log->wpos) { - if (get_log_data(trans) <= 0) - return 0; + if (get_log_data(trans) <= 0) { + len = 0; + goto unlock_mutex; + } } len = min(count, log->wpos - log->rpos); @@ -548,7 +563,8 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf, ret = copy_to_user(buf, &log->data[log->rpos], len); if (ret == len) { pr_err("error copy SPMI register values to user\n"); - return -EFAULT; + len = -EFAULT; + goto unlock_mutex; } /* 'ret' is the number of bytes not copied */ @@ -556,6 +572,9 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf, *ppos += len; log->rpos += len; + +unlock_mutex: + mutex_unlock(&trans->spmi_dfs_lock); return len; } diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 5fb366b4967..a5d264fb7f1 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -113,6 +113,7 @@ struct ion_client { */ struct ion_handle { struct kref ref; + unsigned int user_ref_count; struct ion_client *client; struct ion_buffer *buffer; struct rb_node node; @@ -434,6 +435,50 @@ int ion_handle_put(struct ion_handle *handle) return ret; } +/* Must hold the client lock */ +static void user_ion_handle_get(struct ion_handle *handle) +{ + if (handle->user_ref_count++ == 0) { + kref_get(&handle->ref); + } +} + +/* Must hold the client lock */ +static struct ion_handle* user_ion_handle_get_check_overflow(struct ion_handle *handle) +{ + if (handle->user_ref_count + 1 == 0) + return ERR_PTR(-EOVERFLOW); + user_ion_handle_get(handle); + return handle; +} + +/* passes a kref to the user ref count. + * We know we're holding a kref to the object before and + * after this call, so no need to reverify handle. */ +static struct ion_handle* pass_to_user(struct ion_handle *handle) +{ + struct ion_client *client = handle->client; + struct ion_handle *ret; + + mutex_lock(&client->lock); + ret = user_ion_handle_get_check_overflow(handle); + ion_handle_put_nolock(handle); + mutex_unlock(&client->lock); + return ret; +} + +/* Must hold the client lock */ +static int user_ion_handle_put_nolock(struct ion_handle *handle) +{ + int ret; + + if (--handle->user_ref_count == 0) { + ret = ion_handle_put_nolock(handle); + } + + return ret; +} + static struct ion_handle *ion_handle_lookup(struct ion_client *client, struct ion_buffer *buffer) { @@ -645,6 +690,24 @@ static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle ion_handle_put_nolock(handle); } +static void user_ion_free_nolock(struct ion_client *client, struct ion_handle *handle) +{ + bool valid_handle; + + BUG_ON(client != handle->client); + + valid_handle = ion_handle_validate(client, handle); + if (!valid_handle) { + WARN(1, "%s: invalid handle passed to free.\n", __func__); + return; + } + if (!handle->user_ref_count > 0) { + WARN(1, "%s: User does not have access!\n", __func__); + return; + } + user_ion_handle_put_nolock(handle); +} + void ion_free(struct ion_client *client, struct ion_handle *handle) { BUG_ON(client != handle->client); @@ -1509,7 +1572,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) data.allocation.flags, true); if (IS_ERR(handle)) return PTR_ERR(handle); - + pass_to_user(handle); data.allocation.handle = handle->id; cleanup_handle = handle; @@ -1525,7 +1588,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) mutex_unlock(&client->lock); return PTR_ERR(handle); } - ion_free_nolock(client, handle); + user_ion_free_nolock(client, handle); ion_handle_put_nolock(handle); mutex_unlock(&client->lock); break; @@ -1549,10 +1612,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct ion_handle *handle; handle = ion_import_dma_buf(client, data.fd.fd); - if (IS_ERR(handle)) + if (IS_ERR(handle)) { ret = PTR_ERR(handle); - else - data.handle.handle = handle->id; + } else { + handle = pass_to_user(handle); + if (IS_ERR(handle)) + ret = PTR_ERR(handle); + else + data.handle.handle = handle->id; + } break; } case ION_IOC_SYNC: @@ -1584,8 +1652,10 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (dir & _IOC_READ) { if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { if (cleanup_handle) { - ion_free(client, cleanup_handle); - ion_handle_put(cleanup_handle); + mutex_lock(&client->lock); + user_ion_free_nolock(client, cleanup_handle); + ion_handle_put_nolock(cleanup_handle); + mutex_unlock(&client->lock); } return -EFAULT; } diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c index 7d891936b87..81e9f53d9ca 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -8736,6 +8736,17 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, } StaParams.supported_channels_len = j; } + + if (params->supported_oper_classes_len > + SIR_MAC_MAX_SUPP_OPER_CLASSES) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "received oper classes: %d, resetting it to max" + "supported: %d", params->supported_oper_classes_len, + SIR_MAC_MAX_SUPP_OPER_CLASSES); + params->supported_oper_classes_len = + SIR_MAC_MAX_SUPP_OPER_CLASSES; + } + vos_mem_copy(StaParams.supported_oper_classes, params->supported_oper_classes, params->supported_oper_classes_len); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c index 7ef1862b798..0d1723cdf5c 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c @@ -4377,6 +4377,13 @@ static int __iw_set_ap_genie(struct net_device *dev, return 0; } + if (wrqu->data.length > DOT11F_IE_RSN_MAX_LEN) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WPARSN Ie input length is more than max[%d]", __func__, + wrqu->data.length); + return -EINVAL; + } + switch (genie[0]) { case DOT11F_EID_WPA: diff --git a/drivers/uio/msm_sharedmem/sharedmem_qmi.c b/drivers/uio/msm_sharedmem/sharedmem_qmi.c index 3b04c582cb3..8bd99e1cab0 100644 --- a/drivers/uio/msm_sharedmem/sharedmem_qmi.c +++ b/drivers/uio/msm_sharedmem/sharedmem_qmi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014, 2017, The Linux Foundation. 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 version 2 and @@ -221,6 +221,7 @@ static int sharedmem_qmi_req_cb(struct qmi_handle *handle, void *conn_h, #define DEBUG_BUF_SIZE (2048) static char *debug_buffer; static u32 debug_data_size; +static struct mutex dbg_buf_lock; /* mutex for debug_buffer */ static ssize_t debug_read(struct file *file, char __user *buf, size_t count, loff_t *file_pos) @@ -276,21 +277,29 @@ static u32 fill_debug_info(char *buffer, u32 buffer_size) static int debug_open(struct inode *inode, struct file *file) { u32 buffer_size; - if (debug_buffer != NULL) + mutex_lock(&dbg_buf_lock); + if (debug_buffer != NULL) { + mutex_unlock(&dbg_buf_lock); return -EBUSY; + } buffer_size = DEBUG_BUF_SIZE; debug_buffer = kzalloc(buffer_size, GFP_KERNEL); - if (debug_buffer == NULL) + if (debug_buffer == NULL) { + mutex_unlock(&dbg_buf_lock); return -ENOMEM; + } debug_data_size = fill_debug_info(debug_buffer, buffer_size); + mutex_unlock(&dbg_buf_lock); return 0; } static int debug_close(struct inode *inode, struct file *file) { + mutex_lock(&dbg_buf_lock); kfree(debug_buffer); debug_buffer = NULL; debug_data_size = 0; + mutex_unlock(&dbg_buf_lock); return 0; } @@ -321,6 +330,7 @@ static void debugfs_init(void) { struct dentry *f_ent; + mutex_init(&dbg_buf_lock); dir_ent = debugfs_create_dir("rmt_storage", NULL); if (IS_ERR(dir_ent)) { pr_err("Failed to create debug_fs directory\n"); @@ -349,6 +359,7 @@ static void debugfs_init(void) static void debugfs_exit(void) { debugfs_remove_recursive(dir_ent); + mutex_destroy(&dbg_buf_lock); } static void sharedmem_qmi_svc_recv_msg(struct work_struct *work) diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c index 4cc7a97cff5..049873ca32f 100644 --- a/drivers/video/msm/mdss/mdss_debug.c +++ b/drivers/video/msm/mdss/mdss_debug.c @@ -79,7 +79,7 @@ static ssize_t panel_debug_base_offset_write(struct file *file, buf[count] = 0; /* end of string */ - if (sscanf(buf, "%x %d", &off, &cnt) != 2) + if (sscanf(buf, "%x %u", &off, &cnt) != 2) return -EFAULT; if (off > dbg->max_offset) @@ -171,6 +171,8 @@ static ssize_t panel_debug_base_reg_write(struct file *file, p[2] = 0; pr_debug("p[%d] = %pK:%s\n", i, p, p); cnt = sscanf(p, "%x", &tmp); + if (cnt != 1) + return -EFAULT; reg[i] = tmp; pr_debug("reg[%d] = %x\n", i, (int)reg[i]); } @@ -693,11 +695,11 @@ static ssize_t mdss_debug_factor_write(struct file *file, if (strnchr(buf, count, '/')) { /* Parsing buf as fraction */ - if (sscanf(buf, "%d/%d", &numer, &denom) != 2) + if (sscanf(buf, "%u/%u", &numer, &denom) != 2) return -EFAULT; } else { /* Parsing buf as percentage */ - if (sscanf(buf, "%d", &numer) != 1) + if (kstrtouint(buf, 0, &numer)) return -EFAULT; denom = 100; } @@ -1004,7 +1006,7 @@ static ssize_t mdss_debug_perf_bw_limit_write(struct file *file, if (strnchr(buf, count, ' ')) { /* Parsing buf */ - if (sscanf(buf, "%d %d", &mode, &val) != 2) + if (sscanf(buf, "%u %u", &mode, &val) != 2) return -EFAULT; } diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c index 63cc27ab6ad..1fcbd290380 100644 --- a/drivers/video/msm/mdss/mdss_dsi.c +++ b/drivers/video/msm/mdss/mdss_dsi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. 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 version 2 and @@ -651,6 +651,7 @@ struct buf_data { char *string_buf; /* cmd buf as string, 3 bytes per number */ int sblen; /* string buffer length */ int sync_flag; + struct mutex dbg_mutex; /* mutex to synchronize read/write/flush */ }; struct mdss_dsi_debugfs_info { @@ -738,6 +739,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, char *bp; ssize_t ret = 0; + mutex_lock(&pcmds->dbg_mutex); if (*ppos == 0) { kfree(pcmds->string_buf); pcmds->string_buf = NULL; @@ -756,6 +758,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, buffer = kmalloc(bsize, GFP_KERNEL); if (!buffer) { pr_err("%s: Failed to allocate memory\n", __func__); + mutex_unlock(&pcmds->dbg_mutex); return -ENOMEM; } @@ -791,10 +794,12 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, kfree(pcmds->string_buf); pcmds->string_buf = NULL; pcmds->sblen = 0; + mutex_unlock(&pcmds->dbg_mutex); return 0; /* the end */ } ret = simple_read_from_buffer(buf, count, ppos, pcmds->string_buf, pcmds->sblen); + mutex_unlock(&pcmds->dbg_mutex); return ret; } @@ -806,6 +811,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, int blen = 0; char *string_buf; + mutex_lock(&pcmds->dbg_mutex); if (*ppos == 0) { kfree(pcmds->string_buf); pcmds->string_buf = NULL; @@ -817,6 +823,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, string_buf = krealloc(pcmds->string_buf, blen + 1, GFP_KERNEL); if (!string_buf) { pr_err("%s: Failed to allocate memory\n", __func__); + mutex_unlock(&pcmds->dbg_mutex); return -ENOMEM; } @@ -826,6 +833,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, string_buf[blen] = '\0'; pcmds->string_buf = string_buf; pcmds->sblen = blen; + mutex_unlock(&pcmds->dbg_mutex); return ret; } @@ -836,8 +844,12 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) char *buf, *bufp, *bp; struct dsi_ctrl_hdr *dchdr; - if (!pcmds->string_buf) + mutex_lock(&pcmds->dbg_mutex); + + if (!pcmds->string_buf) { + mutex_unlock(&pcmds->dbg_mutex); return 0; + } /* * Allocate memory for command buffer @@ -850,6 +862,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) kfree(pcmds->string_buf); pcmds->string_buf = NULL; pcmds->sblen = 0; + mutex_unlock(&pcmds->dbg_mutex); return -ENOMEM; } @@ -874,6 +887,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) pr_err("%s: dtsi cmd=%x error, len=%d\n", __func__, dchdr->dtype, dchdr->dlen); kfree(buf); + mutex_unlock(&pcmds->dbg_mutex); return -EINVAL; } bp += sizeof(*dchdr); @@ -885,6 +899,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) pr_err("%s: dcs_cmd=%x len=%d error!\n", __func__, bp[0], len); kfree(buf); + mutex_unlock(&pcmds->dbg_mutex); return -EINVAL; } @@ -897,6 +912,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) pcmds->buf = buf; pcmds->blen = blen; } + mutex_unlock(&pcmds->dbg_mutex); return 0; } @@ -911,6 +927,7 @@ struct dentry *dsi_debugfs_create_dcs_cmd(const char *name, umode_t mode, struct dentry *parent, struct buf_data *cmd, struct dsi_panel_cmds ctrl_cmds) { + mutex_init(&cmd->dbg_mutex); cmd->buf = ctrl_cmds.buf; cmd->blen = ctrl_cmds.blen; cmd->string_buf = NULL; diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index bc593eed7e6..81f217fcce3 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -2,7 +2,7 @@ * Core MDSS framebuffer driver. * * Copyright (C) 2007 Google Incorporated - * Copyright (c) 2008-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -623,8 +623,8 @@ static ssize_t mdss_fb_force_panel_dead(struct device *dev, return len; } - if (sscanf(buf, "%d", &pdata->panel_info.panel_force_dead) != 1) - pr_err("sccanf buf error!\n"); + if (kstrtouint(buf, 0, &pdata->panel_info.panel_force_dead)) + pr_err("kstrtouint buf error\n"); return len; } @@ -737,8 +737,8 @@ static ssize_t mdss_fb_change_dfps_mode(struct device *dev, } pinfo = &pdata->panel_info; - if (sscanf(buf, "%d", &dfps_mode) != 1) { - pr_err("sccanf buf error!\n"); + if (kstrtouint(buf, 0, &dfps_mode)) { + pr_err("kstrtouint buf error\n"); return len; } @@ -3511,8 +3511,6 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, goto buf_sync_err_2; } - sync_fence_install(rel_fence, rel_fen_fd); - ret = copy_to_user(buf_sync->rel_fen_fd, &rel_fen_fd, sizeof(int)); if (ret) { pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name); @@ -3549,8 +3547,6 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, goto buf_sync_err_3; } - sync_fence_install(retire_fence, retire_fen_fd); - ret = copy_to_user(buf_sync->retire_fen_fd, &retire_fen_fd, sizeof(int)); if (ret) { @@ -3561,7 +3557,11 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, goto buf_sync_err_3; } + sync_fence_install(retire_fence, retire_fen_fd); + skip_retire_fence: + sync_fence_install(rel_fence, rel_fen_fd); + mutex_unlock(&sync_pt_data->sync_mutex); if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT) diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c index 5d8deddd8da..3cf0f5f4ea9 100644 --- a/drivers/video/msm/mdss/mdss_mdp.c +++ b/drivers/video/msm/mdss/mdss_mdp.c @@ -1673,7 +1673,7 @@ static ssize_t mdss_mdp_store_max_limit_bw(struct device *dev, struct mdss_data_type *mdata = dev_get_drvdata(dev); u32 data = 0; - if (1 != sscanf(buf, "%d", &data)) { + if (kstrtouint(buf, 0, &data)) { pr_info("Not able scan to bw_mode_bitmap\n"); } else { mdata->bw_mode_bitmap = data; diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c index d81bf44515e..ee9bfdd605c 100644 --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c @@ -3677,6 +3677,11 @@ static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd, if (cursor->set & FB_CUR_SETIMAGE) { u32 cursor_addr; + if (img->width * img->height * 4 > cursor_frame_size) { + pr_err("cursor image size is too large\n"); + ret = -EINVAL; + goto done; + } ret = copy_from_user(mfd->cursor_buf, img->data, cursor_frame_size); if (ret) { diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 7af425f53be..9686c1f1765 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -320,32 +320,26 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { - umode_t mode = inode->i_mode; - retval = posix_acl_equiv_mode(acl, &mode); - if (retval < 0) + struct iattr iattr; + + retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); + if (retval) goto err_out; - else { - struct iattr iattr; - if (retval == 0) { - /* - * ACL can be represented - * by the mode bits. So don't - * update ACL. - */ - acl = NULL; - value = NULL; - size = 0; - } - /* Updte the mode bits */ - iattr.ia_mode = ((mode & S_IALLUGO) | - (inode->i_mode & ~S_IALLUGO)); - iattr.ia_valid = ATTR_MODE; - /* FIXME should we update ctime ? - * What is the following setxattr update the - * mode ? + if (!acl) { + /* + * ACL can be represented + * by the mode bits. So don't + * update ACL. */ - v9fs_vfs_setattr_dotl(dentry, &iattr); + value = NULL; + size = 0; } + iattr.ia_valid = ATTR_MODE; + /* FIXME should we update ctime ? + * What is the following setxattr update the + * mode ? + */ + v9fs_vfs_setattr_dotl(dentry, &iattr); } break; case ACL_TYPE_DEFAULT: diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 0890c83643e..d6d53e5e794 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -118,11 +118,9 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans, case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { - ret = posix_acl_equiv_mode(acl, &inode->i_mode); - if (ret < 0) + ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (ret) return ret; - if (ret == 0) - acl = NULL; } ret = 0; break; diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 110b6b371a4..48c3c2d7d26 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -206,15 +206,11 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) case ACL_TYPE_ACCESS: name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_equiv_mode(acl, &inode->i_mode); - if (error < 0) + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (error) return error; - else { - inode->i_ctime = CURRENT_TIME_SEC; - mark_inode_dirty(inode); - if (error == 0) - acl = NULL; - } + inode->i_ctime = CURRENT_TIME_SEC; + mark_inode_dirty(inode); } break; diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index dbb5ad59a7f..bb2f60a62d8 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -205,15 +205,11 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type, case ACL_TYPE_ACCESS: name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_equiv_mode(acl, &inode->i_mode); - if (error < 0) + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (error) return error; - else { - inode->i_ctime = CURRENT_TIME_SEC; - ext3_mark_inode_dirty(handle, inode); - if (error == 0) - acl = NULL; - } + inode->i_ctime = CURRENT_TIME_SEC; + ext3_mark_inode_dirty(handle, inode); } break; diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 39a54a0e9fe..c844f1bfb45 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -211,15 +211,11 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type, case ACL_TYPE_ACCESS: name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_equiv_mode(acl, &inode->i_mode); - if (error < 0) + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (error) return error; - else { - inode->i_ctime = ext4_current_time(inode); - ext4_mark_inode_dirty(handle, inode); - if (error == 0) - acl = NULL; - } + inode->i_ctime = ext4_current_time(inode); + ext4_mark_inode_dirty(handle, inode); } break; diff --git a/fs/generic_acl.c b/fs/generic_acl.c index b3f3676796d..21408084c3b 100644 --- a/fs/generic_acl.c +++ b/fs/generic_acl.c @@ -87,14 +87,10 @@ generic_acl_set(struct dentry *dentry, const char *name, const void *value, goto failed; switch (type) { case ACL_TYPE_ACCESS: - error = posix_acl_equiv_mode(acl, &inode->i_mode); - if (error < 0) + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (error) goto failed; inode->i_ctime = CURRENT_TIME; - if (error == 0) { - posix_acl_release(acl); - acl = NULL; - } break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) { diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index f69ac0af549..e7b330ef4df 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -268,15 +268,10 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, if (type == ACL_TYPE_ACCESS) { umode_t mode = inode->i_mode; - error = posix_acl_equiv_mode(acl, &mode); + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (error <= 0) { - posix_acl_release(acl); - acl = NULL; - - if (error < 0) - return error; - } + if (error) + goto out_release; error = gfs2_set_mode(inode, mode); if (error) diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 223283c3011..9335b8d3cf5 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -243,9 +243,10 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) case ACL_TYPE_ACCESS: xprefix = JFFS2_XPREFIX_ACL_ACCESS; if (acl) { - umode_t mode = inode->i_mode; - rc = posix_acl_equiv_mode(acl, &mode); - if (rc < 0) + umode_t mode; + + rc = posix_acl_update_mode(inode, &mode, &acl); + if (rc) return rc; if (inode->i_mode != mode) { struct iattr attr; @@ -257,8 +258,6 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) if (rc < 0) return rc; } - if (rc == 0) - acl = NULL; } break; case ACL_TYPE_DEFAULT: diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 42d67f9757b..c79b1d7a53e 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -693,11 +693,11 @@ static int can_set_system_xattr(struct inode *inode, const char *name, return rc; } if (acl) { - rc = posix_acl_equiv_mode(acl, &inode->i_mode); + rc = posix_acl_update_mode(inode, &inode->i_mode, &acl); posix_acl_release(acl); - if (rc < 0) { + if (rc) { printk(KERN_ERR - "posix_acl_equiv_mode returned %d\n", + "posix_acl_update_mode returned %d\n", rc); return rc; } diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 8a404576fb2..2fe643160cf 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -275,19 +275,13 @@ static int ocfs2_set_acl(handle_t *handle, name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { umode_t mode = inode->i_mode; - ret = posix_acl_equiv_mode(acl, &mode); - if (ret < 0) + ret = posix_acl_update_mode(inode, &mode, &acl); + if (ret) + return ret; + ret = ocfs2_acl_set_mode(inode, di_bh, + handle, mode); + if (ret) return ret; - else { - if (ret == 0) - acl = NULL; - - ret = ocfs2_acl_set_mode(inode, di_bh, - handle, mode); - if (ret) - return ret; - - } } break; case ACL_TYPE_DEFAULT: diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 7a82cf1601d..cc6d048fa39 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -455,3 +455,4 @@ posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode) return err; } EXPORT_SYMBOL(posix_acl_chmod); + diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 6c8767fdfc6..2d73589f37d 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -286,13 +286,9 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { - error = posix_acl_equiv_mode(acl, &inode->i_mode); - if (error < 0) + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (error) return error; - else { - if (error == 0) - acl = NULL; - } } break; case ACL_TYPE_DEFAULT: diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 306d883d89b..4f8e4770229 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -389,16 +389,9 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name, if (type == ACL_TYPE_ACCESS) { umode_t mode = inode->i_mode; - error = posix_acl_equiv_mode(acl, &mode); - - if (error <= 0) { - posix_acl_release(acl); - acl = NULL; - - if (error < 0) - return error; - } - + error = posix_acl_update_mode(inode, &mode, &acl); + if (error) + goto out_release; error = xfs_set_mode(inode, mode); if (error) goto out_release; diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 300fcc9c9da..70c7437c41d 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -554,7 +554,7 @@ do { \ #define do_trace_printk(fmt, args...) \ do { \ - static const char *trace_printk_fmt \ + static const char *trace_printk_fmt __used \ __attribute__((section("__trace_printk_fmt"))) = \ __builtin_constant_p(fmt) ? fmt : NULL; \ \ @@ -601,7 +601,7 @@ extern int __trace_puts(unsigned long ip, const char *str, int size); */ #define trace_puts(str) ({ \ - static const char *trace_printk_fmt \ + static const char *trace_printk_fmt __used \ __attribute__((section("__trace_printk_fmt"))) = \ __builtin_constant_p(str) ? str : NULL; \ \ @@ -621,7 +621,7 @@ extern void trace_dump_stack(int skip); #define ftrace_vprintk(fmt, vargs) \ do { \ if (__builtin_constant_p(fmt)) { \ - static const char *trace_printk_fmt \ + static const char *trace_printk_fmt __used \ __attribute__((section("__trace_printk_fmt"))) = \ __builtin_constant_p(fmt) ? fmt : NULL; \ \ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 2d839c0da95..6e04ca49710 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -440,11 +440,6 @@ struct perf_event { #endif /* CONFIG_PERF_EVENTS */ }; -enum perf_event_context_type { - task_context, - cpu_context, -}; - /** * struct perf_event_context - event context structure * @@ -452,7 +447,6 @@ enum perf_event_context_type { */ struct perf_event_context { struct pmu *pmu; - enum perf_event_context_type type; /* * Protect the states of the events in the list, * nr_active, and the list: diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 43cb8d59d0a..8ff25caf81a 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -91,6 +91,7 @@ extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *); extern int posix_acl_create(struct posix_acl **, gfp_t, umode_t *); extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **); extern int posix_acl_chmod(struct posix_acl **, gfp_t, umode_t); +extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **); extern struct posix_acl *get_posix_acl(struct inode *, int); extern int set_posix_acl(struct inode *, int, struct posix_acl *); diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h index 5cc4604615b..614e43768a4 100644 --- a/include/soc/qcom/qseecomi.h +++ b/include/soc/qcom/qseecomi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, The Linux Foundation. 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 version 2 and @@ -18,6 +18,7 @@ #define QSEECOM_KEY_ID_SIZE 32 +#define QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD -19 /*0xFFFFFFED*/ #define QSEOS_RESULT_FAIL_UNSUPPORTED_CE_PIPE -63 #define QSEOS_RESULT_FAIL_KS_OP -64 #define QSEOS_RESULT_FAIL_KEY_ID_EXISTS -65 @@ -62,11 +63,15 @@ enum qseecom_qceos_cmd_id { QSEOS_TEE_INVOKE_MODFD_COMMAND = QSEOS_TEE_INVOKE_COMMAND, QSEOS_TEE_CLOSE_SESSION, QSEOS_TEE_REQUEST_CANCELLATION, + QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST = 0x1F, QSEOS_FSM_LTEOTA_REQ_CMD = 0x109, QSEOS_FSM_LTEOTA_REQ_RSP_CMD = 0x110, QSEOS_FSM_IKE_REQ_CMD = 0x203, QSEOS_FSM_IKE_REQ_RSP_CMD = 0x204, QSEOS_CONTINUE_BLOCKED_REQ_COMMAND, + QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST = 0x1C, + QSEOS_TEE_OPEN_SESSION_WHITELIST = 0x1D, + QSEOS_TEE_INVOKE_COMMAND_WHITELIST = 0x1E, QSEOS_FSM_OEM_FUSE_WRITE_ROW = 0x301, QSEOS_FSM_OEM_FUSE_READ_ROW = 0x302, QSEOS_CMD_MAX = 0xEFFFFFFF @@ -177,6 +182,8 @@ __packed struct qseecom_client_send_data_ireq { uint32_t req_len; uint32_t rsp_ptr;/* First 4 bytes should be the return status */ uint32_t rsp_len; + uint32_t sglistinfo_ptr; + uint32_t sglistinfo_len; }; __packed struct qseecom_client_send_data_64bit_ireq { @@ -186,6 +193,8 @@ __packed struct qseecom_client_send_data_64bit_ireq { uint32_t req_len; uint64_t rsp_ptr; uint32_t rsp_len; + uint64_t sglistinfo_ptr; + uint32_t sglistinfo_len; }; __packed struct qseecom_reg_log_buf_ireq { @@ -205,6 +214,16 @@ __packed struct qseecom_client_listener_data_irsp { uint32_t qsee_cmd_id; uint32_t listener_id; uint32_t status; + uint32_t sglistinfo_ptr; + uint32_t sglistinfo_len; +}; + +__packed struct qseecom_client_listener_data_64bit_irsp { + uint32_t qsee_cmd_id; + uint32_t listener_id; + uint32_t status; + uint64_t sglistinfo_ptr; + uint32_t sglistinfo_len; }; /* @@ -288,6 +307,8 @@ __packed struct qseecom_qteec_ireq { uint32_t req_len; uint32_t resp_ptr; uint32_t resp_len; + uint32_t sglistinfo_ptr; + uint32_t sglistinfo_len; }; __packed struct qseecom_qteec_64bit_ireq { @@ -297,6 +318,8 @@ __packed struct qseecom_qteec_64bit_ireq { uint32_t req_len; uint64_t resp_ptr; uint32_t resp_len; + uint64_t sglistinfo_ptr; + uint32_t sglistinfo_len; }; __packed struct qseecom_client_send_fsm_key_req { @@ -648,4 +671,45 @@ __packed struct qseecom_continue_blocked_request_ireq { #define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID \ TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL) +#define TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ + TZ_SVC_APP_ID_PLACEHOLDER, 0x06) + +#define TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_7( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL) + +#define TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ + TZ_SVC_APP_ID_PLACEHOLDER, 0x07) + +#define TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_7( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL) + +#define TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ + TZ_SVC_APP_ID_PLACEHOLDER, 0x09) + +#define TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_7( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL) + +#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x05) + +#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_4( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \ + TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL) + #endif /* __QSEECOMI_H_ */ diff --git a/include/sound/msm-dts-eagle.h b/include/sound/msm-dts-eagle.h deleted file mode 100644 index 2ef01136b7c..00000000000 --- a/include/sound/msm-dts-eagle.h +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright (c) 2014, The Linux Foundation. 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 version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MSM_DTS_EAGLE_H__ -#define __MSM_DTS_EAGLE_H__ - -#include <linux/compat.h> -#include <sound/soc.h> -#include <sound/devdep_params.h> -#include <sound/q6asm-v2.h> - -#ifdef CONFIG_COMPAT -enum { - DTS_EAGLE_IOCTL_GET_CACHE_SIZE32 = _IOR(0xF2, 0, __s32), - DTS_EAGLE_IOCTL_SET_CACHE_SIZE32 = _IOW(0xF2, 1, __s32), - DTS_EAGLE_IOCTL_GET_PARAM32 = _IOR(0xF2, 2, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_PARAM32 = _IOW(0xF2, 3, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_CACHE_BLOCK32 = - _IOW(0xF2, 4, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE32 = - _IOW(0xF2, 5, compat_uptr_t), - DTS_EAGLE_IOCTL_GET_LICENSE32 = - _IOR(0xF2, 6, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_LICENSE32 = - _IOW(0xF2, 7, compat_uptr_t), - DTS_EAGLE_IOCTL_SEND_LICENSE32 = _IOW(0xF2, 8, __s32), - DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS32 = _IOW(0xF2, 9, - compat_uptr_t), -}; -#endif - -#ifdef CONFIG_DTS_EAGLE -void msm_dts_ion_memmap(struct param_outband *po_); -int msm_dts_eagle_enable_asm(struct audio_client *ac, u32 enable, int module); -int msm_dts_eagle_enable_adm(int port_id, int copp_idx, u32 enable); -void msm_dts_eagle_add_controls(struct snd_soc_platform *platform); -int msm_dts_eagle_set_stream_gain(struct audio_client *ac, - int lgain, int rgain); -int msm_dts_eagle_handle_asm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get, struct audio_client *ac, - struct param_outband *po); -int msm_dts_eagle_handle_adm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get); -int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg); -int msm_dts_eagle_is_hpx_on(void); -int msm_dts_eagle_init_pre(struct audio_client *ac); -int msm_dts_eagle_deinit_pre(struct audio_client *ac); -int msm_dts_eagle_init_post(int port_id, int copp_id); -int msm_dts_eagle_deinit_post(int port_id, int topology); -int msm_dts_eagle_init_master_module(struct audio_client *ac); -int msm_dts_eagle_deinit_master_module(struct audio_client *ac); -int msm_dts_eagle_pcm_new(struct snd_soc_pcm_runtime *runtime); -void msm_dts_eagle_pcm_free(struct snd_pcm *pcm); -int msm_dts_eagle_compat_ioctl(unsigned int cmd, unsigned long arg); -#else -static inline void msm_dts_ion_memmap(struct param_outband *po_) -{ - pr_debug("%s\n", __func__); -} -static inline int msm_dts_eagle_enable_asm(struct audio_client *ac, - u32 enable, int module) -{ - return 0; -} -static inline int msm_dts_eagle_enable_adm(int port_id, int copp_idx, - u32 enable) -{ - return 0; -} -static inline void msm_dts_eagle_add_controls(struct snd_soc_platform *platform) -{ -} -static inline int msm_dts_eagle_set_stream_gain(struct audio_client *ac, - int lgain, int rgain) -{ - pr_debug("%s\n", __func__); - return 0; -} -static inline int msm_dts_eagle_handle_asm(struct dts_eagle_param_desc *depd, - char *buf, bool for_pre, bool get, - struct audio_client *ac, - struct param_outband *po) -{ - return 0; -} -static inline int msm_dts_eagle_handle_adm(struct dts_eagle_param_desc *depd, - char *buf, bool for_pre, bool get) -{ - return 0; -} -static inline int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) -{ - return -EPERM; -} -static inline int msm_dts_eagle_is_hpx_on(void) -{ - return 0; -} -static inline int msm_dts_eagle_init_pre(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_deinit_pre(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_init_post(int port_id, int coppid) -{ - return 0; -} -static inline int msm_dts_eagle_deinit_post(int port_id, int topology) -{ - return 0; -} -static inline int msm_dts_eagle_init_master_module(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_deinit_master_module(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_pcm_new(struct snd_soc_pcm_runtime *runtime) -{ - pr_debug("%s\n", __func__); - return 0; -} -static inline void msm_dts_eagle_pcm_free(struct snd_pcm *pcm) -{ - pr_debug("%s\n", __func__); -} -static inline int msm_dts_eagle_compat_ioctl(unsigned int cmd, - unsigned long arg) -{ - return 0; -} -#endif - -#endif diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h index d3a4da8e456..19b6309e2c1 100644 --- a/include/sound/q6adm-v2.h +++ b/include/sound/q6adm-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. 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 version 2 and @@ -34,7 +34,6 @@ enum { ADM_AUDVOL_CAL, ADM_RTAC_INFO_CAL, ADM_RTAC_APR_CAL, - ADM_DTS_EAGLE, ADM_SRS_TRUMEDIA, ADM_MAX_CAL_TYPES }; diff --git a/kernel/events/core.c b/kernel/events/core.c index ebaf962af46..1bedd73b0c6 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6520,7 +6520,6 @@ skip_type: __perf_event_init_context(&cpuctx->ctx); lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex); lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock); - cpuctx->ctx.type = cpu_context; cpuctx->ctx.pmu = pmu; cpuctx->jiffies_interval = 1; INIT_LIST_HEAD(&cpuctx->rotation_list); @@ -7150,7 +7149,19 @@ SYSCALL_DEFINE5(perf_event_open, * task or CPU context: */ if (move_group) { - if (group_leader->ctx->type != ctx->type) + /* + * Make sure we're both on the same task, or both + * per-cpu events. + */ + if (group_leader->ctx->task != ctx->task) + goto err_context; + + /* + * Make sure we're both events for the same CPU; + * grouping events for different CPUs is broken; since + * you can never concurrently schedule them anyhow. + */ + if (group_leader->cpu != event->cpu) goto err_context; } else { if (group_leader->ctx != ctx) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d4026630f6d..1859cc4183d 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1480,7 +1480,7 @@ void trace_find_cmdline(int pid, char comm[]) arch_spin_lock(&trace_cmdline_lock); map = map_pid_to_cmdline[pid]; if (map != NO_CMDLINE_MAP) - strcpy(comm, saved_cmdlines[map]); + strlcpy(comm, saved_cmdlines[map], TASK_COMM_LEN-1); else strcpy(comm, "<...>"); diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index a9077c1b4ad..f423e8d551c 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -272,7 +272,10 @@ static int t_show(struct seq_file *m, void *v) const char *str = *fmt; int i; - seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt); + if (!*fmt) + return 0; + + seq_printf(m, "0x%lx : \"", 0L); /* * Tabs and new lines need to be converted. diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index dd535e3d97d..3d166535002 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1215,6 +1215,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, int peeked, off = 0; int err; int is_udplite = IS_UDPLITE(sk); + bool checksum_valid = false; bool slow; if (flags & MSG_ERRQUEUE) @@ -1240,11 +1241,12 @@ try_again: */ if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { - if (udp_lib_checksum_complete(skb)) + checksum_valid = !udp_lib_checksum_complete(skb); + if (!checksum_valid) goto csum_copy_err; } - if (skb_csum_unnecessary(skb)) + if (checksum_valid || skb_csum_unnecessary(skb)) err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, copied); else { diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 25f3babd59d..0f22ad1e847 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -370,6 +370,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, int peeked, off = 0; int err; int is_udplite = IS_UDPLITE(sk); + bool checksum_valid = false; int is_udp4; bool slow; @@ -401,11 +402,12 @@ try_again: */ if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { - if (udp_lib_checksum_complete(skb)) + checksum_valid = !udp_lib_checksum_complete(skb); + if (!checksum_valid) goto csum_copy_err; } - if (skb_csum_unnecessary(skb)) + if (checksum_valid || skb_csum_unnecessary(skb)) err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, copied); else { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7a70a5a5671..91a6a2903e8 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -390,7 +390,14 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es up = nla_data(rp); ulen = xfrm_replay_state_esn_len(up); - if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen) + /* Check the overall length and the internal bitmap length to avoid + * potential overflow. */ + if (nla_len(rp) < ulen || + xfrm_replay_state_esn_len(replay_esn) != ulen || + replay_esn->bmp_len != up->bmp_len) + return -EINVAL; + + if (up->replay_window > up->bmp_len * sizeof(__u32) * 8) return -EINVAL; return 0; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 0abdf939a58..33d8c08e564 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1875,10 +1875,10 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) if (substream->timer_running) snd_timer_interrupt(substream->timer, 1); _end: + kill_fasync(&runtime->fasync, SIGIO, POLL_IN); snd_pcm_stream_unlock_irqrestore(substream, flags); if (runtime->transfer_ack_end) runtime->transfer_ack_end(substream); - kill_fasync(&runtime->fasync, SIGIO, POLL_IN); } EXPORT_SYMBOL(snd_pcm_period_elapsed); diff --git a/sound/soc/codecs/wcd9330.c b/sound/soc/codecs/wcd9330.c index f3342d89c9a..df922a15d8c 100644 --- a/sound/soc/codecs/wcd9330.c +++ b/sound/soc/codecs/wcd9330.c @@ -1392,6 +1392,13 @@ static int tomtom_mad_input_put(struct snd_kcontrol *kcontrol, tomtom_mad_input = ucontrol->value.integer.value[0]; micb_4_int_reg = tomtom->resmgr.reg_addr->micb_4_int_rbias; + if (tomtom_mad_input >= ARRAY_SIZE(tomtom_conn_mad_text)) { + dev_err(codec->dev, + "%s: tomtom_mad_input = %d out of bounds\n", + __func__, tomtom_mad_input); + return -EINVAL; + } + pr_debug("%s: tomtom_mad_input = %s\n", __func__, tomtom_conn_mad_text[tomtom_mad_input]); diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c index 7d28b8f79c6..ce38f68f8d3 100644 --- a/sound/soc/msm/msm-cpe-lsm.c +++ b/sound/soc/msm/msm-cpe-lsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, Linux Foundation. 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 version 2 and @@ -1167,13 +1167,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, dev_dbg(rtd->dev, "%s: %s\n", __func__, "SNDRV_LSM_REG_SND_MODEL_V2"); - if (!arg) { - dev_err(rtd->dev, - "%s: Invalid argument to ioctl %s\n", - __func__, - "SNDRV_LSM_REG_SND_MODEL_V2"); - return -EINVAL; - } memcpy(&snd_model, arg, sizeof(struct snd_lsm_sound_model_v2)); @@ -1309,13 +1302,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, dev_dbg(rtd->dev, "%s: %s\n", __func__, "SNDRV_LSM_EVENT_STATUS"); - if (!arg) { - dev_err(rtd->dev, - "%s: Invalid argument to ioctl %s\n", - __func__, - "SNDRV_LSM_EVENT_STATUS"); - return -EINVAL; - } user = arg; @@ -1426,12 +1412,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, break; case SNDRV_LSM_SET_PARAMS: - if (!arg) { - dev_err(rtd->dev, - "%s: %s Invalid argument\n", - __func__, "SNDRV_LSM_SET_PARAMS"); - return -EINVAL; - } memcpy(&det_params, arg, sizeof(det_params)); if (det_params.num_confidence_levels <= 0) { @@ -1881,6 +1861,13 @@ static int msm_cpe_lsm_reg_model(struct snd_pcm_substream *substream, lsm_ops->lsm_get_snd_model_offset(cpe->core_handle, session, &offset); + /* Check if 'p_info->param_size + offset' crosses U32_MAX. */ + if (p_info->param_size > U32_MAX - offset) { + dev_err(rtd->dev, + "%s: Invalid param_size %d\n", + __func__, p_info->param_size); + return -EINVAL; + } session->snd_model_size = p_info->param_size + offset; session->snd_model_data = vzalloc(session->snd_model_size); @@ -2301,12 +2288,6 @@ done: } #ifdef CONFIG_COMPAT -struct snd_lsm_event_status32 { - u16 status; - u16 payload_size; - u8 payload[0]; -}; - struct snd_lsm_sound_model_v2_32 { compat_uptr_t data; compat_uptr_t confidence_level; @@ -2338,8 +2319,6 @@ struct snd_lsm_module_params_32 { }; enum { - SNDRV_LSM_EVENT_STATUS32 = - _IOW('U', 0x02, struct snd_lsm_event_status32), SNDRV_LSM_REG_SND_MODEL_V2_32 = _IOW('U', 0x07, struct snd_lsm_sound_model_v2_32), SNDRV_LSM_SET_PARAMS32 = @@ -2434,7 +2413,7 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, err); } break; - case SNDRV_LSM_EVENT_STATUS32: { + case SNDRV_LSM_EVENT_STATUS: { struct snd_lsm_event_status *event_status = NULL; struct snd_lsm_event_status u_event_status32; struct snd_lsm_event_status *udata_32 = NULL; @@ -2476,7 +2455,6 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, } else { event_status->payload_size = u_event_status32.payload_size; - cmd = SNDRV_LSM_EVENT_STATUS; err = msm_cpe_lsm_ioctl_shared(substream, cmd, event_status); if (err) @@ -2578,14 +2556,6 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, goto done; } - if (!arg) { - dev_err(rtd->dev, - "%s: %s: No Param data to set\n", - __func__, "SET_MODULE_PARAMS_32"); - err = -EINVAL; - goto done; - } - if (copy_from_user(&p_data_32, arg, sizeof(p_data_32))) { dev_err(rtd->dev, @@ -2670,6 +2640,19 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, kfree(params32); break; } + case SNDRV_LSM_REG_SND_MODEL_V2: + case SNDRV_LSM_SET_PARAMS: + case SNDRV_LSM_SET_MODULE_PARAMS: + /* + * In ideal cases, the compat_ioctl should never be called + * with the above unlocked ioctl commands. Print error + * and return error if it does. + */ + dev_err(rtd->dev, + "%s: Invalid cmd for compat_ioctl\n", + __func__); + err = -EINVAL; + break; default: err = msm_cpe_lsm_ioctl_shared(substream, cmd, arg); break; diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c index 562e9a121d4..67ca2bcd0a6 100644 --- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c +++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. 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 version 2 and @@ -136,8 +136,6 @@ size_t get_cal_info_size(int32_t cal_type) case ULP_LSM_CAL_TYPE: size = sizeof(struct audio_cal_info_lsm); break; - case DTS_EAGLE_CAL_TYPE: - size = 0; case AUDIO_CORE_METAINFO_CAL_TYPE: size = sizeof(struct audio_cal_info_metainfo); break; @@ -263,8 +261,6 @@ size_t get_user_cal_type_size(int32_t cal_type) case ULP_LSM_CAL_TYPE: size = sizeof(struct audio_cal_type_lsm); break; - case DTS_EAGLE_CAL_TYPE: - size = 0; case AUDIO_CORE_METAINFO_CAL_TYPE: size = sizeof(struct audio_cal_type_metainfo); break; @@ -567,7 +563,6 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, memset(cal_block, 0, sizeof(*cal_block)); INIT_LIST_HEAD(&cal_block->list); - list_add_tail(&cal_block->list, &cal_type->cal_blocks); cal_block->map_data.ion_map_handle = basic_cal->cal_data.mem_handle; if (basic_cal->cal_data.mem_handle > 0) { @@ -599,6 +594,7 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, goto err; } cal_block->buffer_number = basic_cal->cal_hdr.buffer_number; + list_add_tail(&cal_block->list, &cal_type->cal_blocks); pr_debug("%s: created block for cal type %d, buf num %d, map handle %d, map size %zd paddr 0x%pK!\n", __func__, cal_type->info.reg.cal_type, cal_block->buffer_number, @@ -608,6 +604,8 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, done: return cal_block; err: + kfree(cal_block->cal_info); + kfree(cal_block->client_info); kfree(cal_block); cal_block = NULL; return cal_block; diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c index f76f9a4399e..b794f34a911 100644 --- a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. 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 version 2 and @@ -15,7 +15,6 @@ #include <sound/q6asm-v2.h> #include <sound/compress_params.h> #include <sound/msm-audio-effects-q6-v2.h> -#include <sound/msm-dts-eagle.h> #include <sound/devdep_params.h> #define MAX_ENABLE_CMD_SIZE 32 @@ -49,26 +48,6 @@ bool msm_audio_effects_is_effmodule_supp_in_top(int effect_module, case EQ_MODULE: switch (topology) { case ASM_STREAM_POSTPROC_TOPO_ID_SA_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - return true; - default: - return false; - } - case DTS_EAGLE_MODULE: - switch (topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - return true; - default: - return false; - } - case SOFT_VOLUME2_MODULE: - case DTS_EAGLE_MODULE_ENABLE: - switch (topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: return true; default: return false; @@ -276,7 +255,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -747,7 +726,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -883,7 +862,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -1198,7 +1177,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index 21ae599ff8f..c6b21761f87 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -42,8 +42,6 @@ #include <sound/compress_offload.h> #include <sound/compress_driver.h> #include <sound/msm-audio-effects-q6-v2.h> -#include <sound/msm-dts-eagle.h> - #include "msm-pcm-routing-v2.h" #include "audio_ocmem.h" @@ -82,15 +80,6 @@ const DECLARE_TLV_DB_LINEAR(msm_compr_vol_gain, 0, #define MAX_NUMBER_OF_STREAMS 2 -/* - * Max size for getting DTS EAGLE Param through kcontrol - * Safe for both 32 and 64 bit platforms - * 64 = size of kcontrol value array on 64 bit platform - * 4 = size of parameters Eagle expects before cast to 64 bits - * 40 = size of dts_eagle_param_desc + module_id cast to 64 bits - */ -#define DTS_EAGLE_MAX_PARAM_SIZE_FOR_ALSA ((64 * 4) - 40) - struct msm_compr_gapless_state { bool set_next_stream_id; int32_t stream_opened[MAX_NUMBER_OF_STREAMS]; @@ -259,11 +248,6 @@ static int msm_compr_set_volume(struct snd_compr_stream *cstream, if (rc < 0) pr_err("%s: Send vol gain command failed rc=%d\n", __func__, rc); - else - if (msm_dts_eagle_set_stream_gain(prtd->audio_client, - volume_l, volume_r)) - pr_debug("%s: DTS_EAGLE send stream gain failed\n", - __func__); return rc; } @@ -858,26 +842,6 @@ static int msm_compr_init_pp_params(struct snd_compr_stream *cstream, }; switch (ac->topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: /* HPX + SA+ topology */ - - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_1); - if (ret < 0) - pr_err("%s: Send SoftVolume Param failed ret=%d\n", - __func__, ret); - - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_2); - if (ret < 0) - pr_err("%s: Send SoftVolume2 Param failed ret=%d\n", - __func__, ret); - /* - * HPX module init is trigerred from HAL using ioctl - * DTS_EAGLE_MODULE_ENABLE when stream starts - */ - break; - case ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX: /* HPX topology */ - break; default: ret = q6asm_set_softvolume_v2(ac, &softvol, SOFT_VOLUME_INSTANCE_1); @@ -2334,23 +2298,6 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol, &(audio_effects->equalizer), values); break; - case DTS_EAGLE_MODULE: - pr_debug("%s: DTS_EAGLE_MODULE\n", __func__); - if (!msm_audio_effects_is_effmodule_supp_in_top(effects_module, - prtd->audio_client->topology)) - return 0; - msm_dts_eagle_handle_asm(NULL, (void *)values, true, - false, prtd->audio_client, NULL); - break; - case DTS_EAGLE_MODULE_ENABLE: - pr_debug("%s: DTS_EAGLE_MODULE_ENABLE\n", __func__); - if (msm_audio_effects_is_effmodule_supp_in_top(effects_module, - prtd->audio_client->topology)) - msm_dts_eagle_enable_asm(prtd->audio_client, - (bool)values[0], - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); - - break; case SOFT_VOLUME_MODULE: pr_debug("%s: SOFT_VOLUME_MODULE\n", __func__); break; @@ -2379,7 +2326,6 @@ static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol, struct msm_compr_audio_effects *audio_effects = NULL; struct snd_compr_stream *cstream = NULL; struct msm_compr_audio *prtd = NULL; - long *values = &(ucontrol->value.integer.value[0]); pr_debug("%s\n", __func__); if (fe_id >= MSM_FRONTEND_DAI_MAX) { @@ -2399,28 +2345,6 @@ static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol, return -EINVAL; } - switch (audio_effects->query.mod_id) { - case DTS_EAGLE_MODULE: - pr_debug("%s: DTS_EAGLE_MODULE handling queued get\n", - __func__); - values[0] = (long)audio_effects->query.mod_id; - values[1] = (long)audio_effects->query.parm_id; - values[2] = (long)audio_effects->query.size; - values[3] = (long)audio_effects->query.offset; - values[4] = (long)audio_effects->query.device; - if (values[2] > DTS_EAGLE_MAX_PARAM_SIZE_FOR_ALSA) { - pr_err("%s: DTS_EAGLE_MODULE parameter's requested size (%li) too large (max size is %i)\n", - __func__, values[2], - DTS_EAGLE_MAX_PARAM_SIZE_FOR_ALSA); - return -EINVAL; - } - msm_dts_eagle_handle_asm(NULL, (void *)&values[1], - true, true, prtd->audio_client, NULL); - break; - default: - pr_err("%s: Invalid effects config module\n", __func__); - return -EINVAL; - } return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index 8ef8f49f5fd..714684fdd7c 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. 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 version 2 and @@ -1379,6 +1379,11 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai, pr_err("%s: rx slot not found\n", __func__); return -EINVAL; } + if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) { + pr_err("%s: invalid rx num %d\n", __func__, rx_num); + return -EINVAL; + } + for (i = 0; i < rx_num; i++) { dai_data->port_config.slim_sch.shared_ch_mapping[i] = rx_slot[i]; @@ -1409,6 +1414,11 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai, pr_err("%s: tx slot not found\n", __func__); return -EINVAL; } + if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) { + pr_err("%s: invalid tx num %d\n", __func__, tx_num); + return -EINVAL; + } + for (i = 0; i < tx_num; i++) { dai_data->port_config.slim_sch.shared_ch_mapping[i] = tx_slot[i]; diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c index bb0f890d300..d270b3dcd07 100644 --- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2014, 2016, The Linux Foundation. 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 version 2 and * only version 2 as published by the Free Software Foundation. @@ -18,6 +18,10 @@ #include "msm-dolby-dap-config.h" +#ifndef DOLBY_PARAM_VCNB_MAX_LENGTH +#define DOLBY_PARAM_VCNB_MAX_LENGTH 40 +#endif + /* dolby endp based parameters */ struct dolby_dap_endp_params_s { int device; @@ -677,7 +681,7 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int rc = 0, port_id, copp_idx; - uint32_t idx, j; + uint32_t idx, j, current_offset; uint32_t device = ucontrol->value.integer.value[0]; uint32_t param_id = ucontrol->value.integer.value[1]; uint32_t offset = ucontrol->value.integer.value[2]; @@ -754,6 +758,19 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol, default: { /* cache the parameters */ dolby_dap_params_modified[idx] += 1; + current_offset = dolby_dap_params_offset[idx] + offset; + if (current_offset >= TOTAL_LENGTH_DOLBY_PARAM) { + pr_err("%s: invalid offset %d at idx %d\n", + __func__, offset, idx); + return -EINVAL; + } + if ((0 == length) || (current_offset + length - 1 + < current_offset) || (current_offset + length + > TOTAL_LENGTH_DOLBY_PARAM)) { + pr_err("%s: invalid length %d at idx %d\n", + __func__, length, idx); + return -EINVAL; + } dolby_dap_params_length[idx] = length; pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n", __func__, device, param_id, offset, length); @@ -896,6 +913,11 @@ int msm_dolby_dap_param_visualizer_control_get(struct snd_kcontrol *kcontrol, uint32_t param_payload_len = DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t); int port_id, copp_idx, idx; + if (length > DOLBY_PARAM_VCNB_MAX_LENGTH || length <= 0) { + pr_err("%s Incorrect VCNB length", __func__); + ucontrol->value.integer.value[0] = 0; + return -EINVAL; + } for (idx = 0; idx < AFE_MAX_PORTS; idx++) { port_id = dolby_dap_params_states.port_id[idx]; copp_idx = dolby_dap_params_states.copp_idx[idx]; diff --git a/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c b/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c index 7c35d19bb61..8fc49b29000 100644 --- a/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c +++ b/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2012-2014, 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, 2016-2017, The Linux Foundation. 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 version 2 and @@ -19,7 +20,6 @@ #include <sound/control.h> #include <sound/q6adm-v2.h> #include <sound/asound.h> -#include <sound/msm-dts-eagle.h> #include "msm-dts-srs-tm-config.h" #include "msm-pcm-routing-v2.h" diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c index e80b6fb9cf8..fb44bb71043 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014, 2017 The Linux Foundation. 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 version 2 and @@ -14,8 +14,6 @@ #include <linux/module.h> #include <sound/hwdep.h> #include <sound/devdep_params.h> -#include <sound/msm-dts-eagle.h> - #include "msm-pcm-routing-devdep.h" #include "msm-ds2-dap-config.h" @@ -53,23 +51,6 @@ static int msm_pcm_routing_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER: ret = msm_ds2_dap_ioctl(hw, file, cmd, argp); break; - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE: - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE: - case DTS_EAGLE_IOCTL_GET_PARAM: - case DTS_EAGLE_IOCTL_SET_PARAM: - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK: - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE: - case DTS_EAGLE_IOCTL_GET_LICENSE: - case DTS_EAGLE_IOCTL_SET_LICENSE: - case DTS_EAGLE_IOCTL_SEND_LICENSE: - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS: - ret = msm_dts_eagle_ioctl(cmd, arg); - if (ret == -EPERM) { - pr_err("%s called with invalid control 0x%X\n", - __func__, cmd); - ret = -EINVAL; - } - break; default: pr_err("%s called with invalid control 0x%X\n", __func__, cmd); ret = -EINVAL; @@ -81,7 +62,6 @@ static int msm_pcm_routing_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, void msm_pcm_routing_hwdep_free(struct snd_pcm *pcm) { pr_debug("%s\n", __func__); - msm_dts_eagle_pcm_free(pcm); } #ifdef CONFIG_COMPAT @@ -105,23 +85,6 @@ static int msm_pcm_routing_hwdep_compat_ioctl(struct snd_hwdep *hw, case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER32: ret = msm_ds2_dap_compat_ioctl(hw, file, cmd, argp); break; - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE32: - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE32: - case DTS_EAGLE_IOCTL_GET_PARAM32: - case DTS_EAGLE_IOCTL_SET_PARAM32: - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK32: - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE32: - case DTS_EAGLE_IOCTL_GET_LICENSE32: - case DTS_EAGLE_IOCTL_SET_LICENSE32: - case DTS_EAGLE_IOCTL_SEND_LICENSE32: - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS32: - ret = msm_dts_eagle_compat_ioctl(cmd, arg); - if (ret == -EPERM) { - pr_err("%s called with invalid control 0x%X\n", - __func__, cmd); - ret = -EINVAL; - } - break; default: pr_err("%s called with invalid control 0x%X\n", __func__, cmd); ret = -EINVAL; @@ -167,7 +130,7 @@ int msm_pcm_routing_hwdep_new(struct snd_soc_pcm_runtime *runtime, #ifdef CONFIG_COMPAT hwdep->ops.ioctl_compat = msm_pcm_routing_hwdep_compat_ioctl; #endif - return msm_dts_eagle_pcm_new(runtime); + return rc; } #endif diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 6794c47cf5a..5204839ad77 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. 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 version 2 and @@ -33,7 +33,6 @@ #include <sound/pcm_params.h> #include <sound/q6core.h> #include <sound/audio_cal_utils.h> -#include <sound/msm-dts-eagle.h> #include <sound/audio_effects.h> #include <sound/hwdep.h> @@ -141,10 +140,6 @@ static void msm_pcm_routing_cfg_pp(int port_id, int copp_idx, int topology, __func__, topology, port_id, rc); } break; - case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX: - pr_debug("%s: DTS_EAGLE_COPP_TOPOLOGY_ID\n", __func__); - msm_dts_eagle_init_post(port_id, copp_idx); - break; case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_AUDIOSPHERE: pr_debug("%s: TOPOLOGY_ID_AUDIOSPHERE\n", __func__); msm_qti_pp_asphere_init(port_id, copp_idx); @@ -176,10 +171,6 @@ static void msm_pcm_routing_deinit_pp(int port_id, int topology) msm_dolby_dap_deinit(port_id); } break; - case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX: - pr_debug("%s: DTS_EAGLE_COPP_TOPOLOGY_ID\n", __func__); - msm_dts_eagle_deinit_post(port_id, topology); - break; case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_AUDIOSPHERE: pr_debug("%s: TOPOLOGY_ID_AUDIOSPHERE\n", __func__); msm_qti_pp_asphere_deinit(port_id); @@ -1544,6 +1535,11 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol, int mux = ucontrol->value.enumerated.item[0]; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + if (mux >= e->max) { + pr_err("%s: Invalid mux value %d\n", __func__, mux); + return -EINVAL; + } + mutex_lock(&routing_lock); switch (ucontrol->value.integer.value[0]) { case 0: @@ -1665,9 +1661,14 @@ static int msm_routing_ext_ec_put(struct snd_kcontrol *kcontrol, int ret = 0; bool state = false; + if (mux >= e->max) { + pr_err("%s: Invalid mux value %d\n", __func__, mux); + return -EINVAL; + } + pr_debug("%s: msm_route_ec_ref_rx = %d value = %ld\n", - __func__, msm_route_ext_ec_ref, - ucontrol->value.integer.value[0]); + __func__, msm_route_ext_ec_ref, + ucontrol->value.integer.value[0]); mutex_lock(&routing_lock); switch (ucontrol->value.integer.value[0]) { @@ -6607,8 +6608,6 @@ static int msm_routing_probe(struct snd_soc_platform *platform) device_pp_params_mixer_controls, ARRAY_SIZE(device_pp_params_mixer_controls)); - msm_dts_eagle_add_controls(platform); - snd_soc_add_platform_controls(platform, msm_source_tracking_controls, ARRAY_SIZE(msm_source_tracking_controls)); diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c index 08c4f2ac640..53f57cd39a9 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c @@ -827,6 +827,11 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, (sizeof(buf_node->frame.frm_hdr) + sizeof(buf_node->frame.pktlen)); } + if (ret) { + pr_err("%s: copy from user failed %d\n", + __func__, ret); + return -EFAULT; + } spin_lock_irqsave(&prtd->dsp_lock, dsp_flags); list_add_tail(&buf_node->list, &prtd->in_queue); spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags); diff --git a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c index 1eeb577b0ed..94d6cf7a7c7 100644 --- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c @@ -484,7 +484,7 @@ static int msm_qti_pp_set_auxpcm_lb_vol_mixer(struct snd_kcontrol *kcontrol, static int msm_qti_pp_get_channel_map_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL]; + char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL] = {0}; int i; adm_get_multi_ch_map(channel_map, ADM_PATH_PLAYBACK); diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index f0295948db5..330f147d28f 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -24,7 +24,6 @@ #include <sound/q6afe-v2.h> #include <sound/audio_cal_utils.h> #include <sound/asound.h> -#include <sound/msm-dts-eagle.h> #include "msm-dts-srs-tm-config.h" #include <sound/adsp_err.h> @@ -250,222 +249,6 @@ static int adm_get_next_available_copp(int port_idx) return idx; } -int adm_dts_eagle_set(int port_id, int copp_idx, int param_id, - void *data, uint32_t size) -{ - struct adm_cmd_set_pp_params_v5 admp; - int p_idx, ret = 0, *ob_params; - - pr_debug("DTS_EAGLE_ADM: %s - port id %i, copp idx %i, param id 0x%X size %u\n", - __func__, port_id, copp_idx, param_id, size); - - port_id = afe_convert_virtual_to_portid(port_id); - p_idx = adm_validate_and_get_port_index(port_id); - pr_debug("DTS_EAGLE_ADM: %s - after lookup, port id %i, port idx %i\n", - __func__, port_id, p_idx); - - if (p_idx < 0) { - pr_err("DTS_EAGLE_ADM: %s: invalid port index 0x%x, port id 0x%x\n", - __func__, p_idx, port_id); - return -EINVAL; - } - - if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) { - pr_err("DTS_EAGLE_ADM: %s: Invalid copp_idx: %d\n", __func__, - copp_idx); - return -EINVAL; - } - - ob_params = (int *)this_adm.outband_memmap.kvaddr; - if (ob_params == NULL) { - pr_err("DTS_EAGLE_ADM: %s - NULL memmap. Non Eagle topology selected?\n", - __func__); - ret = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - ret = -EINVAL; - if ((ret < 0) || - (size + APR_CMD_OB_HDR_SZ > this_adm.outband_memmap.size)) { - pr_err("DTS_EAGLE_ADM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, this_adm.outband_memmap.size, - size + APR_CMD_OB_HDR_SZ); - ret = -EINVAL; - goto fail_cmd; - } - *ob_params++ = AUDPROC_MODULE_ID_DTS_HPX_POSTMIX; - *ob_params++ = param_id; - *ob_params++ = size; - memcpy(ob_params, data, size); - - admp.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - admp.hdr.pkt_size = sizeof(admp); - admp.hdr.src_svc = APR_SVC_ADM; - admp.hdr.src_domain = APR_DOMAIN_APPS; - admp.hdr.src_port = port_id; - admp.hdr.dest_svc = APR_SVC_ADM; - admp.hdr.dest_domain = APR_DOMAIN_ADSP; - admp.hdr.dest_port = atomic_read(&this_adm.copp.id[p_idx][copp_idx]); - admp.hdr.token = p_idx << 16 | copp_idx; - admp.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5; - admp.payload_addr_lsw = lower_32_bits(this_adm.outband_memmap.paddr); - admp.payload_addr_msw = populate_upper_32_bits( - this_adm.outband_memmap.paddr); - admp.mem_map_handle = atomic_read(&this_adm.mem_map_handles[ - ADM_DTS_EAGLE]); - admp.payload_size = size + sizeof(struct adm_param_data_v5); - - pr_debug("DTS_EAGLE_ADM: %s - Command was sent now check Q6 - port id = %d, size %d, module id %x, param id %x.\n", - __func__, admp.hdr.dest_port, - admp.payload_size, AUDPROC_MODULE_ID_DTS_HPX_POSTMIX, - param_id); - atomic_set(&this_adm.copp.stat[p_idx][copp_idx], 0); - atomic_set(&this_adm.copp.cmd_err_code[p_idx][copp_idx], 0); - ret = apr_send_pkt(this_adm.apr, (uint32_t *)&admp); - if (ret < 0) { - pr_err("DTS_EAGLE_ADM: %s - ADM enable for port %d failed\n", - __func__, port_id); - ret = -EINVAL; - goto fail_cmd; - } - ret = wait_event_timeout(this_adm.copp.wait[p_idx][copp_idx], - atomic_read(&this_adm.copp.stat[p_idx][copp_idx]), - msecs_to_jiffies(TIMEOUT_MS)); - if (!ret) { - pr_err("DTS_EAGLE_ADM: %s - set params timed out port = %d\n", - __func__, port_id); - ret = -EINVAL; - } else if (atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]) > 0) { - pr_err("%s: DSP returned error[%s]\n", - __func__, adsp_err_get_err_str( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]))); - ret = adsp_err_get_lnx_err_code( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx])); - } else { - ret = 0; - } - -fail_cmd: - return ret; -} - -int adm_dts_eagle_get(int port_id, int copp_idx, int param_id, - void *data, uint32_t size) -{ - struct adm_cmd_get_pp_params_v5 admp; - int p_idx, ret = 0, *ob_params; - uint32_t orig_size = size; - pr_debug("DTS_EAGLE_ADM: %s - port id %i, copp idx %i, param id 0x%X\n", - __func__, port_id, copp_idx, param_id); - - port_id = afe_convert_virtual_to_portid(port_id); - p_idx = adm_validate_and_get_port_index(port_id); - if (p_idx < 0) { - pr_err("DTS_EAGLE_ADM: %s - invalid port index %i, port id %i, copp idx %i\n", - __func__, p_idx, port_id, copp_idx); - return -EINVAL; - } - - if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) { - pr_err("DTS_EAGLE_ADM: %s: Invalid copp_idx: %d\n", __func__, - copp_idx); - return -EINVAL; - } - - if ((size == 0) || !data) { - pr_err("DTS_EAGLE_ADM: %s - invalid size %u or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - - size = (size+3) & 0xFFFFFFFC; - - ob_params = (int *)(this_adm.outband_memmap.kvaddr); - if (ob_params == NULL) { - pr_err("DTS_EAGLE_ADM: %s - NULL memmap. Non Eagle topology selected?", - __func__); - ret = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - ret = -EINVAL; - if ((ret < 0) || - (size + APR_CMD_OB_HDR_SZ > this_adm.outband_memmap.size)) { - pr_err("DTS_EAGLE_ADM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, this_adm.outband_memmap.size, - size + APR_CMD_OB_HDR_SZ); - ret = -EINVAL; - goto fail_cmd; - } - *ob_params++ = AUDPROC_MODULE_ID_DTS_HPX_POSTMIX; - *ob_params++ = param_id; - *ob_params++ = size; - - admp.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - admp.hdr.pkt_size = sizeof(admp); - admp.hdr.src_svc = APR_SVC_ADM; - admp.hdr.src_domain = APR_DOMAIN_APPS; - admp.hdr.src_port = port_id; - admp.hdr.dest_svc = APR_SVC_ADM; - admp.hdr.dest_domain = APR_DOMAIN_ADSP; - admp.hdr.dest_port = atomic_read(&this_adm.copp.id[p_idx][copp_idx]); - admp.hdr.token = p_idx << 16 | copp_idx; - admp.hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5; - admp.data_payload_addr_lsw = - lower_32_bits(this_adm.outband_memmap.paddr); - admp.data_payload_addr_msw = - populate_upper_32_bits( - this_adm.outband_memmap.paddr); - admp.mem_map_handle = atomic_read(&this_adm.mem_map_handles[ - ADM_DTS_EAGLE]); - admp.module_id = AUDPROC_MODULE_ID_DTS_HPX_POSTMIX; - admp.param_id = param_id; - admp.param_max_size = size + sizeof(struct adm_param_data_v5); - admp.reserved = 0; - - atomic_set(&this_adm.copp.stat[p_idx][copp_idx], 0); - atomic_set(&this_adm.copp.cmd_err_code[p_idx][copp_idx], 0); - - ret = apr_send_pkt(this_adm.apr, (uint32_t *)&admp); - if (ret < 0) { - pr_err("DTS_EAGLE_ADM: %s - Failed to get EAGLE Params on port %d\n", - __func__, port_id); - ret = -EINVAL; - goto fail_cmd; - } - ret = wait_event_timeout(this_adm.copp.wait[p_idx][copp_idx], - atomic_read(&this_adm.copp.stat[p_idx][copp_idx]), - msecs_to_jiffies(TIMEOUT_MS)); - if (!ret) { - pr_err("DTS_EAGLE_ADM: %s - EAGLE get params timed out port = %d\n", - __func__, port_id); - ret = -EINVAL; - goto fail_cmd; - } else if (atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]) > 0) { - pr_err("%s: DSP returned error[%s]\n", - __func__, adsp_err_get_err_str( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]))); - ret = adsp_err_get_lnx_err_code( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx])); - goto fail_cmd; - } - - memcpy(data, ob_params, orig_size); - ret = 0; -fail_cmd: - return ret; -} - int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id, void *srs_params) { @@ -2255,13 +2038,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, __func__, port_id, path, rate, channel_mode, perf_mode, topology); - /* For DTS EAGLE only, force 24 bit */ - if ((topology == ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX) && - (perf_mode == LEGACY_PCM_MODE)) { - bit_width = 24; - pr_debug("%s: Force open adm in 24-bit for DTS HPX topology 0x%x\n", - __func__, topology); - } port_id = q6audio_convert_virtual_to_portid(port_id); port_idx = adm_validate_and_get_port_index(port_id); if (port_idx < 0) { @@ -2288,8 +2064,7 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, flags = ADM_LOW_LATENCY_DEVICE_SESSION; if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) || (topology == DS2_ADM_COPP_TOPOLOGY_ID) || - (topology == SRS_TRUMEDIA_TOPOLOGY_ID) || - (topology == ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX)) + (topology == SRS_TRUMEDIA_TOPOLOGY_ID)) topology = DEFAULT_COPP_TOPOLOGY; } else { if (path == ADM_PATH_COMPRESSED_RX) @@ -2357,20 +2132,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, (uint32_t)this_adm.outband_memmap.size); } } - if ((topology == ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX) && - (perf_mode == LEGACY_PCM_MODE)) { - int res = 0; - atomic_set(&this_adm.mem_map_index, ADM_DTS_EAGLE); - msm_dts_ion_memmap(&this_adm.outband_memmap); - res = adm_memory_map_regions( - &this_adm.outband_memmap.paddr, - 0, - (uint32_t *)&this_adm.outband_memmap.size, - 1); - if (res < 0) - pr_err("%s: DTS_EAGLE mmap did not work!", - __func__); - } open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); @@ -2650,21 +2411,6 @@ int adm_close(int port_id, int perf_mode, int copp_idx) } } - if ((perf_mode == LEGACY_PCM_MODE) && - (this_adm.outband_memmap.paddr != 0) && - (atomic_read( - &this_adm.copp.topology[port_idx][copp_idx]) == - ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX)) { - atomic_set(&this_adm.mem_map_index, ADM_DTS_EAGLE); - ret = adm_memory_unmap_regions(); - if (ret < 0) { - pr_err("%s: adm mem unmmap err %d", - __func__, ret); - } else { - atomic_set(&this_adm.mem_map_handles - [ADM_DTS_EAGLE], 0); - } - } if ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) && (this_adm.sourceTrackingData.memmap.paddr != 0)) { @@ -3051,10 +2797,6 @@ static int adm_init_cal_data(void) {NULL, NULL, NULL, NULL, NULL, NULL} }, {NULL, NULL, cal_utils_match_buf_num} }, - {{DTS_EAGLE_CAL_TYPE, - {NULL, NULL, NULL, NULL, NULL, NULL} }, - {NULL, NULL, cal_utils_match_buf_num} }, - {{SRS_TRUMEDIA_CAL_TYPE, {NULL, NULL, NULL, NULL, NULL, NULL} }, {NULL, NULL, cal_utils_match_buf_num} } diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 4960fff4558..eb871ad29fe 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * Author: Brian Swetland <swetland@google.com> * * This software is licensed under the terms of the GNU General Public @@ -40,7 +40,6 @@ #include <sound/q6asm-v2.h> #include <sound/q6audio-v2.h> #include <sound/audio_cal_utils.h> -#include <sound/msm-dts-eagle.h> #define TRUE 0x01 #define FALSE 0x00 @@ -2081,9 +2080,6 @@ static int __q6asm_open_read(struct audio_client *ac, open.src_endpointype = ASM_END_POINT_DEVICE_MATRIX; open.preprocopo_id = q6asm_get_asm_topology(); - if ((open.preprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.preprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS)) - open.preprocopo_id = ASM_STREAM_POSTPROCOPO_ID_NONE; open.bits_per_sample = bits_per_sample; open.mode_flags = 0x0; @@ -2280,16 +2276,9 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format, open.bits_per_sample = bits_per_sample; open.postprocopo_id = q6asm_get_asm_topology(); - if ((ac->perf_mode != LEGACY_PCM_MODE) && - ((open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS))) + if (ac->perf_mode != LEGACY_PCM_MODE) open.postprocopo_id = ASM_STREAM_POSTPROCOPO_ID_NONE; - /* For DTS EAGLE only, force 24 bit */ - if ((open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS)) - open.bits_per_sample = 24; - pr_debug("%s: perf_mode %d asm_topology 0x%x bps %d\n", __func__, ac->perf_mode, open.postprocopo_id, open.bits_per_sample); @@ -2421,10 +2410,6 @@ static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format, topology : open.postprocopo_id; ac->topology = open.postprocopo_id; - /* For DTS EAGLE only, force 24 bit */ - if ((open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER)) - open.bits_per_sample = 24; switch (wr_format) { case FORMAT_LINEAR_PCM: @@ -4172,7 +4157,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, struct asm_buffer_node *buffer_node = NULL; int rc = 0; int i = 0; - int cmd_size = 0; + uint32_t cmd_size = 0; uint32_t bufcnt_t; uint32_t bufsz_t; @@ -4194,10 +4179,25 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, bufsz_t = PAGE_ALIGN(bufsz_t); } + if (bufcnt_t > (UINT_MAX + - sizeof(struct avs_cmd_shared_mem_map_regions)) + / sizeof(struct avs_shared_map_region_payload)) { + pr_err("%s: Unsigned Integer Overflow. bufcnt_t = %u\n", + __func__, bufcnt_t); + return -EINVAL; + } + cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions) + (sizeof(struct avs_shared_map_region_payload) * bufcnt_t); + + if (bufcnt > (UINT_MAX / sizeof(struct asm_buffer_node))) { + pr_err("%s: Unsigned Integer Overflow. bufcnt = %u\n", + __func__, bufcnt); + return -EINVAL; + } + buffer_node = kzalloc(sizeof(struct asm_buffer_node) * bufcnt, GFP_KERNEL); if (!buffer_node) { @@ -4493,215 +4493,6 @@ fail_cmd: return rc; } -int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size, - void *data, struct param_outband *po, int m_id) -{ - int rc = 0, *ob_params = NULL; - uint32_t sz = sizeof(struct asm_dts_eagle_param) + (po ? 0 : size); - struct asm_dts_eagle_param *ad; - - if (!ac || ac->apr == NULL || (size == 0) || !data) { - pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - - ad = kzalloc(sz, GFP_KERNEL); - if (!ad) { - pr_err("DTS_EAGLE_ASM - %s: error allocating mem of size %u\n", - __func__, sz); - return -ENOMEM; - } - pr_debug("DTS_EAGLE_ASM - %s: ac %pK param_id 0x%x size %u data %pK m_id 0x%x\n", - __func__, ac, param_id, size, data, m_id); - q6asm_add_hdr_async(ac, &ad->hdr, sz, 1); - ad->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; - ad->param.data_payload_addr_lsw = 0; - ad->param.data_payload_addr_msw = 0; - - ad->param.mem_map_handle = 0; - ad->param.data_payload_size = size + - sizeof(struct asm_stream_param_data_v2); - ad->data.module_id = m_id; - ad->data.param_id = param_id; - ad->data.param_size = size; - ad->data.reserved = 0; - atomic_set(&ac->cmd_state, 1); - - if (po) { - struct list_head *ptr, *next; - struct asm_buffer_node *node; - pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %pK, physical %pK)\n", - __func__, po->kvaddr, &po->paddr); - ad->param.data_payload_addr_lsw = lower_32_bits(po->paddr); - ad->param.data_payload_addr_msw = populate_upper_32_bits( - po->paddr); - list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) { - node = list_entry(ptr, struct asm_buffer_node, list); - if (node->buf_phys_addr == po->paddr) { - ad->param.mem_map_handle = node->mmap_hdl; - break; - } - } - if (ad->param.mem_map_handle == 0) { - pr_err("DTS_EAGLE_ASM - %s: mem map handle not found\n", - __func__); - rc = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - rc = -EINVAL; - if ((rc < 0) || (size + APR_CMD_OB_HDR_SZ > po->size)) { - pr_err("DTS_EAGLE_ASM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, po->size, size + APR_CMD_OB_HDR_SZ); - rc = -EINVAL; - goto fail_cmd; - } - ob_params = (int *)po->kvaddr; - *ob_params++ = m_id; - *ob_params++ = param_id; - *ob_params++ = size; - memcpy(ob_params, data, size); - } else { - pr_debug("DTS_EAGLE_ASM - %s: using in band\n", __func__); - memcpy(((char *)ad) + sizeof(struct asm_dts_eagle_param), - data, size); - } - rc = apr_send_pkt(ac->apr, (uint32_t *)ad); - if (rc < 0) { - pr_err("DTS_EAGLE_ASM - %s: set-params send failed paramid[0x%x]\n", - __func__, ad->data.param_id); - rc = -EINVAL; - goto fail_cmd; - } - - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) <= 0), 1*HZ); - if (!rc) { - pr_err("DTS_EAGLE_ASM - %s: timeout, set-params paramid[0x%x]\n", - __func__, ad->data.param_id); - rc = -EINVAL; - goto fail_cmd; - } - rc = 0; -fail_cmd: - kfree(ad); - return rc; -} - -int q6asm_dts_eagle_get(struct audio_client *ac, int param_id, uint32_t size, - void *data, struct param_outband *po, int m_id) -{ - struct asm_dts_eagle_param_get *ad; - int rc = 0, *ob_params = NULL; - uint32_t sz = sizeof(struct asm_dts_eagle_param) + APR_CMD_GET_HDR_SZ + - (po ? 0 : size); - - if (!ac || ac->apr == NULL || (size == 0) || !data) { - pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %pK\n", - __func__, size, data); - return -EINVAL; - } - ad = kzalloc(sz, GFP_KERNEL); - if (!ad) { - pr_err("DTS_EAGLE_ASM - %s: error allocating memory of size %u\n", - __func__, sz); - return -ENOMEM; - } - pr_debug("DTS_EAGLE_ASM - %s: ac %pK param_id 0x%x size %u data %pK m_id 0x%x\n", - __func__, ac, param_id, size, data, m_id); - q6asm_add_hdr(ac, &ad->hdr, sz, TRUE); - ad->hdr.opcode = ASM_STREAM_CMD_GET_PP_PARAMS_V2; - ad->param.data_payload_addr_lsw = 0; - ad->param.data_payload_addr_msw = 0; - ad->param.mem_map_handle = 0; - ad->param.module_id = m_id; - ad->param.param_id = param_id; - ad->param.param_max_size = size + APR_CMD_GET_HDR_SZ; - ad->param.reserved = 0; - atomic_set(&ac->cmd_state, 1); - - generic_get_data = kzalloc(size + sizeof(struct generic_get_data_), - GFP_KERNEL); - if (!generic_get_data) { - pr_err("DTS_EAGLE_ASM - %s: error allocating mem of size %u\n", - __func__, size); - rc = -ENOMEM; - goto fail_cmd; - } - - if (po) { - struct list_head *ptr, *next; - struct asm_buffer_node *node; - pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %pK, physical %pK)\n", - __func__, po->kvaddr, &po->paddr); - ad->param.data_payload_addr_lsw = lower_32_bits(po->paddr); - ad->param.data_payload_addr_msw = populate_upper_32_bits( - po->paddr); - list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) { - node = list_entry(ptr, struct asm_buffer_node, list); - if (node->buf_phys_addr == po->paddr) { - ad->param.mem_map_handle = node->mmap_hdl; - break; - } - } - if (ad->param.mem_map_handle == 0) { - pr_err("DTS_EAGLE_ASM - %s: mem map handle not found\n", - __func__); - rc = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - rc = -EINVAL; - if ((rc < 0) || (size + APR_CMD_OB_HDR_SZ > po->size)) { - pr_err("DTS_EAGLE_ASM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, po->size, size + APR_CMD_OB_HDR_SZ); - rc = -EINVAL; - goto fail_cmd; - } - ob_params = (int *)po->kvaddr; - *ob_params++ = m_id; - *ob_params++ = param_id; - *ob_params++ = size; - generic_get_data->is_inband = 0; - } else { - pr_debug("DTS_EAGLE_ASM - %s: using in band\n", __func__); - generic_get_data->is_inband = 1; - } - - rc = apr_send_pkt(ac->apr, (uint32_t *)ad); - if (rc < 0) { - pr_err("DTS_EAGLE_ASM - %s: Commmand 0x%x failed\n", __func__, - ad->hdr.opcode); - goto fail_cmd; - } - - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) <= 0), 1*HZ); - if (!rc) { - pr_err("DTS_EAGLE_ASM - %s: timeout in get\n", - __func__); - rc = -EINVAL; - goto fail_cmd; - } - - if (generic_get_data->valid) { - rc = 0; - memcpy(data, po ? ob_params : generic_get_data->ints, size); - } else { - rc = -EINVAL; - pr_err("DTS_EAGLE_ASM - %s: EAGLE get params problem getting data - check callback error value\n", - __func__); - } -fail_cmd: - kfree(ad); - kfree(generic_get_data); - generic_get_data = NULL; - return rc; -} - static int __q6asm_set_volume(struct audio_client *ac, int volume, int instance) { struct asm_volume_ctrl_master_gain vol; diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c index 1b01a72eb05..2705fc330a5 100644 --- a/sound/soc/msm/qdsp6v2/q6core.c +++ b/sound/soc/msm/qdsp6v2/q6core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. 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 version 2 and @@ -163,7 +163,7 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) generic_get_data->valid = 1; generic_get_data->size_in_ints = data->payload_size/sizeof(int); - pr_debug("DTS_EAGLE_CORE callback size = %i\n", + pr_debug("callback size = %i\n", data->payload_size); memcpy(generic_get_data->ints, data->payload, data->payload_size); @@ -340,115 +340,6 @@ fail_cmd: return ret; } -int core_dts_eagle_set(int size, char *data) -{ - struct adsp_dts_eagle *payload = NULL; - int rc = 0, size_aligned4byte; - - pr_debug("DTS_EAGLE_CORE - %s\n", __func__); - if (size <= 0 || !data) { - pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - - size_aligned4byte = (size+3) & 0xFFFFFFFC; - ocm_core_open(); - if (q6core_lcl.core_handle_q) { - payload = kzalloc(sizeof(struct adsp_dts_eagle) + - size_aligned4byte, GFP_KERNEL); - if (!payload) { - pr_err("DTS_EAGLE_CORE - %s: out of memory (aligned size %i).\n", - __func__, size_aligned4byte); - return -ENOMEM; - } - payload->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT, - APR_HDR_LEN(APR_HDR_SIZE), - APR_PKT_VER); - payload->hdr.pkt_size = sizeof(struct adsp_dts_eagle) + - size_aligned4byte; - payload->hdr.src_port = 0; - payload->hdr.dest_port = 0; - payload->hdr.token = 0; - payload->hdr.opcode = ADSP_CMD_SET_DTS_EAGLE_DATA_ID; - payload->id = DTS_EAGLE_LICENSE_ID; - payload->overwrite = 1; - payload->size = size; - memcpy(payload->data, data, size); - rc = apr_send_pkt(q6core_lcl.core_handle_q, - (uint32_t *)payload); - if (rc < 0) { - pr_err("DTS_EAGLE_CORE - %s: failed op[0x%x]rc[%d]\n", - __func__, payload->hdr.opcode, rc); - } - kfree(payload); - } - return rc; -} - -int core_dts_eagle_get(int id, int size, char *data) -{ - struct apr_hdr ah; - int rc = 0; - - pr_debug("DTS_EAGLE_CORE - %s\n", __func__); - if (size <= 0 || !data) { - pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - ocm_core_open(); - if (q6core_lcl.core_handle_q) { - ah.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - ah.pkt_size = sizeof(struct apr_hdr); - ah.src_port = 0; - ah.dest_port = 0; - ah.token = 0; - ah.opcode = id; - - q6core_lcl.bus_bw_resp_received = 0; - generic_get_data = kzalloc(sizeof(struct generic_get_data_) - + size, GFP_KERNEL); - if (!generic_get_data) { - pr_err("DTS_EAGLE_CORE - %s: error allocating memory of size %i\n", - __func__, size); - return -ENOMEM; - } - - rc = apr_send_pkt(q6core_lcl.core_handle_q, - (uint32_t *)&ah); - if (rc < 0) { - pr_err("DTS_EAGLE_CORE - %s: failed op[0x%x]rc[%d]\n", - __func__, ah.opcode, rc); - goto fail_cmd_2; - } - - rc = wait_event_timeout(q6core_lcl.bus_bw_req_wait, - (q6core_lcl.bus_bw_resp_received == 1), - msecs_to_jiffies(TIMEOUT_MS)); - if (!rc) { - pr_err("DTS_EAGLE_CORE - %s: EAGLE get params timed out\n", - __func__); - rc = -EINVAL; - goto fail_cmd_2; - } - if (generic_get_data->valid) { - rc = 0; - memcpy(data, generic_get_data->ints, size); - } else { - rc = -EINVAL; - pr_err("DTS_EAGLE_CORE - %s: EAGLE get params problem getting data - check callback error value\n", - __func__); - } - } - -fail_cmd_2: - kfree(generic_get_data); - generic_get_data = NULL; - return rc; -} - uint32_t core_set_dolby_manufacturer_id(int manufacturer_id) { struct adsp_dolby_manufacturer_id payload; diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c index face98c72d7..d1f9631d841 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.c +++ b/sound/soc/msm/qdsp6v2/q6voice.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. 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 version 2 and @@ -7525,7 +7525,7 @@ static int voice_alloc_source_tracking_shared_memory(void) &(common.source_tracking_sh_mem.sh_mem_block.handle), BUFFER_BLOCK_SIZE, &(common.source_tracking_sh_mem.sh_mem_block.phys), - (size_t *)&(common.source_tracking_sh_mem.sh_mem_block.size), + &(common.source_tracking_sh_mem.sh_mem_block.size), &(common.source_tracking_sh_mem.sh_mem_block.data)); if (ret < 0) { pr_err("%s: audio ION alloc failed for sh_mem block, ret = %d\n", @@ -7541,14 +7541,14 @@ static int voice_alloc_source_tracking_shared_memory(void) __func__, &(common.source_tracking_sh_mem.sh_mem_block.phys), (void *)(common.source_tracking_sh_mem.sh_mem_block.data), - (size_t)(common.source_tracking_sh_mem.sh_mem_block.size)); + (common.source_tracking_sh_mem.sh_mem_block.size)); ret = msm_audio_ion_alloc("source_tracking_sh_mem_table", &(common.source_tracking_sh_mem.sh_mem_table.client), &(common.source_tracking_sh_mem.sh_mem_table.handle), sizeof(struct vss_imemory_table_t), &(common.source_tracking_sh_mem.sh_mem_table.phys), - (size_t *)&(common.source_tracking_sh_mem.sh_mem_table.size), + &(common.source_tracking_sh_mem.sh_mem_table.size), &(common.source_tracking_sh_mem.sh_mem_table.data)); if (ret < 0) { pr_err("%s: audio ION alloc failed for sh_mem table, ret = %d\n", @@ -7572,7 +7572,7 @@ static int voice_alloc_source_tracking_shared_memory(void) __func__, &(common.source_tracking_sh_mem.sh_mem_table.phys), (void *)(common.source_tracking_sh_mem.sh_mem_table.data), - (size_t)(common.source_tracking_sh_mem.sh_mem_table.size)); + (common.source_tracking_sh_mem.sh_mem_table.size)); done: pr_debug("%s: Exit, ret=%d\n", __func__, ret); diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h index 430c0e0d08e..13782342e42 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.h +++ b/sound/soc/msm/qdsp6v2/q6voice.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. 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 version 2 and @@ -126,7 +126,7 @@ struct share_mem_buf { struct mem_map_table { dma_addr_t phys; void *data; - uint32_t size; /* size of buffer */ + size_t size; /* size of buffer */ struct ion_handle *handle; struct ion_client *client; }; |
